-
Notifications
You must be signed in to change notification settings - Fork 14.3k
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
Conversation
@llvm/pr-subscribers-llvm-transforms Author: dianqk (dianqk) ChangesBackport aa09dbb Requested by: @dianqk Full diff: https://github.com/llvm/llvm-project/pull/142311.diff 2 Files Affected:
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) }
+;.
|
…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)
@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. |
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+. |
Backport aa09dbb
Requested by: @dianqk