diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -472,6 +472,10 @@ /// Whether to emit unused static constants. CODEGENOPT(KeepStaticConsts, 1, 0) +/// Whether to emit all variables that have a persistent storage duration, +/// including global, static and thread local variables. +CODEGENOPT(KeepPersistentStorageVariables, 1, 0) + /// Whether to follow the AAPCS enforcing at least one read before storing to a volatile bitfield CODEGENOPT(ForceAAPCSBitfieldLoad, 1, 0) 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 @@ -1697,6 +1697,10 @@ CodeGenOpts<"KeepStaticConsts">, DefaultFalse, PosFlag, NegFlag, BothFlags<[NoXarchOption], " static const variables if unused">>; +defm keep_persistent_storage_variables : BoolFOption<"keep-persistent-storage-variables", + CodeGenOpts<"KeepPersistentStorageVariables">, DefaultFalse, + PosFlag, NegFlag, + BothFlags<[NoXarchOption], " keeping all variables that have a persistent storage duration, including global, static and thread local variables, to guarantee that they can be directly addressed">>; defm fixed_point : BoolFOption<"fixed-point", LangOpts<"FixedPoint">, DefaultFalse, PosFlag, NegFlag, diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -469,6 +469,9 @@ else if (D.hasAttr()) CGM.addUsedOrCompilerUsedGlobal(var); + if (CGM.getCodeGenOpts().KeepPersistentStorageVariables) + CGM.addUsedOrCompilerUsedGlobal(var); + // We may have to cast the constant because of the initializer // mismatch above. // diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2198,12 +2198,14 @@ if (D && D->hasAttr()) addUsedOrCompilerUsedGlobal(GV); - if (CodeGenOpts.KeepStaticConsts && D && isa(D)) { - const auto *VD = cast(D); - if (VD->getType().isConstQualified() && - VD->getStorageDuration() == SD_Static) - addUsedOrCompilerUsedGlobal(GV); - } + if (const auto *VD = dyn_cast_if_present(D); + VD && + ((CodeGenOpts.KeepPersistentStorageVariables && + (VD->getStorageDuration() == SD_Static || + VD->getStorageDuration() == SD_Thread)) || + (CodeGenOpts.KeepStaticConsts && VD->getStorageDuration() == SD_Static && + VD->getType().isConstQualified()))) + addUsedOrCompilerUsedGlobal(GV); } bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD, @@ -3084,12 +3086,14 @@ if (LangOpts.EmitAllDecls) return true; - if (CodeGenOpts.KeepStaticConsts) { - const auto *VD = dyn_cast(Global); - if (VD && VD->getType().isConstQualified() && - VD->getStorageDuration() == SD_Static) - return true; - } + const auto *VD = dyn_cast(Global); + if (VD && + ((CodeGenOpts.KeepPersistentStorageVariables && + (VD->getStorageDuration() == SD_Static || + VD->getStorageDuration() == SD_Thread)) || + (CodeGenOpts.KeepStaticConsts && VD->getStorageDuration() == SD_Static && + VD->getType().isConstQualified()))) + return true; return getContext().DeclMustBeEmitted(Global); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7294,6 +7294,8 @@ Args.addOptInFlag(CmdArgs, options::OPT_fkeep_static_consts, options::OPT_fno_keep_static_consts); + Args.addOptInFlag(CmdArgs, options::OPT_fkeep_persistent_storage_variables, + options::OPT_fno_keep_persistent_storage_variables); Args.addOptInFlag(CmdArgs, options::OPT_fcomplete_member_pointers, options::OPT_fno_complete_member_pointers); Args.addOptOutFlag(CmdArgs, options::OPT_fcxx_static_destructors, diff --git a/clang/test/CodeGen/keep-persistent-storage-variables.cpp b/clang/test/CodeGen/keep-persistent-storage-variables.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/keep-persistent-storage-variables.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fkeep-persistent-storage-variables -emit-llvm %s -o - -triple=x86_64-unknown-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -fkeep-persistent-storage-variables -emit-llvm %s -o - -triple=powerpc64-ibm-aix-xcoff | FileCheck %s + +// CHECK: @_ZL2g1 = internal global i32 0, align 4 +// CHECK: @_ZL2g2 = internal global i32 1, align 4 +// CHECK: @tl1 = thread_local global i32 0, align 4 +// CHECK: @tl2 = thread_local global i32 3, align 4 +// CHECK: @_ZL3tl3 = internal thread_local global i32 0, align 4 +// CHECK: @_ZL3tl4 = internal thread_local global i32 4, align 4 +// CHECK: @g5 = global i32 0, align 4 +// CHECK: @g6 = global i32 6, align 4 +// CHECK: @_ZZ5test3vE2s3 = internal global i32 0, align 4 +// CHECK: @_ZN12_GLOBAL__N_12s4E = internal global i32 42, align 4 +// CHECK: @_ZZ5test5vE3tl5 = internal thread_local global i32 1, align 4 +// CHECK: @_ZN2ST2s6E = global i32 7, align 4 +// CHECK: @llvm{{(\.compiler)?}}.used = appending global [12 x ptr] [ptr @_ZL2g1, ptr @_ZL2g2, ptr @tl1, ptr @tl2, ptr @_ZL3tl3, ptr @_ZL3tl4, ptr @g5, ptr @g6, ptr @_ZZ5test3vE2s3, ptr @_ZN12_GLOBAL__N_12s4E, ptr @_ZZ5test5vE3tl5, ptr @_ZN2ST2s6E], section "llvm.metadata" + +static int g1; +static int g2 = 1; +__thread int tl1; +__thread int tl2 = 3; +static __thread int tl3; +static __thread int tl4 = 4; +int g5; +int g6 = 6; + +int test3() { + static int s3 = 0; + ++s3; + return s3; +} + +namespace { + int s4 = 42; +} + +int test5() { + static __thread int tl5 = 1; + ++tl5; + return tl5; +} + +struct ST { + static int s6; +}; +int ST::s6 = 7; diff --git a/clang/test/Driver/fkeep-persistent-storage-variables.c b/clang/test/Driver/fkeep-persistent-storage-variables.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/fkeep-persistent-storage-variables.c @@ -0,0 +1,5 @@ +// RUN: %clang -fkeep-persistent-storage-variables -c %s -### 2>&1 | FileCheck %s +// RUN: %clang -fkeep-persistent-storage-variables -fno-keep-persistent-storage-variables -c %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-NOKEEP + +// CHECK: "-fkeep-persistent-storage-variables" +// CHECK-NOKEEP-NOT: "-fkeep-persistent-storage-variables"