[llvm] 431a5d8 - [x86] Implement a tagged-globals backend feature.

Matt Morehouse via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 18 13:31:32 PDT 2021


Author: Matt Morehouse
Date: 2021-10-18T13:31:10-07:00
New Revision: 431a5d8411952b4c9c2185303afd703123ef55cc

URL: https://github.com/llvm/llvm-project/commit/431a5d8411952b4c9c2185303afd703123ef55cc
DIFF: https://github.com/llvm/llvm-project/commit/431a5d8411952b4c9c2185303afd703123ef55cc.diff

LOG: [x86] Implement a tagged-globals backend feature.

The feature tells the backend to allow tags in the upper bits of global
variable addresses.  These tags will be ignored by upcoming CPUs with
the Intel LAM feature but may be used in instrumentation passes (e.g.,
HWASan).

This patch implements the feature by using @GOTPCREL relocations instead
of direct references to the locally defined global.  Thus the full
tagged address can be loaded by a single instruction:
  movq global at GOTPCREL(%rip), %rax

Reviewed By: eugenis

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

Added: 
    llvm/test/CodeGen/X86/tagged-globals-pic.ll
    llvm/test/CodeGen/X86/tagged-globals-static.ll

Modified: 
    llvm/lib/Target/X86/X86.td
    llvm/lib/Target/X86/X86Subtarget.cpp
    llvm/lib/Target/X86/X86Subtarget.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td
index 2d7d4dd14c1ad..32f8ade5f9b6d 100644
--- a/llvm/lib/Target/X86/X86.td
+++ b/llvm/lib/Target/X86/X86.td
@@ -374,6 +374,13 @@ def FeatureLVILoadHardening
           "Insert LFENCE instructions to prevent data speculatively injected "
           "into loads from being used maliciously.">;
 
