Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1135,7 +1135,7 @@ def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group; def mfpu_EQ : Joined<["-"], "mfpu=">, Group; def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group; -def mglobal_merge : Flag<["-"], "mglobal-merge">, Group; +def mglobal_merge : Flag<["-"], "mglobal-merge">, Group, Flags<[CC1Option]>; def mhard_float : Flag<["-"], "mhard-float">, Group; def miphoneos_version_min_EQ : Joined<["-"], "miphoneos-version-min=">, Group; def mios_version_min_EQ : Joined<["-"], "mios-version-min=">, Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -433,8 +433,6 @@ BackendArgs.push_back("-time-passes"); for (unsigned i = 0, e = CodeGenOpts.BackendOptions.size(); i != e; ++i) BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str()); - if (CodeGenOpts.NoGlobalMerge) - BackendArgs.push_back("-enable-global-merge=false"); BackendArgs.push_back(nullptr); llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, BackendArgs.data()); Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1199,6 +1199,10 @@ /// Emits target specific Metadata for global declarations. void EmitTargetMetadata(); + /// Emit the module flag metadata used to pass options controlling the + /// the backend to LLVM. + void EmitBackendOptionsMetadata(); + /// Emit the llvm.gcov metadata used to tell LLVM where to emit the .gcno and /// .gcda files in a way that persists in .bc files. void EmitCoverageFile(); Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -418,6 +418,8 @@ EmitVersionIdentMetadata(); EmitTargetMetadata(); + + EmitBackendOptionsMetadata(); } void CodeGenModule::UpdateCompletedType(const TagDecl *TD) { @@ -3609,6 +3611,19 @@ } } +void CodeGenModule::EmitBackendOptionsMetadata() { + // Only emit the "Global Merge" flag on targets that support it (ARM/AArch64). + llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch(); + if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb || + Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb || + Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) { + if (getCodeGenOpts().NoGlobalMerge) + getModule().addModuleFlag(llvm::Module::Override, "Global Merge", 0u); + else + getModule().addModuleFlag(llvm::Module::Error, "Global Merge", 1u); + } +} + void CodeGenModule::EmitCoverageFile() { if (!getCodeGenOpts().CoverageFile.empty()) { if (llvm::NamedMDNode *CUNode = TheModule.getNamedMetadata("llvm.dbg.cu")) { Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -861,12 +861,14 @@ } } - // Setting -mno-global-merge disables the codegen global merge pass. Setting - // -mglobal-merge has no effect as the pass is enabled by default. + // Forward the -mglobal-merge option, for explicit control over the + // global-merge pass. if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, options::OPT_mno_global_merge)) { if (A->getOption().matches(options::OPT_mno_global_merge)) CmdArgs.push_back("-mno-global-merge"); + else + CmdArgs.push_back("-mglobal-merge"); } if (!Args.hasFlag(options::OPT_mimplicit_float, @@ -957,12 +959,14 @@ CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1"); } - // Setting -mno-global-merge disables the codegen global merge pass. Setting - // -mglobal-merge has no effect as the pass is enabled by default. + // Forward the -mglobal-merge option, for explicit control over the + // global-merge pass. if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, options::OPT_mno_global_merge)) { if (A->getOption().matches(options::OPT_mno_global_merge)) CmdArgs.push_back("-mno-global-merge"); + else + CmdArgs.push_back("-mglobal-merge"); } if (Args.hasArg(options::OPT_ffixed_x18)) { Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -309,6 +309,17 @@ return "default"; } +static bool shouldEnableGlobalMergeForTarget(const llvm::Triple &T, + const unsigned OptLevel) { + llvm::Triple::ArchType Arch = T.getArch(); + // FIXME: ARM should probably also require -O3. + return (OptLevel > 0 && + (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb || + Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb)) || + (OptLevel > 2 && + (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be)); +} + /// \brief Create a new Regex instance out of the string value in \p RpassArg. /// It returns a pointer to the newly generated Regex instance. static std::shared_ptr @@ -445,7 +456,12 @@ Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option); Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags); - Opts.NoGlobalMerge = Args.hasArg(OPT_mno_global_merge); + + Opts.NoGlobalMerge = !Args.hasFlag( + OPT_mglobal_merge, OPT_mno_global_merge, + shouldEnableGlobalMergeForTarget(llvm::Triple(TargetOpts.Triple), + Opts.OptimizationLevel)); + Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings); Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks); Index: test/CodeGen/global-merge.c =================================================================== --- /dev/null +++ test/CodeGen/global-merge.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-- -mglobal-merge %s -o - | FileCheck %s -check-prefix=CHECK-NONE +// RUN: %clang_cc1 -emit-llvm -triple x86_64-- -mno-global-merge %s -o - | FileCheck %s -check-prefix=CHECK-NONE +// RUN: %clang_cc1 -emit-llvm -triple x86_64-- -O3 %s -o - | FileCheck %s -check-prefix=CHECK-NONE + +// RUN: %clang_cc1 -emit-llvm -triple arm64-- -O0 %s -o - | FileCheck %s -check-prefix=CHECK-NGM +// RUN: %clang_cc1 -emit-llvm -triple arm64-- -O1 %s -o - | FileCheck %s -check-prefix=CHECK-NGM +// RUN: %clang_cc1 -emit-llvm -triple arm64-- -O3 %s -o - | FileCheck %s -check-prefix=CHECK-GM +// RUN: %clang_cc1 -emit-llvm -triple arm64-- -O0 -mglobal-merge %s -o - | FileCheck %s -check-prefix=CHECK-GM +// RUN: %clang_cc1 -emit-llvm -triple arm64-- -O3 -mno-global-merge %s -o - | FileCheck %s -check-prefix=CHECK-NGM + +// RUN: %clang_cc1 -emit-llvm -triple arm-- -O0 %s -o - | FileCheck %s -check-prefix=CHECK-NGM +// RUN: %clang_cc1 -emit-llvm -triple arm-- -O1 %s -o - | FileCheck %s -check-prefix=CHECK-GM +// RUN: %clang_cc1 -emit-llvm -triple arm-- -O3 %s -o - | FileCheck %s -check-prefix=CHECK-GM +// RUN: %clang_cc1 -emit-llvm -triple arm-- -O0 -mglobal-merge %s -o - | FileCheck %s -check-prefix=CHECK-GM +// RUN: %clang_cc1 -emit-llvm -triple arm-- -O3 -mno-global-merge %s -o - | FileCheck %s -check-prefix=CHECK-NGM + +// CHECK-NONE-NOT: Global Merge + +// CHECK-GM: !llvm.module.flags = !{{{.*}}} +// CHECK-GM: !{{[0-9]+}} = !{i32 1, !"Global Merge", i32 1} + +// CHECK-NGM: !llvm.module.flags = !{{{.*}}} +// CHECK-NGM: !{{[0-9]+}} = !{i32 4, !"Global Merge", i32 0} Index: test/Driver/mglobal-merge.c =================================================================== --- test/Driver/mglobal-merge.c +++ test/Driver/mglobal-merge.c @@ -16,5 +16,16 @@ // RUN: -mglobal-merge -### -fsyntax-only %s 2> %t // RUN: FileCheck --check-prefix=CHECK-GM < %t %s -// CHECK-GM-NOT: "-mglobal-merge" +// CHECK-GM: "-mglobal-merge" + +// RUN: %clang -target x86_64-apple-darwin10 \ +// RUN: -mno-global-merge -### -fsyntax-only %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-NONE < %t %s + +// RUN: %clang -target x86_64-apple-darwin10 \ +// RUN: -mglobal-merge -### -fsyntax-only %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-NONE < %t %s + +// CHECK-NONE-NOT: "-mglobal-merge" +// CHECK-NONE-NOT: "-mno-global-merge"