[llvm] [InstSimplify] Unwrap DSOLocalEquivalent in simplifyRelativeLoad (PR #225522)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 14:01:17 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: PiJoules

<details>
<summary>Changes</summary>

When simplifying `@<!-- -->llvm.load.relative` against a relative table, the pointed to global can be a `DSOLocalEquivalent` (as used by relative vtables). Previously, this returned the `DSOLocalEquivalent` directly, leaking it into instruction operands (e.g. call operands).

Downstream passes like the inliner failed to inline the call because `CallBase::getCalledFunction()` returns `nullptr` for non-`Function` operands, and GlobalISel crashed attempting to translate the unhandled constant.

Unwrap `DSOLocalEquivalent` to its underlying `GlobalValue` so `@<!-- -->llvm.load.relative` simplifies to the target function directly.

---
Full diff: https://github.com/llvm/llvm-project/pull/225522.diff


4 Files Affected:

- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+2) 
- (added) llvm/test/CodeGen/AArch64/GlobalISel/load-relative.ll (+15) 
- (added) llvm/test/Transforms/Inline/load-relative.ll (+21) 
- (modified) llvm/test/Transforms/InstSimplify/load-relative.ll (+11) 


``````````diff
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index baea0c2425812..19a76d26c7c2c 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6563,6 +6563,8 @@ static Value *simplifyRelativeLoad(Constant *Ptr, Constant *Offset,
       PtrSym != LoadedRHSSym || PtrOffset != LoadedRHSOffset)
     return nullptr;
 
+  if (auto *Equiv = dyn_cast<DSOLocalEquivalent>(LoadedLHSPtr))
+    return Equiv->getGlobalValue();
   return LoadedLHSPtr;
 }
 
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/load-relative.ll b/llvm/test/CodeGen/AArch64/GlobalISel/load-relative.ll
new file mode 100644
index 0000000000000..5a44d2da32b4e
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/load-relative.ll
@@ -0,0 +1,15 @@
+; RUN: opt < %s -passes=instsimplify -S | llc -mtriple=aarch64 -global-isel -verify-machineinstrs -o - | FileCheck %s
+
+declare void @target()
+
+ at vt = constant [1 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @target to i64), i64 ptrtoint (ptr @vt to i64)) to i32)]
+
+declare ptr @llvm.load.relative.i32(ptr, i32)
+
+; CHECK-LABEL: test:
+; CHECK: bl target
+define void @test() {
+  %fn = call ptr @llvm.load.relative.i32(ptr @vt, i32 0)
+  call void %fn()
+  ret void
+}
diff --git a/llvm/test/Transforms/Inline/load-relative.ll b/llvm/test/Transforms/Inline/load-relative.ll
new file mode 100644
index 0000000000000..9bb6397511e4e
--- /dev/null
+++ b/llvm/test/Transforms/Inline/load-relative.ll
@@ -0,0 +1,21 @@
+; RUN: opt < %s -passes='module(function(instsimplify),cgscc(inline))' -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define internal i32 @callee() {
+  ret i32 42
+}
+
+ at vt = constant [1 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @callee to i64), i64 ptrtoint (ptr @vt to i64)) to i32)]
+
+declare ptr @llvm.load.relative.i32(ptr, i32)
+
+; CHECK-LABEL: define i32 @caller
+; CHECK-NOT: call
+; CHECK: ret i32 42
+define i32 @caller() {
+  %fn = call ptr @llvm.load.relative.i32(ptr @vt, i32 0)
+  %res = call i32 %fn()
+  ret i32 %res
+}
diff --git a/llvm/test/Transforms/InstSimplify/load-relative.ll b/llvm/test/Transforms/InstSimplify/load-relative.ll
index 75d38d555d329..6e9f4a84b27a6 100644
--- a/llvm/test/Transforms/InstSimplify/load-relative.ll
+++ b/llvm/test/Transforms/InstSimplify/load-relative.ll
@@ -71,5 +71,16 @@ define ptr @f8() {
   ret ptr %l
 }
 
+ at c_equiv = constant i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @fn to i64), i64 ptrtoint (ptr @c_equiv to i64)) to i32)
+
+; CHECK-LABEL: @f_equiv
+; CHECK-NOT: dso_local_equivalent
+; CHECK: ret ptr @fn
+define ptr @f_equiv() {
+  %l = call ptr @llvm.load.relative.i32(ptr @c_equiv, i32 0)
+  ret ptr %l
+}
+
+declare void @fn()
 declare ptr @llvm.load.relative.i32(ptr, i32)
 declare ptr @llvm.load.relative.i64(ptr, i64)

``````````

</details>


https://github.com/llvm/llvm-project/pull/225522


More information about the llvm-commits mailing list