Skip to content

Commit da19383

Browse files
authored
[RISCV] Fold (X & -4096) == 0 -> (X >> 12) == 0 (llvm#154233)
This is a more general form of the recently added isel pattern (seteq (i64 (and GPR:$rs1, 0x8000000000000000)), 0) -> (XORI (i64 (SRLI GPR:$rs1, 63)), 1) We can use a shift right for any AND mask that is a negated power of 2. But for every other constant we need to use seqz instead of xori. I don't think there is a benefit to xori over seqz as neither are compressible. We already do this transform from target independent code when the setcc constant is a non-zero subset of the AND mask that is not a legal icmp immediate. I don't believe any of these patterns comparing MSBs to 0 are canonical according to InstCombine. The canonical form is (X < 4096). I'm curious if these appear during SelectionDAG and if so, how. My goal here was just to remove the special case isel patterns.
1 parent 2817873 commit da19383

File tree

4 files changed

+80
-16
lines changed

4 files changed

+80
-16
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16588,8 +16588,10 @@ combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC,
1658816588
// (seteq (i64 (sext_inreg (X, i32)), C1')) where C1' is C1 sign extended from
1658916589
// bit 31. Same for setne. C1' may be cheaper to materialize and the sext_inreg
1659016590
// can become a sext.w instead of a shift pair.
16591-
static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG,
16591+
static SDValue performSETCCCombine(SDNode *N,
16592+
TargetLowering::DAGCombinerInfo &DCI,
1659216593
const RISCVSubtarget &Subtarget) {
16594+
SelectionDAG &DAG = DCI.DAG;
1659316595
SDLoc dl(N);
1659416596
SDValue N0 = N->getOperand(0);
1659516597
SDValue N1 = N->getOperand(1);
@@ -16605,6 +16607,20 @@ static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG,
1660516607
combineVectorSizedSetCCEquality(VT, N0, N1, Cond, dl, DAG, Subtarget))
1660616608
return V;
1660716609

16610+
// (X & -4096) == 0 -> (X >> 12) == 0 if the AND constant can't use ANDI.
16611+
if (DCI.isAfterLegalizeDAG() && isNullConstant(N1) &&
16612+
N0.getOpcode() == ISD::AND && N0.hasOneUse() &&
16613+
isa<ConstantSDNode>(N0.getOperand(1))) {
16614+
const APInt &AndRHSC =
16615+
cast<ConstantSDNode>(N0.getOperand(1))->getAPIntValue();
16616+
if (!isInt<12>(AndRHSC.getSExtValue()) && AndRHSC.isNegatedPowerOf2()) {
16617+
unsigned ShiftBits = AndRHSC.countr_zero();
16618+
SDValue Shift = DAG.getNode(ISD::SRL, dl, VT, N0.getOperand(0),
16619+
DAG.getConstant(ShiftBits, dl, VT));
16620+
return DAG.getSetCC(dl, VT, Shift, N1, Cond);
16621+
}
16622+
}
16623+
1660816624
if (OpVT != MVT::i64 || !Subtarget.is64Bit())
1660916625
return SDValue();
1661016626

@@ -20091,7 +20107,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
2009120107
return SDValue();
2009220108
}
2009320109
case ISD::SETCC:
20094-
return performSETCCCombine(N, DAG, Subtarget);
20110+
return performSETCCCombine(N, DCI, Subtarget);
2009520111
case ISD::SIGN_EXTEND_INREG:
2009620112
return performSIGN_EXTEND_INREGCombine(N, DCI, Subtarget);
2009720113
case ISD::ZERO_EXTEND:

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,13 +1695,9 @@ multiclass SelectCC_GPR_riirr<DAGOperand valty, DAGOperand imm> {
16951695
}
16961696

