@@ -35,7 +35,7 @@ class RISCVMergeBaseOffsetOpt : public MachineFunctionPass {
35
35
bool detectFoldable (MachineInstr &Hi, MachineInstr *&Lo);
36
36
37
37
bool detectAndFoldOffset (MachineInstr &Hi, MachineInstr &Lo);
38
- void foldOffset (MachineInstr &Hi, MachineInstr &Lo, MachineInstr &Tail,
38
+ bool foldOffset (MachineInstr &Hi, MachineInstr &Lo, MachineInstr &Tail,
39
39
int64_t Offset);
40
40
bool foldLargeOffset (MachineInstr &Hi, MachineInstr &Lo,
41
41
MachineInstr &TailAdd, Register GSReg);
@@ -142,9 +142,21 @@ bool RISCVMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi,
142
142
// Update the offset in Hi and Lo instructions.
143
143
// Delete the tail instruction and update all the uses to use the
144
144
// output from Lo.
145
- void RISCVMergeBaseOffsetOpt::foldOffset (MachineInstr &Hi, MachineInstr &Lo,
145
+ bool RISCVMergeBaseOffsetOpt::foldOffset (MachineInstr &Hi, MachineInstr &Lo,
146
146
MachineInstr &Tail, int64_t Offset) {
147
147
assert (isInt<32 >(Offset) && " Unexpected offset" );
148
+
149
+ // If Hi is an AUIPC, don't fold the offset if it is outside the bounds of
150
+ // the global object. The object may be within 2GB of the PC, but addresses
151
+ // outside of the object might not be.
152
+ if (Hi.getOpcode () == RISCV::AUIPC && Hi.getOperand (1 ).isGlobal ()) {
153
+ const GlobalValue *GV = Hi.getOperand (1 ).getGlobal ();
154
+ Type *Ty = GV->getValueType ();
155
+ if (!Ty->isSized () || Offset < 0 ||
156
+ (uint64_t )Offset > GV->getDataLayout ().getTypeAllocSize (Ty))
157
+ return false ;
158
+ }
159
+
148
160
// Put the offset back in Hi and the Lo
149
161
Hi.getOperand (1 ).setOffset (Offset);
150
162
if (Hi.getOpcode () != RISCV::AUIPC)
@@ -156,6 +168,7 @@ void RISCVMergeBaseOffsetOpt::foldOffset(MachineInstr &Hi, MachineInstr &Lo,
156
168
Tail.eraseFromParent ();
157
169
LLVM_DEBUG (dbgs () << " Merged offset " << Offset << " into base.\n "
158
170
<< " " << Hi << " " << Lo;);
171
+ return true ;
159
172
}
160
173
161
174
// Detect patterns for large offsets that are passed into an ADD instruction.
@@ -205,7 +218,8 @@ bool RISCVMergeBaseOffsetOpt::foldLargeOffset(MachineInstr &Hi,
205
218
// Handle rs1 of ADDI is X0.
206
219
if (AddiReg == RISCV::X0) {
207
220
LLVM_DEBUG (dbgs () << " Offset Instrs: " << OffsetTail);
208
- foldOffset (Hi, Lo, TailAdd, OffLo);
221
+ if (!foldOffset (Hi, Lo, TailAdd, OffLo))
222
+ return false ;
209
223
OffsetTail.eraseFromParent ();
210
224
return true ;
211
225
}
@@ -226,7 +240,8 @@ bool RISCVMergeBaseOffsetOpt::foldLargeOffset(MachineInstr &Hi,
226
240
return false ;
227
241
LLVM_DEBUG (dbgs () << " Offset Instrs: " << OffsetTail
228
242
<< " " << OffsetLui);
229
- foldOffset (Hi, Lo, TailAdd, Offset);
243
+ if (!foldOffset (Hi, Lo, TailAdd, Offset))
244
+ return false ;
230
245
OffsetTail.eraseFromParent ();
231
246
OffsetLui.eraseFromParent ();
232
247
return true ;
@@ -235,7 +250,8 @@ bool RISCVMergeBaseOffsetOpt::foldLargeOffset(MachineInstr &Hi,
235
250
// exists.
236
251
LLVM_DEBUG (dbgs () << " Offset Instr: " << OffsetTail);
237
252
int64_t Offset = SignExtend64<32 >(OffsetTail.getOperand (1 ).getImm () << 12 );
238
- foldOffset (Hi, Lo, TailAdd, Offset);
253
+ if (!foldOffset (Hi, Lo, TailAdd, Offset))
254
+ return false ;
239
255
OffsetTail.eraseFromParent ();
240
256
return true ;
241
257
}
@@ -294,7 +310,8 @@ bool RISCVMergeBaseOffsetOpt::foldShiftedOffset(MachineInstr &Hi,
294
310
Offset = (uint64_t )Offset << ShAmt;
295
311
296
312
LLVM_DEBUG (dbgs () << " Offset Instr: " << OffsetTail);
297
- foldOffset (Hi, Lo, TailShXAdd, Offset);
313
+ if (!foldOffset (Hi, Lo, TailShXAdd, Offset))
314
+ return false ;
298
315
OffsetTail.eraseFromParent ();
299
316
return true ;
300
317
}
@@ -327,15 +344,15 @@ bool RISCVMergeBaseOffsetOpt::detectAndFoldOffset(MachineInstr &Hi,
327
344
if (TailTail.getOpcode () == RISCV::ADDI) {
328
345
Offset += TailTail.getOperand (2 ).getImm ();
329
346
LLVM_DEBUG (dbgs () << " Offset Instrs: " << Tail << TailTail);
330
- foldOffset (Hi, Lo, TailTail, Offset);
347
+ if (!foldOffset (Hi, Lo, TailTail, Offset))
348
+ return false ;
331
349
Tail.eraseFromParent ();
332
350
return true ;
333
351
}
334
352
}
335
353
336
354
LLVM_DEBUG (dbgs () << " Offset Instr: " << Tail);
337
- foldOffset (Hi, Lo, Tail, Offset);
338
- return true ;
355
+ return foldOffset (Hi, Lo, Tail, Offset);
339
356
}
340
357
case RISCV::ADD:
341
358
// The offset is too large to fit in the immediate field of ADDI.
0 commit comments