[TLS]: Clamp the alignment of TLS global variables if required by the target
authorWolfgang Pieb <wolfgang_pieb@playstation.sony.com>
Mon, 6 Feb 2023 21:50:37 +0000 (13:50 -0800)
committerWolfgang Pieb <wolfgang_pieb@playstation.sony.com>
Wed, 8 Feb 2023 18:34:56 +0000 (10:34 -0800)
Adding a module flag 'MaxTLSAlign' describing the maximum alignment a global TLS
variable can have. Optimizers are prevented from increasing the alignment of such
variables beyond this threshold.

Reviewed By: probinson

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

clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGen/tls-maxalign-modflag.c [new file with mode: 0644]
llvm/include/llvm/IR/Module.h
llvm/lib/IR/Module.cpp
llvm/lib/Transforms/Utils/Local.cpp
llvm/test/CodeGen/X86/tls-align.ll [new file with mode: 0644]

index 57c9e58..0f93c33 100644 (file)
@@ -947,6 +947,10 @@ void CodeGenModule::Release() {
   if (getCodeGenOpts().SkipRaxSetup)
     getModule().addModuleFlag(llvm::Module::Override, "SkipRaxSetup", 1);
 
+  if (getContext().getTargetInfo().getMaxTLSAlign())
+    getModule().addModuleFlag(llvm::Module::Error, "MaxTLSAlign",
+                              getContext().getTargetInfo().getMaxTLSAlign());
+
   getTargetCodeGenInfo().emitTargetMetadata(*this, MangledDeclNames);
 
   EmitBackendOptionsMetadata(getCodeGenOpts());
diff --git a/clang/test/CodeGen/tls-maxalign-modflag.c b/clang/test/CodeGen/tls-maxalign-modflag.c
new file mode 100644 (file)
index 0000000..d2936b6
--- /dev/null
@@ -0,0 +1,12 @@
+// REQUIRES: x86-registered-target
+
+// Test that we get the module flag TLSMaxAlign on the PS platforms.
+// RUN: %clang_cc1 -triple x86_64-scei-ps4 -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-scei-ps5 -S -emit-llvm -o - %s | FileCheck %s
+
+int main(void) {
+  return 0;
+}
+
+// CHECK-DAG: ![[MDID:[0-9]+]] = !{i32 1, !"MaxTLSAlign", i32 256}
+// CHECK-DAG: llvm.module.flags = {{.*}}![[MDID]]
index cd71a84..e868804 100644 (file)
@@ -923,6 +923,8 @@ public:
   unsigned getOverrideStackAlignment() const;
   void setOverrideStackAlignment(unsigned Align);
 
+  unsigned getMaxTLSAlignment() const;
+
   /// @name Utility functions for querying and setting the build SDK version
   /// @{
 
index 49fadc9..3df1e7b 100644 (file)
@@ -746,6 +746,13 @@ unsigned Module::getOverrideStackAlignment() const {
   return 0;
 }
 
+unsigned Module::getMaxTLSAlignment() const {
+  Metadata *MD = getModuleFlag("MaxTLSAlign");
+  if (auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(MD))
+    return CI->getZExtValue();
+  return 0;
+}
+
 void Module::setOverrideStackAlignment(unsigned Align) {
   addModuleFlag(ModFlagBehavior::Error, "override-stack-alignment", Align);
 }
index 624907a..ddef654 100644 (file)
@@ -1423,6 +1423,12 @@ static Align tryEnforceAlignment(Value *V, Align PrefAlign,
     if (!GO->canIncreaseAlignment())
       return CurrentAlign;
 
+    if (GO->isThreadLocal()) {
+      unsigned MaxTLSAlign = GO->getParent()->getMaxTLSAlignment() / CHAR_BIT;
+      if (MaxTLSAlign && PrefAlign > Align(MaxTLSAlign))
+        PrefAlign = Align(MaxTLSAlign);
+    }
+
     GO->setAlignment(PrefAlign);
     return PrefAlign;
   }
diff --git a/llvm/test/CodeGen/X86/tls-align.ll b/llvm/test/CodeGen/X86/tls-align.ll
new file mode 100644 (file)
index 0000000..3c8ee6b
--- /dev/null
@@ -0,0 +1,20 @@
+; REQUIRES: x86-registered-target
+; RUN: opt -passes=instcombine -S < %s | FileCheck %s
+
+%class.Arr = type <{ [160 x %class.Derived], i32, [4 x i8] }>
+%class.Derived = type { %class.Base, ptr }
+%class.Base = type { ptr }
+
+@array = hidden thread_local global %class.Arr zeroinitializer, align 32
+; CHECK: @array{{.*}}align 32
+
+@_ZTV7Derived = constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr null, ptr null] }, align 8
+
+define internal fastcc void @foo() unnamed_addr {
+entry:
+  store <8 x ptr> <ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr null, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr null, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr null, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr null>, ptr @array, align 32
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"MaxTLSAlign", i32 256}