Skip to content

Commit 61e4d23

Browse files
authored
[RISCV] Fold (X & -(1 << C1) & 0xffffffff) == C2 << C1 to sraiw X, C1 == C2. (#157617)
We had an existing fold for (X & -(1 << C1) & 0xffffffff) == 0 which we can generalize to support comparing to constants other than 0. Previously we used srliw, but this generalizes better using sraiw. I'm restricting to the case where C2 is simm12 or 2048 to allow sraiw+addi/xori+seqz/snez to be used. Other constants require a more careful analysis of the constants involved.
1 parent 397e5a4 commit 61e4d23

File tree

3 files changed

+84
-19
lines changed

3 files changed

+84
-19
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16761,29 +16761,37 @@ static SDValue performSETCCCombine(SDNode *N,
1676116761
combineVectorSizedSetCCEquality(VT, N0, N1, Cond, dl, DAG, Subtarget))
1676216762
return V;
1676316763

16764-
if (DCI.isAfterLegalizeDAG() && isNullConstant(N1) &&
16764+
if (DCI.isAfterLegalizeDAG() && isa<ConstantSDNode>(N1) &&
1676516765
N0.getOpcode() == ISD::AND && N0.hasOneUse() &&
1676616766
isa<ConstantSDNode>(N0.getOperand(1))) {
16767-
const APInt &AndRHSC =
16768-
cast<ConstantSDNode>(N0.getOperand(1))->getAPIntValue();
16767+
const APInt &AndRHSC = N0.getConstantOperandAPInt(1);
1676916768
// (X & -(1 << C)) == 0 -> (X >> C) == 0 if the AND constant can't use ANDI.
16770-
if (!isInt<12>(AndRHSC.getSExtValue()) && AndRHSC.isNegatedPowerOf2()) {
16769+
if (isNullConstant(N1) && !isInt<12>(AndRHSC.getSExtValue()) &&
16770+
AndRHSC.isNegatedPowerOf2()) {
1677116771
unsigned ShiftBits = AndRHSC.countr_zero();
1677216772
SDValue Shift = DAG.getNode(ISD::SRL, dl, OpVT, N0.getOperand(0),
1677316773
DAG.getConstant(ShiftBits, dl, OpVT));
1677416774
return DAG.getSetCC(dl, VT, Shift, N1, Cond);
1677516775
}
1677616776

16777-
// Similar to above but handling the lower 32 bits by using srliw.
16778-
// FIXME: Handle the case where N1 is non-zero.
16779-
if (OpVT == MVT::i64 && AndRHSC.getZExtValue() <= 0xffffffff &&
16780-
isPowerOf2_32(-uint32_t(AndRHSC.getZExtValue()))) {
16781-
unsigned ShiftBits = llvm::countr_zero(AndRHSC.getZExtValue());
16782-
SDValue And = DAG.getNode(ISD::AND, dl, OpVT, N0.getOperand(0),
16783-
DAG.getConstant(0xffffffff, dl, OpVT));
16784-
SDValue Shift = DAG.getNode(ISD::SRL, dl, OpVT, And,
16785-
DAG.getConstant(ShiftBits, dl, OpVT));
16786-
return DAG.getSetCC(dl, VT, Shift, N1, Cond);
16777+
// Similar to above but handling the lower 32 bits by using sraiw. Allow
16778+
// comparing with constants other than 0 if the constant can be folded into
16779+
// addi or xori after shifting.
16780+
uint64_t N1Int = cast<ConstantSDNode>(N1)->getZExtValue();
16781+
uint64_t AndRHSInt = AndRHSC.getZExtValue();
16782+
if (OpVT == MVT::i64 && AndRHSInt <= 0xffffffff &&
16783+
isPowerOf2_32(-uint32_t(AndRHSInt)) && (N1Int & AndRHSInt) == N1Int) {
16784+
unsigned ShiftBits = llvm::countr_zero(AndRHSInt);
16785+
int64_t NewC = SignExtend64<32>(N1Int) >> ShiftBits;
16786+
if (NewC >= -2048 && NewC <= 2048) {
16787+
SDValue SExt =
16788+
DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, OpVT, N0.getOperand(0),
16789+
DAG.getValueType(MVT::i32));
16790+
SDValue Shift = DAG.getNode(ISD::SRA, dl, OpVT, SExt,
16791+
DAG.getConstant(ShiftBits, dl, OpVT));
16792+
return DAG.getSetCC(dl, VT, Shift,
16793+
DAG.getSignedConstant(NewC, dl, OpVT), Cond);
16794+
}
1678716795
}
1678816796
}
1678916797

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

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ define i1 @test5(i64 %x) {
7474
;
7575
; RV64-LABEL: test5:
7676
; RV64: # %bb.0:
77-
; RV64-NEXT: srliw a0, a0, 29
77+
; RV64-NEXT: sraiw a0, a0, 29
7878
; RV64-NEXT: seqz a0, a0
7979
; RV64-NEXT: ret
8080
%a = and i64 %x, u0xE0000000
@@ -91,10 +91,67 @@ define i1 @test6(i64 %x) {
9191
;
9292
; RV64-LABEL: test6:
9393
; RV64: # %bb.0:
94-
; RV64-NEXT: srliw a0, a0, 29
94+
; RV64-NEXT: sraiw a0, a0, 29
9595
; RV64-NEXT: snez a0, a0
9696
; RV64-NEXT: ret
9797
%a = and i64 %x, u0xE0000000
9898
%b = icmp ne i64 %a, 0
9999
ret i1 %b
100100
}
101+
102+
define i1 @test7(i64 %x) {
103+
; RV32-LABEL: test7:
104+
; RV32: # %bb.0:
105+
; RV32-NEXT: srli a0, a0, 29
106+
; RV32-NEXT: addi a0, a0, -6
107+
; RV32-NEXT: seqz a0, a0
108+
; RV32-NEXT: ret
109+
;
110+
; RV64-LABEL: test7:
111+
; RV64: # %bb.0:
112+
; RV64-NEXT: sraiw a0, a0, 29
113+
; RV64-NEXT: addi a0, a0, 2
114+
; RV64-NEXT: seqz a0, a0
115+
; RV64-NEXT: ret
116+
%a = and i64 %x, u0xE0000000
117+
%b = icmp eq i64 %a, u0xC0000000
118+
ret i1 %b
119+
}
120+
121+
define i1 @test8(i64 %x) {
122+
; RV32-LABEL: test8:
123+
; RV32: # %bb.0:
124+
; RV32-NEXT: srai a0, a0, 20
125+
; RV32-NEXT: xori a0, a0, -2048
126+
; RV32-NEXT: snez a0, a0
127+
; RV32-NEXT: ret
128+
;
129+
; RV64-LABEL: test8:
130+
; RV64: # %bb.0:
131+
; RV64-NEXT: sraiw a0, a0, 20
132+
; RV64-NEXT: xori a0, a0, -2048
133+
; RV64-NEXT: snez a0, a0
134+
; RV64-NEXT: ret
135+
%a = and i64 %x, u0xFFF00000
136+
%b = icmp ne i64 %a, u0x80000000
137+
ret i1 %b
138+
}
139+
140+
define i1 @test9(i64 %x) {
141+
; RV32-LABEL: test9:
142+
; RV32: # %bb.0:
143+
; RV32-NEXT: srli a0, a0, 16
144+
; RV32-NEXT: addi a0, a0, -2048
145+
; RV32-NEXT: seqz a0, a0
146+
; RV32-NEXT: ret
147+
;
148+
; RV64-LABEL: test9:
149+
; RV64: # %bb.0:
150+
; RV64-NEXT: sraiw a0, a0, 16
151+
; RV64-NEXT: addi a0, a0, -2048
152+
; RV64-NEXT: seqz a0, a0
153+
; RV64-NEXT: ret
154+
%a = and i64 %x, u0xFFFF0000
155+
%b = icmp eq i64 %a, u0x08000000
156+
ret i1 %b
157+
}

llvm/test/CodeGen/RISCV/bittest.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,13 @@ define i64 @bittest_31_i64(i64 %a) nounwind {
187187
;
188188
; RV64ZBS-LABEL: bittest_31_i64:
189189
; RV64ZBS: # %bb.0:
190-
; RV64ZBS-NEXT: srliw a0, a0, 31
190+
; RV64ZBS-NEXT: sraiw a0, a0, 31
191191
; RV64ZBS-NEXT: seqz a0, a0
192192
; RV64ZBS-NEXT: ret
193193
;
194194
; RV64XTHEADBS-LABEL: bittest_31_i64:
195195
; RV64XTHEADBS: # %bb.0:
196-
; RV64XTHEADBS-NEXT: srliw a0, a0, 31
196+
; RV64XTHEADBS-NEXT: sraiw a0, a0, 31
197197
; RV64XTHEADBS-NEXT: seqz a0, a0
198198
; RV64XTHEADBS-NEXT: ret
199199
%shr = lshr i64 %a, 31
@@ -3517,7 +3517,7 @@ define i32 @bittest_31_andeq0_i64(i64 %x) {
35173517
;
35183518
; RV64-LABEL: bittest_31_andeq0_i64:
35193519
; RV64: # %bb.0:
3520-
; RV64-NEXT: srliw a0, a0, 31
3520+
; RV64-NEXT: sraiw a0, a0, 31
35213521
; RV64-NEXT: seqz a0, a0
35223522
; RV64-NEXT: ret
35233523
%and = and i64 %x, 2147483648

0 commit comments

Comments
 (0)