Index: clang/include/clang/Driver/ToolChain.h =================================================================== --- clang/include/clang/Driver/ToolChain.h +++ clang/include/clang/Driver/ToolChain.h @@ -122,6 +122,11 @@ enum FileType { FT_Object, FT_Static, FT_Shared }; + enum LTOPluginType { + LTOPT_LLVMgold, // LTO plugin used by toolchains that use the GNU linker. + LTOPT_LLVMldlld // LTO plugin used by toolchains that use the ld.lld. + }; + private: friend class RegisterEffectiveTriple; @@ -175,6 +180,10 @@ EffectiveTriple = std::move(ET); } + // Used by ToolChains to override the default (gold plugin) if they use a + // specialized LTO plugin interface. + virtual LTOPluginType getLTOPluginTypeImpl() const; + mutable llvm::Optional cxxStdlibType; mutable llvm::Optional runtimeLibType; mutable llvm::Optional unwindLibType; @@ -352,6 +361,14 @@ /// LLD's supported flags, error output, etc. std::string GetLinkerPath(bool *LinkerIsLLD = nullptr) const; + /// Returns the plugin type used by the toolchain linker to interface with + /// LTO. + LTOPluginType getLTOPluginType() const; + + /// Returns the LTO plugin prefix or an empty string if the toolchain doesn't + /// require a linker plugin to interface with LTO. + StringRef getLTOPluginPrefix() const; + /// Returns the linker path for emitting a static library. std::string GetStaticLibToolPath() const; Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -638,6 +638,30 @@ return GetProgramPath(getDefaultLinker()); } +ToolChain::LTOPluginType ToolChain::getLTOPluginType() const { + std::string Linker = GetLinkerPath(); + + // The LLVM linker doesn't require an LTO plugin. + if (llvm::sys::path::filename(Linker) == "ld.lld" || + llvm::sys::path::stem(Linker) == "ld.lld") + return LTOPluginType::LTOPT_LLVMldlld; + + return getLTOPluginTypeImpl(); +} + +ToolChain::LTOPluginType ToolChain::getLTOPluginTypeImpl() const { + return LTOPluginType::LTOPT_LLVMgold; +} + +StringRef ToolChain::getLTOPluginPrefix() const { + switch (getLTOPluginType()) { + case LTOPluginType::LTOPT_LLVMgold: + case LTOPluginType::LTOPT_LLVMldlld: + return "-plugin-opt="; + } + llvm_unreachable("Unexpected LTO plugin type"); +} + std::string ToolChain::GetStaticLibToolPath() const { // TODO: Add support for static lib archiving on Windows if (Triple.isOSDarwin()) Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -2204,8 +2204,9 @@ void Clang::AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { - const Driver &D = getToolChain().getDriver(); - addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/false); + const ToolChain &T = getToolChain(); + const Driver &D = T.getDriver(); + addX86AlignBranchArgs(T, Args, CmdArgs, /*IsLTO=*/false); if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || Args.hasArg(options::OPT_mkernel) || @@ -7053,7 +7054,7 @@ options::OPT_fno_cxx_static_destructors, true)) CmdArgs.push_back("-fno-c++-static-destructors"); - addMachineOutlinerArgs(D, Args, CmdArgs, Triple, /*IsLTO=*/false); + addMachineOutlinerArgs(D, Args, CmdArgs, Triple, /*IsLTO=*/false, ""); if (Arg *A = Args.getLastArg(options::OPT_moutline_atomics, options::OPT_mno_outline_atomics)) { @@ -7640,7 +7641,7 @@ void ClangAs::AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { - addX86AlignBranchArgs(getToolChain().getDriver(), Args, CmdArgs, + addX86AlignBranchArgs(getToolChain(), Args, CmdArgs, /*IsLTO=*/false); if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) { Index: clang/lib/Driver/ToolChains/CommonArgs.h =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.h +++ clang/lib/Driver/ToolChains/CommonArgs.h @@ -171,7 +171,7 @@ void addMultilibFlag(bool Enabled, const char *const Flag, Multilib::flags_list &Flags); -void addX86AlignBranchArgs(const Driver &D, const llvm::opt::ArgList &Args, +void addX86AlignBranchArgs(const ToolChain &T, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, bool IsLTO); void checkAMDGPUCodeObjectVersion(const Driver &D, @@ -185,7 +185,8 @@ void addMachineOutlinerArgs(const Driver &D, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, - const llvm::Triple &Triple, bool IsLTO); + const llvm::Triple &Triple, bool IsLTO, + StringRef PluginOptPrefix); void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -63,21 +63,31 @@ using namespace clang; using namespace llvm::opt; -static void renderRpassOptions(const ArgList &Args, ArgStringList &CmdArgs) { +static void MakePluginOpt(const ToolChain &ToolChain, const ArgList &Args, + ArgStringList &CmdArgs, const llvm::Twine &opt, + bool Seperator = false) { + CmdArgs.push_back(Args.MakeArgString(Twine(ToolChain.getLTOPluginPrefix()) + + (Seperator ? Twine("-") : Twine("")) + + opt)); +} + +static void renderRpassOptions(const ToolChain &ToolChain, const ArgList &Args, + ArgStringList &CmdArgs) { if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ)) - CmdArgs.push_back(Args.MakeArgString(Twine("--plugin-opt=-pass-remarks=") + - A->getValue())); + MakePluginOpt(ToolChain, Args, CmdArgs, + Twine("pass-remarks=") + A->getValue(), true); if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ)) - CmdArgs.push_back(Args.MakeArgString( - Twine("--plugin-opt=-pass-remarks-missed=") + A->getValue())); + MakePluginOpt(ToolChain, Args, CmdArgs, + Twine("pass-remarks-missed=") + A->getValue(), true); if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ)) - CmdArgs.push_back(Args.MakeArgString( - Twine("--plugin-opt=-pass-remarks-analysis=") + A->getValue())); + MakePluginOpt(ToolChain, Args, CmdArgs, + Twine("pass-remarks-analysis=") + A->getValue(), true); } -static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs, +static void renderRemarksOptions(const ToolChain &ToolChain, + const ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple, const InputInfo &Input, const InputInfo &Output) { @@ -94,29 +104,29 @@ assert(!F.empty() && "Cannot determine remarks output name."); // Append "opt.ld." to the end of the file name. - CmdArgs.push_back( - Args.MakeArgString(Twine("--plugin-opt=opt-remarks-filename=") + F + - Twine(".opt.ld.") + Format)); + MakePluginOpt(ToolChain, Args, CmdArgs, + "opt-remarks-filename=" + F + Twine(".opt.ld.") + Format); if (const Arg *A = Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) - CmdArgs.push_back(Args.MakeArgString( - Twine("--plugin-opt=opt-remarks-passes=") + A->getValue())); + MakePluginOpt(ToolChain, Args, CmdArgs, + Twine("opt-remarks-passes=") + A->getValue()); - CmdArgs.push_back(Args.MakeArgString( - Twine("--plugin-opt=opt-remarks-format=") + Format.data())); + MakePluginOpt(ToolChain, Args, CmdArgs, + Twine("opt-remarks-format=") + Format.data()); } -static void renderRemarksHotnessOptions(const ArgList &Args, +static void renderRemarksHotnessOptions(const ToolChain &ToolChain, + const ArgList &Args, ArgStringList &CmdArgs) { if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness, options::OPT_fno_diagnostics_show_hotness, false)) - CmdArgs.push_back("--plugin-opt=opt-remarks-with-hotness"); + MakePluginOpt(ToolChain, Args, CmdArgs, "opt-remarks-with-hotness"); if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) - CmdArgs.push_back(Args.MakeArgString( - Twine("--plugin-opt=opt-remarks-hotness-threshold=") + A->getValue())); + MakePluginOpt(ToolChain, Args, CmdArgs, + Twine("opt-remarks-hotness-threshold=") + A->getValue()); } void tools::addPathIfExists(const Driver &D, const Twine &Path, @@ -483,10 +493,9 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, ArgStringList &CmdArgs, const InputInfo &Output, const InputInfo &Input, bool IsThinLTO) { - const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); + const ToolChain::LTOPluginType LTOPluginType = ToolChain.getLTOPluginType(); const Driver &D = ToolChain.getDriver(); - if (llvm::sys::path::filename(Linker) != "ld.lld" && - llvm::sys::path::stem(Linker) != "ld.lld") { + if (LTOPluginType != ToolChain::LTOPluginType::LTOPT_LLVMldlld) { // Tell the linker to load the plugin. This has to come before // AddLinkerInputs as gold requires -plugin to come before any -plugin-opt // that -Wl might forward. @@ -513,7 +522,7 @@ // Handle flags for selecting CPU variants. std::string CPU = getCPUName(D, Args, ToolChain.getTriple()); if (!CPU.empty()) - CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU)); + MakePluginOpt(ToolChain, Args, CmdArgs, Twine("mcpu=") + CPU); if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { // The optimization level matches @@ -531,34 +540,32 @@ } else if (A->getOption().matches(options::OPT_O0)) OOpt = "0"; if (!OOpt.empty()) - CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=O") + OOpt)); + MakePluginOpt(ToolChain, Args, CmdArgs, Twine("O") + OOpt); } if (Args.hasArg(options::OPT_gsplit_dwarf)) { - CmdArgs.push_back( - Args.MakeArgString(Twine("-plugin-opt=dwo_dir=") + - Output.getFilename() + "_dwo")); + MakePluginOpt(ToolChain, Args, CmdArgs, + Twine("dwo_dir=") + Output.getFilename() + "_dwo"); } if (IsThinLTO) - CmdArgs.push_back("-plugin-opt=thinlto"); + MakePluginOpt(ToolChain, Args, CmdArgs, "thinlto"); StringRef Parallelism = getLTOParallelism(Args, D); if (!Parallelism.empty()) - CmdArgs.push_back( - Args.MakeArgString("-plugin-opt=jobs=" + Twine(Parallelism))); + MakePluginOpt(ToolChain, Args, CmdArgs, "jobs=" + Twine(Parallelism)); // If an explicit debugger tuning argument appeared, pass it along. if (Arg *A = Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) { if (A->getOption().matches(options::OPT_glldb)) - CmdArgs.push_back("-plugin-opt=-debugger-tune=lldb"); + MakePluginOpt(ToolChain, Args, CmdArgs, "debugger-tune=lldb", true); else if (A->getOption().matches(options::OPT_gsce)) - CmdArgs.push_back("-plugin-opt=-debugger-tune=sce"); + MakePluginOpt(ToolChain, Args, CmdArgs, "debugger-tune=sce", true); else if (A->getOption().matches(options::OPT_gdbx)) - CmdArgs.push_back("-plugin-opt=-debugger-tune=dbx"); + MakePluginOpt(ToolChain, Args, CmdArgs, "debugger-tune=dbx", true); else - CmdArgs.push_back("-plugin-opt=-debugger-tune=gdb"); + MakePluginOpt(ToolChain, Args, CmdArgs, "debugger-tune=gdb", true); } bool UseSeparateSections = @@ -566,12 +573,12 @@ if (Args.hasFlag(options::OPT_ffunction_sections, options::OPT_fno_function_sections, UseSeparateSections)) { - CmdArgs.push_back("-plugin-opt=-function-sections"); + MakePluginOpt(ToolChain, Args, CmdArgs, "function-sections", true); } if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections, UseSeparateSections)) { - CmdArgs.push_back("-plugin-opt=-data-sections"); + MakePluginOpt(ToolChain, Args, CmdArgs, "data-sections", true); } if (Arg *A = getLastProfileSampleUseArg(Args)) { @@ -579,8 +586,7 @@ if (!llvm::sys::fs::exists(FName)) D.Diag(diag::err_drv_no_such_file) << FName; else - CmdArgs.push_back( - Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName)); + MakePluginOpt(ToolChain, Args, CmdArgs, Twine("sample-profile=") + FName); } auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate, @@ -593,56 +599,54 @@ auto *ProfileUseArg = getLastProfileUseArg(Args); if (CSPGOGenerateArg) { - CmdArgs.push_back(Args.MakeArgString("-plugin-opt=cs-profile-generate")); + MakePluginOpt(ToolChain, Args, CmdArgs, "cs-profile-generate"); if (CSPGOGenerateArg->getOption().matches( options::OPT_fcs_profile_generate_EQ)) { SmallString<128> Path(CSPGOGenerateArg->getValue()); llvm::sys::path::append(Path, "default_%m.profraw"); - CmdArgs.push_back( - Args.MakeArgString(Twine("-plugin-opt=cs-profile-path=") + Path)); + MakePluginOpt(ToolChain, Args, CmdArgs, Twine("cs-profile-path=") + Path); } else - CmdArgs.push_back( - Args.MakeArgString("-plugin-opt=cs-profile-path=default_%m.profraw")); + MakePluginOpt(ToolChain, Args, CmdArgs, + "cs-profile-path=default_%m.profraw"); } else if (ProfileUseArg) { SmallString<128> Path( ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue()); if (Path.empty() || llvm::sys::fs::is_directory(Path)) llvm::sys::path::append(Path, "default.profdata"); - CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=cs-profile-path=") + - Path)); + MakePluginOpt(ToolChain, Args, CmdArgs, + Twine("-plugin-opt=cs-profile-path=") + Path); } // Pass an option to enable/disable the new pass manager. if (auto *A = Args.getLastArg(options::OPT_flegacy_pass_manager, options::OPT_fno_legacy_pass_manager)) { if (A->getOption().matches(options::OPT_flegacy_pass_manager)) - CmdArgs.push_back("-plugin-opt=legacy-pass-manager"); + MakePluginOpt(ToolChain, Args, CmdArgs, "legacy-pass-manager"); else - CmdArgs.push_back("-plugin-opt=new-pass-manager"); + MakePluginOpt(ToolChain, Args, CmdArgs, "new-pass-manager"); } // Setup statistics file output. SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D); if (!StatsFile.empty()) - CmdArgs.push_back( - Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile)); + MakePluginOpt(ToolChain, Args, CmdArgs, Twine("stats-file=") + StatsFile); - addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/true); + addX86AlignBranchArgs(ToolChain, Args, CmdArgs, /*IsLTO=*/true); // Handle remark diagnostics on screen options: '-Rpass-*'. - renderRpassOptions(Args, CmdArgs); + renderRpassOptions(ToolChain, Args, CmdArgs); // Handle serialized remarks options: '-fsave-optimization-record' // and '-foptimization-record-*'. if (willEmitRemarks(Args)) - renderRemarksOptions(Args, CmdArgs, ToolChain.getEffectiveTriple(), Input, - Output); + renderRemarksOptions(ToolChain, Args, CmdArgs, + ToolChain.getEffectiveTriple(), Input, Output); // Handle remarks hotness/threshold related options. - renderRemarksHotnessOptions(Args, CmdArgs); + renderRemarksHotnessOptions(ToolChain, Args, CmdArgs); addMachineOutlinerArgs(D, Args, CmdArgs, ToolChain.getEffectiveTriple(), - /*IsLTO=*/true); + /*IsLTO=*/true, ToolChain.getLTOPluginPrefix()); } void tools::addOpenMPRuntimeSpecificRPath(const ToolChain &TC, @@ -1562,11 +1566,13 @@ Flags.push_back(std::string(Enabled ? "+" : "-") + Flag); } -void tools::addX86AlignBranchArgs(const Driver &D, const ArgList &Args, +void tools::addX86AlignBranchArgs(const ToolChain &T, const ArgList &Args, ArgStringList &CmdArgs, bool IsLTO) { + const Driver &D = T.getDriver(); + StringRef PluginOptPrefix = T.getLTOPluginPrefix(); auto addArg = [&, IsLTO](const Twine &Arg) { if (IsLTO) { - CmdArgs.push_back(Args.MakeArgString("-plugin-opt=" + Arg)); + CmdArgs.push_back(Args.MakeArgString(PluginOptPrefix + Arg)); } else { CmdArgs.push_back("-mllvm"); CmdArgs.push_back(Args.MakeArgString(Arg)); @@ -1959,10 +1965,11 @@ void tools::addMachineOutlinerArgs(const Driver &D, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, - const llvm::Triple &Triple, bool IsLTO) { + const llvm::Triple &Triple, bool IsLTO, + StringRef PluginOptPrefix) { auto addArg = [&, IsLTO](const Twine &Arg) { if (IsLTO) { - CmdArgs.push_back(Args.MakeArgString("-plugin-opt=" + Arg)); + CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + Arg)); } else { CmdArgs.push_back("-mllvm"); CmdArgs.push_back(Args.MakeArgString(Arg)); Index: clang/test/Driver/opt-record.c =================================================================== --- clang/test/Driver/opt-record.c +++ clang/test/Driver/opt-record.c @@ -53,28 +53,28 @@ // RUN: %clang -target x86_64-linux -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=100 -Rpass=inline -Rpass-missed=inline -Rpass-analysis=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-PASS-RPASS // RUN: %clang -target x86_64-linux -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=auto -Rpass=inline -Rpass-missed=inline -Rpass-analysis=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-PASS-AUTO -// CHECK-NOPASS-NOT: "--plugin-opt=opt-remarks-filename=" -// CHECK-NOPASS-NOT: "--plugin-opt=opt-remarks-passes=inline" -// CHECK-NOPASS-NOT: "--plugin-opt=opt-remarks-format=yaml" -// CHECK-NOPASS-NOT: "--plugin-opt=opt-remarks-hotness-threshold=100" - -// CHECK-PASS-A: "--plugin-opt=opt-remarks-filename=a.out.opt.ld.yaml" -// CHECK-PASS-A-SAME: "--plugin-opt=opt-remarks-passes=inline" -// CHECK-PASS-A-SAME: "--plugin-opt=opt-remarks-format=yaml" -// CHECK-PASS-A-SAME: "--plugin-opt=opt-remarks-hotness-threshold=100" - -// CHECK-PASS: "--plugin-opt=opt-remarks-filename=FOO.opt.ld.yaml" -// CHECK-PASS-SAME: "--plugin-opt=opt-remarks-passes=inline" -// CHECK-PASS-SAME: "--plugin-opt=opt-remarks-format=yaml" -// CHECK-PASS-SAME: "--plugin-opt=opt-remarks-hotness-threshold=100" - -// CHECK-PASS-CUSTOM: "--plugin-opt=opt-remarks-filename=FOO.txt.opt.ld.some-format" -// CHECK-PASS-CUSTOM-SAME: "--plugin-opt=opt-remarks-format=some-format" -// CHECK-PASS-CUSTOM-SAME: "--plugin-opt=opt-remarks-hotness-threshold=100" - -// CHECK-PASS-RPASS: "--plugin-opt=-pass-remarks=inline" -// CHECK-PASS-RPASS-SAME: "--plugin-opt=-pass-remarks-missed=inline" -// CHECK-PASS-RPASS-SAME: "--plugin-opt=-pass-remarks-analysis=inline" -// CHECK-PASS-RPASS-SAME: "--plugin-opt=opt-remarks-hotness-threshold=100" - -// CHECK-PASS-AUTO: "--plugin-opt=opt-remarks-hotness-threshold=auto" +// CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-filename=" +// CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-passes=inline" +// CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-format=yaml" +// CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-hotness-threshold=100" + +// CHECK-PASS-A: "-plugin-opt=opt-remarks-filename=a.out.opt.ld.yaml" +// CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-passes=inline" +// CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-format=yaml" +// CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" + +// CHECK-PASS: "-plugin-opt=opt-remarks-filename=FOO.opt.ld.yaml" +// CHECK-PASS-SAME: "-plugin-opt=opt-remarks-passes=inline" +// CHECK-PASS-SAME: "-plugin-opt=opt-remarks-format=yaml" +// CHECK-PASS-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" + +// CHECK-PASS-CUSTOM: "-plugin-opt=opt-remarks-filename=FOO.txt.opt.ld.some-format" +// CHECK-PASS-CUSTOM-SAME: "-plugin-opt=opt-remarks-format=some-format" +// CHECK-PASS-CUSTOM-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" + +// CHECK-PASS-RPASS: "-plugin-opt=-pass-remarks=inline" +// CHECK-PASS-RPASS-SAME: "-plugin-opt=-pass-remarks-missed=inline" +// CHECK-PASS-RPASS-SAME: "-plugin-opt=-pass-remarks-analysis=inline" +// CHECK-PASS-RPASS-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" + +// CHECK-PASS-AUTO: "-plugin-opt=opt-remarks-hotness-threshold=auto" Index: clang/test/Driver/print-supported-cpus.c =================================================================== --- clang/test/Driver/print-supported-cpus.c +++ clang/test/Driver/print-supported-cpus.c @@ -10,10 +10,9 @@ // RUN: %clang --target=x86_64-unknown-linux-gnu -mcpu=? 2>&1 | \ // RUN: FileCheck %s --check-prefix=CHECK-X86 -// RUN: %clang --target=x86_64-unknown-linux-gnu -mtune=? -fuse-ld=dummy 2>&1 | \ +// RUN: %clang --target=x86_64-unknown-linux-gnu -mtune=? 2>&1 | \ // RUN: FileCheck %s --check-prefix=CHECK-X86 -// CHECK-NOT: warning: argument unused during compilation // CHECK-X86: Target: x86_64-unknown-linux-gnu // CHECK-X86: corei7 // CHECK-X86: Use -mcpu or -mtune to specify the target's processor.