[llvm] ARM: Thread float ABI through ARMSubtarget (NFC) (PR #212931)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 30 09:26:02 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/212931

>From da78b71b7575a54415bb97612640a99a072d1417 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 20 Jul 2026 14:14:55 +0200
Subject: [PATCH 1/2] ARM: Thread float ABI through ARMSubtarget (NFC)

Preparation to use the "float-abi" module flag. Store the resolved
float ABI in ARMSubtarget and fold it into the subtarget key. The
value is still sourced from TargetOptions::FloatABIType.

Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
---
 llvm/lib/Target/ARM/ARMAsmPrinter.cpp          |  4 ++--
 llvm/lib/Target/ARM/ARMFastISel.cpp            |  3 +--
 llvm/lib/Target/ARM/ARMISelLowering.cpp        |  5 ++---
 llvm/lib/Target/ARM/ARMSubtarget.cpp           |  7 ++++---
 llvm/lib/Target/ARM/ARMSubtarget.h             | 12 +++++++++++-
 llvm/lib/Target/ARM/ARMTargetMachine.cpp       | 12 +++++++++---
 llvm/lib/Target/ARM/ARMTargetMachine.h         |  6 ------
 llvm/unittests/Target/ARM/InstSizes.cpp        |  3 ++-
 llvm/unittests/Target/ARM/MachineInstrTest.cpp | 18 ++++++++++++------
 9 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
index b067c1e60c4b2..34b83d3aefb2f 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -699,7 +699,7 @@ void ARMAsmPrinter::emitAttributes() {
   const ARMBaseTargetMachine &ATM =
       static_cast<const ARMBaseTargetMachine &>(TM);
   const ARMSubtarget STI(TT, std::string(CPU), ArchFS, ATM,
-                         ATM.isLittleEndian());
+                         ATM.isLittleEndian(), ATM.Options.FloatABIType);
 
   // Emit build attributes for the available hardware.
   ATS.emitTargetAttributes(STI);
@@ -807,7 +807,7 @@ void ARMAsmPrinter::emitAttributes() {
   ATS.emitAttribute(ARMBuildAttrs::ABI_align_preserved, 1);
 
   // Hard float.  Use both S and D registers and conform to AAPCS-VFP.
-  if (getTM().isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard)
+  if (getTM().isAAPCS_ABI() && STI.isTargetHardFloat())
     ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS);
 
   // FIXME: To support emitting this build attribute as GCC does, the
diff --git a/llvm/lib/Target/ARM/ARMFastISel.cpp b/llvm/lib/Target/ARM/ARMFastISel.cpp
index 2c5d286e11c4f..26804a6265e63 100644
--- a/llvm/lib/Target/ARM/ARMFastISel.cpp
+++ b/llvm/lib/Target/ARM/ARMFastISel.cpp
@@ -1906,8 +1906,7 @@ CCAssignFn *ARMFastISel::CCAssignFnForCall(CallingConv::ID CC,
   case CallingConv::CXX_FAST_TLS:
     // Use target triple & subtarget features to do actual dispatch.
     if (TM.isAAPCS_ABI()) {
-      if (Subtarget->hasFPRegs() &&
-          TM.Options.FloatABIType == FloatABI::Hard && !isVarArg)
+      if (Subtarget->hasFPRegs() && Subtarget->isTargetHardFloat() && !isVarArg)
         return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
       else
         return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS);
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index bbef8449676b0..a88cea970e9e9 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1709,8 +1709,7 @@ ARMTargetLowering::getEffectiveCallingConv(CallingConv::ID CC,
     if (!getTM().isAAPCS_ABI())
       return CallingConv::ARM_APCS;
     else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
-             getTargetMachine().Options.FloatABIType == FloatABI::Hard &&
-             !isVarArg)
+             Subtarget->isTargetHardFloat() && !isVarArg)
       return CallingConv::ARM_AAPCS_VFP;
     else
       return CallingConv::ARM_AAPCS;
@@ -2989,7 +2988,7 @@ ARMTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
     SDValue Arg = OutVals[realRVLocIdx];
     bool ReturnF16 = false;
 
-    if (Subtarget->hasFullFP16() && getTM().isTargetHardFloat()) {
+    if (Subtarget->hasFullFP16() && Subtarget->isTargetHardFloat()) {
       // Half-precision return values can be returned like this:
       //
       // t11 f16 = fadd ...
diff --git a/llvm/lib/Target/ARM/ARMSubtarget.cpp b/llvm/lib/Target/ARM/ARMSubtarget.cpp
index 57cfd8ec71a97..f3db0d0ef2d08 100644
--- a/llvm/lib/Target/ARM/ARMSubtarget.cpp
+++ b/llvm/lib/Target/ARM/ARMSubtarget.cpp
@@ -88,15 +88,16 @@ ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU,
 ARMSubtarget::ARMSubtarget(const Triple &TT, const std::string &CPU,
                            const std::string &FS,
                            const ARMBaseTargetMachine &TM, bool IsLittle,
-                           bool MinSize, DenormalMode DM)
+                           FloatABI::ABIType FloatABI, bool MinSize,
+                           DenormalMode DM)
     : ARMGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
       UseMulOps(UseFusedMulOps), CPUString(CPU), OptMinSize(MinSize),
       IsLittle(IsLittle), DM(DM), TargetTriple(TT), Options(TM.Options), TM(TM),
-      FrameLowering(initializeFrameLowering(CPU, FS)),
+      FloatABIType(FloatABI), FrameLowering(initializeFrameLowering(CPU, FS)),
       // At this point initializeSubtargetDependencies has been called so
       // we can query directly.
       InstrInfo(isThumb1Only() ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this)
-                : !isThumb()   ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this)
+                : !isThumb() ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this)
                              : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)),
       TLInfo(TM, *this) {
 
diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h
index 3d59d44bbd204..f41be8308b3d4 100644
--- a/llvm/lib/Target/ARM/ARMSubtarget.h
+++ b/llvm/lib/Target/ARM/ARMSubtarget.h
@@ -206,13 +206,17 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
 
   const ARMBaseTargetMachine &TM;
 
+  /// The floating-point ABI in effect for this subtarget.
+  FloatABI::ABIType FloatABIType;
+
 public:
   /// This constructor initializes the data members to match that
   /// of the specified triple.
   ///
   ARMSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS,
                const ARMBaseTargetMachine &TM, bool IsLittle,
-               bool MinSize = false, DenormalMode DM = DenormalMode::getIEEE());
+               FloatABI::ABIType FloatABI, bool MinSize = false,
+               DenormalMode DM = DenormalMode::getIEEE());
 
   /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size
   /// that still makes it profitable to inline the call.
