Skip to content

Commit 4c67bdd

Browse files
authored
[RISCV] Don't fold offsets into auipc if offset is larger than the reference global variable. (#135297)
The global variable should be within 2GB of the PC, but an offset to an address outside the global might not be. Fixes #134525.
1 parent 957bd6a commit 4c67bdd

File tree

2 files changed

+95
-9
lines changed

2 files changed

+95
-9
lines changed

llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class RISCVMergeBaseOffsetOpt : public MachineFunctionPass {
3535
bool detectFoldable(MachineInstr &Hi, MachineInstr *&Lo);
3636

3737
bool detectAndFoldOffset(MachineInstr &Hi, MachineInstr &Lo);
38-
void foldOffset(MachineInstr &Hi, MachineInstr &Lo, MachineInstr &Tail,
38+
bool foldOffset(MachineInstr &Hi, MachineInstr &Lo, MachineInstr &Tail,
3939
int64_t Offset);
4040
bool foldLargeOffset(MachineInstr &Hi, MachineInstr &Lo,
4141
MachineInstr &TailAdd, Register GSReg);
@@ -142,9 +142,21 @@ bool RISCVMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi,
142142
// Update the offset in Hi and Lo instructions.
143143
// Delete the tail instruction and update all the uses to use the
144144
// output from Lo.
145-
void RISCVMergeBaseOffsetOpt::foldOffset(MachineInstr &Hi, MachineInstr &Lo,
145+
bool RISCVMergeBaseOffsetOpt::foldOffset(MachineInstr &Hi, MachineInstr &Lo,
146146
MachineInstr &Tail, int64_t Offset) {
147147
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+
148160
// Put the offset back in Hi and the Lo
149161
Hi.getOperand(1).setOffset(Offset);
150162
if (Hi.getOpcode() != RISCV::AUIPC)
@@ -156,6 +168,7 @@ void RISCVMergeBaseOffsetOpt::foldOffset(MachineInstr &Hi, MachineInstr &Lo,
156168
Tail.eraseFromParent();
157169
LLVM_DEBUG(dbgs() << " Merged offset " << Offset << " into base.\n"
158170
<< " " << Hi << " " << Lo;);
171+
return true;
159172
}
160173

161174
// Detect patterns for large offsets that are passed into an ADD instruction.
@@ -205,7 +218,8 @@ bool RISCVMergeBaseOffsetOpt::foldLargeOffset(MachineInstr &Hi,
205218
// Handle rs1 of ADDI is X0.
206219
if (AddiReg == RISCV::X0) {
207220
LLVM_DEBUG(dbgs() << " Offset Instrs: " << OffsetTail);
208-
foldOffset(Hi, Lo, TailAdd, OffLo);
221+
if (!foldOffset(Hi, Lo, TailAdd, OffLo))
222+
return false;
209223
OffsetTail.eraseFromParent();
210224
return true;
211225
}
@@ -226,7 +240,8 @@ bool RISCVMergeBaseOffsetOpt::foldLargeOffset(MachineInstr &Hi,
226240
return false;
227241
LLVM_DEBUG(dbgs() << " Offset Instrs: " << OffsetTail
228242
<< " " << OffsetLui);
229-
foldOffset(Hi, Lo, TailAdd, Offset);
243+
if (!foldOffset(Hi, Lo, TailAdd, Offset))
244+
return false;
230245
OffsetTail.eraseFromParent();
231246
OffsetLui.eraseFromParent();
232247
return true;
@@ -235,7 +250,8 @@ bool RISCVMergeBaseOffsetOpt::foldLargeOffset(MachineInstr &Hi,
235250
// exists.
236251
LLVM_DEBUG(dbgs() << " Offset Instr: " << OffsetTail);
237252
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;
239255
OffsetTail.eraseFromParent();
240256
return true;
241257
}
@@ -294,7 +310,8 @@ bool RISCVMergeBaseOffsetOpt::foldShiftedOffset(MachineInstr &Hi,
294310
Offset = (uint64_t)Offset << ShAmt;
295311

296312
LLVM_DEBUG(dbgs() << " Offset Instr: " << OffsetTail);
297-
foldOffset(Hi, Lo, TailShXAdd, Offset);
313+
if (!foldOffset(Hi, Lo, TailShXAdd, Offset))
314+
return false;
298315
OffsetTail.eraseFromParent();
299316
return true;
300317
}
@@ -327,15 +344,15 @@ bool RISCVMergeBaseOffsetOpt::detectAndFoldOffset(MachineInstr &Hi,
327344
if (TailTail.getOpcode() == RISCV::ADDI) {
328345
Offset += TailTail.getOperand(2).getImm();
329346
LLVM_DEBUG(dbgs() << " Offset Instrs: " << Tail << TailTail);
330-
foldOffset(Hi, Lo, TailTail, Offset);
347+
if (!foldOffset(Hi, Lo, TailTail, Offset))
348+
return false;
331349
Tail.eraseFromParent();
332350
return true;
333351
}
334352
}
335353

336354
LLVM_DEBUG(dbgs() << " Offset Instr: " << Tail);
337-
foldOffset(Hi, Lo, Tail, Offset);
338-
return true;
355+
return foldOffset(Hi, Lo, Tail, Offset);
339356
}
340357
case RISCV::ADD:
341358
// The offset is too large to fit in the immediate field of ADDI.

llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,3 +1227,72 @@ for.inc.peel: ; preds = %entry
12271227
store i32 %spec.select, ptr null, align 4
12281228
ret i32 0
12291229
}
1230+
1231+
@ki_end = external dso_local global [0 x i8], align 1
1232+
1233+
define i1 @pr134525() nounwind {
1234+
; RV32I-LABEL: pr134525:
1235+
; RV32I: # %bb.0: # %entry
1236+
; RV32I-NEXT: lui a0, %hi(ki_end)
1237+
; RV32I-NEXT: addi a0, a0, %lo(ki_end)
1238+
; RV32I-NEXT: lui a1, 523776
1239+
; RV32I-NEXT: lui a2, 32
1240+
; RV32I-NEXT: add a1, a0, a1
1241+
; RV32I-NEXT: addi a2, a2, 1
1242+
; RV32I-NEXT: sltu a2, a1, a2
1243+
; RV32I-NEXT: sltu a0, a1, a0
1244+
; RV32I-NEXT: not a0, a0
1245+
; RV32I-NEXT: and a0, a0, a2
1246+
; RV32I-NEXT: ret
1247+
;
1248+
; RV32I-MEDIUM-LABEL: pr134525:
1249+
; RV32I-MEDIUM: # %bb.0: # %entry
1250+
; RV32I-MEDIUM-NEXT: .Lpcrel_hi15:
1251+
; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ki_end)
1252+
; RV32I-MEDIUM-NEXT: lui a1, 523776
1253+
; RV32I-MEDIUM-NEXT: lui a2, 32
1254+
; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi15)
1255+
; RV32I-MEDIUM-NEXT: addi a2, a2, 1
1256+
; RV32I-MEDIUM-NEXT: add a1, a0, a1
1257+
; RV32I-MEDIUM-NEXT: sltu a2, a1, a2
1258+
; RV32I-MEDIUM-NEXT: sltu a0, a1, a0
1259+
; RV32I-MEDIUM-NEXT: not a0, a0
1260+
; RV32I-MEDIUM-NEXT: and a0, a0, a2
1261+
; RV32I-MEDIUM-NEXT: ret
1262+
;
1263+
; RV64I-LABEL: pr134525:
1264+
; RV64I: # %bb.0: # %entry
1265+
; RV64I-NEXT: lui a0, %hi(ki_end+2145386496)
1266+
; RV64I-NEXT: addi a0, a0, %lo(ki_end+2145386496)
1267+
; RV64I-NEXT: lui a1, 32
1268+
; RV64I-NEXT: addiw a1, a1, 1
1269+
; RV64I-NEXT: sltu a0, a0, a1
1270+
; RV64I-NEXT: ret
1271+
;
1272+
; RV64I-MEDIUM-LABEL: pr134525:
1273+
; RV64I-MEDIUM: # %bb.0: # %entry
1274+
; RV64I-MEDIUM-NEXT: .Lpcrel_hi15:
1275+
; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ki_end)
1276+
; RV64I-MEDIUM-NEXT: lui a1, 523776
1277+
; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi15)
1278+
; RV64I-MEDIUM-NEXT: add a0, a0, a1
1279+
; RV64I-MEDIUM-NEXT: lui a1, 32
1280+
; RV64I-MEDIUM-NEXT: addiw a1, a1, 1
1281+
; RV64I-MEDIUM-NEXT: sltu a0, a0, a1
1282+
; RV64I-MEDIUM-NEXT: ret
1283+
;
1284+
; RV64I-LARGE-LABEL: pr134525:
1285+
; RV64I-LARGE: # %bb.0: # %entry
1286+
; RV64I-LARGE-NEXT: .Lpcrel_hi16:
1287+
; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI22_0)
1288+
; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi16)(a0)
1289+
; RV64I-LARGE-NEXT: lui a1, 523776
1290+
; RV64I-LARGE-NEXT: add a0, a0, a1
1291+
; RV64I-LARGE-NEXT: lui a1, 32
1292+
; RV64I-LARGE-NEXT: addiw a1, a1, 1
1293+
; RV64I-LARGE-NEXT: sltu a0, a0, a1
1294+
; RV64I-LARGE-NEXT: ret
1295+
entry:
1296+
%cmp = icmp ult i64 sub (i64 ptrtoint (ptr @ki_end to i64), i64 -2145386496), 131073
1297+
ret i1 %cmp
1298+
}

0 commit comments

Comments
 (0)