diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -3376,7 +3376,10 @@ MachineFunction &MF = *I.getParent()->getParent(); MF.getFrameInfo().setAdjustsStack(true); - const GlobalValue &GV = *I.getOperand(1).getGlobal(); + const auto &GlobalOp = I.getOperand(1); + assert(GlobalOp.getOffset() == 0 && + "Shouldn't have an offset on TLS globals!"); + const GlobalValue &GV = *GlobalOp.getGlobal(); MachineIRBuilder MIB(I); auto LoadGOT = diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp @@ -118,6 +118,8 @@ MachineFunction &MF = *MI.getMF(); auto &GlobalOp = MI.getOperand(1); auto *GV = GlobalOp.getGlobal(); + if (GV->isThreadLocal()) + return false; // Don't allow anything that could represent offsets etc. if (MF.getSubtarget().ClassifyGlobalReference( diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/fold-global-offsets.mir b/llvm/test/CodeGen/AArch64/GlobalISel/fold-global-offsets.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/fold-global-offsets.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/fold-global-offsets.mir @@ -6,6 +6,7 @@ %opaque = type opaque @unsized = external hidden global %opaque + @thread_local = thread_local global i32 0 define void @one_ptr_add() { ret void } define void @add_to_offset() { ret void } @@ -18,6 +19,7 @@ define void @dont_fold_max_offset() { ret void } define void @dont_fold_offset_larger_than_type_alloc() { ret void } define void @dont_fold_unsized_type() { ret void } + define void @dont_fold_thread_local() { ret void } ... --- name: one_ptr_add @@ -282,3 +284,25 @@ %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) $x0 = COPY %ptr_add(p0) RET_ReallyLR implicit $x0 + +... +--- +name: dont_fold_thread_local +alignment: 4 +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0: + ; Check that we don't touch thread-local globals. + + ; CHECK-LABEL: name: dont_fold_thread_local + ; CHECK: %global:_(p0) = G_GLOBAL_VALUE @thread_local + ; CHECK: %offset:_(s64) = G_CONSTANT i64 16 + ; CHECK: %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) + ; CHECK: $x0 = COPY %ptr_add(p0) + ; CHECK: RET_ReallyLR implicit $x0 + %global:_(p0) = G_GLOBAL_VALUE @thread_local + %offset:_(s64) = G_CONSTANT i64 16 + %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) + $x0 = COPY %ptr_add(p0) + RET_ReallyLR implicit $x0