+def FeatureTaggedGlobals
+    : SubtargetFeature<
+          "tagged-globals", "AllowTaggedGlobals", "true",
+          "Use an instruction sequence for taking the address of a global "
+          "that allows a memory tag in the upper address bits. Currently "
+          "also requires -mrelax-relocations=no to work properly.">;
+
 //===----------------------------------------------------------------------===//
 // X86 Subtarget Tuning features
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index b985a3aa52102..45732fafdcc2b 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -67,6 +67,13 @@ X86Subtarget::classifyGlobalReference(const GlobalValue *GV) const {
 
 unsigned char
 X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
+  // Tagged globals have non-zero upper bits, which makes direct references
+  // require a 64-bit immediate.  On the small code model this causes relocation
+  // errors, so we go through the GOT instead.
+  if (AllowTaggedGlobals && TM.getCodeModel() == CodeModel::Small &&
+      !isa_and_nonnull<Function>(GV))
+    return X86II::MO_GOTPCREL;
+
   // If we're not PIC, it's not very interesting.
   if (!isPositionIndependent())
     return X86II::MO_NO_FLAG;

diff  --git a/llvm/lib/Target/X86/X86Subtarget.h b/llvm/lib/Target/X86/X86Subtarget.h
index 796bd83f2a273..455e947c7b67e 100644
--- a/llvm/lib/Target/X86/X86Subtarget.h
+++ b/llvm/lib/Target/X86/X86Subtarget.h
@@ -476,6 +476,10 @@ class X86Subtarget final : public X86GenSubtargetInfo {
   /// loads from being used maliciously.
   bool UseLVILoadHardening = false;
 
+  /// Use an instruction sequence for taking the address of a global that allows
+  /// a memory tag in the upper address bits.
+  bool AllowTaggedGlobals = false;
+
   /// Use software floating point for code generation.
   bool UseSoftFloat = false;
 
@@ -795,6 +799,7 @@ class X86Subtarget final : public X86GenSubtargetInfo {
   bool preferMaskRegisters() const { return PreferMaskRegisters; }
   bool useGLMDivSqrtCosts() const { return UseGLMDivSqrtCosts; }
   bool useLVIControlFlowIntegrity() const { return UseLVIControlFlowIntegrity; }
+  bool allowTaggedGlobals() const { return AllowTaggedGlobals; }
   bool useLVILoadHardening() const { return UseLVILoadHardening; }
   bool useSpeculativeExecutionSideEffectSuppression() const {
     return UseSpeculativeExecutionSideEffectSuppression;

diff  --git a/llvm/test/CodeGen/X86/tagged-globals-pic.ll b/llvm/test/CodeGen/X86/tagged-globals-pic.ll
new file mode 100644
index 0000000000000..98bf75a5326a1
--- /dev/null
+++ b/llvm/test/CodeGen/X86/tagged-globals-pic.ll
@@ -0,0 +1,45 @@
+; RUN: llc --relocation-model=pic < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at global = external global i32
+declare void @func()
+
+define i32* @global_addr() #0 {
+  ; CHECK-LABEL: global_addr:
+  ; CHECK: movq global at GOTPCREL(%rip), %rax
+  ; CHECK: retq
+
+  ret i32* @global
+}
+
+define i32 @global_load() #0 {
+  ; CHECK-LABEL: global_load:
+  ; CHECK: movq global at GOTPCREL(%rip), [[REG:%r[0-9a-z]+]]
+  ; CHECK: movl ([[REG]]), %eax
+  ; CHECK: retq
+
+  %load = load i32, i32* @global
+  ret i32 %load
+}
+
+define void @global_store() #0 {
+  ; CHECK-LABEL: global_store:
+  ; CHECK: movq global at GOTPCREL(%rip), [[REG:%r[0-9a-z]+]]
+  ; CHECK: movl $0, ([[REG]])
+  ; CHECK: retq
+
+  store i32 0, i32* @global
+  ret void
+}
+
+define void ()* @func_addr() #0 {
+  ; CHECK-LABEL: func_addr:
+  ; CHECK: movq func at GOTPCREL(%rip), %rax
+  ; CHECK: retq
+
+  ret void ()* @func
+}
+
+attributes #0 = { "target-features"="+tagged-globals" }

diff  --git a/llvm/test/CodeGen/X86/tagged-globals-static.ll b/llvm/test/CodeGen/X86/tagged-globals-static.ll
new file mode 100644
index 0000000000000..af2fae227ed4d
--- /dev/null
+++ b/llvm/test/CodeGen/X86/tagged-globals-static.ll
@@ -0,0 +1,45 @@
+; RUN: llc --relocation-model=static < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at global = external dso_local global i32
+declare dso_local void @func()
+
+define i32* @global_addr() #0 {
+  ; CHECK-LABEL: global_addr:
+  ; CHECK: movq global at GOTPCREL(%rip), %rax
+  ; CHECK: retq
+
+  ret i32* @global
+}
+
+define i32 @global_load() #0 {
+  ; CHECK-LABEL: global_load:
+  ; CHECK: movq global at GOTPCREL(%rip), [[REG:%r[0-9a-z]+]]
+  ; CHECK: movl ([[REG]]), %eax
+  ; CHECK: retq
+
+  %load = load i32, i32* @global
+  ret i32 %load
+}
+
+define void @global_store() #0 {
+  ; CHECK-LABEL: global_store:
+  ; CHECK: movq global at GOTPCREL(%rip), [[REG:%r[0-9a-z]+]]
+  ; CHECK: movl $0, ([[REG]])
+  ; CHECK: retq
+
+  store i32 0, i32* @global
+  ret void
+}
+
+define void ()* @func_addr() #0 {
+  ; CHECK-LABEL: func_addr:
+  ; CHECK: movl $func, %eax
+  ; CHECK: retq
+
+  ret void ()* @func
+}
+
+attributes #0 = { "target-features"="+tagged-globals" }


        


More information about the llvm-commits mailing list