[llvm] [ARM] Specify inlining behavior in TableGen (PR #205763)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 25 03:02:00 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: Nikita Popov (nikic)

<details>
<summary>Changes</summary>

Move the ARM inlining feature whitelist into the SubtargetFeature definitions. For this purpose, add a new InlineMustMatch inlining behavior, for features where no differences between caller/callee are allowed.

This is intended as an NFC patch to build future changes on top of: All the features in the whitelist are explicitly annotated as InlineDefault. All other features are explicitly annotated as InlineMustMatch, with a TODO to evaluate whether that is correct in a following change (except for the three that were explicitly called out as requiring those semantics).

---

Patch is 74.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/205763.diff


9 Files Affected:

- (modified) llvm/include/llvm/CodeGen/BasicTTIImpl.h (+7) 
- (modified) llvm/include/llvm/CodeGen/TargetSubtargetInfo.h (+2) 
- (modified) llvm/include/llvm/Target/Target.td (+3) 
- (modified) llvm/lib/Target/ARM/ARMArchitectures.td (+3-1) 
- (modified) llvm/lib/Target/ARM/ARMFeatures.td (+265-137) 
- (modified) llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp (-67) 
- (modified) llvm/lib/Target/ARM/ARMTargetTransformInfo.h (-134) 
- (modified) llvm/unittests/CodeGen/MFCommon.inc (+5) 
- (modified) llvm/utils/TableGen/SubtargetEmitter.cpp (+2) 


``````````diff
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 8c4df6664cf1d..5b3638803a3a1 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -401,6 +401,9 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
     const TargetSubtargetInfo *CalleeSTI = TM.getSubtargetImpl(*Callee);
     FeatureBitset InlineIgnoreFeatures = CallerSTI->getInlineIgnoreFeatures();
     FeatureBitset InlineInverseFeatures = CallerSTI->getInlineInverseFeatures();
+    FeatureBitset InlineMustMatchFeatures =
+        CallerSTI->getInlineMustMatchFeatures();
+
     FeatureBitset CallerBits =
         (CallerSTI->getFeatureBits() ^ InlineInverseFeatures) &
         ~InlineIgnoreFeatures;
@@ -408,6 +411,10 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
         (CalleeSTI->getFeatureBits() ^ InlineInverseFeatures) &
         ~InlineIgnoreFeatures;
 
+    if ((CallerBits & InlineMustMatchFeatures) !=
+        (CalleeBits & InlineMustMatchFeatures))
+      return false;
+
     // Inline a callee if its target-features are a subset of the callers
     // target-features.
     return (CallerBits & CalleeBits) == CalleeBits;
diff --git a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
index fe71a17146184..52bd274b86a84 100644
--- a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
@@ -370,6 +370,8 @@ class LLVM_ABI TargetSubtargetInfo : public MCSubtargetInfo {
   /// Target features where the callee may have an additional feature,
   /// instead of the caller.
   virtual const FeatureBitset &getInlineInverseFeatures() const = 0;
+  /// Target features where all mismatches prevent inlining.
+  virtual const FeatureBitset &getInlineMustMatchFeatures() const = 0;
 };
 } // end namespace llvm
 
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 455b9f40f8b72..cb97ab5d1bae4 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -534,6 +534,9 @@ def InlineDefault : InlineBehavior;
 // A callee without this feature enabled cannot be inlined into a caller with
 // it enabled.
 def InlineInverse : InlineBehavior;
+// The feature must be either enabled in both caller and callee, or disabled in
+// both.
+def InlineMustMatch : InlineBehavior;
 
 //===----------------------------------------------------------------------===//
 // SubtargetFeature - A characteristic of the chip set.