16971697
let Predicates = [IsRV32] in {
1698-
def : Pat<(i32 (seteq (i32 (and GPR:$rs1, 0xffffffff80000000)), 0)),
1699-
(XORI (i32 (SRLI GPR:$rs1, 31)), 1)>;
17001698
def : Pat<(i32 (setlt (i32 GPR:$rs1), 0)), (SRLI GPR:$rs1, 31)>; // compressible
17011699
}
17021700
let Predicates = [IsRV64] in {
1703-
def : Pat<(i64 (seteq (i64 (and GPR:$rs1, 0x8000000000000000)), 0)),
1704-
(XORI (i64 (SRLI GPR:$rs1, 63)), 1)>;
17051701
def : Pat<(i64 (seteq (i64 (and GPR:$rs1, 0x0000000080000000)), 0)),
17061702
(XORI (i64 (SRLIW GPR:$rs1, 31)), 1)>;
17071703
def : Pat<(i64 (setlt (i64 GPR:$rs1), 0)), (SRLI GPR:$rs1, 63)>; // compressible
Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,66 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2-
; RUN: llc < %s -mtriple=riscv64 | FileCheck %s
2+
; RUN: llc < %s -mtriple=riscv32 | FileCheck %s --check-prefixes=CHECK,RV32
3+
; RUN: llc < %s -mtriple=riscv64 | FileCheck %s --check-prefixes=CHECK,RV64
34

4-
define i1 @src(i64 %x) {
5-
; CHECK-LABEL: src:
5+
define i1 @test1(i64 %x) {
6+
; RV32-LABEL: test1:
7+
; RV32: # %bb.0:
8+
; RV32-NEXT: slli a2, a1, 2
9+
; RV32-NEXT: srli a0, a0, 30
10+
; RV32-NEXT: srai a1, a1, 30
11+
; RV32-NEXT: or a0, a0, a2
12+
; RV32-NEXT: xori a0, a0, -2
13+
; RV32-NEXT: not a1, a1
14+
; RV32-NEXT: or a0, a0, a1
15+
; RV32-NEXT: seqz a0, a0
16+
; RV32-NEXT: ret
17+
;
18+
; RV64-LABEL: test1:
19+
; RV64: # %bb.0:
20+
; RV64-NEXT: srai a0, a0, 30
21+
; RV64-NEXT: addi a0, a0, 2
22+
; RV64-NEXT: seqz a0, a0
23+
; RV64-NEXT: ret
24+
%a = and i64 %x, -1073741824
25+
%b = icmp eq i64 %a, -2147483648
26+
ret i1 %b
27+
}
28+
29+
define i1 @test2(i32 signext %x) {
30+
; CHECK-LABEL: test2:
631
; CHECK: # %bb.0:
7-
; CHECK-NEXT: srai a0, a0, 30
8-
; CHECK-NEXT: addi a0, a0, 2
32+
; CHECK-NEXT: srli a0, a0, 30
933
; CHECK-NEXT: seqz a0, a0
1034
; CHECK-NEXT: ret
11-
%a = and i64 %x, -1073741824
12-
%b = icmp eq i64 %a, -2147483648
35+
%a = and i32 %x, -1073741824
36+
%b = icmp eq i32 %a, 0
37+
ret i1 %b
38+
}
39+
40+
define i1 @test3(i32 signext %x) {
41+
; CHECK-LABEL: test3:
42+
; CHECK: # %bb.0:
43+
; CHECK-NEXT: srli a0, a0, 29
44+
; CHECK-NEXT: snez a0, a0
45+
; CHECK-NEXT: ret
46+
%a = and i32 %x, -536870912
47+
%b = icmp ne i32 %a, 0
48+
ret i1 %b
49+
}
50+
51+
define i1 @test4(i64 %x) {
52+
; RV32-LABEL: test4:
53+
; RV32: # %bb.0:
54+
; RV32-NEXT: srli a1, a1, 14
55+
; RV32-NEXT: seqz a0, a1
56+
; RV32-NEXT: ret
57+
;
58+
; RV64-LABEL: test4:
59+
; RV64: # %bb.0:
60+
; RV64-NEXT: srli a0, a0, 46
61+
; RV64-NEXT: seqz a0, a0
62+
; RV64-NEXT: ret
63+
%a = and i64 %x, -70368744177664
64+
%b = icmp eq i64 %a, 0
1365
ret i1 %b
1466
}

llvm/test/CodeGen/RISCV/bittest.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3512,7 +3512,7 @@ define i32 @bittest_31_andeq0_i64(i64 %x) {
35123512
; RV32-LABEL: bittest_31_andeq0_i64:
35133513
; RV32: # %bb.0:
35143514
; RV32-NEXT: srli a0, a0, 31
3515-
; RV32-NEXT: xori a0, a0, 1
3515+
; RV32-NEXT: seqz a0, a0
35163516
; RV32-NEXT: ret
35173517
;
35183518
; RV64-LABEL: bittest_31_andeq0_i64:
@@ -3530,13 +3530,13 @@ define i32 @bittest_63_andeq0_i64(i64 %x) {
35303530
; RV32-LABEL: bittest_63_andeq0_i64:
35313531
; RV32: # %bb.0:
35323532
; RV32-NEXT: srli a1, a1, 31
3533-
; RV32-NEXT: xori a0, a1, 1
3533+
; RV32-NEXT: seqz a0, a1
35343534
; RV32-NEXT: ret
35353535
;
35363536
; RV64-LABEL: bittest_63_andeq0_i64:
35373537
; RV64: # %bb.0:
35383538
; RV64-NEXT: srli a0, a0, 63
3539-
; RV64-NEXT: xori a0, a0, 1
3539+
; RV64-NEXT: seqz a0, a0
35403540
; RV64-NEXT: ret
35413541
%and = and i64 %x, 9223372036854775808
35423542
%cmp = icmp eq i64 %and, 0

0 commit comments

Comments
 (0)