Skip to content

Commit 6ab8401

Browse files
authored
[RISCV][GISel] Port AddiPair optimization (#120463)
Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1), in which imm = imm0 + imml and both imm0 and imm1 are simm12. We make imm0 as large as possible and imm1 as small as possible so that we might be able to use c.addi for the small immediate.
1 parent c7451ff commit 6ab8401

File tree

3 files changed

+283
-2
lines changed

3 files changed

+283
-2
lines changed

llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ class RISCVInstructionSelector : public InstructionSelector {
137137
void renderXLenSubTrailingOnes(MachineInstrBuilder &MIB,
138138
const MachineInstr &MI, int OpIdx) const;
139139

140+
void renderAddiPairImmLarge(MachineInstrBuilder &MIB, const MachineInstr &MI,
141+
int OpIdx) const;
142+
void renderAddiPairImmSmall(MachineInstrBuilder &MIB, const MachineInstr &MI,
143+
int OpIdx) const;
144+
140145
const RISCVSubtarget &STI;
141146
const RISCVInstrInfo &TII;
142147
const RISCVRegisterInfo &TRI;
@@ -871,6 +876,25 @@ void RISCVInstructionSelector::renderXLenSubTrailingOnes(
871876
MIB.addImm(Subtarget->getXLen() - llvm::countr_one(C));
872877
}
873878

879+
void RISCVInstructionSelector::renderAddiPairImmSmall(MachineInstrBuilder &MIB,
880+
const MachineInstr &MI,
881+
int OpIdx) const {
882+
assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
883+
"Expected G_CONSTANT");
884+
int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
885+
int64_t Adj = Imm < 0 ? -2048 : 2047;
886+
MIB.addImm(Imm - Adj);
887+
}
888+
889+
void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
890+
const MachineInstr &MI,
891+
int OpIdx) const {
892+
assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
893+
"Expected G_CONSTANT");
894+
int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue() < 0 ? -2048 : 2047;
895+
MIB.addImm(Imm);
896+
}
897+
874898
const TargetRegisterClass *RISCVInstructionSelector::getRegClassForTypeOnBank(
875899
LLT Ty, const RegisterBank &RB) const {
876900
if (RB.getID() == RISCV::GPRBRegBankID) {

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,14 @@ def AddiPair : PatLeaf<(imm), [{
454454
// The immediate operand must be in range [-4096,-2049] or [2048,4094].
455455
int64_t Imm = N->getSExtValue();
456456
return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094);
457-
}]>;
457+
}]> {
458+
let GISelPredicateCode = [{
459+
if (!MRI.hasOneNonDBGUse(MI.getOperand(0).getReg()))
460+
return false;
461+
int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
462+
return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094);
463+
}];
464+
}
458465

