[clang] [Clang] Check features of tune CPU against target CPU (PR #68861)

Qiu Chaofan via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 12 00:53:13 PDT 2023


https://github.com/ecnelises created https://github.com/llvm/llvm-project/pull/68861

Tune CPU relies on model of instruction sets. Compiler should warn if not all instruction sets of current target CPU are supported by tune CPU. Although there is limitation that Clang cannot analyze actual required features of a function.

This is enabled to PowerPC only, because feature lists of targets are complex.

>From 04d3c01ca7bb645191d8355dacb6e22daa6d3287 Mon Sep 17 00:00:00 2001
From: Qiu Chaofan <qiucofan at cn.ibm.com>
Date: Thu, 12 Oct 2023 15:47:17 +0800
Subject: [PATCH] [Clang] Check features of tune CPU against target CPU

Tune CPU relies on model of instruction sets. Compiler should warn if
not all instruction sets of current target CPU are supported by tune
CPU. Although there is limitation that Clang cannot analyze actual
required features of a function.

This is enabled to PowerPC only, because feature lists of targets are
complex.
---
 .../clang/Basic/DiagnosticFrontendKinds.td       |  3 +++
 clang/include/clang/Basic/TargetInfo.h           |  6 ++++++
 clang/lib/Basic/Targets.cpp                      | 16 ++++++++++++++++
 clang/lib/Basic/Targets/PPC.h                    |  8 ++++++++
 clang/test/Frontend/tune-cpu-features.c          |  8 ++++++++
 5 files changed, 41 insertions(+)
 create mode 100644 clang/test/Frontend/tune-cpu-features.c

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 715e0c0dc8fa84e..4adc433ac11b9f9 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<UnsupportedTargetOpt>;
 
 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 9d56e97a3d4bb88..b941b2201b84e1c 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 8130f90a276749e..d73535f53af3bf6 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<bool> TuneFeatureMap;
+    Target->initFeatureMap(TuneFeatureMap, Diags, Opts->TuneCPU, {});
+    if (std::any_of(Opts->FeatureMap.begin(), Opts->FeatureMap.end(),
+                    [&](const llvm::StringMapEntry<bool> &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 4d62673ba7fb8c5..3f95708f695b096 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<std::string> &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<bool> &Features) const;
   void addFutureSpecificFeatures(llvm::StringMap<bool> &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 000000000000000..df0fe7f94a09cf4
--- /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



More information about the cfe-commits mailing list