[llvm] [RISCV] Don't fold offsets into auipc if offset is larger than the reference global variable. (PR #135297)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 10 18:54:33 PDT 2025
https://github.com/topperc created https://github.com/llvm/llvm-project/pull/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.
>From 94e909e8fe3efabd1e31c7a70f339123d17d3689 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Thu, 10 Apr 2025 18:17:10 -0700
Subject: [PATCH] [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.
---
.../lib/Target/RISCV/RISCVMergeBaseOffset.cpp | 35 +++++++---
.../test/CodeGen/RISCV/fold-addi-loadstore.ll | 69 +++++++++++++++++++
2 files changed, 95 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp b/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp
index bbbb1e1595982..eb3d43c9af7c2 100644
--- a/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp
+++ b/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp
@@ -35,7 +35,7 @@ class RISCVMergeBaseOffsetOpt : public MachineFunctionPass {
bool detectFoldable(MachineInstr &Hi, MachineInstr *&Lo);
bool detectAndFoldOffset(MachineInstr &Hi, MachineInstr &Lo);
- void foldOffset(MachineInstr &Hi, MachineInstr &Lo, MachineInstr &Tail,
+ bool foldOffset(MachineInstr &Hi, MachineInstr &Lo, MachineInstr &Tail,
int64_t Offset);
bool foldLargeOffset(MachineInstr &Hi, MachineInstr &Lo,
MachineInstr &TailAdd, Register GSReg);
@@ -142,9 +142,21 @@ bool RISCVMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi,
// Update the offset in Hi and Lo instructions.
// Delete the tail instruction and update all the uses to use the
// output from Lo.
-void RISCVMergeBaseOffsetOpt::foldOffset(MachineInstr &Hi, MachineInstr &Lo,
+bool RISCVMergeBaseOffsetOpt::foldOffset(MachineInstr &Hi, MachineInstr &Lo,
MachineInstr &Tail, int64_t Offset) {
assert(isInt<32>(Offset) && "Unexpected offset");
+
+ // If Hi is an AUIPC, don't fold the offset if it is outside the bounds of
+ // the global object. The object may be within 2GB of the PC, but addresses
+ // outside of the object might not be.
+ if (Hi.getOpcode() == RISCV::AUIPC && Hi.getOperand(1).isGlobal()) {
+ const GlobalValue *GV = Hi.getOperand(1).getGlobal();
+ Type *Ty = GV->getValueType();
+ if (!Ty->isSized() || Offset < 0 ||
+ (uint64_t)Offset > GV->getDataLayout().getTypeAllocSize(Ty))
+ return false;
+ }
+
// Put the offset back in Hi and the Lo
Hi.getOperand(1).setOffset(Offset);
if (Hi.getOpcode() != RISCV::AUIPC)
@@ -156,6 +168,7 @@ void RISCVMergeBaseOffsetOpt::foldOffset(MachineInstr &Hi, MachineInstr &Lo,
Tail.eraseFromParent();
LLVM_DEBUG(dbgs() << " Merged offset " << Offset << " into base.\n"
<< " " << Hi << " " << Lo;);
+ return true;
}
// Detect patterns for large offsets that are passed into an ADD instruction.
@@ -205,7 +218,8 @@ bool RISCVMergeBaseOffsetOpt::foldLargeOffset(MachineInstr &Hi,
// Handle rs1 of ADDI is X0.
if (AddiReg == RISCV::X0) {
LLVM_DEBUG(dbgs() << " Offset Instrs: " << OffsetTail);
- foldOffset(Hi, Lo, TailAdd, OffLo);
+ if (!foldOffset(Hi, Lo, TailAdd, OffLo))
+ return false;
OffsetTail.eraseFromParent();
return true;
}
@@ -226,7 +240,8 @@ bool RISCVMergeBaseOffsetOpt::foldLargeOffset(MachineInstr &Hi,
return false;
LLVM_DEBUG(dbgs() << " Offset Instrs: " << OffsetTail
<< " " << OffsetLui);
- foldOffset(Hi, Lo, TailAdd, Offset);
+ if (!foldOffset(Hi, Lo, TailAdd, Offset))
+ return false;
OffsetTail.eraseFromParent();
OffsetLui.eraseFromParent();
return true;
@@ -235,7 +250,8 @@ bool RISCVMergeBaseOffsetOpt::foldLargeOffset(MachineInstr &Hi,
// exists.
LLVM_DEBUG(dbgs() << " Offset Instr: " << OffsetTail);
int64_t Offset = SignExtend64<32>(OffsetTail.getOperand(1).getImm() << 12);
- foldOffset(Hi, Lo, TailAdd, Offset);
+ if (!foldOffset(Hi, Lo, TailAdd, Offset))
+ return false;
OffsetTail.eraseFromParent();
return true;
}
@@ -294,7 +310,8 @@ bool RISCVMergeBaseOffsetOpt::foldShiftedOffset(MachineInstr &Hi,
Offset = (uint64_t)Offset << ShAmt;
LLVM_DEBUG(dbgs() << " Offset Instr: " << OffsetTail);
- foldOffset(Hi, Lo, TailShXAdd, Offset);
+ if (!foldOffset(Hi, Lo, TailShXAdd, Offset))
+ return false;
OffsetTail.eraseFromParent();
return true;
}
@@ -327,15 +344,15 @@ bool RISCVMergeBaseOffsetOpt::detectAndFoldOffset(MachineInstr &Hi,
if (TailTail.getOpcode() == RISCV::ADDI) {
Offset += TailTail.getOperand(2).getImm();
LLVM_DEBUG(dbgs() << " Offset Instrs: " << Tail << TailTail);
- foldOffset(Hi, Lo, TailTail, Offset);
+ if (!foldOffset(Hi, Lo, TailTail, Offset))
+ return false;
Tail.eraseFromParent();
return true;
}
}
LLVM_DEBUG(dbgs() << " Offset Instr: " << Tail);
- foldOffset(Hi, Lo, Tail, Offset);
- return true;
+ return foldOffset(Hi, Lo, Tail, Offset);
}
case RISCV::ADD:
// The offset is too large to fit in the immediate field of ADDI.
diff --git a/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll b/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll
index b8dc7804c4908..255e65490195c 100644
--- a/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll
+++ b/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll
@@ -1227,3 +1227,72 @@ for.inc.peel: ; preds = %entry
store i32 %spec.select, ptr null, align 4
ret i32 0
}
+
+ at ki_end = external dso_local global [0 x i8], align 1
+
+define i1 @pr134525() nounwind {
+; RV32I-LABEL: pr134525:
+; RV32I: # %bb.0: # %entry
+; RV32I-NEXT: lui a0, %hi(ki_end)
+; RV32I-NEXT: addi a0, a0, %lo(ki_end)
+; RV32I-NEXT: lui a1, 523776
+; RV32I-NEXT: lui a2, 32
+; RV32I-NEXT: add a1, a0, a1
+; RV32I-NEXT: addi a2, a2, 1
+; RV32I-NEXT: sltu a2, a1, a2
+; RV32I-NEXT: sltu a0, a1, a0
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: and a0, a0, a2
+; RV32I-NEXT: ret
+;
+; RV32I-MEDIUM-LABEL: pr134525:
+; RV32I-MEDIUM: # %bb.0: # %entry
+; RV32I-MEDIUM-NEXT: .Lpcrel_hi15:
+; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ki_end)
+; RV32I-MEDIUM-NEXT: lui a1, 523776
+; RV32I-MEDIUM-NEXT: lui a2, 32
+; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi15)
+; RV32I-MEDIUM-NEXT: addi a2, a2, 1
+; RV32I-MEDIUM-NEXT: add a1, a0, a1
+; RV32I-MEDIUM-NEXT: sltu a2, a1, a2
+; RV32I-MEDIUM-NEXT: sltu a0, a1, a0
+; RV32I-MEDIUM-NEXT: not a0, a0
+; RV32I-MEDIUM-NEXT: and a0, a0, a2
+; RV32I-MEDIUM-NEXT: ret
+;
+; RV64I-LABEL: pr134525:
+; RV64I: # %bb.0: # %entry
+; RV64I-NEXT: lui a0, %hi(ki_end+2145386496)
+; RV64I-NEXT: addi a0, a0, %lo(ki_end+2145386496)
+; RV64I-NEXT: lui a1, 32
+; RV64I-NEXT: addiw a1, a1, 1
+; RV64I-NEXT: sltu a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64I-MEDIUM-LABEL: pr134525:
+; RV64I-MEDIUM: # %bb.0: # %entry
+; RV64I-MEDIUM-NEXT: .Lpcrel_hi15:
+; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(ki_end)
+; RV64I-MEDIUM-NEXT: lui a1, 523776
+; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi15)
+; RV64I-MEDIUM-NEXT: add a0, a0, a1
+; RV64I-MEDIUM-NEXT: lui a1, 32
+; RV64I-MEDIUM-NEXT: addiw a1, a1, 1
+; RV64I-MEDIUM-NEXT: sltu a0, a0, a1
+; RV64I-MEDIUM-NEXT: ret
+;
+; RV64I-LARGE-LABEL: pr134525:
+; RV64I-LARGE: # %bb.0: # %entry
+; RV64I-LARGE-NEXT: .Lpcrel_hi16:
+; RV64I-LARGE-NEXT: auipc a0, %pcrel_hi(.LCPI22_0)
+; RV64I-LARGE-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi16)(a0)
+; RV64I-LARGE-NEXT: lui a1, 523776
+; RV64I-LARGE-NEXT: add a0, a0, a1
+; RV64I-LARGE-NEXT: lui a1, 32
+; RV64I-LARGE-NEXT: addiw a1, a1, 1
+; RV64I-LARGE-NEXT: sltu a0, a0, a1
+; RV64I-LARGE-NEXT: ret
+entry:
+ %cmp = icmp ult i64 sub (i64 ptrtoint (ptr @ki_end to i64), i64 -2145386496), 131073
+ ret i1 %cmp
+}
More information about the llvm-commits
mailing list