Skip to content

Commit 94e909e

Browse files
committed
[RISCV] Don't fold offsets into auipc if offset is larger than the reference global variable.
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 27bc8a1 commit 94e909e

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)