Skip to content

Commit b844a7b

Browse files
committed
[RISCV] Fold (X & (3 << 30)) == 0 -> (srliw X, 30) == 0 for RV64.
This is similar to the recently added (X & -4096) == 0 -> (X >> 12) == 0, but operating only on the lower 32 bits. This also removes the (X & (1 << 31)) == 0 -> (xor (srliw X, 31), 1) isel pattern. seqz and xori 1 should have similar cost and encoding size.
1 parent 83f1b12 commit b844a7b

File tree

4 files changed

+22
-14
lines changed

4 files changed

+22
-14
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16726,10 +16726,6 @@ combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC,
1672616726
DAG.getConstant(0, DL, XLenVT), CC);
1672716727
}
1672816728

16729-
// Replace (seteq (i64 (and X, 0xffffffff)), C1) with
16730-
// (seteq (i64 (sext_inreg (X, i32)), C1')) where C1' is C1 sign extended from
16731-
// bit 31. Same for setne. C1' may be cheaper to materialize and the sext_inreg
16732-
// can become a sext.w instead of a shift pair.
1673316729
static SDValue performSETCCCombine(SDNode *N,
1673416730
TargetLowering::DAGCombinerInfo &DCI,
1673516731
const RISCVSubtarget &Subtarget) {
@@ -16749,20 +16745,36 @@ static SDValue performSETCCCombine(SDNode *N,
1674916745
combineVectorSizedSetCCEquality(VT, N0, N1, Cond, dl, DAG, Subtarget))
1675016746
return V;
1675116747

16752-
// (X & -4096) == 0 -> (X >> 12) == 0 if the AND constant can't use ANDI.
1675316748
if (DCI.isAfterLegalizeDAG() && isNullConstant(N1) &&
1675416749
N0.getOpcode() == ISD::AND && N0.hasOneUse() &&
1675516750
isa<ConstantSDNode>(N0.getOperand(1))) {
1675616751
const APInt &AndRHSC =
1675716752
cast<ConstantSDNode>(N0.getOperand(1))->getAPIntValue();
16753+
// (X & -4096) == 0 -> (X >> 12) == 0 if the AND constant can't use ANDI.
1675816754
if (!isInt<12>(AndRHSC.getSExtValue()) && AndRHSC.isNegatedPowerOf2()) {
1675916755
unsigned ShiftBits = AndRHSC.countr_zero();
16760-
SDValue Shift = DAG.getNode(ISD::SRL, dl, VT, N0.getOperand(0),
16761-
DAG.getConstant(ShiftBits, dl, VT));
16756+
SDValue Shift = DAG.getNode(ISD::SRL, dl, OpVT, N0.getOperand(0),
16757+
DAG.getConstant(ShiftBits, dl, OpVT));
16758+
return DAG.getSetCC(dl, VT, Shift, N1, Cond);
16759+
}
16760+
16761+
// Similar to above but handling the lower 32 bits by using srliw.
16762+
// FIXME: Handle the case where N1 is non-zero.
16763+
if (OpVT == MVT::i64 && AndRHSC.getZExtValue() <= 0xffffffff &&
16764+
isPowerOf2_32(-uint32_t(AndRHSC.getZExtValue()))) {
16765+
unsigned ShiftBits = llvm::countr_zero(AndRHSC.getZExtValue());
16766+
SDValue And = DAG.getNode(ISD::AND, dl, OpVT, N0.getOperand(0),
16767+
DAG.getConstant(0xffffffff, dl, OpVT));
16768+
SDValue Shift = DAG.getNode(ISD::SRL, dl, OpVT, And,
16769+
DAG.getConstant(ShiftBits, dl, OpVT));
1676216770
return DAG.getSetCC(dl, VT, Shift, N1, Cond);
1676316771
}
1676416772
}
1676516773

16774+
// Replace (seteq (i64 (and X, 0xffffffff)), C1) with
16775+
// (seteq (i64 (sext_inreg (X, i32)), C1')) where C1' is C1 sign extended from
16776+
// bit 31. Same for setne. C1' may be cheaper to materialize and the
16777+
// sext_inreg can become a sext.w instead of a shift pair.
1676616778
if (OpVT != MVT::i64 || !Subtarget.is64Bit())
1676716779
return SDValue();
1676816780

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,8 +1698,6 @@ let Predicates = [IsRV32] in {
16981698
def : Pat<(i32 (setlt (i32 GPR:$rs1), 0)), (SRLI GPR:$rs1, 31)>; // compressible
16991699
}
17001700
let Predicates = [IsRV64] in {
1701-
def : Pat<(i64 (seteq (i64 (and GPR:$rs1, 0x0000000080000000)), 0)),
1702-
(XORI (i64 (SRLIW GPR:$rs1, 31)), 1)>;
17031701
def : Pat<(i64 (setlt (i64 GPR:$rs1), 0)), (SRLI GPR:$rs1, 63)>; // compressible
17041702
def : Pat<(i64 (setlt (sext_inreg GPR:$rs1, i32), 0)), (SRLIW GPR:$rs1, 31)>;
17051703
}

llvm/test/CodeGen/RISCV/and-negpow2-cmp.ll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ define i1 @test5(i64 %x) {
7575
; RV64-LABEL: test5:
7676
; RV64: # %bb.0:
7777
; RV64-NEXT: srliw a0, a0, 29
78-
; RV64-NEXT: slli a0, a0, 29
7978
; RV64-NEXT: seqz a0, a0
8079
; RV64-NEXT: ret
8180
%a = and i64 %x, u0xE0000000
@@ -93,7 +92,6 @@ define i1 @test6(i64 %x) {
9392
; RV64-LABEL: test6:
9493
; RV64: # %bb.0:
9594
; RV64-NEXT: srliw a0, a0, 29
96-
; RV64-NEXT: slli a0, a0, 29
9795
; RV64-NEXT: snez a0, a0
9896
; RV64-NEXT: ret
9997
%a = and i64 %x, u0xE0000000

llvm/test/CodeGen/RISCV/bittest.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,13 @@ define i64 @bittest_31_i64(i64 %a) nounwind {
188188
; RV64ZBS-LABEL: bittest_31_i64:
189189
; RV64ZBS: # %bb.0:
190190
; RV64ZBS-NEXT: srliw a0, a0, 31
191-
; RV64ZBS-NEXT: xori a0, a0, 1
191+
; RV64ZBS-NEXT: seqz a0, a0
192192
; RV64ZBS-NEXT: ret
193193
;
194194
; RV64XTHEADBS-LABEL: bittest_31_i64:
195195
; RV64XTHEADBS: # %bb.0:
196196
; RV64XTHEADBS-NEXT: srliw a0, a0, 31
197-
; RV64XTHEADBS-NEXT: xori a0, a0, 1
197+
; RV64XTHEADBS-NEXT: seqz a0, a0
198198
; RV64XTHEADBS-NEXT: ret
199199
%shr = lshr i64 %a, 31
200200
%not = xor i64 %shr, -1
@@ -3518,7 +3518,7 @@ define i32 @bittest_31_andeq0_i64(i64 %x) {
35183518
; RV64-LABEL: bittest_31_andeq0_i64:
35193519
; RV64: # %bb.0:
35203520
; RV64-NEXT: srliw a0, a0, 31
3521-
; RV64-NEXT: xori a0, a0, 1
3521+
; RV64-NEXT: seqz a0, a0
35223522
; RV64-NEXT: ret
35233523
%and = and i64 %x, 2147483648
35243524
%cmp = icmp eq i64 %and, 0

0 commit comments

Comments
 (0)