diff --git a/llvm/lib/Target/ARM/ARMArchitectures.td b/llvm/lib/Target/ARM/ARMArchitectures.td
index bfcecfe27091f..25e5e28168a59 100644
--- a/llvm/lib/Target/ARM/ARMArchitectures.td
+++ b/llvm/lib/Target/ARM/ARMArchitectures.td
@@ -1,6 +1,8 @@
+// TODO: Does this need to be InlineMustMatch?
 class Architecture<string fname, string aname, list<SubtargetFeature> features>
   : SubtargetFeature<fname, "ARMArch", aname,
-                     !strconcat(aname, " architecture"), features>;
+                     !strconcat(aname, " architecture"), features,
+                     InlineMustMatch>;
 
 //===----------------------------------------------------------------------===//
 // ARM architectures
diff --git a/llvm/lib/Target/ARM/ARMFeatures.td b/llvm/lib/Target/ARM/ARMFeatures.td
index e562b2170db5c..a1e93baf008ac 100644
--- a/llvm/lib/Target/ARM/ARMFeatures.td
+++ b/llvm/lib/Target/ARM/ARMFeatures.td
@@ -4,12 +4,14 @@
 
 // True if compiling for Thumb, false for ARM.
 def ModeThumb             : SubtargetFeature<"thumb-mode", "IsThumb",
-                                             "true", "Thumb mode">;
+                                             "true", "Thumb mode",
+                                             [], InlineMustMatch>;
 
 // True if we're using software floating point features.
 def ModeSoftFloat         : SubtargetFeature<"soft-float","UseSoftFloat",
                                              "true", "Use software floating "
-                                             "point features.">;
+                                             "point features.",
+                                             [], InlineMustMatch>;
 
 //===----------------------------------------------------------------------===//
 // ARM Subtarget features.
@@ -32,27 +34,29 @@ class Extension<
 // FP loads/stores/moves, shared between VFP and MVE (even in the integer-only
 // version).
 def FeatureFPRegs         : SubtargetFeature<"fpregs", "HasFPRegs", "true",
-                                             "Enable FP registers">;
+                                             "Enable FP registers",
+                                             [], InlineDefault>;
 
 // 16-bit FP loads/stores/moves, shared between VFP (with the v8.2A FP16
 // extension) and MVE (even in the integer-only version).
 def FeatureFPRegs16       : SubtargetFeature<"fpregs16", "HasFPRegs16", "true",
                                              "Enable 16-bit FP registers",
-                                             [FeatureFPRegs]>;
+                                             [FeatureFPRegs], InlineDefault>;
 
 def FeatureFPRegs64       : SubtargetFeature<"fpregs64", "HasFPRegs64", "true",
                                              "Enable 64-bit FP registers",
-                                             [FeatureFPRegs]>;
+                                             [FeatureFPRegs], InlineDefault>;
 
 // True if the floating point unit supports double precision.
 def FeatureFP64           : SubtargetFeature<"fp64", "HasFP64", "true",
                                              "Floating point unit supports "
                                              "double precision",
-                                             [FeatureFPRegs64]>;
+                                             [FeatureFPRegs64], InlineDefault>;
 
 // True if subtarget has the full 32 double precision FP registers for VFPv3.
 def FeatureD32            : SubtargetFeature<"d32", "HasD32", "true",
-                                             "Extend FP to 32 double registers">;
+                                             "Extend FP to 32 double registers",
+                                             [], InlineDefault>;
 
 /// Versions of the VFP flags restricted to single precision, or to
 /// 16 d-registers, or both.
