@@ -50,6 +50,9 @@ struct RISCVMergeBaseOffsetOpt : public MachineFunctionPass {
50
50
void foldOffset (MachineInstr &HiLUI, MachineInstr &LoADDI, MachineInstr &Tail,
51
51
int64_t Offset);
52
52
bool matchLargeOffset (MachineInstr &TailAdd, Register GSReg, int64_t &Offset);
53
+ bool matchShiftedOffset (MachineInstr &TailShXAdd, Register GSReg,
54
+ int64_t &Offset);
55
+
53
56
RISCVMergeBaseOffsetOpt () : MachineFunctionPass(ID) {}
54
57
55
58
MachineFunctionProperties getRequiredProperties () const override {
@@ -193,6 +196,59 @@ bool RISCVMergeBaseOffsetOpt::matchLargeOffset(MachineInstr &TailAdd,
193
196
return false ;
194
197
}
195
198
199
+ // Detect patterns for offsets that are passed into a SHXADD instruction.
200
+ // The offset has 1,2, or 3 trailing zeros and fits in simm13, simm14, simm15.
201
+ // The constant is created with addi voff, x0, C, and shXadd is used to
202
+ // fill insert the trailing zeros and do the addition.
203
+ //
204
+ // HiLUI: lui vreg1, %hi(s)
205
+ // LoADDI: addi vreg2, vreg1, %lo(s)
206
+ // OffsetTail: addi voff, x0, C
207
+ // TailAdd: shXadd vreg4, voff, vreg2
208
+ bool RISCVMergeBaseOffsetOpt::matchShiftedOffset (MachineInstr &TailShXAdd,
209
+ Register GAReg,
210
+ int64_t &Offset) {
211
+ assert ((TailShXAdd.getOpcode () == RISCV::SH1ADD ||
212
+ TailShXAdd.getOpcode () == RISCV::SH2ADD ||
213
+ TailShXAdd.getOpcode () == RISCV::SH3ADD) &&
214
+ " Expected SHXADD instruction!" );
215
+
216
+ // The first source is the shifted operand.
217
+ Register Rs1 = TailShXAdd.getOperand (1 ).getReg ();
218
+
219
+ if (GAReg != TailShXAdd.getOperand (2 ).getReg ())
220
+ return false ;
221
+
222
+ // Can't fold if the register has more than one use.
223
+ if (!MRI->hasOneUse (Rs1))
224
+ return false ;
225
+ // This can point to an ADDI X0, C.
226
+ MachineInstr &OffsetTail = *MRI->getVRegDef (Rs1);
227
+ if (OffsetTail.getOpcode () != RISCV::ADDI)
228
+ return false ;
229
+ if (!OffsetTail.getOperand (1 ).isReg () ||
230
+ OffsetTail.getOperand (1 ).getReg () != RISCV::X0 ||
231
+ !OffsetTail.getOperand (2 ).isImm ())
232
+ return false ;
233
+
234
+ Offset = OffsetTail.getOperand (2 ).getImm ();
235
+ assert (isInt<12 >(Offset) && " Unexpected offset" );
236
+
237
+ unsigned ShAmt;
238
+ switch (TailShXAdd.getOpcode ()) {
239
+ default : llvm_unreachable (" Unexpected opcode" );
240
+ case RISCV::SH1ADD: ShAmt = 1 ; break ;
241
+ case RISCV::SH2ADD: ShAmt = 2 ; break ;
242
+ case RISCV::SH3ADD: ShAmt = 3 ; break ;
243
+ }
244
+
245
+ Offset = (uint64_t )Offset << ShAmt;
246
+
247
+ LLVM_DEBUG (dbgs () << " Offset Instr: " << OffsetTail);
248
+ DeadInstrs.insert (&OffsetTail);
249
+ return true ;
250
+ }
251
+
196
252
bool RISCVMergeBaseOffsetOpt::detectAndFoldOffset (MachineInstr &HiLUI,
197
253
MachineInstr &LoADDI) {
198
254
Register DestReg = LoADDI.getOperand (0 ).getReg ();
@@ -240,6 +296,18 @@ bool RISCVMergeBaseOffsetOpt::detectAndFoldOffset(MachineInstr &HiLUI,
240
296
foldOffset (HiLUI, LoADDI, Tail, Offset);
241
297
return true ;
242
298
}
299
+ case RISCV::SH1ADD:
300
+ case RISCV::SH2ADD:
301
+ case RISCV::SH3ADD: {
302
+ // The offset is too large to fit in the immediate field of ADDI.
303
+ // It may be encoded as (SH2ADD (ADDI X0, C), DestReg) or
304
+ // (SH3ADD (ADDI X0, C), DestReg).
305
+ int64_t Offset;
306
+ if (!matchShiftedOffset (Tail, DestReg, Offset))
307
+ return false ;
308
+ foldOffset (HiLUI, LoADDI, Tail, Offset);
309
+ return true ;
310
+ }
243
311
case RISCV::LB:
244
312
case RISCV::LH:
245
313
case RISCV::LW:
0 commit comments