@@ -366,6 +370,12 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
   }
   /// @}
 
+  /// Returns the floating-point ABI in effect for this subtarget.
+  FloatABI::ABIType getFloatABI() const { return FloatABIType; }
+
+  /// Returns true if the subtarget uses the hard floating-point ABI.
+  bool isTargetHardFloat() const { return FloatABIType == FloatABI::Hard; }
+
   bool isReadTPSoft() const {
     return !(isReadTPTPIDRURW() || isReadTPTPIDRURO() || isReadTPTPIDRPRW());
   }
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index 7a91884b95efc..e31c578720fa1 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -155,9 +155,11 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const Triple &TT,
       TargetABI(ARM::computeTargetABI(TT, Options.MCOptions.ABIName)),
       TLOF(createTLOF(getTargetTriple())), isLittle(TT.isLittleEndian()) {
 
-  // Default to triple-appropriate float ABI
+  // Default to triple-appropriate float ABI. -target-abi=aapcs16 forces hard
+  // float regardless of the triple default.
   if (Options.FloatABIType == FloatABI::Default) {
-    if (isTargetHardFloat())
+    if (TargetABI == ARM::ARM_ABI_AAPCS16 ||
+        TT.getDefaultFloatABI() == FloatABI::Hard)
       this->Options.FloatABIType = FloatABI::Hard;
     else
       this->Options.FloatABIType = FloatABI::Soft;
@@ -225,6 +227,8 @@ ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
   if (SoftFloat)
     FS += FS.empty() ? "+soft-float" : ",+soft-float";
 
+  FloatABI::ABIType FloatABI = Options.FloatABIType;
+
   // Use the optminsize to identify the subtarget, but don't use it in the
   // feature string.
   std::string Key = CPU + FS;
@@ -235,10 +239,12 @@ ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
   if (DM != DenormalMode::getIEEE())
     Key += "denormal-fp-math=" + DM.str();
 
+  Key += FloatABI == FloatABI::Hard ? "+hard-float-abi" : "+soft-float-abi";
+
   auto &I = SubtargetMap[Key];
   if (!I) {
     I = std::make_unique<ARMSubtarget>(TargetTriple, CPU, FS, *this, isLittle,
-                                       F.hasMinSize(), DM);
+                                       FloatABI, F.hasMinSize(), DM);
 
     if (!I->isThumb() && !I->hasARMOps())
       F.getContext().emitError("Function '" + F.getName() + "' uses ARM "
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.h b/llvm/lib/Target/ARM/ARMTargetMachine.h
index e0707461db989..1d373e65978f9 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.h
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.h
@@ -78,12 +78,6 @@ class ARMBaseTargetMachine : public CodeGenTargetMachineImpl {
     return TargetABI == ARM::ARM_ABI_AAPCS16;
   }
 
-  bool isTargetHardFloat() const {
-    // -target-abi=aapcs16 overrides the triple default.
-    return TargetABI == ARM::ARM_ABI_AAPCS16 ||
-           TargetTriple.getDefaultFloatABI() == FloatABI::Hard;
-  }
-
   bool targetSchedulesPostRAScheduling() const override { return true; };
 
   MachineFunctionInfo *
diff --git a/llvm/unittests/Target/ARM/InstSizes.cpp b/llvm/unittests/Target/ARM/InstSizes.cpp
index ba4e0501e4f72..ea7fdbeea93ca 100644
--- a/llvm/unittests/Target/ARM/InstSizes.cpp
+++ b/llvm/unittests/Target/ARM/InstSizes.cpp
@@ -87,7 +87,8 @@ TEST(InstSizes, PseudoInst) {
                              std::nullopt, CodeGenOptLevel::Default));
   ARMSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
                   std::string(TM->getTargetFeatureString()),
-                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false);
+                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false,
+                  TM->getTargetTriple().getDefaultFloatABI());
   const ARMBaseInstrInfo *II = ST.getInstrInfo();
 
   auto cmpInstSize = [](const ARMBaseInstrInfo &II, MachineFunction &MF,
diff --git a/llvm/unittests/Target/ARM/MachineInstrTest.cpp b/llvm/unittests/Target/ARM/MachineInstrTest.cpp
index 1b0775a921d59..5add058e7a38f 100644
--- a/llvm/unittests/Target/ARM/MachineInstrTest.cpp
+++ b/llvm/unittests/Target/ARM/MachineInstrTest.cpp
@@ -88,7 +88,8 @@ TEST(MachineInstructionDoubleWidthResult, IsCorrect) {
                              std::nullopt, CodeGenOptLevel::Default));
   ARMSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
                   std::string(TM->getTargetFeatureString()),