@@ -65,45 +69,50 @@ multiclass VFPver<string name, string query, string description,
     description#" with only 16 d-registers and no double precision",
     !foreach(v, prev, !cast<SubtargetFeature>(v # "_D16_SP")) #
       !foreach(v, vfp2prev, !cast<SubtargetFeature>(v # "_SP")) #
-      otherimplies>;
+      otherimplies, InlineDefault>;
   def _SP: SubtargetFeature<
     name#"sp", query#"SP", "true",
     description#" with no double precision",
     !foreach(v, prev, !cast<SubtargetFeature>(v # "_SP")) #
-      otherimplies # [FeatureD32, !cast<SubtargetFeature>(NAME # "_D16_SP")]>;
+      otherimplies # [FeatureD32, !cast<SubtargetFeature>(NAME # "_D16_SP")],
+    InlineDefault>;
   def _D16: SubtargetFeature<
     name#"d16", query#"D16", "true",
     description#" with only 16 d-registers",
     !foreach(v, prev, !cast<SubtargetFeature>(v # "_D16")) #
       vfp2prev #
-      otherimplies # [FeatureFP64, !cast<SubtargetFeature>(NAME # "_D16_SP")]>;
+      otherimplies # [FeatureFP64, !cast<SubtargetFeature>(NAME # "_D16_SP")],
+    InlineDefault>;
   def "": SubtargetFeature<
     name, query, "true", description,
     prev # otherimplies # [
         !cast<SubtargetFeature>(NAME # "_D16"),
-        !cast<SubtargetFeature>(NAME # "_SP")]>;
+        !cast<SubtargetFeature>(NAME # "_SP")],
+    InlineDefault>;
 }
 
 def FeatureVFP2_SP        : SubtargetFeature<"vfp2sp", "HasVFPv2SP", "true",
                                              "Enable VFP2 instructions with "
                                              "no double precision",
-                                             [FeatureFPRegs]>;
+                                             [FeatureFPRegs], InlineDefault>;
 
 def FeatureVFP2           : SubtargetFeature<"vfp2", "HasVFPv2", "true",
                                              "Enable VFP2 instructions",
-                                             [FeatureFP64, FeatureVFP2_SP]>;
+                                             [FeatureFP64, FeatureVFP2_SP],
+                                             InlineDefault>;
 
 defm FeatureVFP3: VFPver<"vfp3", "HasVFPv3", "Enable VFP3 instructions",
                          [], [], [FeatureVFP2]>;
 
 def FeatureNEON           : SubtargetFeature<"neon", "HasNEON", "true",
                                              "Enable NEON instructions",
-                                             [FeatureVFP3]>;
+                                             [FeatureVFP3], InlineDefault>;
 
 // True if subtarget supports half-precision FP conversions.
 def FeatureFP16           : SubtargetFeature<"fp16", "HasFP16", "true",
                                              "Enable half-precision "
-                                             "floating point">;
+                                             "floating point",
+                                             [], InlineDefault>;
 
 defm FeatureVFP4: VFPver<"vfp4", "HasVFPv4", "Enable VFP4 instructions",
                          [FeatureVFP3], [FeatureFP16]>;
@@ -115,55 +124,64 @@ defm FeatureFPARMv8: VFPver<"fp-armv8", "HasFPARMv8", "Enable ARMv8 FP",
 def FeatureFullFP16       : SubtargetFeature<"fullfp16", "HasFullFP16", "true",
                                              "Enable full half-precision "
                                              "floating point",
-                                             [FeatureFPARMv8_D16_SP, FeatureFPRegs16]>;
+                                             [FeatureFPARMv8_D16_SP, FeatureFPRegs16],
+                                             InlineDefault>;
 
 // True if subtarget supports half-precision FP fml operations.
 def FeatureFP16FML        : SubtargetFeature<"fp16fml", "HasFP16FML", "true",
                                              "Enable full half-precision "
                                              "floating point fml instructions",
-                                             [FeatureFullFP16]>;
+                                             [FeatureFullFP16], InlineDefault>;
 
 // True if subtarget supports [su]div in Thumb mode.
 def FeatureHWDivThumb     : SubtargetFeature<"hwdiv",
                                              "HasDivideInThumbMode", "true",
-                                             "Enable divide instructions in Thumb">;
+                                             "Enable divide instructions in Thumb",
+                                             [], InlineDefault>;
 
 // True if subtarget supports [su]div in ARM mode.
 def FeatureHWDivARM       : SubtargetFeature<"hwdiv-arm",
                                              "HasDivideInARMMode", "true",
-                                             "Enable divide instructions in ARM mode">;
+                                             "Enable divide instructions in ARM mode",
+                                             [], InlineDefault>;
 
 // Atomic Support
 
 // True if the subtarget supports DMB / DSB data barrier instructions.
 def FeatureDB             : SubtargetFeature<"db", "HasDataBarrier", "true",
-                                             "Has data barrier (dmb/dsb) instructions">;
+                                             "Has data barrier (dmb/dsb) instructions",
+                                             [], InlineDefault>;
 
 // True if the subtarget supports CLREX instructions.
 def FeatureV7Clrex        : SubtargetFeature<"v7clrex", "HasV7Clrex", "true",
-                                             "Has v7 clrex instruction">;
+                                             "Has v7 clrex instruction",
+                                             [], InlineDefault>;
 
 // True if the subtarget supports DFB data barrier instruction.
 def FeatureDFB  : SubtargetFeature<"dfb", "HasFullDataBarrier", "true",
-                                   "Has full data barrier (dfb) instruction">;
+                                   "Has full data barrier (dfb) instruction",
+                                   [], InlineDefault>;
 
 // True if the subtarget supports v8 atomics (LDA/LDAEX etc) instructions.
 def FeatureAcquireRelease : SubtargetFeature<"acquire-release",
                                              "HasAcquireRelease", "true",
                                              "Has v8 acquire/release (lda/ldaex "
-                                             " etc) instructions">;
+                                             " etc) instructions",
+                                             [], InlineDefault>;
 
 
 // True if floating point compare + branch is slow.
 def FeatureSlowFPBrcc     : SubtargetFeature<"slow-fp-brcc", "IsFPBrccSlow", "true",
-                                             "FP compare + branch is slow">;
+                                             "FP compare + branch is slow",
+                                             [], InlineDefault>;
 
 // True if the processor supports the Performance Monitor Extensions. These
 // include a generic cycle-counter as well as more fine-grained (often
 // implementation-specific) events.
 def FeaturePerfMon        : SubtargetFeature<"perfmon", "HasPerfMon", "true",
                                              "Enable support for Performance "
-                                             "Monitor extensions">;
+                                             "Monitor extensions",
+                                             [], InlineDefault>;
 
 
 // TrustZone Security Extensions
@@ -171,106 +189,129 @@ def FeaturePerfMon        : SubtargetFeature<"perfmon", "HasPerfMon", "true",
 // True if processor supports TrustZone security extensions.
 def FeatureTrustZone      : SubtargetFeature<"trustzone", "HasTrustZone", "true",
                                              "Enable support for TrustZone "
-                                             "security extensions">;
+                                             "security extensions",
+                                             [], InlineDefault>;
 
 // True if processor supports ARMv8-M Security Extensions.
 def Feature8MSecExt       : SubtargetFeature<"8msecext", "Has8MSecExt", "true",
                                              "Enable support for ARMv8-M "
-                                             "Security Extensions">;
+                                             "Security Extensions",
+                                             [], InlineDefault>;
 
 // True if processor supports SHA1 and SHA256.
 def FeatureSHA2           : SubtargetFeature<"sha2", "HasSHA2", "true",
-                                             "Enable SHA1 and SHA256 support", [FeatureNEON]>;
+                                             "Enable SHA1 and SHA256 support",
+                                             [FeatureNEON], InlineDefault>;
 
 def FeatureAES            : SubtargetFeature<"aes", "HasAES", "true",
-                                             "Enable AES support", [FeatureNEON]>;
+                                             "Enable AES support",
+                                             [FeatureNEON], InlineDefault>;
 
 // True if processor supports Cryptography extensions.
 def FeatureCrypto         : SubtargetFeature<"crypto", "HasCrypto", "true",
                                              "Enable support for "
                                              "Cryptography extensions",
-                                             [FeatureNEON, FeatureSHA2, FeatureAES]>;
+                                             [FeatureNEON, FeatureSHA2, FeatureAES],
+                                             InlineDefault>;
 
 // True if processor supports CRC instructions.
 def FeatureCRC            : SubtargetFeature<"crc", "HasCRC", "true",
-                                             "Enable support for CRC instructions">;
+                                             "Enable support for CRC instructions",
+                                             [], InlineDefault>;
 
 // True if the ARMv8.2A dot product instructions are supported.
 def FeatureDotProd        : SubtargetFeature<"dotprod", "HasDotProd", "true",
                                              "Enable support for dot product instructions",
-                                             [FeatureNEON]>;
+                                             [FeatureNEON], InlineDefault>;
 
 // True if the processor supports RAS extensions.
 // Not to be confused with FeatureHasRetAddrStack (return address stack).
 def FeatureRAS            : SubtargetFeature<"ras", "HasRAS", "true",
                                              "Enable Reliability, Availability "
-                                             "and Serviceability extensions">;
+                                             "and Serviceability extensions",
+                                             [], InlineDefault>;
 
 // Fast computation of non-negative address offsets.
 // True if processor does positive address offset computation faster.
 def FeatureFPAO           : SubtargetFeature<"fpao", "HasFPAO", "true",
                                              "Enable fast computation of "
-                                             "positive address offsets">;
+                                             "positive address offsets",
+                                             [], InlineDefault>;
 
 // Fast execution of AES crypto operations.
 // True if processor executes back to back AES instruction pairs faster.
 def FeatureFuseAES        : SubtargetFeature<"fuse-aes", "HasFuseAES", "true",
-                                             "CPU fuses AES crypto operations">;
+                                             "CPU fuses AES crypto operations",
+                                             [], InlineDefault>;
 
 // Fast execution of bottom and top halves of literal generation.
 // True if processor executes back to back bottom and top halves of literal generation faster.
 def FeatureFuseLiterals   : SubtargetFeature<"fuse-literals", "HasFuseLiterals", "true",
-                                             "CPU fuses literal generation operations">;
+                                             "CPU fuses literal generation operations",
+                                             [], InlineDefault>;
 
 // Choice of hardware register to use as the thread pointer, if any.
+// TODO: Does this need to be InlineMustMatch?
 def FeatureReadTpTPIDRURW :  SubtargetFeature<"read-tp-tpidrurw", "IsReadTPTPIDRURW", "true",
-                                      "Reading thread pointer from TPIDRURW register">;
+                                      "Reading thread pointer from TPIDRURW register",
+                                      [], InlineMustMatch>;
+// TODO: Does this need to be InlineMustMatch?
 def FeatureReadTpTPIDRURO :  SubtargetFeature<"read-tp-tpidruro", "IsReadTPTPIDRURO", "true",
-                                      "Reading thread pointer from TPIDRURO register">;
+                                      "Reading thread pointer from TPIDRURO register",
+                                      [], InlineMustMatch>;
+// TODO: Does this need to be InlineMustMatch?
 def FeatureReadTpTPIDRPRW :  SubtargetFeature<"read-tp-tpidrprw", "IsReadTPTPIDRPRW", "true",
-                                      "Reading thread pointer from TPIDRPRW register">;
+                                      "Reading thread pointer from TPIDRPRW register",
+                                      [], InlineMustMatch>;
 
 // Cyclone can zero VFP registers in 0 cycles.
 // True if the instructions "vmov.i32 d0, #0" and "vmov.i32 q0, #0" are
 // particularly effective at zeroing a VFP register.
 def FeatureZCZeroing      : SubtargetFeature<"zcz", "HasZeroCycleZeroing", "true",
-                                             "Has zero-cycle zeroing instructions">;
+                                             "Has zero-cycle zeroing instructions",
+                                             [], InlineDefault>;
 
 // Whether it is profitable to unpredic...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/205763


More information about the llvm-commits mailing list