459466
// Return imm - (imm < 0 ? -2048 : 2047).
460467
def AddiPairImmSmall : SDNodeXForm<imm, [{
@@ -463,13 +470,17 @@ def AddiPairImmSmall : SDNodeXForm<imm, [{
463470
return CurDAG->getSignedTargetConstant(Imm - Adj, SDLoc(N),
464471
N->getValueType(0));
465472
}]>;
473+
def GIAddiPairImmSmall : GICustomOperandRenderer<"renderAddiPairImmSmall">,
474+
GISDNodeXFormEquiv<AddiPairImmSmall>;
466475

467476
// Return -2048 if immediate is negative or 2047 if positive. These are the
468477
// largest simm12 values.
469478
def AddiPairImmLarge : SDNodeXForm<imm, [{
470479
int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047;
471480
return CurDAG->getSignedTargetConstant(Imm, SDLoc(N), N->getValueType(0));
472481
}]>;
482+
def GIAddiPairImmLarge : GICustomOperandRenderer<"renderAddiPairImmLarge">,
483+
GISDNodeXFormEquiv<AddiPairImmLarge>;
473484

474485
def TrailingZeros : SDNodeXForm<imm, [{
475486
return CurDAG->getTargetConstant(llvm::countr_zero(N->getZExtValue()),
@@ -537,7 +548,6 @@ def LeadingOnesWMask : PatLeaf<(imm), [{
537548
return !isInt<32>(Imm) && isUInt<32>(Imm) && isShiftedMask_64(Imm) &&
538549
Imm != UINT64_C(0xffffffff);
539550
}];
540-
541551
}
542552

543553
//===----------------------------------------------------------------------===//
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=riscv32 -global-isel < %s \
3+
; RUN: | FileCheck %s -check-prefix=RV32I
4+
; RUN: llc -mtriple=riscv64 -global-isel < %s \
5+
; RUN: | FileCheck %s -check-prefix=RV64I
6+
7+
; These test how the immediate in an addition is materialized.
8+
9+
define i32 @add_positive_low_bound_reject(i32 %a) nounwind {
10+
; RV32I-LABEL: add_positive_low_bound_reject:
11+
; RV32I: # %bb.0:
12+
; RV32I-NEXT: addi a0, a0, 2047
13+
; RV32I-NEXT: ret
14+
;
15+
; RV64I-LABEL: add_positive_low_bound_reject:
16+
; RV64I: # %bb.0:
17+
; RV64I-NEXT: addi a0, a0, 2047
18+
; RV64I-NEXT: ret
19+
%1 = add i32 %a, 2047
20+
ret i32 %1
21+
}
22+
23+
define i32 @add_positive_low_bound_accept(i32 %a) nounwind {
24+
; RV32I-LABEL: add_positive_low_bound_accept:
25+
; RV32I: # %bb.0:
26+
; RV32I-NEXT: addi a0, a0, 2047
27+
; RV32I-NEXT: addi a0, a0, 1
28+
; RV32I-NEXT: ret
29+
;
30+
; RV64I-LABEL: add_positive_low_bound_accept:
31+
; RV64I: # %bb.0:
32+
; RV64I-NEXT: addi a0, a0, 2047
33+
; RV64I-NEXT: addi a0, a0, 1
34+
; RV64I-NEXT: ret
35+
%1 = add i32 %a, 2048
36+
ret i32 %1
37+
}
38+
39+
define i32 @add_positive_high_bound_accept(i32 %a) nounwind {
40+
; RV32I-LABEL: add_positive_high_bound_accept:
41+
; RV32I: # %bb.0:
42+
; RV32I-NEXT: addi a0, a0, 2047
43+
; RV32I-NEXT: addi a0, a0, 2047
44+
; RV32I-NEXT: ret
45+
;
46+
; RV64I-LABEL: add_positive_high_bound_accept:
47+
; RV64I: # %bb.0:
48+
; RV64I-NEXT: addi a0, a0, 2047
49+
; RV64I-NEXT: addi a0, a0, 2047
50+
; RV64I-NEXT: ret
51+
%1 = add i32 %a, 4094
52+
ret i32 %1
53+
}
54+
55+
define i32 @add_positive_high_bound_reject(i32 %a) nounwind {
56+
; RV32I-LABEL: add_positive_high_bound_reject:
57+
; RV32I: # %bb.0:
58+
; RV32I-NEXT: lui a1, 1
59+
; RV32I-NEXT: addi a1, a1, -1
60+
; RV32I-NEXT: add a0, a0, a1
61+
; RV32I-NEXT: ret
62+
;
63+
; RV64I-LABEL: add_positive_high_bound_reject:
64+
; RV64I: # %bb.0:
65+
; RV64I-NEXT: lui a1, 1
66+
; RV64I-NEXT: addiw a1, a1, -1
67+
; RV64I-NEXT: add a0, a0, a1
68+
; RV64I-NEXT: ret
69+
%1 = add i32 %a, 4095
70+
ret i32 %1
71+
}
72+
73+
define i32 @add_negative_high_bound_reject(i32 %a) nounwind {
74+
; RV32I-LABEL: add_negative_high_bound_reject:
75+
; RV32I: # %bb.0:
76+
; RV32I-NEXT: addi a0, a0, -2048
77+
; RV32I-NEXT: ret
78+
;
79+
; RV64I-LABEL: add_negative_high_bound_reject:
80+
; RV64I: # %bb.0:
81+
; RV64I-NEXT: addi a0, a0, -2048
82+
; RV64I-NEXT: ret
83+
%1 = add i32 %a, -2048
84+
ret i32 %1
85+
}
86+
87+
define i32 @add_negative_high_bound_accept(i32 %a) nounwind {
88+
; RV32I-LABEL: add_negative_high_bound_accept:
89+
; RV32I: # %bb.0:
90+
; RV32I-NEXT: addi a0, a0, -2048
91+
; RV32I-NEXT: addi a0, a0, -1
92+
; RV32I-NEXT: ret
93+
;
94+
; RV64I-LABEL: add_negative_high_bound_accept:
95+
; RV64I: # %bb.0:
96+
; RV64I-NEXT: addi a0, a0, -2048
97+
; RV64I-NEXT: addi a0, a0, -1
98+
; RV64I-NEXT: ret
99+
%1 = add i32 %a, -2049
100+
ret i32 %1
101+
}
102+
103+
define i32 @add_negative_low_bound_accept(i32 %a) nounwind {
104+
; RV32I-LABEL: add_negative_low_bound_accept:
105+
; RV32I: # %bb.0:
106+
; RV32I-NEXT: addi a0, a0, -2048
107+
; RV32I-NEXT: addi a0, a0, -2048
108+
; RV32I-NEXT: ret
109+
;
110+
; RV64I-LABEL: add_negative_low_bound_accept:
111+
; RV64I: # %bb.0:
112+
; RV64I-NEXT: addi a0, a0, -2048
113+
; RV64I-NEXT: addi a0, a0, -2048
114+
; RV64I-NEXT: ret
115+
%1 = add i32 %a, -4096
116+
ret i32 %1
117+
}
118+
119+
define i32 @add_negative_low_bound_reject(i32 %a) nounwind {
120+
; RV32I-LABEL: add_negative_low_bound_reject:
121+
; RV32I: # %bb.0:
122+
; RV32I-NEXT: lui a1, 1048575
123+
; RV32I-NEXT: addi a1, a1, -1
124+
; RV32I-NEXT: add a0, a0, a1
125+
; RV32I-NEXT: ret
126+
;
127+
; RV64I-LABEL: add_negative_low_bound_reject:
128+
; RV64I: # %bb.0:
129+
; RV64I-NEXT: lui a1, 1048575
130+
; RV64I-NEXT: addiw a1, a1, -1
131+
; RV64I-NEXT: add a0, a0, a1
132+
; RV64I-NEXT: ret
133+
%1 = add i32 %a, -4097
134+
ret i32 %1
135+
}
136+
137+
define i32 @add32_accept(i32 %a) nounwind {
138+
; RV32I-LABEL: add32_accept:
139+
; RV32I: # %bb.0:
140+
; RV32I-NEXT: addi a0, a0, 2047
141+
; RV32I-NEXT: addi a0, a0, 952
142+
; RV32I-NEXT: ret
143+
;
144+
; RV64I-LABEL: add32_accept:
145+
; RV64I: # %bb.0:
146+
; RV64I-NEXT: addi a0, a0, 2047
147+
; RV64I-NEXT: addi a0, a0, 952
148+
; RV64I-NEXT: ret
149+
%1 = add i32 %a, 2999
150+
ret i32 %1
151+
}
152+
153+
define signext i32 @add32_sext_accept(i32 signext %a) nounwind {
154+
; RV32I-LABEL: add32_sext_accept:
155+
; RV32I: # %bb.0:
156+
; RV32I-NEXT: addi a0, a0, 2047
157+
; RV32I-NEXT: addi a0, a0, 952
158+
; RV32I-NEXT: ret
159+
;
160+
; RV64I-LABEL: add32_sext_accept:
161+
; RV64I: # %bb.0:
162+
; RV64I-NEXT: addi a0, a0, 2047
163+
; RV64I-NEXT: addiw a0, a0, 952
164+
; RV64I-NEXT: ret
165+
%1 = add i32 %a, 2999
166+
ret i32 %1
167+
}
168+
169+
@gv0 = global i32 0, align 4
170+
define signext i32 @add32_sext_reject_on_rv64(i32 signext %a) nounwind {
171+
; RV32I-LABEL: add32_sext_reject_on_rv64:
172+
; RV32I: # %bb.0:
173+
; RV32I-NEXT: lui a1, %hi(gv0)
174+
; RV32I-NEXT: addi a0, a0, 2047
175+
; RV32I-NEXT: addi a0, a0, 953
176+
; RV32I-NEXT: sw a0, %lo(gv0)(a1)
177+
; RV32I-NEXT: ret
178+
;
179+
; RV64I-LABEL: add32_sext_reject_on_rv64:
180+
; RV64I: # %bb.0:
181+
; RV64I-NEXT: lui a1, %hi(gv0)
182+
; RV64I-NEXT: addi a0, a0, 2047
183+
; RV64I-NEXT: addiw a0, a0, 953
184+
; RV64I-NEXT: sw a0, %lo(gv0)(a1)
185+
; RV64I-NEXT: ret
186+
%b = add nsw i32 %a, 3000
187+
store i32 %b, ptr @gv0, align 4
188+
ret i32 %b
189+
}
190+
191+
define i64 @add64_accept(i64 %a) nounwind {
192+
; RV32I-LABEL: add64_accept:
193+
; RV32I: # %bb.0:
194+
; RV32I-NEXT: lui a2, 1
195+
; RV32I-NEXT: addi a2, a2, -1097
196+
; RV32I-NEXT: add a0, a0, a2
197+
; RV32I-NEXT: sltu a2, a0, a2
198+
; RV32I-NEXT: add a1, a1, a2
199+
; RV32I-NEXT: ret
200+
;
201+
; RV64I-LABEL: add64_accept:
202+
; RV64I: # %bb.0:
203+
; RV64I-NEXT: addi a0, a0, 2047
204+
; RV64I-NEXT: addi a0, a0, 952
205+
; RV64I-NEXT: ret
206+
%1 = add i64 %a, 2999
207+
ret i64 %1
208+
}
209+
210+
@ga = global i32 0, align 4
211+
@gb = global i32 0, align 4
212+
define void @add32_reject() nounwind {
213+
; RV32I-LABEL: add32_reject:
214+
; RV32I: # %bb.0:
215+
; RV32I-NEXT: lui a0, %hi(ga)
216+
; RV32I-NEXT: lui a1, %hi(gb)
217+
; RV32I-NEXT: lw a2, %lo(ga)(a0)
218+
; RV32I-NEXT: lw a3, %lo(gb)(a1)
219+
; RV32I-NEXT: lui a4, 1
220+
; RV32I-NEXT: addi a4, a4, -1096
221+
; RV32I-NEXT: add a2, a2, a4
222+
; RV32I-NEXT: add a3, a3, a4
223+
; RV32I-NEXT: sw a2, %lo(ga)(a0)
224+
; RV32I-NEXT: sw a3, %lo(gb)(a1)
225+
; RV32I-NEXT: ret
226+
;
227+
; RV64I-LABEL: add32_reject:
228+
; RV64I: # %bb.0:
229+
; RV64I-NEXT: lui a0, %hi(ga)
230+
; RV64I-NEXT: lui a1, %hi(gb)
231+
; RV64I-NEXT: lw a2, %lo(ga)(a0)
232+
; RV64I-NEXT: lw a3, %lo(gb)(a1)
233+
; RV64I-NEXT: lui a4, 1
234+
; RV64I-NEXT: addi a4, a4, -1096
235+
; RV64I-NEXT: add a2, a2, a4
236+
; RV64I-NEXT: add a3, a3, a4
237+
; RV64I-NEXT: sw a2, %lo(ga)(a0)
238+
; RV64I-NEXT: sw a3, %lo(gb)(a1)
239+
; RV64I-NEXT: ret
240+
%1 = load i32, ptr @ga, align 4
241+
%2 = load i32, ptr @gb, align 4
242+
%3 = add i32 %1, 3000
243+
%4 = add i32 %2, 3000
244+
store i32 %3, ptr @ga, align 4
245+
store i32 %4, ptr @gb, align 4
246+
ret void
247+
}

0 commit comments

Comments
 (0)