[llvm] [RISCV] Don't fold offsets into auipc if offset is larger than the reference global variable. (PR #135297)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 10 18:55:05 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Craig Topper (topperc)
<details>
<summary>Changes</summary>
The global variable should be within 2GB of the PC, but an offset to an address outside the global might not be.
Fixes #<!-- -->134525.
---
Full diff: https://github.com/llvm/llvm-project/pull/135297.diff
2 Files Affected:
- (modified) llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp (+26-9)
- (modified) llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll (+69)
``````````diff
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
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/135297
More information about the llvm-commits
mailing list