Skip to content

release/20.x: [RelLookupTableConverter] Drop unnamed_addr to avoid generating GOTPCREL relocations (#142304) #142311

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 3, 2025

Conversation

dianqk
Copy link
Member

@dianqk dianqk commented Jun 1, 2025

Backport aa09dbb

Requested by: @dianqk

@dianqk dianqk requested review from nikic and MaskRay June 1, 2025 14:49
@llvmbot
Copy link
Member

llvmbot commented Jun 1, 2025

@llvm/pr-subscribers-llvm-transforms

Author: dianqk (dianqk)

Changes

Backport aa09dbb

Requested by: @dianqk


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp (+17)
  • (added) llvm/test/Transforms/RelLookupTableConverter/unnamed_addr.ll (+119)
diff --git a/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp b/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp
index 2700b4307308c..4486cba2bf6c0 100644
--- a/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp
+++ b/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp
@@ -18,6 +18,7 @@
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Module.h"
+#include "llvm/TargetParser/Triple.h"
 
 using namespace llvm;
 
@@ -108,8 +109,24 @@ static GlobalVariable *createRelLookupTable(Function &Func,
   uint64_t Idx = 0;
   SmallVector<Constant *, 64> RelLookupTableContents(NumElts);
 
+  Triple TT(M.getTargetTriple());
+  // FIXME: This should be removed in the future.
+  bool ShouldDropUnnamedAddr =
+      // Drop unnamed_addr to avoid matching pattern in
+      // `handleIndirectSymViaGOTPCRel`, which generates GOTPCREL relocations
+      // not supported by the GNU linker and LLD versions below 18 on aarch64.
+      TT.isAArch64()
+      // Apple's ld64 (and ld-prime on Xcode 15.2) miscompile something on
+      // x86_64-apple-darwin. See
+      // https://github.com/rust-lang/rust/issues/140686 and
+      // https://github.com/rust-lang/rust/issues/141306.
+      || (TT.isX86() && TT.isOSDarwin());
+
   for (Use &Operand : LookupTableArr->operands()) {
     Constant *Element = cast<Constant>(Operand);
+    if (ShouldDropUnnamedAddr)
+      if (auto *GlobalElement = dyn_cast<GlobalValue>(Element))
+        GlobalElement->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
     Type *IntPtrTy = M.getDataLayout().getIntPtrType(M.getContext());
     Constant *Base = llvm::ConstantExpr::getPtrToInt(RelLookupTable, IntPtrTy);
     Constant *Target = llvm::ConstantExpr::getPtrToInt(Element, IntPtrTy);
diff --git a/llvm/test/Transforms/RelLookupTableConverter/unnamed_addr.ll b/llvm/test/Transforms/RelLookupTableConverter/unnamed_addr.ll
new file mode 100644
index 0000000000000..78b8a4aa126c9
--- /dev/null
+++ b/llvm/test/Transforms/RelLookupTableConverter/unnamed_addr.ll
@@ -0,0 +1,119 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
+; REQUIRES: x86-registered-target
+; REQUIRES: aarch64-registered-target
+; RUN: opt < %s -passes=rel-lookup-table-converter -relocation-model=pic -mtriple=x86_64-apple-darwin -S | FileCheck -check-prefix=x86_64-apple-darwin %s
+; RUN: opt < %s -passes=rel-lookup-table-converter -relocation-model=pic -mtriple=aarch64 -S | FileCheck -check-prefix=aarch64 %s
+; RUN: opt < %s -passes=rel-lookup-table-converter -relocation-model=pic -mtriple=x86_64 -S | FileCheck -check-prefix=x86_64 %s
+
+@a0 = private unnamed_addr constant i32 0
+@a1 = private unnamed_addr constant i32 1
+@a2 = private unnamed_addr constant i32 2
+@load_relative_1.table = private unnamed_addr constant [3 x ptr] [ptr @a0, ptr @a1, ptr @a2]
+
+@x0 = internal unnamed_addr constant i64 0
+@x1 = internal unnamed_addr constant i64 1
+@x2 = internal unnamed_addr constant i64 2
+@x3 = internal unnamed_addr constant i64 3
+@y0 = internal unnamed_addr constant ptr @x3
+@y1 = internal unnamed_addr constant ptr @x2
+@y2 = internal unnamed_addr constant ptr @x1
+@y3 = internal unnamed_addr constant ptr @x0
+@load_relative_2.table = private unnamed_addr constant [4 x ptr] [ptr @y3, ptr @y2, ptr @y1, ptr @y0]
+
+;.
+; x86_64-apple-darwin: @a0 = private constant i32 0
+; x86_64-apple-darwin: @a1 = private constant i32 1
+; x86_64-apple-darwin: @a2 = private constant i32 2
+; x86_64-apple-darwin: @load_relative_1.table.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @a0 to i64), i64 ptrtoint (ptr @load_relative_1.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @a1 to i64), i64 ptrtoint (ptr @load_relative_1.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @a2 to i64), i64 ptrtoint (ptr @load_relative_1.table.rel to i64)) to i32)], align 4
+; x86_64-apple-darwin: @x0 = internal unnamed_addr constant i64 0
+; x86_64-apple-darwin: @x1 = internal unnamed_addr constant i64 1
+; x86_64-apple-darwin: @x2 = internal unnamed_addr constant i64 2
+; x86_64-apple-darwin: @x3 = internal unnamed_addr constant i64 3
+; x86_64-apple-darwin: @y0 = internal constant ptr @x3
+; x86_64-apple-darwin: @y1 = internal constant ptr @x2
+; x86_64-apple-darwin: @y2 = internal constant ptr @x1
+; x86_64-apple-darwin: @y3 = internal constant ptr @x0
+; x86_64-apple-darwin: @load_relative_2.table.rel = private unnamed_addr constant [4 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @y3 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y2 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y1 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y0 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32)], align 4
+;.
+; aarch64: @a0 = private constant i32 0
+; aarch64: @a1 = private constant i32 1
+; aarch64: @a2 = private constant i32 2
+; aarch64: @load_relative_1.table.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @a0 to i64), i64 ptrtoint (ptr @load_relative_1.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @a1 to i64), i64 ptrtoint (ptr @load_relative_1.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @a2 to i64), i64 ptrtoint (ptr @load_relative_1.table.rel to i64)) to i32)], align 4
+; aarch64: @x0 = internal unnamed_addr constant i64 0
+; aarch64: @x1 = internal unnamed_addr constant i64 1
+; aarch64: @x2 = internal unnamed_addr constant i64 2
+; aarch64: @x3 = internal unnamed_addr constant i64 3
+; aarch64: @y0 = internal constant ptr @x3
+; aarch64: @y1 = internal constant ptr @x2
+; aarch64: @y2 = internal constant ptr @x1
+; aarch64: @y3 = internal constant ptr @x0
+; aarch64: @load_relative_2.table.rel = private unnamed_addr constant [4 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @y3 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y2 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y1 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y0 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32)], align 4
+;.
+; x86_64: @a0 = private unnamed_addr constant i32 0
+; x86_64: @a1 = private unnamed_addr constant i32 1
+; x86_64: @a2 = private unnamed_addr constant i32 2
+; x86_64: @load_relative_1.table.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @a0 to i64), i64 ptrtoint (ptr @load_relative_1.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @a1 to i64), i64 ptrtoint (ptr @load_relative_1.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @a2 to i64), i64 ptrtoint (ptr @load_relative_1.table.rel to i64)) to i32)], align 4
+; x86_64: @x0 = internal unnamed_addr constant i64 0
+; x86_64: @x1 = internal unnamed_addr constant i64 1
+; x86_64: @x2 = internal unnamed_addr constant i64 2
+; x86_64: @x3 = internal unnamed_addr constant i64 3
+; x86_64: @y0 = internal unnamed_addr constant ptr @x3
+; x86_64: @y1 = internal unnamed_addr constant ptr @x2
+; x86_64: @y2 = internal unnamed_addr constant ptr @x1
+; x86_64: @y3 = internal unnamed_addr constant ptr @x0
+; x86_64: @load_relative_2.table.rel = private unnamed_addr constant [4 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @y3 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y2 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y1 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @y0 to i64), i64 ptrtoint (ptr @load_relative_2.table.rel to i64)) to i32)], align 4
+;.
+define ptr @load_relative_1(i64 %offset) {
+; x86_64-apple-darwin-LABEL: define ptr @load_relative_1(
+; x86_64-apple-darwin-SAME: i64 [[OFFSET:%.*]]) {
+; x86_64-apple-darwin-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i64 [[OFFSET]], 2
+; x86_64-apple-darwin-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i64(ptr @load_relative_1.table.rel, i64 [[RELTABLE_SHIFT]])
+; x86_64-apple-darwin-NEXT:    ret ptr [[RELTABLE_INTRINSIC]]
+;
+; aarch64-LABEL: define ptr @load_relative_1(
+; aarch64-SAME: i64 [[OFFSET:%.*]]) {
+; aarch64-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i64 [[OFFSET]], 2
+; aarch64-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i64(ptr @load_relative_1.table.rel, i64 [[RELTABLE_SHIFT]])
+; aarch64-NEXT:    ret ptr [[RELTABLE_INTRINSIC]]
+;
+; x86_64-LABEL: define ptr @load_relative_1(
+; x86_64-SAME: i64 [[OFFSET:%.*]]) {
+; x86_64-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i64 [[OFFSET]], 2
+; x86_64-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i64(ptr @load_relative_1.table.rel, i64 [[RELTABLE_SHIFT]])
+; x86_64-NEXT:    ret ptr [[RELTABLE_INTRINSIC]]
+;
+  %gep = getelementptr inbounds [3 x ptr], ptr @load_relative_1.table, i64 0, i64 %offset
+  %load = load ptr, ptr %gep
+  ret ptr %load
+}
+
+define ptr @load_relative_2(i64 %offset) {
+; x86_64-apple-darwin-LABEL: define ptr @load_relative_2(
+; x86_64-apple-darwin-SAME: i64 [[OFFSET:%.*]]) {
+; x86_64-apple-darwin-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i64 [[OFFSET]], 2
+; x86_64-apple-darwin-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i64(ptr @load_relative_2.table.rel, i64 [[RELTABLE_SHIFT]])
+; x86_64-apple-darwin-NEXT:    ret ptr [[RELTABLE_INTRINSIC]]
+;
+; aarch64-LABEL: define ptr @load_relative_2(
+; aarch64-SAME: i64 [[OFFSET:%.*]]) {
+; aarch64-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i64 [[OFFSET]], 2
+; aarch64-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i64(ptr @load_relative_2.table.rel, i64 [[RELTABLE_SHIFT]])
+; aarch64-NEXT:    ret ptr [[RELTABLE_INTRINSIC]]
+;
+; x86_64-LABEL: define ptr @load_relative_2(
+; x86_64-SAME: i64 [[OFFSET:%.*]]) {
+; x86_64-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i64 [[OFFSET]], 2
+; x86_64-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i64(ptr @load_relative_2.table.rel, i64 [[RELTABLE_SHIFT]])
+; x86_64-NEXT:    ret ptr [[RELTABLE_INTRINSIC]]
+;
+  %gep = getelementptr inbounds [4 x ptr], ptr @load_relative_2.table, i64 0, i64 %offset
+  %load = load ptr, ptr %gep
+  ret ptr %load
+}
+;.
+; x86_64-apple-darwin: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
+;.
+; aarch64: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
+;.
+; x86_64: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
+;.

@github-project-automation github-project-automation bot moved this from Needs Triage to Needs Merge in LLVM Release Status Jun 2, 2025
…REL relocations (llvm#142304)

Follow
llvm#72584 (comment),
the patch will drop the `unnamed_addr` attribute when generating
relative lookup tables. I'm not very confident about this patch, but it
does resolve rust-lang/rust#140686,
rust-lang/rust#141306 and
rust-lang/rust#141737.

But I don't think this will result in worse problems.

> LLVM provides that the calculation of such a constant initializer will
not overflow at link time under the medium code model if x is an
unnamed_addr function. However, it does not provide this guarantee for a
constant initializer folded into a function body. This intrinsic can be
used to avoid the possibility of overflows when loading from such a
constant. ([‘llvm.load.relative’
Intrinsic](https://llvm.org/docs/LangRef.html#id2592))

This is my concern. I'm not sure how unnamed_addr provides this
guarantee, and I haven't found any test cases.

(cherry picked from commit aa09dbb)
@tstellar tstellar merged commit e0586e2 into llvm:release/20.x Jun 3, 2025
7 of 10 checks passed
@github-project-automation github-project-automation bot moved this from Needs Merge to Done in LLVM Release Status Jun 3, 2025
Copy link

github-actions bot commented Jun 3, 2025

@dianqk (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR.

@dianqk dianqk deleted the backport-142304 branch June 3, 2025 23:55
@dianqk
Copy link
Member Author

dianqk commented Jun 3, 2025

@dianqk (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR.

Add a workaround for relocations in the data sections for Apple's ld64, ld-prime, and GNU linker, which will be removed in the future.

@dianqk
Copy link
Member Author

dianqk commented Jun 3, 2025

Note to me: I propose to keep a major version around until the gnu linker release supports it and GitHub Actions defaults to Xcode 15.3+.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

5 participants