Skip to content

Commit 5dcfd5c

Browse files
pfusikIanWood1
authored andcommitted
[RISCV] Select (add x, C) -> (sub x, -C) if -C cheaper to materialize (llvm#137309)
RV64 only. For 32-bit constants, a negated constant is never cheaper. This change is similar to how llvm#120221 selects inverted bitwise instructions.
1 parent 04e628a commit 5dcfd5c

File tree

4 files changed

+39
-12
lines changed

4 files changed

+39
-12
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3206,6 +3206,23 @@ bool RISCVDAGToDAGISel::selectSHXADD_UWOp(SDValue N, unsigned ShAmt,
32063206
return false;
32073207
}
32083208

3209+
bool RISCVDAGToDAGISel::selectNegImm(SDValue N, SDValue &Val) {
3210+
if (!isa<ConstantSDNode>(N) || !N.hasOneUse())
3211+
return false;
3212+
int64_t Imm = cast<ConstantSDNode>(N)->getSExtValue();
3213+
if (isInt<32>(Imm))
3214+
return false;
3215+
int OrigImmCost = RISCVMatInt::getIntMatCost(APInt(64, Imm), 64, *Subtarget,
3216+
/*CompressionCost=*/true);
3217+
int NegImmCost = RISCVMatInt::getIntMatCost(APInt(64, -Imm), 64, *Subtarget,
3218+
/*CompressionCost=*/true);
3219+
if (OrigImmCost <= NegImmCost)
3220+
return false;
3221+
3222+
Val = selectImm(CurDAG, SDLoc(N), N->getSimpleValueType(0), -Imm, *Subtarget);
3223+
return true;
3224+
}
3225+
32093226
bool RISCVDAGToDAGISel::selectInvLogicImm(SDValue N, SDValue &Val) {
32103227
if (!isa<ConstantSDNode>(N))
32113228
return false;

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
120120
return selectSHXADD_UWOp(N, ShAmt, Val);
121121
}
122122

123+
bool selectNegImm(SDValue N, SDValue &Val);
123124
bool selectInvLogicImm(SDValue N, SDValue &Val);
124125

125126
bool hasAllNBitUsers(SDNode *Node, unsigned Bits,

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2120,11 +2120,16 @@ def : Pat<(XLenVT (add GPR:$rs1, immop_oneuse<AddiPair>:$rs2)),
21202120
(ADDI (XLenVT (ADDI GPR:$rs1, (AddiPairImmLarge imm:$rs2))),
21212121
(AddiPairImmSmall imm:$rs2))>;
21222122

2123+
def negImm : ComplexPattern<i64, 1, "selectNegImm", [], [], 0>;
2124+
21232125
let Predicates = [IsRV64] in {
21242126
// Select W instructions if only the lower 32-bits of the result are used.
21252127
def : Pat<(binop_allwusers<add> GPR:$rs1, immop_oneuse<AddiPair>:$rs2),
21262128
(ADDIW (i64 (ADDIW GPR:$rs1, (AddiPairImmLarge imm:$rs2))),
21272129
(AddiPairImmSmall imm:$rs2))>;
2130+
2131+
// Select SUB if the negated constant is cheaper to materialize.
2132+
def : Pat<(i64 (add GPR:$rs1, negImm:$rs2)), (SUB GPR:$rs1, negImm:$rs2)>;
21282133
}
21292134

21302135
//===----------------------------------------------------------------------===//

llvm/test/CodeGen/RISCV/add-imm64-to-sub.ll

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
55
define i64 @add_b31(i64 %x) {
66
; NOZBS-LABEL: add_b31:
77
; NOZBS: # %bb.0:
8-
; NOZBS-NEXT: li a1, 1
9-
; NOZBS-NEXT: slli a1, a1, 31
10-
; NOZBS-NEXT: add a0, a0, a1
8+
; NOZBS-NEXT: lui a1, 524288
9+
; NOZBS-NEXT: sub a0, a0, a1
1110
; NOZBS-NEXT: ret
1211
;
1312
; ZBS-LABEL: add_b31:
@@ -20,12 +19,18 @@ define i64 @add_b31(i64 %x) {
2019
}
2120

2221
define i64 @add_b32(i64 %x) {
23-
; CHECK-LABEL: add_b32:
24-
; CHECK: # %bb.0:
25-
; CHECK-NEXT: li a1, -1
26-
; CHECK-NEXT: slli a1, a1, 32
27-
; CHECK-NEXT: add a0, a0, a1
28-
; CHECK-NEXT: ret
22+
; NOZBS-LABEL: add_b32:
23+
; NOZBS: # %bb.0:
24+
; NOZBS-NEXT: li a1, -1
25+
; NOZBS-NEXT: slli a1, a1, 32
26+
; NOZBS-NEXT: add a0, a0, a1
27+
; NOZBS-NEXT: ret
28+
;
29+
; ZBS-LABEL: add_b32:
30+
; ZBS: # %bb.0:
31+
; ZBS-NEXT: bseti a1, zero, 32
32+
; ZBS-NEXT: sub a0, a0, a1
33+
; ZBS-NEXT: ret
2934
%add = add i64 %x, -4294967296
3035
ret i64 %add
3136
}
@@ -34,9 +39,8 @@ define i64 @sub_0xffffffffff(i64 %x) {
3439
; CHECK-LABEL: sub_0xffffffffff:
3540
; CHECK: # %bb.0:
3641
; CHECK-NEXT: li a1, -1
37-
; CHECK-NEXT: slli a1, a1, 40
38-
; CHECK-NEXT: addi a1, a1, 1
39-
; CHECK-NEXT: add a0, a0, a1
42+
; CHECK-NEXT: srli a1, a1, 24
43+
; CHECK-NEXT: sub a0, a0, a1
4044
; CHECK-NEXT: ret
4145
%sub = sub i64 %x, 1099511627775
4246
ret i64 %sub

0 commit comments

Comments
 (0)