-                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false);
+                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false,
+                  TM->getTargetTriple().getDefaultFloatABI());
   const ARMBaseInstrInfo *TII = ST.getInstrInfo();
   auto MII = TM->getMCInstrInfo();
 
@@ -244,7 +245,8 @@ TEST(MachineInstructionHorizontalReduction, IsCorrect) {
                              std::nullopt, CodeGenOptLevel::Default));
   ARMSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
                   std::string(TM->getTargetFeatureString()),
-                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false);
+                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false,
+                  TM->getTargetTriple().getDefaultFloatABI());
   const ARMBaseInstrInfo *TII = ST.getInstrInfo();
   auto MII = TM->getMCInstrInfo();
 
@@ -343,7 +345,8 @@ TEST(MachineInstructionRetainsPreviousHalfElement, IsCorrect) {
                              std::nullopt, CodeGenOptLevel::Default));
   ARMSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
                   std::string(TM->getTargetFeatureString()),
-                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false);
+                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false,
+                  TM->getTargetTriple().getDefaultFloatABI());
   const ARMBaseInstrInfo *TII = ST.getInstrInfo();
   auto MII = TM->getMCInstrInfo();
 
@@ -1049,7 +1052,8 @@ TEST(MachineInstrValidTailPredication, IsCorrect) {
                              std::nullopt, CodeGenOptLevel::Default));
   ARMSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
                   std::string(TM->getTargetFeatureString()),
-                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false);
+                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false,
+                  TM->getTargetTriple().getDefaultFloatABI());
 
   auto MII = TM->getMCInstrInfo();
   for (unsigned i = 0; i < ARM::INSTRUCTION_LIST_END; ++i) {
@@ -1192,7 +1196,8 @@ TEST(MachineInstr, HasSideEffects) {
                              std::nullopt, CodeGenOptLevel::Default));
   ARMSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
                   std::string(TM->getTargetFeatureString()),
-                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false);
+                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false,
+                  TM->getTargetTriple().getDefaultFloatABI());
   const ARMBaseInstrInfo *TII = ST.getInstrInfo();
   auto MII = TM->getMCInstrInfo();
 
@@ -2072,7 +2077,8 @@ TEST(MachineInstr, MVEVecSize) {
                              std::nullopt, CodeGenOptLevel::Default));
   ARMSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
                   std::string(TM->getTargetFeatureString()),
-                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false);
+                  *static_cast<const ARMBaseTargetMachine *>(TM.get()), false,
+                  TM->getTargetTriple().getDefaultFloatABI());
 
   auto MII = TM->getMCInstrInfo();
   for (unsigned i = 0; i < ARM::INSTRUCTION_LIST_END; ++i) {

>From 11f07fb576dbbbebf5a7d553681ad8c8fe415ac3 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Thu, 30 Jul 2026 18:20:48 +0200
Subject: [PATCH 2/2] Review comments

---
 llvm/lib/Target/ARM/ARMTargetMachine.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index e31c578720fa1..9df4123fd3193 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -227,8 +227,6 @@ ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
   if (SoftFloat)
     FS += FS.empty() ? "+soft-float" : ",+soft-float";
 
-  FloatABI::ABIType FloatABI = Options.FloatABIType;
-
   // Use the optminsize to identify the subtarget, but don't use it in the
   // feature string.
   std::string Key = CPU + FS;
@@ -239,6 +237,10 @@ ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
   if (DM != DenormalMode::getIEEE())
     Key += "denormal-fp-math=" + DM.str();
 
+  FloatABI::ABIType FloatABI = this->Options.FloatABIType;
+
+  // It is legal to have FloatABI::Hard with +soft-float for targets with SIMD
+  // registers, but no floating-point hardware (mve+nofp)
   Key += FloatABI == FloatABI::Hard ? "+hard-float-abi" : "+soft-float-abi";
 
   auto &I = SubtargetMap[Key];



More information about the llvm-commits mailing list