[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