[clang] 28ba4b2 - [ARM][Driver] Warn if -mhard-float is incompatible

Michael Platings via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 6 03:40:39 PDT 2023


Author: Michael Platings
Date: 2023-06-06T11:39:19+01:00
New Revision: 28ba4b23177e90fa94c88f0bd9a99eb46dbc82c3

URL: https://github.com/llvm/llvm-project/commit/28ba4b23177e90fa94c88f0bd9a99eb46dbc82c3
DIFF: https://github.com/llvm/llvm-project/commit/28ba4b23177e90fa94c88f0bd9a99eb46dbc82c3.diff

LOG: [ARM][Driver] Warn if -mhard-float is incompatible

Mixing -mfloat-abi=hard with a CPU that doesn't have floating point
registers is an error in GCC:
  cc1: error: '-mfloat-abi=hard': selected processor lacks an FPU

Since there is code in the wild (including in clang tests) that relies
on Clang's current behaviour, emit a warning instead of an error.

Unlike the GCC error, the new warning refers to floating point
registers instead of an FPU. This is because -mfloat-abi=hard and
-march=armv8.1-m.main+mve+nofp are compatible - in that case floating
point registers are required, but an FPU is not required.

My initial thought was to use the floating point ABI calculated by
arm::getARMFloatABI() but in invalid cases which error for other
reasons the ABI is miscalculated and the warning would cause confusion.
Therefore only warn if the user specifies the float ABI explicitly.

Fixes part of https://github.com/llvm/llvm-project/issues/55755

Differential Revision: https://reviews.llvm.org/D150902

Added: 
    clang/test/Driver/arm-no-float-regs.c

Modified: 
    clang/include/clang/Basic/DiagnosticDriverKinds.td
    clang/lib/Driver/ToolChains/Arch/ARM.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index d7e59879cfa58..ff0f693061a39 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -417,6 +417,9 @@ def warn_drv_assuming_mfloat_abi_is : Warning<
 def warn_drv_unsupported_float_abi_by_lib : Warning<
   "float ABI '%0' is not supported by current library">,
   InGroup<DiagGroup<"unsupported-abi">>;
+def warn_drv_no_floating_point_registers: Warning<
+  "'%0': selected processor lacks floating point registers; flag ignored">,
+  InGroup<OptionIgnored>;
 def warn_ignoring_ftabstop_value : Warning<
   "ignoring invalid -ftabstop value '%0', using default value %1">;
 def warn_drv_overriding_flag_option : Warning<

diff  --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index d5d5ec6114a1d..705457805ed64 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -144,6 +144,22 @@ static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
         << A->getSpelling() << A->getValue();
 }
 
+// If -mfloat-abi=hard or -mhard-float are specified explicitly then check that
+// floating point registers are available on the target CPU.
+static void checkARMFloatABI(const Driver &D, const ArgList &Args,
+                             bool HasFPRegs) {
+  if (HasFPRegs)
+    return;
+  const Arg *A =
+      Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+                      options::OPT_mfloat_abi_EQ);
+  if (A && (A->getOption().matches(options::OPT_mhard_float) ||
+            (A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
+             A->getValue() == StringRef("hard"))))
+    D.Diag(clang::diag::warn_drv_no_floating_point_registers)
+        << A->getAsString(Args);
+}
+
 bool arm::useAAPCSForMachO(const llvm::Triple &T) {
   // The backend is hardwired to assume AAPCS for M-class processors, ensure
   // the frontend matches that.
@@ -636,13 +652,15 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
   // -march/-mcpu effectively disables the FPU (GCC ignores the -mfpu options in
   // this case). Note that the ABI can also be set implicitly by the target
   // selected.
+  bool HasFPRegs = true;
   if (ABI == arm::FloatABI::Soft) {
     llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
 
     // Disable all features relating to hardware FP, not already disabled by the
     // above call.
-    Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-bf16", "-mve",
-                                     "-mve.fp", "-fpregs"});
+    Features.insert(Features.end(),
+                    {"-dotprod", "-fp16fml", "-bf16", "-mve", "-mve.fp"});
+    HasFPRegs = false;
   } else if (FPUKind == llvm::ARM::FK_NONE ||
              ArchArgFPUKind == llvm::ARM::FK_NONE ||
              CPUArgFPUKind == llvm::ARM::FK_NONE) {
@@ -652,9 +670,10 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
     // latter, is still supported.
     Features.insert(Features.end(),
                     {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
-    if (!hasIntegerMVE(Features))
-      Features.emplace_back("-fpregs");
+    HasFPRegs = hasIntegerMVE(Features);
   }
+  if (!HasFPRegs)
+    Features.emplace_back("-fpregs");
 
   // En/disable crc code generation.
   if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
@@ -910,6 +929,8 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
 
   if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
     Features.push_back("+no-bti-at-return-twice");
+
+  checkARMFloatABI(D, Args, HasFPRegs);
 }
 
 std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {

diff  --git a/clang/test/Driver/arm-no-float-regs.c b/clang/test/Driver/arm-no-float-regs.c
new file mode 100644
index 0000000000000..b542f7d2805fe
--- /dev/null
+++ b/clang/test/Driver/arm-no-float-regs.c
@@ -0,0 +1,23 @@
+// REQUIRES: arm-registered-target
+
+// Check that -mfloat-abi=hard gives a warning if FP registers aren't available.
+// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m0 -mfloat-abi=hard -### -c %s 2>&1
+
+// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m0 -mhard-float -### -c %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=HARDFLOAT %s
+
+// -mfloat-abi=hard and -march=...+nofp are incompatible in this instance:
+// RUN: %clang --target=arm-none-eabi -march=armv8.1-m.main+nofp -mfloat-abi=hard -### -c %s 2>&1
+// -mfloat-abi=hard and -march=...+nofp are compatible in this instance:
+// RUN: %clang --target=arm-none-eabi -march=armv8.1-m.main+mve+nofp -mfloat-abi=hard -### -c %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=NOWARN %s
+
+// Here the float ABI is calculated as "hard" and FP registers are
+// calculated to not be available. Since the float ABI wasn't specified
+// explicitly, the warning should not be emitted.
+// RUN: %clang -target thumbv5-windows -mcpu=arm10tdmi -### -c %s -o /dev/null 2>&1 \
+// RUN:   | FileCheck -check-prefix=NOWARN %s
+
+// CHECK: warning: '-mfloat-abi=hard': selected processor lacks floating point registers
+// HARDFLOAT: warning: '-mhard-float': selected processor lacks floating point registers
+// NOWARN-NOT: selected processor lacks floating point registers


        


More information about the cfe-commits mailing list