[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