Author: David Zbarsky
Date: 2026-06-17T17:53:37+01:00
New Revision: d4b22fba2cedf7d6d7ce332837129a857f987a77

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

LOG: [AArch64] Compact scalable-vector intrinsic maps (#202618)

SVE and SME code generation only reads BuiltinID, LLVMIntrinsic, and
TypeModifier from its generated intrinsic maps. Store those fields in a
16-byte ARMScalableVectorIntrinsicInfo instead of the 32-byte
ARMVectorIntrinsicInfo used by NEON and SISD code generation. Update
both the classic and CIR consumers.

On an LLVM 22.1.7 arm64 release build, stripped standalone clang shrinks
from 115,097,192 to 114,816,456 bytes, saving 280,736 bytes (0.244%).

Work towards #202616

AI tool disclosure: Co-authored with OpenAI Codex.

Added: 
    

Modified: 
    clang/include/clang/Basic/AArch64CodeGenUtils.h
    clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
    clang/lib/CodeGen/TargetBuiltins/ARM.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/AArch64CodeGenUtils.h 
b/clang/include/clang/Basic/AArch64CodeGenUtils.h
index 3b9145920bd5f..d6a4df66ad232 100644
--- a/clang/include/clang/Basic/AArch64CodeGenUtils.h
+++ b/clang/include/clang/Basic/AArch64CodeGenUtils.h
@@ -49,7 +49,14 @@ enum {
       AddRetType | VectorizeRetType | Add1ArgType | InventFloatType
 };
 
-struct ARMVectorIntrinsicInfo {
+/// Describes an ARM or AArch64 NEON intrinsic, or an AArch64 SISD intrinsic.
+///
+/// NEON and SISD code generation use NameHint and AltLLVMIntrinsic in addition
+/// to BuiltinID, LLVMIntrinsic, and TypeModifier. SVE and SME code generation
+/// does not use those fields, so AArch64SVEAndSMEVectorIntrinsicInfo omits
+/// them. On 64-bit hosts, the separate structure reduces each SVE and SME map
+/// entry from 32 to 16 bytes and avoids storing a name pointer for each entry.
+struct ARMNeonVectorIntrinsicInfo {
   const char *NameHint;
   unsigned BuiltinID;
   unsigned LLVMIntrinsic;
@@ -59,11 +66,32 @@ struct ARMVectorIntrinsicInfo {
   bool operator<(unsigned RHSBuiltinID) const {
     return BuiltinID < RHSBuiltinID;
   }
-  bool operator<(const ARMVectorIntrinsicInfo &TE) const {
+  bool operator<(const ARMNeonVectorIntrinsicInfo &TE) const {
     return BuiltinID < TE.BuiltinID;
   }
 };
 
+static_assert(sizeof(ARMNeonVectorIntrinsicInfo) == 16 + 2 * sizeof(void *));
+
+/// Describes an AArch64 SVE or SME intrinsic.
+///
+/// See ARMNeonVectorIntrinsicInfo for the reason that SVE and SME use a
+/// separate structure.
+struct AArch64SVEAndSMEVectorIntrinsicInfo {
+  unsigned BuiltinID;
+  unsigned LLVMIntrinsic;
+  uint64_t TypeModifier;
+
+  bool operator<(unsigned RHSBuiltinID) const {
+    return BuiltinID < RHSBuiltinID;
+  }
+  bool operator<(const AArch64SVEAndSMEVectorIntrinsicInfo &TE) const {
+    return BuiltinID < TE.BuiltinID;
+  }
+};
+
+static_assert(sizeof(AArch64SVEAndSMEVectorIntrinsicInfo) == 16);
+
 #define NEONMAP0(NameBase)                                                     
\
   {#NameBase, NEON::BI__builtin_neon_##NameBase, 0, 0, 0}
 
@@ -77,7 +105,7 @@ struct ARMVectorIntrinsicInfo {
    TypeModifier}
 
 // clang-format off
-const inline ARMVectorIntrinsicInfo AArch64SIMDIntrinsicMap [] = {
+const inline ARMNeonVectorIntrinsicInfo AArch64SIMDIntrinsicMap [] = {
   NEONMAP0(splat_lane_v),
   NEONMAP0(splat_laneq_v),
   NEONMAP0(splatq_lane_v),
@@ -373,7 +401,7 @@ const inline ARMVectorIntrinsicInfo AArch64SIMDIntrinsicMap 
[] = {
 //
 // TODO: Either rename this table to better reflect its contents, or
 // restrict it to true SISD intrinsics only.
-const inline ARMVectorIntrinsicInfo AArch64SISDIntrinsicMap[] = {
+const inline ARMNeonVectorIntrinsicInfo AArch64SISDIntrinsicMap[] = {
   NEONMAP1(vabdd_f64, aarch64_sisd_fabd, Add1ArgType),
   NEONMAP1(vabds_f32, aarch64_sisd_fabd, Add1ArgType),
   NEONMAP1(vabsd_s64, aarch64_neon_abs, Add1ArgType),

diff  --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 2a7ba08f3f135..b52e978fa0f4d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -45,12 +45,11 @@ static mlir::Value genVscaleTimesFactor(mlir::Location loc,
 }
 
 #define SVEMAP1(NameBase, LLVMIntrinsic, TypeModifier)                         
\
-  {#NameBase, SVE::BI__builtin_sve_##NameBase, Intrinsic::LLVMIntrinsic, 0,    
\
-   TypeModifier}
+  {SVE::BI__builtin_sve_##NameBase, Intrinsic::LLVMIntrinsic, TypeModifier}
 
 #define SVEMAP2(NameBase, TypeModifier)                                        
\
-  {#NameBase, SVE::BI__builtin_sve_##NameBase, 0, 0, TypeModifier}
-static const ARMVectorIntrinsicInfo aarch64SVEIntrinsicMap[] = {
+  {SVE::BI__builtin_sve_##NameBase, 0, TypeModifier}
+static const AArch64SVEAndSMEVectorIntrinsicInfo aarch64SVEIntrinsicMap[] = {
 #define GET_SVE_LLVM_INTRINSIC_MAP
 #include "clang/Basic/arm_sve_builtin_cg.inc"
 #undef GET_SVE_LLVM_INTRINSIC_MAP
@@ -62,8 +61,9 @@ static bool aarch64SVEIntrinsicsProvenSorted = false;
 
 // Check if Builtin `builtinId` is present in `intrinsicMap`. If yes, returns
 // the corresponding info struct.
-static const ARMVectorIntrinsicInfo *
-findARMVectorIntrinsicInMap(ArrayRef<ARMVectorIntrinsicInfo> intrinsicMap,
+template <typename IntrinsicInfo>
+static const IntrinsicInfo *
+findARMVectorIntrinsicInMap(ArrayRef<IntrinsicInfo> intrinsicMap,
                             unsigned builtinID, bool &mapProvenSorted) {
 
 #ifndef NDEBUG
@@ -73,8 +73,7 @@ findARMVectorIntrinsicInMap(ArrayRef<ARMVectorIntrinsicInfo> 
intrinsicMap,
   }
 #endif
 
-  const ARMVectorIntrinsicInfo *info =
-      llvm::lower_bound(intrinsicMap, builtinID);
+  const IntrinsicInfo *info = llvm::lower_bound(intrinsicMap, builtinID);
 
   if (info != intrinsicMap.end() && info->BuiltinID == builtinID)
     return info;
@@ -260,7 +259,7 @@ static cir::VectorType 
getNeonPairwiseWidenInputType(cir::VectorType resType,
 // Derive the LLVM intrinsic's per-operand argument types and its result
 // type for use when emitting the intrinsic call.
 //
-// `modifier` is the TypeModifier bitmask from `ARMVectorIntrinsicInfo`
+// `modifier` is the TypeModifier bitmask from `ARMNeonVectorIntrinsicInfo`
 // (callers pass `info.TypeModifier`; see AArch64CodeGenUtils.h). It encodes
 // how the intrinsic's argument and return types relate to the builtin's
 // scalar types. For SISD builtins the key flags are:
@@ -320,7 +319,7 @@ deriveNeonSISDIntrinsicOperandTypes(CIRGenFunction &cgf, 
unsigned modifier,
 }
 
 static mlir::Value emitCommonNeonSISDBuiltinExpr(
-    CIRGenFunction &cgf, const ARMVectorIntrinsicInfo &info,
+    CIRGenFunction &cgf, const ARMNeonVectorIntrinsicInfo &info,
     llvm::SmallVectorImpl<mlir::Value> &ops, const CallExpr *expr) {
   assert(info.LLVMIntrinsic && "Generic code assumes a valid intrinsic");
 
@@ -1201,8 +1200,9 @@ CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned 
builtinID,
 
   assert(!cir::MissingFeatures::aarch64SVEIntrinsics());
 
-  auto *builtinIntrInfo = findARMVectorIntrinsicInMap(
-      aarch64SVEIntrinsicMap, builtinID, aarch64SVEIntrinsicsProvenSorted);
+  auto *builtinIntrInfo =
+      findARMVectorIntrinsicInMap(ArrayRef(aarch64SVEIntrinsicMap), builtinID,
+                                  aarch64SVEIntrinsicsProvenSorted);
 
   // The operands of the builtin call
   llvm::SmallVector<mlir::Value> ops;
@@ -2348,8 +2348,9 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
         emitScalarOrConstFoldImmArg(iceArguments, i, expr->getArg(i)));
   }
 
-  const ARMVectorIntrinsicInfo *builtin = findARMVectorIntrinsicInMap(
-      AArch64SISDIntrinsicMap, builtinID, aarch64SISDIntrinsicsProvenSorted);
+  const ARMNeonVectorIntrinsicInfo *builtin =
+      findARMVectorIntrinsicInMap(ArrayRef(AArch64SISDIntrinsicMap), builtinID,
+                                  aarch64SISDIntrinsicsProvenSorted);
   if (builtin)
     return emitCommonNeonSISDBuiltinExpr(*this, *builtin, ops, expr);
 
@@ -2373,8 +2374,9 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
 
   // Not all intrinsics handled by the common case work for AArch64 yet, so 
only
   // defer to common code if it's been added to our special map.
-  builtin = findARMVectorIntrinsicInMap(AArch64SIMDIntrinsicMap, builtinID,
-                                        aarch64SIMDIntrinsicsProvenSorted);
+  builtin =
+      findARMVectorIntrinsicInMap(ArrayRef(AArch64SIMDIntrinsicMap), builtinID,
+                                  aarch64SIMDIntrinsicsProvenSorted);
   if (builtin)
     return emitCommonNeonBuiltinExpr(
         *this, builtin->BuiltinID, builtin->LLVMIntrinsic,

diff  --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp 
b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index 6d6f87a9439df..dd355821fe5ff 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -537,7 +537,7 @@ Value *CodeGenFunction::EmitNeonRShiftImm(Value *Vec, Value 
*Shift,
 }
 
 // clang-format off
-static const ARMVectorIntrinsicInfo ARMSIMDIntrinsicMap [] = {
+static const ARMNeonVectorIntrinsicInfo ARMSIMDIntrinsicMap [] = {
   NEONMAP1(__a32_vcvt_bf16_f32, arm_neon_vcvtfp2bf, 0),
   NEONMAP0(splat_lane_v),
   NEONMAP0(splat_laneq_v),
@@ -1008,14 +1008,11 @@ static const std::pair<unsigned, unsigned> 
NEONEquivalentIntrinsicMap[] = {
 #undef NEONMAP2
 
 #define SVEMAP1(NameBase, LLVMIntrinsic, TypeModifier)                         
\
-  {                                                                            
\
-    #NameBase, SVE::BI__builtin_sve_##NameBase, Intrinsic::LLVMIntrinsic, 0,   
\
-        TypeModifier                                                           
\
-  }
+  {SVE::BI__builtin_sve_##NameBase, Intrinsic::LLVMIntrinsic, TypeModifier}
 
 #define SVEMAP2(NameBase, TypeModifier)                                        
\
-  { #NameBase, SVE::BI__builtin_sve_##NameBase, 0, 0, TypeModifier }
-static const ARMVectorIntrinsicInfo AArch64SVEIntrinsicMap[] = {
+  {SVE::BI__builtin_sve_##NameBase, 0, TypeModifier}
+static const AArch64SVEAndSMEVectorIntrinsicInfo AArch64SVEIntrinsicMap[] = {
 #define GET_SVE_LLVM_INTRINSIC_MAP
 #include "clang/Basic/arm_sve_builtin_cg.inc"
 #include "clang/Basic/BuiltinsAArch64NeonSVEBridge_cg.def"
@@ -1026,14 +1023,11 @@ static const ARMVectorIntrinsicInfo 
AArch64SVEIntrinsicMap[] = {
 #undef SVEMAP2
 
 #define SMEMAP1(NameBase, LLVMIntrinsic, TypeModifier)                         
\
-  {                                                                            
\
-    #NameBase, SME::BI__builtin_sme_##NameBase, Intrinsic::LLVMIntrinsic, 0,   
\
-        TypeModifier                                                           
\
-  }
+  {SME::BI__builtin_sme_##NameBase, Intrinsic::LLVMIntrinsic, TypeModifier}
 
 #define SMEMAP2(NameBase, TypeModifier)                                        
\
-  { #NameBase, SME::BI__builtin_sme_##NameBase, 0, 0, TypeModifier }
-static const ARMVectorIntrinsicInfo AArch64SMEIntrinsicMap[] = {
+  {SME::BI__builtin_sme_##NameBase, 0, TypeModifier}
+static const AArch64SVEAndSMEVectorIntrinsicInfo AArch64SMEIntrinsicMap[] = {
 #define GET_SME_LLVM_INTRINSIC_MAP
 #include "clang/Basic/arm_sme_builtin_cg.inc"
 #undef GET_SME_LLVM_INTRINSIC_MAP
@@ -1051,8 +1045,9 @@ static bool AArch64SMEIntrinsicsProvenSorted = false;
 
 // Check if Builtin `BuiltinId` is present in `IntrinsicMap`. If yes, returns
 // the corresponding info struct.
-static const ARMVectorIntrinsicInfo *
-findARMVectorIntrinsicInMap(ArrayRef<ARMVectorIntrinsicInfo> IntrinsicMap,
+template <typename IntrinsicInfo>
+static const IntrinsicInfo *
+findARMVectorIntrinsicInMap(ArrayRef<IntrinsicInfo> IntrinsicMap,
                             unsigned BuiltinID, bool &MapProvenSorted) {
 
 #ifndef NDEBUG
@@ -1062,8 +1057,7 @@ 
findARMVectorIntrinsicInMap(ArrayRef<ARMVectorIntrinsicInfo> IntrinsicMap,
   }
 #endif
 
-  const ARMVectorIntrinsicInfo *Builtin =
-      llvm::lower_bound(IntrinsicMap, BuiltinID);
+  const IntrinsicInfo *Builtin = llvm::lower_bound(IntrinsicMap, BuiltinID);
 
   if (Builtin != IntrinsicMap.end() && Builtin->BuiltinID == BuiltinID)
     return Builtin;
@@ -1114,7 +1108,7 @@ Function 
*CodeGenFunction::LookupNeonLLVMIntrinsic(unsigned IntrinsicID,
 //  Emit-helpers
 
//===----------------------------------------------------------------------===//
 static Value *EmitCommonNeonSISDBuiltinExpr(
-    CodeGenFunction &CGF, const ARMVectorIntrinsicInfo &SISDInfo,
+    CodeGenFunction &CGF, const ARMNeonVectorIntrinsicInfo &SISDInfo,
     SmallVectorImpl<Value *> &Ops, const CallExpr *E) {
   assert(SISDInfo.LLVMIntrinsic && "Generic code assumes a valid intrinsic");
 
@@ -2723,7 +2717,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned 
BuiltinID,
   // Many NEON builtins have identical semantics and uses in ARM and
   // AArch64. Emit these in a single function.
   auto IntrinsicMap = ArrayRef(ARMSIMDIntrinsicMap);
-  const ARMVectorIntrinsicInfo *Builtin = findARMVectorIntrinsicInMap(
+  const ARMNeonVectorIntrinsicInfo *Builtin = findARMVectorIntrinsicInMap(
       IntrinsicMap, BuiltinID, NEONSIMDIntrinsicsProvenSorted);
   if (Builtin)
     return EmitCommonNeonBuiltinExpr(
@@ -4023,8 +4017,9 @@ Value 
*CodeGenFunction::EmitAArch64SVEBuiltinExpr(unsigned BuiltinID,
     return EmitSVEReinterpret(Val, Ty);
   }
 
-  auto *Builtin = findARMVectorIntrinsicInMap(AArch64SVEIntrinsicMap, 
BuiltinID,
-                                              
AArch64SVEIntrinsicsProvenSorted);
+  auto *Builtin =
+      findARMVectorIntrinsicInMap(ArrayRef(AArch64SVEIntrinsicMap), BuiltinID,
+                                  AArch64SVEIntrinsicsProvenSorted);
 
   llvm::SmallVector<Value *, 4> Ops;
   SVETypeFlags TypeFlags(Builtin->TypeModifier);
@@ -4406,8 +4401,9 @@ static void swapCommutativeSMEOperands(unsigned BuiltinID,
 
 Value *CodeGenFunction::EmitAArch64SMEBuiltinExpr(unsigned BuiltinID,
                                                   const CallExpr *E) {
-  auto *Builtin = findARMVectorIntrinsicInMap(AArch64SMEIntrinsicMap, 
BuiltinID,
-                                              
AArch64SMEIntrinsicsProvenSorted);
+  auto *Builtin =
+      findARMVectorIntrinsicInMap(ArrayRef(AArch64SMEIntrinsicMap), BuiltinID,
+                                  AArch64SMEIntrinsicsProvenSorted);
 
   llvm::SmallVector<Value *, 4> Ops;
   SVETypeFlags TypeFlags(Builtin->TypeModifier);
@@ -5344,7 +5340,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned 
BuiltinID,
 
   // Check whether this is an SISD builtin.
   auto SISDMap = ArrayRef(AArch64SISDIntrinsicMap);
-  const ARMVectorIntrinsicInfo *Builtin = findARMVectorIntrinsicInMap(
+  const ARMNeonVectorIntrinsicInfo *Builtin = findARMVectorIntrinsicInMap(
       SISDMap, BuiltinID, AArch64SISDIntrinsicsProvenSorted);
   bool IsSISD = (Builtin != nullptr);
 
@@ -5408,8 +5404,9 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned 
BuiltinID,
 
   // Not all intrinsics handled by the common case work for AArch64 yet, so 
only
   // defer to common code if it's been added to our special map.
-  Builtin = findARMVectorIntrinsicInMap(AArch64SIMDIntrinsicMap, BuiltinID,
-                                        AArch64SIMDIntrinsicsProvenSorted);
+  Builtin =
+      findARMVectorIntrinsicInMap(ArrayRef(AArch64SIMDIntrinsicMap), BuiltinID,
+                                  AArch64SIMDIntrinsicsProvenSorted);
 
   if (Builtin)
     return EmitCommonNeonBuiltinExpr(


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to