Skip to content

Commit 2c21ea6

Browse files
committed
[RISCV] Addi optimization ported for GIsel
Signed-off-by: Luke Quinn <[email protected]>
1 parent 0e8d022 commit 2c21ea6

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)