diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4089,6 +4089,12 @@ def mprivileged : Flag<["-"], "mprivileged">, Group; } // let Flags = [TargetSpecific] +def maix_small_local_exec_tls : Flag<["-"], "maix-small-local-exec-tls">, + Group, + HelpText<"Produce a faster access sequence for local-exec TLS variables " + "where the offset from the thread pointer value is encoded as an " + "immediate operand (AIX 64-bit only). " + "This access sequence is not used for variables larger than 32KB.">; def maix_struct_return : Flag<["-"], "maix-struct-return">, Group, Flags<[CC1Option]>, HelpText<"Return all structs in memory (PPC32 only)">, diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -60,6 +60,7 @@ bool HasMMA = false; bool HasROPProtect = false; bool HasPrivileged = false; + bool HasAIXSmallLocalExecTLS = false; bool HasVSX = false; bool UseCRBits = false; bool HasP8Vector = false; diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -77,6 +77,8 @@ HasROPProtect = true; } else if (Feature == "+privileged") { HasPrivileged = true; + } else if (Feature == "+aix-small-local-exec-tls") { + HasAIXSmallLocalExecTLS = true; } else if (Feature == "+isa-v206-instructions") { IsISA2_06 = true; } else if (Feature == "+isa-v207-instructions") { @@ -541,6 +543,10 @@ // Privileged instructions are off by default. Features["privileged"] = false; + // The code generated by the -maix-small-local-exec-tls option is turned + // off by default. + Features["aix-small-local-exec-tls"] = false; + Features["spe"] = llvm::StringSwitch(CPU) .Case("8548", true) .Case("e500", true) @@ -635,6 +641,13 @@ return false; } + if (!getTriple().isOSAIX() && + llvm::is_contained(FeaturesVec, "+aix-small-local-exec-tls")) { + Diags.Report(diag::err_opt_not_valid_on_target) + << "-maix-small-local-exec-tls"; + return false; + } + return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); } @@ -676,6 +689,7 @@ .Case("mma", HasMMA) .Case("rop-protect", HasROPProtect) .Case("privileged", HasPrivileged) + .Case("aix-small-local-exec-tls", HasAIXSmallLocalExecTLS) .Case("isa-v206-instructions", IsISA2_06) .Case("isa-v207-instructions", IsISA2_07) .Case("isa-v30-instructions", IsISA3_0) diff --git a/clang/test/Driver/aix-small-local-exec-tls.c b/clang/test/Driver/aix-small-local-exec-tls.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/aix-small-local-exec-tls.c @@ -0,0 +1,29 @@ +// RUN: %clang -target powerpc64-unknown-aix -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -target powerpc-unknown-aix -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -target powerpc64le-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -target powerpc64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s + +// RUN: %clang -target powerpc64-unknown-aix -maix-small-local-exec-tls -S -emit-llvm \ +// RUN: %s -o - | FileCheck %s --check-prefix=CHECK-AIX_SMALL_LOCALEXEC_TLS +// RUN: %clang -target powerpc-unknown-aix -maix-small-local-exec-tls -S -emit-llvm \ +// RUN: %s -o - | FileCheck %s --check-prefix=CHECK-AIX_SMALL_LOCALEXEC_TLS + +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -maix-small-local-exec-tls -fsyntax-only \ +// RUN: %s 2>&1 | FileCheck --check-prefix=CHECK-UNSUPPORTED-LINUX %s +// RUN: not %clang -target powerpc64-unknown-linux-gnu -maix-small-local-exec-tls -fsyntax-only \ +// RUN: %s 2>&1 | FileCheck --check-prefix=CHECK-UNSUPPORTED-LINUX %s + +int test(void) { + return 0; +} + +// CHECK: test() #0 { +// CHECK: attributes #0 = { +// CHECK-SAME: -aix-small-local-exec-tls + +// CHECK-UNSUPPORTED-LINUX: option '-maix-small-local-exec-tls' cannot be specified on this target + +// CHECK-AIX_SMALL_LOCALEXEC_TLS: test() #0 { +// CHECK-AIX_SMALL_LOCALEXEC_TLS: attributes #0 = { +// CHECK-AIX_SMALL_LOCALEXEC_TLS-SAME: +aix-small-local-exec-tls + diff --git a/clang/test/OpenMP/target_data_map_codegen_hold.cpp b/clang/test/OpenMP/target_data_map_codegen_hold.cpp --- a/clang/test/OpenMP/target_data_map_codegen_hold.cpp +++ b/clang/test/OpenMP/target_data_map_codegen_hold.cpp @@ -517,7 +517,7 @@ #endif //. -// CHECK-PPC64LE: attributes #[[ATTR0:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-altivec,-bpermd,-crbits,-crypto,-direct-move,-extdiv,-htm,-isa-v206-instructions,-isa-v207-instructions,-isa-v30-instructions,-power8-vector,-power9-vector,-privileged,-quadword-atomics,-rop-protect,-spe,-vsx" } +// CHECK-PPC64LE: attributes #[[ATTR0:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-aix-small-local-exec-tls,-altivec,-bpermd,-crbits,-crypto,-direct-move,-extdiv,-htm,-isa-v206-instructions,-isa-v207-instructions,-isa-v30-instructions,-power8-vector,-power9-vector,-privileged,-quadword-atomics,-rop-protect,-spe,-vsx" } // CHECK-PPC64LE: attributes #[[ATTR1:[0-9]+]] = { nounwind } // CHECK-PPC64LE: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } //. diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td --- a/llvm/lib/Target/PowerPC/PPC.td +++ b/llvm/lib/Target/PowerPC/PPC.td @@ -318,6 +318,14 @@ SubtargetFeature<"privileged", "HasPrivileged", "true", "Add privileged instructions">; +def FeatureAIXLocalExecTLS : + SubtargetFeature<"aix-small-local-exec-tls", "HasAIXSmallLocalExecTLS", "true", + "Produce a faster access sequence for local-exec TLS " + "variables where the offset from the thread pointer value " + "is encoded as an immediate operand (AIX 64-bit only). " + "This access sequence is not used for variables larger " + "than 32KB.">; + def FeaturePredictableSelectIsExpensive : SubtargetFeature<"predictable-select-expensive", "PredictableSelectIsExpensive", diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp --- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -123,6 +123,11 @@ // Determine endianness. IsLittleEndian = TM.isLittleEndian(); + + if ((!TargetTriple.isOSAIX()) && HasAIXSmallLocalExecTLS) + report_fatal_error( + "The aix-small-local-exec-tls attribute is only supported on AIX.\n", + false); } bool PPCSubtarget::enableMachineScheduler() const { return true; } diff --git a/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt.ll b/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/check-aix-small-local-exec-tls-opt.ll @@ -0,0 +1,18 @@ +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -mattr=+aix-small-local-exec-tls \ +; RUN: -ppc-asm-full-reg-names < %s | FileCheck %s +; RUN: not llc -mtriple powerpc64le-unknown-linux-gnu -mattr=+aix-small-local-exec-tls \ +; RUN: -ppc-asm-full-reg-names < %s 2>&1 | \ +; RUN: FileCheck %s --check-prefix=CHECK-NOT-SUPPORTED + +define dso_local signext i32 @f() { +entry: + ret i32 0 +} + +; Check that the -maix-small-local-exec-tls option is not supported on Linux. +; CHECK-NOT-SUPPORTED: The aix-small-local-exec-tls attribute is only supported on AIX. + +; Make sure that the test was actually compiled successfully after using the +; -maix-small-local-exec-tls option. +; CHECK: li r3, 0 +; CHECK-NEXT: blr