From 58b8b35b174fa0a108b7ed1e0b209504e5144cfc Mon Sep 17 00:00:00 2001 From: dianqk Date: Sat, 28 Jun 2025 06:42:42 +0800 Subject: [PATCH] [RelLookupTableConverter] Drop unnamed_addr for GVs in entries to avoid generating GOTPCREL relocations (#146068) The entry in a relative lookup table is a global variable with a constant offset, such as `@gv`, `GEP @gv, 1`, and so on. We cannot only consider the case of a trivial global variable. This PR handles all cases using the existing `IsConstantOffsetFromGlobal` function. (cherry picked from commit c43282ab69d7ff1b64f8ef5c84eab46e57553075) --- .../Utils/RelLookupTableConverter.cpp | 37 ++++++++------- .../RelLookupTableConverter/unnamed_addr.ll | 45 +++++++++++++++++++ 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp b/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp index 4486cba2bf6c0..fe1fe391f5982 100644 --- a/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp +++ b/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp @@ -67,6 +67,20 @@ static bool shouldConvertToRelLookupTable(Module &M, GlobalVariable &GV) { if (!ElemType->isPointerTy() || DL.getPointerTypeSizeInBits(ElemType) != 64) return false; + SmallVector GVOps; + 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 (const Use &Op : Array->operands()) { Constant *ConstOp = cast(&Op); GlobalValue *GVOp; @@ -86,8 +100,15 @@ static bool shouldConvertToRelLookupTable(Module &M, GlobalVariable &GV) { !GlovalVarOp->isDSOLocal() || !GlovalVarOp->isImplicitDSOLocal()) return false; + + if (ShouldDropUnnamedAddr) + GVOps.push_back(GlovalVarOp); } + if (ShouldDropUnnamedAddr) + for (auto *GVOp : GVOps) + GVOp->setUnnamedAddr(GlobalValue::UnnamedAddr::None); + return true; } @@ -109,24 +130,8 @@ static GlobalVariable *createRelLookupTable(Function &Func, uint64_t Idx = 0; SmallVector 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(Operand); - if (ShouldDropUnnamedAddr) - if (auto *GlobalElement = dyn_cast(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 index 78b8a4aa126c9..322c38d090fe1 100644 --- a/llvm/test/Transforms/RelLookupTableConverter/unnamed_addr.ll +++ b/llvm/test/Transforms/RelLookupTableConverter/unnamed_addr.ll @@ -20,6 +20,14 @@ @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] +@b0 = private unnamed_addr constant [8 x i8] c"00000000" +@b1 = private unnamed_addr constant [8 x i8] c"11111111" +@b2 = private unnamed_addr constant [8 x i8] c"22222222" +@load_relative_3.table = private unnamed_addr constant [3 x ptr] [ + ptr getelementptr inbounds (i8, ptr @b0, i64 8), + ptr getelementptr inbounds (i8, ptr @b1, i64 8), + ptr getelementptr inbounds (i8, ptr @b2, i64 8)] + ;. ; x86_64-apple-darwin: @a0 = private constant i32 0 ; x86_64-apple-darwin: @a1 = private constant i32 1 @@ -34,6 +42,10 @@ ; 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 +; x86_64-apple-darwin: @b0 = private constant [8 x i8] c"00000000" +; x86_64-apple-darwin: @b1 = private constant [8 x i8] c"11111111" +; x86_64-apple-darwin: @b2 = private constant [8 x i8] c"22222222" +; x86_64-apple-darwin: @load_relative_3.table.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b0, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b1, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b2, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32)], align 4 ;. ; aarch64: @a0 = private constant i32 0 ; aarch64: @a1 = private constant i32 1 @@ -48,6 +60,10 @@ ; 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 +; aarch64: @b0 = private constant [8 x i8] c"00000000" +; aarch64: @b1 = private constant [8 x i8] c"11111111" +; aarch64: @b2 = private constant [8 x i8] c"22222222" +; aarch64: @load_relative_3.table.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b0, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b1, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b2, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.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 @@ -62,6 +78,10 @@ ; 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 +; x86_64: @b0 = private unnamed_addr constant [8 x i8] c"00000000" +; x86_64: @b1 = private unnamed_addr constant [8 x i8] c"11111111" +; x86_64: @b2 = private unnamed_addr constant [8 x i8] c"22222222" +; x86_64: @load_relative_3.table.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b0, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b1, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @b2, i64 8) to i64), i64 ptrtoint (ptr @load_relative_3.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( @@ -110,6 +130,31 @@ define ptr @load_relative_2(i64 %offset) { %load = load ptr, ptr %gep ret ptr %load } + +define ptr @load_relative_3(i64 %offset) { +; x86_64-apple-darwin-LABEL: define ptr @load_relative_3( +; 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_3.table.rel, i64 [[RELTABLE_SHIFT]]) +; x86_64-apple-darwin-NEXT: ret ptr [[RELTABLE_INTRINSIC]] +; +; aarch64-LABEL: define ptr @load_relative_3( +; 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_3.table.rel, i64 [[RELTABLE_SHIFT]]) +; aarch64-NEXT: ret ptr [[RELTABLE_INTRINSIC]] +; +; x86_64-LABEL: define ptr @load_relative_3( +; 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_3.table.rel, i64 [[RELTABLE_SHIFT]]) +; x86_64-NEXT: ret ptr [[RELTABLE_INTRINSIC]] +; + %gep = getelementptr inbounds [3 x ptr], ptr @load_relative_3.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) } ;.