diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -306,6 +306,9 @@ } bool isValidTuneCPUName(StringRef Name) const override { + if (Name == "generic") + return true; + // Allow 32-bit only CPUs regardless of 64-bit mode unlike isValidCPUName. // NOTE: gcc rejects 32-bit mtune CPUs in 64-bit mode. But being lenient // since mtune was ignored by clang for so long. 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 @@ -2074,20 +2074,27 @@ } // Handle -mtune. - // FIXME: We should default to "generic" unless -march is set to match gcc. + + // Default to "generic" unless -march is present. + std::string TuneCPU; + if (!Args.hasArg(clang::driver::options::OPT_march_EQ)) + TuneCPU = "generic"; + + // Override based on -mtune. if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) { StringRef Name = A->getValue(); - if (Name == "native") + if (Name == "native") { Name = llvm::sys::getHostCPUName(); + if (!Name.empty()) + TuneCPU = std::string(Name); + } else + TuneCPU = std::string(Name); + } - // Ignore generic either from getHostCPUName or from command line. - // FIXME: We need to support this eventually but isValidCPUName and the - // backend aren't ready for it yet. - if (Name != "generic") { - CmdArgs.push_back("-tune-cpu"); - CmdArgs.push_back(Args.MakeArgString(Name)); - } + if (!TuneCPU.empty()) { + CmdArgs.push_back("-tune-cpu"); + CmdArgs.push_back(Args.MakeArgString(TuneCPU)); } } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3877,7 +3877,7 @@ // Extend the signature with the target options. code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU, - TargetOpts->ABI); + TargetOpts->TuneCPU, TargetOpts->ABI); for (const auto &FeatureAsWritten : TargetOpts->FeaturesAsWritten) code = hash_combine(code, FeatureAsWritten); diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -561,6 +561,7 @@ Out.indent(2) << "Target options:\n"; Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n"; Out.indent(4) << " CPU: " << TargetOpts.CPU << "\n"; + Out.indent(4) << " TuneCPU: " << TargetOpts.TuneCPU << "\n"; Out.indent(4) << " ABI: " << TargetOpts.ABI << "\n"; if (!TargetOpts.FeaturesAsWritten.empty()) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -390,8 +390,10 @@ // We can tolerate different CPUs in many cases, notably when one CPU // supports a strict superset of another. When allowing compatible // differences skip this check. - if (!AllowCompatibleDifferences) + if (!AllowCompatibleDifferences) { CHECK_TARGET_OPT(CPU, "target CPU"); + CHECK_TARGET_OPT(TuneCPU, "tune CPU"); + } #undef CHECK_TARGET_OPT @@ -5779,6 +5781,7 @@ TargetOptions TargetOpts; TargetOpts.Triple = ReadString(Record, Idx); TargetOpts.CPU = ReadString(Record, Idx); + TargetOpts.TuneCPU = ReadString(Record, Idx); TargetOpts.ABI = ReadString(Record, Idx); for (unsigned N = Record[Idx++]; N; --N) { TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx)); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1272,6 +1272,7 @@ const TargetOptions &TargetOpts = Target.getTargetOpts(); AddString(TargetOpts.Triple, Record); AddString(TargetOpts.CPU, Record); + AddString(TargetOpts.TuneCPU, Record); AddString(TargetOpts.ABI, Record); Record.push_back(TargetOpts.FeaturesAsWritten.size()); for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) { diff --git a/clang/test/Driver/x86-mtune.c b/clang/test/Driver/x86-mtune.c --- a/clang/test/Driver/x86-mtune.c +++ b/clang/test/Driver/x86-mtune.c @@ -1,5 +1,14 @@ // Ensure we support the -mtune flag. -// + +// Default mtune should be generic. +// RUN: %clang -target x86_64-unknown-unknown -c -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=notune +// notune: "-tune-cpu" "generic" + +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -mtune=generic 2>&1 \ +// RUN: | FileCheck %s -check-prefix=generic +// generic: "-tune-cpu" "generic" + // RUN: %clang -target x86_64-unknown-unknown -c -### %s -mtune=nocona 2>&1 \ // RUN: | FileCheck %s -check-prefix=nocona // nocona: "-tune-cpu" "nocona" @@ -18,3 +27,16 @@ // RUN: | FileCheck %s -check-prefix=athlon // athlon: "-tune-cpu" "athlon" +// Check interaction between march and mtune. + +// -march should remove default mtune generic. +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=core2 2>&1 \ +// RUN: | FileCheck %s -check-prefix=marchcore2 +// marchcore2: "-target-cpu" "core2" +// marchcore2-NOT: "-tune-cpu" + +// -march should remove default mtune generic. +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=core2 -mtune=nehalem 2>&1 \ +// RUN: | FileCheck %s -check-prefix=marchmtune +// marchmtune: "-target-cpu" "core2" +// mmarchmtune: "-tune-cpu" "nehalem" diff --git a/clang/test/Modules/module_file_info.m b/clang/test/Modules/module_file_info.m --- a/clang/test/Modules/module_file_info.m +++ b/clang/test/Modules/module_file_info.m @@ -28,6 +28,7 @@ // CHECK: Target options: // CHECK: Triple: // CHECK: CPU: +// CHECK: TuneCPU: // CHECK: ABI: // CHECK: Header search options: