Skip to content

Commit 97d4c7d

Browse files
authored
[RISCV] Fold (X & (7 << 29)) == 0 -> (srliw X, 29) == 0 for RV64. (#156769)
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 3fa3932 commit 97d4c7d

File tree

4 files changed

+56
-12
lines changed

4 files changed

+56
-12
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 & -(1 << C)) == 0 -> (X >> C) == 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: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,37 @@ define i1 @test4(i64 %x) {
6464
%b = icmp eq i64 %a, 0
6565
ret i1 %b
6666
}
67+
68+
define i1 @test5(i64 %x) {
69+
; RV32-LABEL: test5:
70+
; RV32: # %bb.0:
71+
; RV32-NEXT: srli a0, a0, 29
72+
; RV32-NEXT: seqz a0, a0
73+
; RV32-NEXT: ret
74+
;
75+
; RV64-LABEL: test5:
76+
; RV64: # %bb.0:
77+
; RV64-NEXT: srliw a0, a0, 29
78+
; RV64-NEXT: seqz a0, a0
79+
; RV64-NEXT: ret
80+
%a = and i64 %x, u0xE0000000
81+
%b = icmp eq i64 %a, 0
82+
ret i1 %b
83+
}
84+
85+
define i1 @test6(i64 %x) {
86+
; RV32-LABEL: test6:
87+
; RV32: # %bb.0:
88+
; RV32-NEXT: srli a0, a0, 29
89+
; RV32-NEXT: snez a0, a0
90+
; RV32-NEXT: ret
91+
;
92+
; RV64-LABEL: test6:
93+
; RV64: # %bb.0:
94+
; RV64-NEXT: srliw a0, a0, 29
95+
; RV64-NEXT: snez a0, a0
96+
; RV64-NEXT: ret
97+
%a = and i64 %x, u0xE0000000
98+
%b = icmp ne i64 %a, 0
99+
ret i1 %b
100+
}

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)