[AArch64][GlobalISel] Don't match thread-local globals in matchFoldGlobalOffset
authorJessica Paquette <jpaquette@apple.com>
Wed, 28 Apr 2021 18:13:19 +0000 (11:13 -0700)
committerJessica Paquette <jpaquette@apple.com>
Wed, 28 Apr 2021 20:48:18 +0000 (13:48 -0700)
SelectionDAG has separate ISD opcodes for regular global values and thread-local
global values, while GlobalISel does not.

This combine was ported from SDAG directly without knowing that. As a result,
it was running on TLS globals.

This makes it so that `matchFoldGlobalOffset` doesn't match on TLS globals, and
adds an assert to `selectTLSGlobalValue` to make sure that TLS globals never
have offsets.

Differential Revision: https://reviews.llvm.org/D101478

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
llvm/test/CodeGen/AArch64/GlobalISel/fold-global-offsets.mir

index a0bc543..4d3ffb6 100644 (file)
@@ -3376,7 +3376,10 @@ bool AArch64InstructionSelector::selectTLSGlobalValue(
   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 =
index 4efc63e..a87dc0d 100644 (file)
@@ -118,6 +118,8 @@ static bool matchFoldGlobalOffset(MachineInstr &MI, MachineRegisterInfo &MRI,
   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<AArch64Subtarget>().ClassifyGlobalReference(
index 514cef0..8d659ac 100644 (file)
@@ -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 @@ body:             |
     %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