diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 715e0c0dc8fa84..4adc433ac11b9f 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -278,6 +278,9 @@ def err_builtin_needs_feature : Error<"%0 needs target feature %1">; def err_function_needs_feature : Error< "always_inline function %1 requires target feature '%2', but would " "be inlined into function %0 that is compiled without support for '%2'">; +def warn_tune_cpu_feature_unavailable : Warning< + "instructions of current target may not be supported by tune CPU '%0'">, + InGroup; def warn_avx_calling_convention : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' " diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 9d56e97a3d4bb8..b941b2201b84e1 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -976,6 +976,12 @@ class TargetInfo : public TransferrableTargetInfo, /// with this target. virtual BuiltinVaListKind getBuiltinVaListKind() const = 0; + /// Return whether a feature matters for tune CPU. If true, present in + /// current target but missing in tune CPU triggers a warning. + virtual bool isFeatureConsumedByTuneCPU(StringRef Feature) const { + return false; + } + /// Returns whether or not type \c __builtin_ms_va_list type is /// available on this target. bool hasBuiltinMSVaList() const { return HasBuiltinMSVaList; } diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 8130f90a276749..d73535f53af3bf 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -833,6 +833,22 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, if (!Target->handleTargetFeatures(Opts->Features, Diags)) return nullptr; + // If TuneCPU is set, check if it contains all instruction sets needed by + // current feature map. + if (!Opts->TuneCPU.empty() && Opts->TuneCPU != Opts->CPU) { + llvm::StringMap TuneFeatureMap; + Target->initFeatureMap(TuneFeatureMap, Diags, Opts->TuneCPU, {}); + if (std::any_of(Opts->FeatureMap.begin(), Opts->FeatureMap.end(), + [&](const llvm::StringMapEntry &F) { + return F.getValue() && + Target->isFeatureConsumedByTuneCPU(F.getKey()) && + (!TuneFeatureMap.contains(F.getKey()) || + !TuneFeatureMap[F.getKey()]); + })) { + Diags.Report(diag::warn_tune_cpu_feature_unavailable) << Opts->TuneCPU; + } + } + Target->setSupportedOpenCLOpts(); Target->setCommandLineOpenCLOpts(); Target->setMaxAtomicWidth(); diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index 4d62673ba7fb8c..3f95708f695b09 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -187,6 +187,14 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { StringRef CPU, const std::vector &FeaturesVec) const override; + bool isFeatureConsumedByTuneCPU(StringRef Feature) const override { + // FIXME: Ignore htm to avoid unnecessary warning on cpu=pwr8/tune=pwr10, + // once clang can analyze function features with granularity, remove it. + return Feature != "aix-small-local-exec-tls" && Feature != "rop-protect" && + Feature != "pcrelative-memops" && Feature != "quadword-atomics" && + Feature != "htm"; + } + void addP10SpecificFeatures(llvm::StringMap &Features) const; void addFutureSpecificFeatures(llvm::StringMap &Features) const; diff --git a/clang/test/Frontend/tune-cpu-features.c b/clang/test/Frontend/tune-cpu-features.c new file mode 100644 index 00000000000000..df0fe7f94a09cf --- /dev/null +++ b/clang/test/Frontend/tune-cpu-features.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu pwr10 -tune-cpu pwr8 %s 2>&1 | FileCheck --check-prefix=P8 %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu pwr9 -tune-cpu pwr8 %s 2>&1 | FileCheck --check-prefix=P8 %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu g5 -tune-cpu pwr8 %s 2>&1 | FileCheck --check-prefix=NONE --allow-empty %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu pwr8 -tune-cpu pwr9 %s 2>&1 | FileCheck --check-prefix=NONE --allow-empty %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu pwr8 -tune-cpu pwr10 %s 2>&1 | FileCheck --check-prefix=NONE --allow-empty %s + +// P8: instructions of current target may not be supported by tune CPU 'pwr8' +// NONE-NOT: instructions of current target may not be supported by tune CPU