Index: clang/include/clang/Basic/CodeGenOptions.def =================================================================== --- clang/include/clang/Basic/CodeGenOptions.def +++ clang/include/clang/Basic/CodeGenOptions.def @@ -75,6 +75,7 @@ ///< each (it means check ///< the original debug info ///< metadata preservation). +CODEGENOPT(TlsAddrLoadHoist, 1, 0) ///< Set when -mtls-load-hoist is specified. CODEGENOPT(IndirectTlsSegRefs, 1, 0) ///< Set when -mno-tls-direct-seg-refs ///< is specified. CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls. Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -3622,6 +3622,11 @@ def moslib_EQ : Joined<["-"], "moslib=">, Group; def mpascal_strings : Flag<["-"], "mpascal-strings">, Alias; def mred_zone : Flag<["-"], "mred-zone">, Group; +def mno_tls_load_hoist : Flag<["-"], "mno-tls-load-hoist">, Group, + HelpText<"Disable hoisting TLS address">; +def mtls_load_hoist : Flag<["-"], "mtls-load-hoist">, Group, Flags<[CC1Option]>, + HelpText<"Hoist fetching TLS address in PIC model to remove redundant TLS address call">, + MarshallingInfoFlag>; def mtls_direct_seg_refs : Flag<["-"], "mtls-direct-seg-refs">, Group, HelpText<"Enable direct TLS access through segment registers (default)">; def mregparm_EQ : Joined<["-"], "mregparm=">, Group; Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -1799,6 +1799,8 @@ FuncAttrs.addAttribute(llvm::Attribute::NoRedZone); if (CodeGenOpts.IndirectTlsSegRefs) FuncAttrs.addAttribute("indirect-tls-seg-refs"); + if (CodeGenOpts.TlsAddrLoadHoist && Context.getLangOpts().PICLevel > 0) + FuncAttrs.addAttribute("tls-load-hoist"); if (CodeGenOpts.NoImplicitFloat) FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat); Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5970,6 +5970,11 @@ Args.AddLastArg(CmdArgs, options::OPT_fdigraphs, options::OPT_fno_digraphs); Args.AddLastArg(CmdArgs, options::OPT_femulated_tls, options::OPT_fno_emulated_tls); + + if (Args.hasFlag(options::OPT_mtls_load_hoist, + options::OPT_mno_tls_load_hoist, false)) + CmdArgs.push_back("-mtls-load-hoist"); + Args.AddLastArg(CmdArgs, options::OPT_fzero_call_used_regs_EQ); if (Arg *A = Args.getLastArg(options::OPT_fzero_call_used_regs_EQ)) { Index: clang/test/CodeGen/X86/tls_loads.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/X86/tls_loads.cpp @@ -0,0 +1,44 @@ +// RUN: %clang -target x86_64-unknown-unknown -fPIC -ftls-model=global-dynamic -mtls-load-hoist -O2 -S -o - %s -emit-llvm | FileCheck %s --check-prefix=HOIST +// RUN: %clang -target x86_64-unknown-unknown -fPIC -ftls-model=global-dynamic -mno-tls-load-hoist -O2 -S -o - %s -emit-llvm | FileCheck %s --check-prefix=NOHOIST + +// Use this test generate IR test for llvm/test/CodeGen/X86/intel-tls-loads-control*.ll +thread_local int thl_x; +thread_local int thl_x2; + +struct SS { + char thl_c; + int num; +}; + +int gfunc(); +int gfunc2(int); + +int f1(int c) { + int *px = &thl_x; + while (c--) + *px += gfunc2(thl_x2); + return *px; +} + +int f2(int c) { + thread_local struct SS st; + while (c--) { + thl_x += gfunc(); + st.thl_c += (char)gfunc(); + st.num += gfunc(); + } + return thl_x; +} + +int f3(int c) { + int *px = &thl_x; + gfunc2(*px); + gfunc2(*px); + return 1; +} + +// HOIST: attributes {{.*}}"tls-load-hoist" +// HOIST: attributes {{.*}}"tls-load-hoist" +// HOIST: attributes {{.*}}"tls-load-hoist" + +// NOHOIST-NOT: attributes {{.*}}"tls-load-hoist" Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -2122,7 +2122,7 @@ ``"tls-load-hoist"`` This attribute indicates that the function will try to reduce redundant - tls address caculation by hoisting tls variable. + tls address calculation by hoisting tls variables. ``uwtable[(sync|async)]`` This attribute indicates that the ABI being targeted requires that Index: llvm/lib/Transforms/Scalar/TLSVariableHoist.cpp =================================================================== --- llvm/lib/Transforms/Scalar/TLSVariableHoist.cpp +++ llvm/lib/Transforms/Scalar/TLSVariableHoist.cpp @@ -40,16 +40,10 @@ #define DEBUG_TYPE "tlshoist" -// TODO: Support "strict" model if we need to strictly load TLS address, -// because "non-optimize" may also do some optimization in other passes. -static cl::opt TLSLoadHoist( - "tls-load-hoist", - cl::desc( - "hoist the TLS loads in PIC model: " - "tls-load-hoist=optimize: Eleminate redundant TLS load(s)." - "tls-load-hoist=strict: Strictly load TLS address before every use." - "tls-load-hoist=non-optimize: Generally load TLS before use(s)."), - cl::init("non-optimize"), cl::Hidden); +static cl::opt TLSLoadHoist( + "tls-load-hoist", cl::init(false), cl::Hidden, + cl::desc("hoist the TLS loads in PIC model to eleminate redundant " + "TLS address calculation.")); namespace { @@ -282,8 +276,7 @@ if (Fn.hasOptNone()) return false; - if (TLSLoadHoist != "optimize" && - !Fn.getAttributes().hasFnAttr("tls-load-hoist")) + if (!TLSLoadHoist && !Fn.getAttributes().hasFnAttr("tls-load-hoist")) return false; this->LI = &LI; Index: llvm/test/CodeGen/X86/tls-loads-control.ll =================================================================== --- llvm/test/CodeGen/X86/tls-loads-control.ll +++ llvm/test/CodeGen/X86/tls-loads-control.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=x86_64-unknown-unknown -O2 --relocation-model=pic --tls-load-hoist=optimize --stop-after=tlshoist -o - %s | FileCheck %s +; RUN: llc -mtriple=x86_64-unknown-unknown -O2 --relocation-model=pic --tls-load-hoist=true --stop-after=tlshoist -o - %s | FileCheck %s ; RUN: llc -mtriple=x86_64-unknown-unknown -O2 --relocation-model=pic --stop-after=tlshoist -o - %s | FileCheck %s ; This test come from compiling clang/test/CodeGen/intel/tls_loads.cpp with: Index: llvm/test/CodeGen/X86/tls-loads-control2.ll =================================================================== --- llvm/test/CodeGen/X86/tls-loads-control2.ll +++ llvm/test/CodeGen/X86/tls-loads-control2.ll @@ -1,5 +1,4 @@ -; RUN: opt -S -mtriple=x86_64-unknown-unknown -tlshoist --relocation-model=pic --tls-load-hoist=optimize -o - %s | FileCheck %s --check-prefix=HOIST0 -; RUN: opt -S -mtriple=x86_64-unknown-unknown -tlshoist --relocation-model=pic --tls-load-hoist=non-optimize -o - %s | FileCheck %s --check-prefix=HOIST2 +; RUN: opt -S -mtriple=x86_64-unknown-unknown -tlshoist --relocation-model=pic --tls-load-hoist=true -o - %s | FileCheck %s --check-prefix=HOIST0 ; RUN: opt -S -mtriple=x86_64-unknown-unknown -tlshoist --relocation-model=pic -o - %s | FileCheck %s --check-prefix=HOIST2 $_ZTW5thl_x = comdat any Index: llvm/test/CodeGen/X86/tls-loads-control3.ll =================================================================== --- llvm/test/CodeGen/X86/tls-loads-control3.ll +++ llvm/test/CodeGen/X86/tls-loads-control3.ll @@ -1,6 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=x86_64-unknown-unknown -O2 --relocation-model=pic --tls-load-hoist=optimize -o - %s | FileCheck %s --check-prefix=HOIST0 -; RUN: llc -mtriple=x86_64-unknown-unknown -O2 --relocation-model=pic --tls-load-hoist=non-optimize -o - %s | FileCheck %s --check-prefix=HOIST2 +; RUN: llc -mtriple=x86_64-unknown-unknown -O2 --relocation-model=pic --tls-load-hoist=true -o - %s | FileCheck %s --check-prefix=HOIST0 ; RUN: llc -mtriple=x86_64-unknown-unknown -O2 --relocation-model=pic -o - %s | FileCheck %s --check-prefix=HOIST2 ; This test has no module flag {"tls-load-hoist", i32 0}, so use --tls-load-hoist=x