[clang] [clang][CodeGen][X86_64] Honor per-function AVX ABI in C/C++ call paths, maintain old psABI for PlayStation. (PR #193298)

Benjamin Luke via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 25 16:00:15 PDT 2026


https://github.com/freaknbigpanda updated https://github.com/llvm/llvm-project/pull/193298

>From 763522bd0a12e156a1250cd8e07a234162066f4c Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Mon, 9 Mar 2026 14:00:09 -0700
Subject: [PATCH 01/13] [clang][CodeGen][X86_64] Honor per-function AVX ABI in
 C/C++ call paths, maintain old psABI for PlayStation.

Wire per fucntion x86 AVX ABI level into CodeGen arrangement methods so target("avx") /
target("avx512f") on methods, ctors, and free-functions affects ABI lowering consistently.

Specifically:
- Added X86AVXABILevel member to CGFunctionInfo.
- Populated X86AVXABILevel member in CGFunctionInfo objects via arrangement methods declared
in CodeGenTypes.h.
- Respect CGFunctionInfo AVX Level in X86_64ABIInfo::computeInfo.
- Call site ABI is determined by caller AVX level, matching GCC behaviour
- Add/extend regression tests for:
  - free-function target-attribute AVX ABI lowering
  - C++ method/ctor target-attribute AVX ABI lowering
  - PS4/PS5 legacy ABI behavior (no per-function AVX ABI change)
---
 clang/include/clang/Basic/ABIVersions.def     |   5 +
 clang/include/clang/CodeGen/CGFunctionInfo.h  |  16 +-
 clang/include/clang/CodeGen/CodeGenABITypes.h |   6 +-
 clang/lib/CodeGen/CGCall.cpp                  | 147 ++++++++++++++----
 clang/lib/CodeGen/CGClass.cpp                 |   7 +-
 clang/lib/CodeGen/CGExpr.cpp                  |   2 +-
 clang/lib/CodeGen/CGExprCXX.cpp               |  11 +-
 clang/lib/CodeGen/CodeGenABITypes.cpp         |  13 +-
 clang/lib/CodeGen/CodeGenFunction.cpp         |   7 +
 clang/lib/CodeGen/CodeGenFunction.h           |   1 +
 clang/lib/CodeGen/CodeGenModule.cpp           |  38 ++++-
 clang/lib/CodeGen/CodeGenModule.h             |   3 +
 clang/lib/CodeGen/CodeGenTypes.h              |  34 +++-
 clang/lib/CodeGen/Targets/X86.cpp             |  13 ++
 clang/test/CodeGen/sysv_abi.c                 |  18 +++
 clang/test/CodeGen/target-avx-function-abi.c  |  71 +++++++++
 .../test/CodeGenCXX/target-avx-method-abi.cpp | 121 ++++++++++++++
 .../unittests/CodeGen/CodeGenExternalTest.cpp | 136 ++++++++++++++--
 clang/unittests/CodeGen/TestCompiler.h        |  16 +-
 19 files changed, 589 insertions(+), 76 deletions(-)
 create mode 100644 clang/test/CodeGen/target-avx-function-abi.c
 create mode 100644 clang/test/CodeGenCXX/target-avx-method-abi.cpp

diff --git a/clang/include/clang/Basic/ABIVersions.def b/clang/include/clang/Basic/ABIVersions.def
index 92edcd830f031..bc083b19dd4a5 100644
--- a/clang/include/clang/Basic/ABIVersions.def
+++ b/clang/include/clang/Basic/ABIVersions.def
@@ -135,6 +135,11 @@ ABI_VER_MAJOR(20)
 ///    operator delete.
 ABI_VER_MAJOR(21)
 
+/// Attempt to be ABI-compatible with code generated by Clang 22.0.x.
+/// This causes clang to:
+///   - Not ignore function __attribute(__target(...)) directives that change the ABI
+ABI_VER_MAJOR(22)
+
 /// Conform to the underlying platform's C and C++ ABIs as closely as we can.
 ABI_VER_LATEST(Latest)
 
diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h
index 713b52a4cc2b8..a394d18780e6e 100644
--- a/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -653,6 +653,10 @@ class CGFunctionInfo final
   /// Log 2 of the maximum vector width.
   unsigned MaxVectorWidth : 4;
 
+  /// Effective x86 AVX ABI level used during ABI classification. Used to
+  /// support target attributes.
+  unsigned X86AVXABILevel : 2;
+
   RequiredArgs Required;
 
   /// The struct representing all arguments passed in memory.  Only used when
@@ -683,7 +687,8 @@ class CGFunctionInfo final
 public:
   static CGFunctionInfo *
   create(unsigned llvmCC, bool instanceMethod, bool chainCall,
-         bool delegateCall, const FunctionType::ExtInfo &extInfo,
+         bool delegateCall, unsigned X86AVXABILevel,
+         const FunctionType::ExtInfo &extInfo,
          ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
          ArrayRef<CanQualType> argTypes, RequiredArgs required);
   void operator delete(void *p) { ::operator delete(p); }
@@ -809,6 +814,12 @@ class CGFunctionInfo final
     MaxVectorWidth = llvm::countr_zero(Width) + 1;
   }
 
+  unsigned getX86AVXABILevel() const { return X86AVXABILevel; }
+  void setX86AVXABILevel(unsigned Level) {
+    assert(Level <= 2 && "invalid AVX ABI level");
+    X86AVXABILevel = Level;
+  }
+
   void Profile(llvm::FoldingSetNodeID &ID) {
     ID.AddInteger(getASTCallingConvention());
     ID.AddBoolean(InstanceMethod);
@@ -821,6 +832,7 @@ class CGFunctionInfo final
     ID.AddInteger(RegParm);
     ID.AddBoolean(NoCfCheck);
     ID.AddBoolean(CmseNSCall);
+    ID.AddInteger(X86AVXABILevel);
     ID.AddInteger(Required.getOpaqueData());
     ID.AddBoolean(HasExtParameterInfos);
     if (HasExtParameterInfos) {
@@ -833,6 +845,7 @@ class CGFunctionInfo final
   }
   static void Profile(llvm::FoldingSetNodeID &ID, bool InstanceMethod,
                       bool ChainCall, bool IsDelegateCall,
+                      unsigned X86AVXABILevel,
                       const FunctionType::ExtInfo &info,
                       ArrayRef<ExtParameterInfo> paramInfos,
                       RequiredArgs required, CanQualType resultType,
@@ -848,6 +861,7 @@ class CGFunctionInfo final
     ID.AddInteger(info.getRegParm());
     ID.AddBoolean(info.getNoCfCheck());
     ID.AddBoolean(info.getCmseNSCall());
+    ID.AddInteger(X86AVXABILevel);
     ID.AddInteger(required.getOpaqueData());
     ID.AddBoolean(!paramInfos.empty());
     if (!paramInfos.empty()) {
diff --git a/clang/include/clang/CodeGen/CodeGenABITypes.h b/clang/include/clang/CodeGen/CodeGenABITypes.h
index 627dd0f0453ac..b9b9a8a23c7b2 100644
--- a/clang/include/clang/CodeGen/CodeGenABITypes.h
+++ b/clang/include/clang/CodeGen/CodeGenABITypes.h
@@ -81,13 +81,13 @@ const CGFunctionInfo &
 arrangeCXXMethodCall(CodeGenModule &CGM, CanQualType returnType,
                      ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info,
                      ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
-                     RequiredArgs args);
+                     RequiredArgs args, const FunctionDecl *CallerFD = nullptr);
 
 const CGFunctionInfo &arrangeFreeFunctionCall(
     CodeGenModule &CGM, CanQualType returnType, ArrayRef<CanQualType> argTypes,
     FunctionType::ExtInfo info,
-    ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
-    RequiredArgs args);
+    ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, RequiredArgs args,
+    const FunctionDecl *CallerFD = nullptr);
 
 // An overload with an empty `paramInfos`
 inline const CGFunctionInfo &
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 7194b81459922..62270584a7022 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -357,10 +357,16 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
 
   // Add the 'this' pointer.
   argTypes.push_back(DeriveThisType(RD, MD));
-
-  return ::arrangeLLVMFunctionInfo(
-      *this, /*instanceMethod=*/true, argTypes,
-      FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
+  auto CanonicalFTP =
+      FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>();
+  ExtParameterInfoList paramInfos;
+  RequiredArgs required = RequiredArgs::forPrototypePlus(
+      CanonicalFTP.getTypePtr(), argTypes.size());
+  appendParameterTypes(*this, argTypes, paramInfos, CanonicalFTP);
+  return arrangeLLVMFunctionInfo(
+      CanonicalFTP->getReturnType().getUnqualifiedType(),
+      FnInfoOpts::IsInstanceMethod, argTypes, CanonicalFTP->getExtInfo(),
+      paramInfos, required, MD);
 }
 
 /// Set calling convention for CUDA/HIP kernel.
@@ -393,7 +399,13 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) {
     return arrangeCXXMethodType(ThisType, prototype.getTypePtr(), MD);
   }
 
-  return arrangeFreeFunctionType(prototype);
+  CanQualTypeList argTypes;
+  ExtParameterInfoList paramInfos;
+  appendParameterTypes(*this, argTypes, paramInfos, prototype);
+  return arrangeLLVMFunctionInfo(
+      prototype->getReturnType().getUnqualifiedType(), FnInfoOpts::None,
+      argTypes, prototype->getExtInfo(), paramInfos,
+      RequiredArgs::forPrototypePlus(prototype.getTypePtr(), 0), MD);
 }
 
 bool CodeGenTypes::inheritingCtorHasParams(
@@ -452,7 +464,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(GlobalDecl GD) {
                                ? CGM.getContext().VoidPtrTy
                                : Context.VoidTy;
   return arrangeLLVMFunctionInfo(resultType, FnInfoOpts::IsInstanceMethod,
-                                 argTypes, extInfo, paramInfos, required);
+                                 argTypes, extInfo, paramInfos, required, MD);
 }
 
 static CanQualTypeList getArgTypesForCall(ASTContext &ctx,
@@ -492,6 +504,15 @@ getExtParameterInfosForCall(const FunctionProtoType *proto, unsigned prefixArgs,
 const CGFunctionInfo &CodeGenTypes::arrangeCXXConstructorCall(
     const CallArgList &args, const CXXConstructorDecl *D, CXXCtorType CtorKind,
     unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs, bool PassProtoArgs) {
+  return arrangeCXXConstructorCall(
+      args, D, CtorKind, ExtraPrefixArgs, ExtraSuffixArgs,
+      CGM.getDefaultX86AVXABILevel(), PassProtoArgs);
+}
+
+const CGFunctionInfo &CodeGenTypes::arrangeCXXConstructorCall(
+    const CallArgList &args, const CXXConstructorDecl *D, CXXCtorType CtorKind,
+    unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs, unsigned X86AVXABILevel,
+    bool PassProtoArgs) {
   CanQualTypeList ArgTypes;
   for (const auto &Arg : args)
     ArgTypes.push_back(Context.getCanonicalParamType(Arg.Ty));
@@ -522,7 +543,8 @@ const CGFunctionInfo &CodeGenTypes::arrangeCXXConstructorCall(
   }
 
   return arrangeLLVMFunctionInfo(ResultType, FnInfoOpts::IsInstanceMethod,
-                                 ArgTypes, Info, ParamInfos, Required);
+                                 ArgTypes, Info, ParamInfos, Required,
+                                 X86AVXABILevel);
 }
 
 /// Arrange the argument and result information for the declaration or
@@ -551,10 +573,17 @@ CodeGenTypes::arrangeFunctionDeclaration(const GlobalDecl GD) {
   if (CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>()) {
     return arrangeLLVMFunctionInfo(noProto->getReturnType(), FnInfoOpts::None,
                                    {}, noProto->getExtInfo(), {},
-                                   RequiredArgs::All);
+                                   RequiredArgs::All, FD);
   }
 
-  return arrangeFreeFunctionType(FTy.castAs<FunctionProtoType>());
+  CanQual<FunctionProtoType> FTP = FTy.castAs<FunctionProtoType>();
+  CanQualTypeList argTypes;
+  ExtParameterInfoList paramInfos;
+  appendParameterTypes(*this, argTypes, paramInfos, FTP);
+  return arrangeLLVMFunctionInfo(FTP->getReturnType().getUnqualifiedType(),
+                                 FnInfoOpts::None, argTypes, FTP->getExtInfo(),
+                                 paramInfos,
+                                 RequiredArgs::forPrototypePlus(FTP, 0), FD);
 }
 
 /// Arrange the argument and result information for the declaration or
@@ -664,7 +693,8 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD,
 static const CGFunctionInfo &
 arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, CodeGenModule &CGM,
                             const CallArgList &args, const FunctionType *fnType,
-                            unsigned numExtraRequiredArgs, bool chainCall) {
+                            unsigned numExtraRequiredArgs, bool chainCall,
+                            unsigned X86AVXABILevel) {
   assert(args.size() >= numExtraRequiredArgs);
 
   ExtParameterInfoList paramInfos;
@@ -697,7 +727,7 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, CodeGenModule &CGM,
   FnInfoOpts opts = chainCall ? FnInfoOpts::IsChainCall : FnInfoOpts::None;
   return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()),
                                      opts, argTypes, fnType->getExtInfo(),
-                                     paramInfos, required);
+                                     paramInfos, required, X86AVXABILevel);
 }
 
 /// Figure out the rules for calling a function with the given formal
@@ -706,8 +736,17 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, CodeGenModule &CGM,
 /// target-dependent in crazy ways.
 const CGFunctionInfo &CodeGenTypes::arrangeFreeFunctionCall(
     const CallArgList &args, const FunctionType *fnType, bool chainCall) {
-  return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType,
-                                     chainCall ? 1 : 0, chainCall);
+  return arrangeFreeFunctionCall(
+      args, fnType, chainCall,
+      static_cast<unsigned>(CGM.getDefaultX86AVXABILevel()));
+}
+
+const CGFunctionInfo &
+CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
+                                      const FunctionType *fnType,
+                                      bool chainCall, unsigned X86AVXABILevel) {
+  return arrangeFreeFunctionLikeCall(
+      *this, CGM, args, fnType, chainCall ? 1 : 0, chainCall, X86AVXABILevel);
 }
 
 /// A block function is essentially a free function with an
@@ -715,8 +754,10 @@ const CGFunctionInfo &CodeGenTypes::arrangeFreeFunctionCall(
 const CGFunctionInfo &
 CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args,
                                        const FunctionType *fnType) {
-  return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, 1,
-                                     /*chainCall=*/false);
+  return arrangeFreeFunctionLikeCall(
+      *this, CGM, args, fnType, 1,
+      /*chainCall=*/false,
+      static_cast<unsigned>(CGM.getDefaultX86AVXABILevel()));
 }
 
 const CGFunctionInfo &
@@ -777,6 +818,14 @@ const CGFunctionInfo &CodeGenTypes::arrangeDeviceKernelCallerDeclaration(
 const CGFunctionInfo &CodeGenTypes::arrangeCXXMethodCall(
     const CallArgList &args, const FunctionProtoType *proto,
     RequiredArgs required, unsigned numPrefixArgs) {
+  return arrangeCXXMethodCall(
+      args, proto, required, numPrefixArgs,
+      static_cast<unsigned>(CGM.getDefaultX86AVXABILevel()));
+}
+
+const CGFunctionInfo &CodeGenTypes::arrangeCXXMethodCall(
+    const CallArgList &args, const FunctionProtoType *proto,
+    RequiredArgs required, unsigned numPrefixArgs, unsigned X86AVXABILevel) {
   assert(numPrefixArgs + 1 <= args.size() &&
          "Emitting a call with less args than the required prefix?");
   // Add one to account for `this`. It's a bit awkward here, but we don't count
@@ -789,7 +838,7 @@ const CGFunctionInfo &CodeGenTypes::arrangeCXXMethodCall(
   FunctionType::ExtInfo info = proto->getExtInfo();
   return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()),
                                  FnInfoOpts::IsInstanceMethod, argTypes, info,
-                                 paramInfos, required);
+                                 paramInfos, required, X86AVXABILevel);
 }
 
 const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
@@ -800,6 +849,13 @@ const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
 
 const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
                                                 const CallArgList &args) {
+  return arrangeCall(signature, args,
+                     static_cast<unsigned>(CGM.getDefaultX86AVXABILevel()));
+}
+
+const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
+                                                const CallArgList &args,
+                                                unsigned X86AVXABILevel) {
   assert(signature.arg_size() <= args.size());
   if (signature.arg_size() == args.size())
     return signature;
@@ -821,9 +877,13 @@ const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
     opts |= FnInfoOpts::IsChainCall;
   if (signature.isDelegateCall())
     opts |= FnInfoOpts::IsDelegateCall;
-  return arrangeLLVMFunctionInfo(signature.getReturnType(), opts, argTypes,
-                                 signature.getExtInfo(), paramInfos,
-                                 signature.getRequiredArgs());
+
+  const CGFunctionInfo *newFI = findOrInsertCGFunctionInfo(
+      signature.isInstanceMethod(), signature.isChainCall(),
+      signature.isDelegateCall(), X86AVXABILevel, signature.getExtInfo(),
+      paramInfos, signature.getRequiredArgs(), signature.getReturnType(),
+      argTypes);
+  return *newFI;
 }
 
 namespace clang {
@@ -893,6 +953,16 @@ ABIArgInfo CodeGenModule::convertABIArgInfo(const llvm::abi::ArgInfo &AbiInfo,
   llvm_unreachable("Unexpected llvm::abi::ArgInfo kind");
 }
 
+const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
+    CanQualType resultType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
+    FunctionType::ExtInfo info,
+    ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
+    RequiredArgs required, const FunctionDecl *FD) {
+  return arrangeLLVMFunctionInfo(
+      resultType, opts, argTypes, info, paramInfos, required,
+      static_cast<unsigned>(CGM.getEffectiveX86AVXABILevel(FD)));
+}
+
 /// Arrange the argument and result information for an abstract value
 /// of a given function type.  This is the method which all of the
 /// above functions ultimately defer to.
@@ -900,7 +970,7 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
     CanQualType resultType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
     FunctionType::ExtInfo info,
     ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
-    RequiredArgs required) {
+    RequiredArgs required, unsigned X86AVXABILevel) {
   assert(llvm::all_of(argTypes,
                       [](CanQualType T) { return T.isCanonicalAsParam(); }));
 
@@ -912,19 +982,35 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
       (opts & FnInfoOpts::IsChainCall) == FnInfoOpts::IsChainCall;
   bool isDelegateCall =
       (opts & FnInfoOpts::IsDelegateCall) == FnInfoOpts::IsDelegateCall;
+
+  const CGFunctionInfo *newFI = findOrInsertCGFunctionInfo(
+      isInstanceMethod, isChainCall, isDelegateCall, X86AVXABILevel, info,
+      paramInfos, required, resultType, argTypes);
+  return *newFI;
+}
+
+CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
+    bool isInstanceMethod, bool isChainCall, bool isDelegateCall,
+    unsigned X86AVXABILevel, const FunctionType::ExtInfo &info,
+    ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
+    RequiredArgs required, CanQualType resultType,
+    ArrayRef<CanQualType> argTypes) {
+  llvm::FoldingSetNodeID ID;
   CGFunctionInfo::Profile(ID, isInstanceMethod, isChainCall, isDelegateCall,
-                          info, paramInfos, required, resultType, argTypes);
+                          X86AVXABILevel, info, paramInfos, required,
+                          resultType, argTypes);
 
   void *insertPos = nullptr;
   CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos);
   if (FI)
-    return *FI;
+    return FI;
 
   unsigned CC = ClangCallConvToLLVMCallConv(info.getCC());
 
   // Construct the function info.  We co-allocate the ArgInfos.
   FI = CGFunctionInfo::create(CC, isInstanceMethod, isChainCall, isDelegateCall,
-                              info, paramInfos, resultType, argTypes, required);
+                              X86AVXABILevel, info, paramInfos, resultType,
+                              argTypes, required);
   FunctionInfos.InsertNode(FI, insertPos);
 
   bool inserted = FunctionsBeingProcessed.insert(FI).second;
@@ -963,16 +1049,14 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
   (void)erased;
   assert(erased && "Not in set?");
 
-  return *FI;
+  return FI;
 }
 
-CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod,
-                                       bool chainCall, bool delegateCall,
-                                       const FunctionType::ExtInfo &info,
-                                       ArrayRef<ExtParameterInfo> paramInfos,
-                                       CanQualType resultType,
-                                       ArrayRef<CanQualType> argTypes,
-                                       RequiredArgs required) {
+CGFunctionInfo *CGFunctionInfo::create(
+    unsigned llvmCC, bool instanceMethod, bool chainCall, bool delegateCall,
+    unsigned X86AVXABILevel, const FunctionType::ExtInfo &info,
+    ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
+    ArrayRef<CanQualType> argTypes, RequiredArgs required) {
   assert(paramInfos.empty() || paramInfos.size() == argTypes.size());
   assert(!required.allowsOptionalArgs() ||
          required.getNumRequiredArgs() <= argTypes.size());
@@ -995,6 +1079,7 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod,
   FI->Required = required;
   FI->HasRegParm = info.getHasRegParm();
   FI->RegParm = info.getRegParm();
+  FI->X86AVXABILevel = X86AVXABILevel;
   FI->ArgStruct = nullptr;
   FI->ArgStructAlign = 0;
   FI->NumArgs = argTypes.size();
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index e52c5f6af2851..149fe1e71ffce 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -2316,8 +2316,8 @@ static bool canEmitDelegateCallArgs(CodeGenFunction &CGF,
         return false;
 
     // Likewise if they're inalloca.
-    const CGFunctionInfo &Info =
-        CGF.CGM.getTypes().arrangeCXXConstructorCall(Args, Ctor, Type, 0, 0);
+    const CGFunctionInfo &Info = CGF.CGM.getTypes().arrangeCXXConstructorCall(
+        Args, Ctor, Type, 0, 0, CGF.getCurrentFunctionX86AVXABILevel());
     if (Info.usesInAlloca())
       return false;
   }
@@ -2377,7 +2377,8 @@ void CodeGenFunction::EmitCXXConstructorCall(
   // Emit the call.
   llvm::Constant *CalleePtr = CGM.getAddrOfCXXStructor(GlobalDecl(D, Type));
   const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall(
-      Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix, PassPrototypeArgs);
+      Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix,
+      getCurrentFunctionX86AVXABILevel(), PassPrototypeArgs);
   CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(D, Type));
   EmitCall(Info, Callee, ReturnValueSlot(), Args, CallOrInvoke, false, Loc);
 
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 77fd47ed42f03..5fda07432ca36 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -7086,7 +7086,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
                E->getDirectCallee(), /*ParamsToSkip=*/0, Order);
 
   const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall(
-      Args, FnType, /*ChainCall=*/Chain);
+      Args, FnType, /*ChainCall=*/Chain, getCurrentFunctionX86AVXABILevel());
 
   if (ResolvedFnInfo)
     *ResolvedFnInfo = &FnInfo;
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 0dc2e0bb82114..58a58cf15a7b2 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -92,7 +92,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
   MemberCallInfo CallInfo = commonEmitCXXMemberOrOperatorCall(
       *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs);
   auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall(
-      Args, FPT, CallInfo.ReqArgs, CallInfo.PrefixSize);
+      Args, FPT, CallInfo.ReqArgs, CallInfo.PrefixSize,
+      getCurrentFunctionX86AVXABILevel());
   return EmitCall(FnInfo, Callee, ReturnValue, Args, CallOrInvoke,
                   CE && CE == MustTailCall,
                   CE ? CE->getExprLoc() : SourceLocation());
@@ -482,8 +483,9 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
 
   // And the rest of the call args
   EmitCallArgs(Args, FPT, E->arguments());
-  return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required,
-                                                      /*PrefixSize=*/0),
+  return EmitCall(CGM.getTypes().arrangeCXXMethodCall(
+                      Args, FPT, required,
+                      /*PrefixSize=*/0, getCurrentFunctionX86AVXABILevel()),
                   Callee, ReturnValue, Args, CallOrInvoke, E == MustTailCall,
                   E->getExprLoc());
 }
@@ -1342,7 +1344,8 @@ static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
   llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl);
   CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(CalleeDecl));
   RValue RV = CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(
-                               Args, CalleeType, /*ChainCall=*/false),
+                               Args, CalleeType, /*ChainCall=*/false,
+                               CGF.getCurrentFunctionX86AVXABILevel()),
                            Callee, ReturnValueSlot(), Args, &CallOrInvoke);
 
   /// C++1y [expr.new]p10:
diff --git a/clang/lib/CodeGen/CodeGenABITypes.cpp b/clang/lib/CodeGen/CodeGenABITypes.cpp
index aad286f3de53c..5713f9be37b60 100644
--- a/clang/lib/CodeGen/CodeGenABITypes.cpp
+++ b/clang/lib/CodeGen/CodeGenABITypes.cpp
@@ -60,20 +60,21 @@ CodeGen::arrangeCXXMethodType(CodeGenModule &CGM,
 const CGFunctionInfo &CodeGen::arrangeCXXMethodCall(
     CodeGenModule &CGM, CanQualType returnType, ArrayRef<CanQualType> argTypes,
     FunctionType::ExtInfo info,
-    ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
-    RequiredArgs args) {
+    ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, RequiredArgs args,
+    const FunctionDecl *CallerFD) {
   return CGM.getTypes().arrangeLLVMFunctionInfo(
       returnType, FnInfoOpts::IsInstanceMethod, argTypes, info, paramInfos,
-      args);
+      args, static_cast<unsigned>(CGM.getEffectiveX86AVXABILevel(CallerFD)));
 }
 
 const CGFunctionInfo &CodeGen::arrangeFreeFunctionCall(
     CodeGenModule &CGM, CanQualType returnType, ArrayRef<CanQualType> argTypes,
     FunctionType::ExtInfo info,
-    ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
-    RequiredArgs args) {
+    ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, RequiredArgs args,
+    const FunctionDecl *CallerFD) {
   return CGM.getTypes().arrangeLLVMFunctionInfo(
-      returnType, FnInfoOpts::None, argTypes, info, paramInfos, args);
+      returnType, FnInfoOpts::None, argTypes, info, paramInfos, args,
+      static_cast<unsigned>(CGM.getEffectiveX86AVXABILevel(CallerFD)));
 }
 
 ImplicitCXXConstructorArgs
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index b920266b59808..53cc191150e95 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -90,6 +90,13 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
   SetFastMathFlags(CurFPFeatures);
 }
 
+unsigned CodeGenFunction::getCurrentFunctionX86AVXABILevel() const {
+  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl);
+  if (!FD)
+    FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl);
+  return static_cast<unsigned>(CGM.getEffectiveX86AVXABILevel(FD));
+}
+
 CodeGenFunction::~CodeGenFunction() {
   assert(LifetimeExtendedCleanupStack.empty() && "failed to emit a cleanup");
   assert(DeferredDeactivationCleanupStack.empty() &&
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 3ce0ef1235561..71ac5254f1dd5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2234,6 +2234,7 @@ class CodeGenFunction : public CodeGenTypeCache {
   const TargetCodeGenInfo &getTargetHooks() const {
     return CGM.getTargetCodeGenInfo();
   }
+  unsigned getCurrentFunctionX86AVXABILevel() const;
 
   //===--------------------------------------------------------------------===//
   //                                  Cleanups
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 236738e9975d3..2df2bc35ff678 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -111,6 +111,8 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
   llvm_unreachable("invalid C++ ABI kind");
 }
 
+static X86AVXABILevel getDefaultX86AVXABILevel(const TargetInfo &Target);
+
 static std::unique_ptr<TargetCodeGenInfo>
 createTargetCodeGenInfo(CodeGenModule &CGM) {
   const TargetInfo &Target = CGM.getTarget();
@@ -268,10 +270,7 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
   }
 
   case llvm::Triple::x86_64: {
-    StringRef ABI = Target.getABI();
-    X86AVXABILevel AVXLevel = (ABI == "avx512" ? X86AVXABILevel::AVX512
-                               : ABI == "avx"  ? X86AVXABILevel::AVX
-                                               : X86AVXABILevel::None);
+    X86AVXABILevel AVXLevel = getDefaultX86AVXABILevel(Target);
 
     switch (Triple.getOS()) {
     case llvm::Triple::UEFI:
@@ -333,6 +332,18 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
   }
 }
 
+static X86AVXABILevel getDefaultX86AVXABILevel(const TargetInfo &Target) {
+  X86AVXABILevel Level = X86AVXABILevel::None;
+  if (Target.getTriple().isX86_64()) {
+    StringRef ABI = Target.getABI();
+    if (ABI == "avx512")
+      Level = X86AVXABILevel::AVX512;
+    else if (ABI == "avx")
+      Level = X86AVXABILevel::AVX;
+  }
+  return Level;
+}
+
 const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
   if (!TheTargetCodeGenInfo)
     TheTargetCodeGenInfo = createTargetCodeGenInfo(*this);
@@ -6267,6 +6278,25 @@ const ABIInfo &CodeGenModule::getABIInfo() {
   return getTargetCodeGenInfo().getABIInfo();
 }
 
+unsigned CodeGenModule::getDefaultX86AVXABILevel() const {
+  return static_cast<unsigned>(::getDefaultX86AVXABILevel(Target));
+}
+
+unsigned
+CodeGenModule::getEffectiveX86AVXABILevel(const FunctionDecl *FD) const {
+  X86AVXABILevel Level = ::getDefaultX86AVXABILevel(Target);
+  if (!FD)
+    return static_cast<unsigned>(Level);
+
+  llvm::StringMap<bool> FeatureMap;
+  Context.getFunctionFeatureMap(FeatureMap, FD);
+  if (FeatureMap.lookup("avx512f"))
+    return static_cast<unsigned>(std::max(Level, X86AVXABILevel::AVX512));
+  if (FeatureMap.lookup("avx"))
+    return static_cast<unsigned>(std::max(Level, X86AVXABILevel::AVX));
+  return static_cast<unsigned>(Level);
+}
+
 /// Pass IsTentative as true if you want to create a tentative definition.
 void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
                                             bool IsTentative) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 5e5e73d9c4c44..48a4485f76a39 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -919,6 +919,9 @@ class CodeGenModule : public CodeGenTypeCache {
   /// in classification, and write the results back into FI.
   void computeABIInfoUsingLib(CGFunctionInfo &FI);
 
+  unsigned getDefaultX86AVXABILevel() const;
+  unsigned getEffectiveX86AVXABILevel(const FunctionDecl *FD) const;
+
   CGCXXABI &getCXXABI() const { return *ABI; }
   llvm::LLVMContext &getLLVMContext() { return VMContext; }
 
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 9de7e0a83579d..4d8627bc32276 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -89,9 +89,18 @@ class CodeGenTypes {
   llvm::DenseMap<const Type *, llvm::Type *> RecordsWithOpaqueMemberPointers;
 
   static constexpr unsigned FunctionInfosLog2InitSize = 9;
+
   /// Helper for ConvertType.
   llvm::Type *ConvertFunctionTypeInternal(QualType FT);
 
+  // Helper to insert CGFunctionInfo objects
+  CGFunctionInfo *findOrInsertCGFunctionInfo(
+      bool isInstanceMethod, bool isChainCall, bool isDelegateCall,
+      unsigned X86AVXABILevel, const FunctionType::ExtInfo &info,
+      ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
+      RequiredArgs required, CanQualType resultType,
+      ArrayRef<CanQualType> argTypes);
+
 public:
   CodeGenTypes(CodeGenModule &cgm);
   ~CodeGenTypes();
@@ -204,6 +213,9 @@ class CodeGenTypes {
   /// Often this will be able to simply return the declaration info.
   const CGFunctionInfo &arrangeCall(const CGFunctionInfo &declFI,
                                     const CallArgList &args);
+  const CGFunctionInfo &arrangeCall(const CGFunctionInfo &declFI,
+                                    const CallArgList &args,
+                                    unsigned X86AVXABILevel);
 
   /// Free functions are functions that are compatible with an ordinary
   /// C function pointer type.
@@ -211,6 +223,10 @@ class CodeGenTypes {
   const CGFunctionInfo &arrangeFreeFunctionCall(const CallArgList &Args,
                                                 const FunctionType *Ty,
                                                 bool ChainCall);
+  const CGFunctionInfo &arrangeFreeFunctionCall(const CallArgList &Args,
+                                                const FunctionType *Ty,
+                                                bool ChainCall,
+                                                unsigned X86AVXABILevel);
   const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty);
   const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty);
 
@@ -261,10 +277,21 @@ class CodeGenTypes {
                                                   unsigned ExtraSuffixArgs,
                                                   bool PassProtoArgs = true);
 
+  const CGFunctionInfo &
+  arrangeCXXConstructorCall(const CallArgList &Args,
+                            const CXXConstructorDecl *D, CXXCtorType CtorKind,
+                            unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs,
+                            unsigned X86AVXABILevel, bool PassProtoArgs = true);
+
   const CGFunctionInfo &arrangeCXXMethodCall(const CallArgList &args,
                                              const FunctionProtoType *type,
                                              RequiredArgs required,
                                              unsigned numPrefixArgs);
+  const CGFunctionInfo &arrangeCXXMethodCall(const CallArgList &args,
+                                             const FunctionProtoType *type,
+                                             RequiredArgs required,
+                                             unsigned numPrefixArgs,
+                                             unsigned X86AVXABILevel);
   const CGFunctionInfo &
   arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD);
   const CGFunctionInfo &arrangeMSCtorClosure(const CXXConstructorDecl *CD,
@@ -283,7 +310,12 @@ class CodeGenTypes {
       CanQualType returnType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
       FunctionType::ExtInfo info,
       ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
-      RequiredArgs args);
+      RequiredArgs args, unsigned X86AVXABILevel);
+  const CGFunctionInfo &arrangeLLVMFunctionInfo(
+      CanQualType returnType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
+      FunctionType::ExtInfo info,
+      ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
+      RequiredArgs args, const FunctionDecl *FD = nullptr);
 
   /// Compute a new LLVM record layout object for the given record.
   std::unique_ptr<CGRecordLayout> ComputeRecordLayout(const RecordDecl *D,
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 61ab591f55be9..b63c6ad9c2c60 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2961,6 +2961,19 @@ X86_64ABIInfo::classifyRegCallStructType(QualType Ty, unsigned &NeededInt,
 }
 
 void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
+  bool shouldRespectFunctionAVXLevel =
+      !getTarget().getTriple().isPS() &&
+      getContext().getLangOpts().getClangABICompat() >
+          LangOptions::ClangABI::Ver22;
+
+  if (shouldRespectFunctionAVXLevel &&
+      FI.getX86AVXABILevel() != static_cast<unsigned>(AVXLevel)) {
+    auto EffectiveAVXLevel =
+        static_cast<X86AVXABILevel>(FI.getX86AVXABILevel());
+    X86_64ABIInfo EffectiveABIInfo(CGT, EffectiveAVXLevel);
+    EffectiveABIInfo.computeInfo(FI);
+    return;
+  }
 
   const unsigned CallingConv = FI.getCallingConvention();
   // It is possible to force Win64 calling convention on any x86_64 target by
diff --git a/clang/test/CodeGen/sysv_abi.c b/clang/test/CodeGen/sysv_abi.c
index a66ecc6e26242..81d2b26a09629 100644
--- a/clang/test/CodeGen/sysv_abi.c
+++ b/clang/test/CodeGen/sysv_abi.c
@@ -53,3 +53,21 @@ void use_vectors(void) {
 // NOAVX: call {{(x86_64_sysvcc )?}}void @take_m256(ptr noundef byval(<8 x float>) align 32 %{{.*}})
 // NOAVX: call {{(x86_64_sysvcc )?}}<16 x float> @get_m512()
 // NOAVX: call {{(x86_64_sysvcc )?}}void @take_m512(ptr noundef byval(<16 x float>) align 64 %{{.*}})
+
+// Added test to explicitly cover the case when __attribute__((target("avx"))) is used 
+// with __attribute__((sysv_abi))
+
+__attribute__((target("avx"))) my_m256 SYSV_CC get_avx_m256(void);
+__attribute__((target("avx"))) void SYSV_CC take_avx_m256(my_m256);
+
+__attribute__((target("avx")))
+void use_target_attr_vectors(void) {
+  my_m256 v = get_avx_m256();
+  take_avx_m256(v);
+}
+
+// CHECK: define {{(dso_local )?}}void @use_target_attr_vectors()
+// AVX: call {{(x86_64_sysvcc )?}}<8 x float> @get_avx_m256()
+// AVX: call {{(x86_64_sysvcc )?}}void @take_avx_m256(<8 x float> noundef %{{.*}})
+// NOAVX: call {{(x86_64_sysvcc )?}}<8 x float> @get_avx_m256()
+// NOAVX: call {{(x86_64_sysvcc )?}}void @take_avx_m256(<8 x float> noundef %{{.*}})
diff --git a/clang/test/CodeGen/target-avx-function-abi.c b/clang/test/CodeGen/target-avx-function-abi.c
new file mode 100644
index 0000000000000..6ea0fd39a29f1
--- /dev/null
+++ b/clang/test/CodeGen/target-avx-function-abi.c
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=SYSV
+// RUN: %clang_cc1 -triple x86_64-scei-ps4 -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=PS
+// RUN: %clang_cc1 -triple x86_64-sie-ps5 -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=PS
+
+typedef float v8f __attribute__((vector_size(32)));
+typedef float v16f __attribute__((vector_size(64)));
+
+v8f g256(v8f x) { return x; }
+v16f g512(v16f x) { return x; }
+
+__attribute__((target("avx"))) v8f l256(v8f x) { return x; }
+__attribute__((target("avx512f"))) v16f l512(v16f x) { return x; }
+
+__attribute__((target("avx"))) v8f call_l256(v8f x) { return l256(x); }
+__attribute__((target("avx512f"))) v16f call_l512(v16f x) { return l512(x); }
+
+__attribute__((target("avx"))) v8f call_ptr_l256(v8f x) {
+  v8f (*fp)(v8f) = l256;
+  return fp(x);
+}
+
+__attribute__((target("avx512f"))) v16f call_ptr_l512(v16f x) {
+  v16f (*fp)(v16f) = l512;
+  return fp(x);
+}
+
+// SYSV-LABEL: define dso_local <8 x float> @g256(
+// SYSV: byval(<8 x float>) align 32
+
+// SYSV-LABEL: define dso_local <16 x float> @g512(
+// SYSV: byval(<16 x float>) align 64
+
+// SYSV-LABEL: define dso_local <8 x float> @l256(<8 x float> noundef %x)
+// SYSV-LABEL: define dso_local <16 x float> @l512(<16 x float> noundef %x)
+
+// SYSV-LABEL: define dso_local <8 x float> @call_l256(<8 x float> noundef %x)
+// SYSV: call <8 x float> @l256(<8 x float> noundef
+
+// SYSV-LABEL: define dso_local <16 x float> @call_l512(<16 x float> noundef %x)
+// SYSV: call <16 x float> @l512(<16 x float> noundef
+
+// SYSV-LABEL: define dso_local <8 x float> @call_ptr_l256(<8 x float> noundef %x)
+// SYSV: call <8 x float> %{{.*}}(<8 x float> noundef
+
+// SYSV-LABEL: define dso_local <16 x float> @call_ptr_l512(<16 x float> noundef %x)
+// SYSV: call <16 x float> %{{.*}}(<16 x float> noundef
+
+// PlayStation keeps the legacy ABI which always returns AVX vectors in registers & only uses AVX level from module/TU level even with AVX target attributes.
+// PS-LABEL: define dso_local <8 x float> @g256(
+// PS: byval(<8 x float>) align 32
+
+// PS-LABEL: define dso_local <16 x float> @g512(
+// PS: byval(<16 x float>) align 64
+
+// PS-LABEL: define dso_local <8 x float> @l256(
+// PS: byval(<8 x float>) align 32
+
+// PS-LABEL: define dso_local <16 x float> @l512(
+// PS: byval(<16 x float>) align 64
+
+// PS-LABEL: define dso_local <8 x float> @call_l256(
+// PS: call <8 x float> @l256(ptr noundef byval(<8 x float>) align 32
+
+// PS-LABEL: define dso_local <16 x float> @call_l512(
+// PS: call <16 x float> @l512(ptr noundef byval(<16 x float>) align 64
+
+// PS-LABEL: define dso_local <8 x float> @call_ptr_l256(
+// PS: call <8 x float> %{{.*}}(ptr noundef byval(<8 x float>) align 32
+
+// PS-LABEL: define dso_local <16 x float> @call_ptr_l512(
+// PS: call <16 x float> %{{.*}}(ptr noundef byval(<16 x float>) align 64
diff --git a/clang/test/CodeGenCXX/target-avx-method-abi.cpp b/clang/test/CodeGenCXX/target-avx-method-abi.cpp
new file mode 100644
index 0000000000000..47bd1d3ca8c83
--- /dev/null
+++ b/clang/test/CodeGenCXX/target-avx-method-abi.cpp
@@ -0,0 +1,121 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=SYSV
+// RUN: %clang_cc1 -triple x86_64-scei-ps4 -std=c++20 -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=PS
+// RUN: %clang_cc1 -triple x86_64-sie-ps5 -std=c++20 -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=PS
+
+typedef float v8f __attribute__((vector_size(32)));
+typedef float v16f __attribute__((vector_size(64)));
+
+struct S {
+  __attribute__((target("avx"))) 
+  v8f m(v8f x) { return x; }
+};
+
+struct C {
+  v8f field;
+  __attribute__((target("avx"))) 
+  C(v8f x) : field(x) {}
+};
+
+__attribute__((target("avx"))) 
+v8f callm(S *s, v8f x) { 
+  return s->m(x); 
+}
+
+__attribute__((target("avx"))) 
+v8f callctor(v8f x) {
+  C c(x);
+  return c.field;
+}
+
+__attribute__((target("avx")))
+v8f callm_ptr(S *s, v8f x) {
+  v8f (S::*pmf)(v8f) = &S::m;
+  return (s->*pmf)(x);
+}
+
+struct S512 {
+  __attribute__((target("avx512f")))
+  v16f m512(v16f x) { return x; }
+};
+
+struct D512 {
+  v16f field;
+  __attribute__((target("avx512f")))
+  D512(v16f x) : field(x) {}
+};
+
+__attribute__((target("avx512f")))
+v16f callm512(S512 *s, v16f x) {
+  return s->m512(x);
+}
+
+__attribute__((target("avx512f")))
+v16f callctor512(v16f x) {
+  D512 c(x);
+  return c.field;
+}
+
+__attribute__((target("avx512f")))
+v16f callm512_ptr(S512 *s, v16f x) {
+  v16f (S512::*pmf)(v16f) = &S512::m512;
+  return (s->*pmf)(x);
+}
+
+// Desired ABI behavior: AVX-targeted member functions should pass/return AVX
+// vectors directly, just like AVX-targeted free functions.
+// SYSV-LABEL: define dso_local noundef <8 x float> @_Z5callmP1SDv8_f(
+// SYSV: call noundef <8 x float> @_ZN1S1mEDv8_f(ptr noundef
+// SYSV-LABEL: define linkonce_odr noundef <8 x float> @_ZN1S1mEDv8_f(
+// SYSV-SAME: ptr noundef nonnull align 1 dereferenceable(1) %this, <8 x float> noundef %x)
+// SYSV-LABEL: define dso_local noundef <8 x float> @_Z8callctorDv8_f(
+// SYSV: call void @_ZN1CC1EDv8_f(ptr noundef nonnull align 32 dereferenceable(32)
+// SYSV-SAME: <8 x float> noundef
+// SYSV-LABEL: define linkonce_odr void @_ZN1CC1EDv8_f(
+// SYSV-SAME: ptr noundef nonnull align 32 dereferenceable(32) %this, <8 x float> noundef %x)
+// SYSV-LABEL: define dso_local noundef <8 x float> @_Z9callm_ptrP1SDv8_f(
+// SYSV-SAME: ptr noundef %s, <8 x float> noundef %x)
+// SYSV: call noundef <8 x float> %{{.*}}(ptr noundef nonnull align 1 dereferenceable(1) %{{.*}}, <8 x float> noundef
+// SYSV-LABEL: define dso_local noundef <16 x float> @_Z8callm512P4S512Dv16_f(
+// SYSV: call noundef <16 x float> @_ZN4S5124m512EDv16_f(ptr noundef
+// SYSV-LABEL: define linkonce_odr noundef <16 x float> @_ZN4S5124m512EDv16_f(
+// SYSV-SAME: ptr noundef nonnull align 1 dereferenceable(1) %this, <16 x float> noundef %x)
+// SYSV-LABEL: define dso_local noundef <16 x float> @_Z11callctor512Dv16_f(
+// SYSV: call void @_ZN4D512C1EDv16_f(ptr noundef nonnull align 64 dereferenceable(64)
+// SYSV-SAME: <16 x float> noundef
+// SYSV-LABEL: define linkonce_odr void @_ZN4D512C1EDv16_f(
+// SYSV-SAME: ptr noundef nonnull align 64 dereferenceable(64) %this, <16 x float> noundef %x)
+// SYSV-LABEL: define dso_local noundef <16 x float> @_Z12callm512_ptrP4S512Dv16_f(
+// SYSV-SAME: ptr noundef %s, <16 x float> noundef %x)
+// SYSV: call noundef <16 x float> %{{.*}}(ptr noundef nonnull align 1 dereferenceable(1) %{{.*}}, <16 x float> noundef
+// SYSV-LABEL: define linkonce_odr void @_ZN1CC2EDv8_f(
+// SYSV-SAME: ptr noundef nonnull align 32 dereferenceable(32) %this, <8 x float> noundef %x)
+// SYSV-LABEL: define linkonce_odr void @_ZN4D512C2EDv16_f(
+// SYSV-SAME: ptr noundef nonnull align 64 dereferenceable(64) %this, <16 x float> noundef %x)
+
+// PlayStation keeps the legacy ABI which always returns AVX vectors in registers & only uses AVX level from module/TU level even with AVX target attributes.
+// PS-LABEL: define dso_local noundef <8 x float> @_Z5callmP1SDv8_f(
+// PS: byval(<8 x float>) align 32
+// PS: call noundef <8 x float> @_ZN1S1mEDv8_f(
+// PS-LABEL: define linkonce_odr noundef <8 x float> @_ZN1S1mEDv8_f(
+// PS: byval(<8 x float>) align 32
+// PS-LABEL: define dso_local noundef <8 x float> @_Z8callctorDv8_f(
+// PS-LABEL: define linkonce_odr void @_ZN1CC1EDv8_f(
+// PS-SAME: ptr noundef nonnull align 32 dereferenceable(32) %this, ptr noundef byval(<8 x float>) align 32
+// PS-LABEL: define dso_local noundef <8 x float> @_Z9callm_ptrP1SDv8_f(
+// PS-SAME: ptr noundef %s, ptr noundef byval(<8 x float>) align 32
+// PS: call noundef <8 x float> %{{.*}}(ptr noundef nonnull align 1 dereferenceable(1) %{{.*}}, ptr noundef byval(<8 x float>) align 32
+// PS-LABEL: define dso_local noundef <16 x float> @_Z8callm512P4S512Dv16_f(
+// PS: byval(<16 x float>) align 64
+// PS: call noundef <16 x float> @_ZN4S5124m512EDv16_f(
+// PS-LABEL: define linkonce_odr noundef <16 x float> @_ZN4S5124m512EDv16_f(
+// PS: byval(<16 x float>) align 64
+// PS-LABEL: define dso_local noundef <16 x float> @_Z11callctor512Dv16_f(
+// PS-LABEL: define linkonce_odr void @_ZN4D512C1EDv16_f(
+// PS-SAME: ptr noundef nonnull align 64 dereferenceable(64) %this, ptr noundef byval(<16 x float>) align 64
+// PS-LABEL: define dso_local noundef <16 x float> @_Z12callm512_ptrP4S512Dv16_f(
+// PS-SAME: ptr noundef %s, ptr noundef byval(<16 x float>) align 64
+// PS: call noundef <16 x float> %{{.*}}(ptr noundef nonnull align 1 dereferenceable(1) %{{.*}}, ptr noundef byval(<16 x float>) align 64
+// PS-LABEL: define linkonce_odr void @_ZN1CC2EDv8_f(
+// PS-SAME: ptr noundef nonnull align 32 dereferenceable(32) %this, ptr noundef byval(<8 x float>) align 32
+// PS-LABEL: define linkonce_odr void @_ZN4D512C2EDv16_f(
+// PS-SAME: ptr noundef nonnull align 64 dereferenceable(64) %this, ptr noundef byval(<16 x float>) align 64
diff --git a/clang/unittests/CodeGen/CodeGenExternalTest.cpp b/clang/unittests/CodeGen/CodeGenExternalTest.cpp
index be3be147460f3..2f622474ed98b 100644
--- a/clang/unittests/CodeGen/CodeGenExternalTest.cpp
+++ b/clang/unittests/CodeGen/CodeGenExternalTest.cpp
@@ -10,6 +10,7 @@
 
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
 #include "clang/AST/GlobalDecl.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Basic/TargetInfo.h"
@@ -42,8 +43,10 @@ static const bool DebugThisTest = false;
 
 // forward declarations
 struct MyASTConsumer;
-static void test_codegen_fns(MyASTConsumer *my);
-static bool test_codegen_fns_ran;
+static void test_generic_codegen_fns(MyASTConsumer *my);
+static void test_x86_avx_abi_codegen_fns(MyASTConsumer *my);
+static bool test_generic_codegen_fns_ran;
+static bool test_x86_avx_abi_codegen_fns_ran;
 
 // This forwards the calls to the Clang CodeGenerator
 // so that we can test CodeGen functions while it is open.
@@ -52,13 +55,15 @@ static bool test_codegen_fns_ran;
 // before forwarding that function to the CodeGenerator.
 
 struct MyASTConsumer : public ASTConsumer {
+  using TestFn = void (*)(MyASTConsumer *);
+
   std::unique_ptr<CodeGenerator> Builder;
+  TestFn TestFunction;
   std::vector<Decl*> toplevel_decls;
 
-  MyASTConsumer(std::unique_ptr<CodeGenerator> Builder_in)
-    : ASTConsumer(), Builder(std::move(Builder_in))
-  {
-  }
+  MyASTConsumer(std::unique_ptr<CodeGenerator> Builder_in, TestFn TestFunction)
+      : ASTConsumer(), Builder(std::move(Builder_in)),
+        TestFunction(TestFunction) {}
 
   ~MyASTConsumer() { }
 
@@ -104,7 +109,7 @@ void MyASTConsumer::HandleInterestingDecl(DeclGroupRef D) {
 }
 
 void MyASTConsumer::HandleTranslationUnit(ASTContext &Context) {
-  test_codegen_fns(this);
+  TestFunction(this);
   // HandleTranslationUnit can close the module
   Builder->HandleTranslationUnit(Context);
 }
@@ -161,13 +166,30 @@ bool MyASTConsumer::shouldSkipFunctionBody(Decl *D) {
   return Builder->shouldSkipFunctionBody(D);
 }
 
-const char TestProgram[] =
+const char GenericTestProgram[] =
     "struct mytest_struct { char x; short y; char p; long z; };\n"
     "int mytest_fn(int x) { return x; }\n";
 
-// This function has the real test code here
-static void test_codegen_fns(MyASTConsumer *my) {
-
+const char X86AVXABITestProgram[] =
+    "typedef float mytest_v8f __attribute__((vector_size(32)));\n"
+    "struct mytest_avx_method_holder {\n"
+    "  __attribute__((target(\"avx\"))) mytest_v8f method(mytest_v8f x) {\n"
+    "    return x;\n"
+    "  }\n"
+    "};\n"
+    "__attribute__((target(\"avx\"))) mytest_v8f mytest_avx_fn(mytest_v8f x) "
+    "{\n"
+    "  return x;\n"
+    "}\n"
+    "__attribute__((target(\"avx\"))) void caller() "
+    "{\n"
+    "  mytest_v8f hello = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};\n"
+    "  mytest_avx_fn(hello);\n"
+    "  mytest_avx_method_holder holder = mytest_avx_method_holder();\n"
+    "  holder.method(hello);\n"
+    "}\n";
+
+static void test_generic_codegen_fns(MyASTConsumer *my) {
   bool mytest_fn_ok = false;
   bool mytest_struct_ok = false;
 
@@ -254,7 +276,73 @@ static void test_codegen_fns(MyASTConsumer *my) {
   ASSERT_TRUE(mytest_fn_ok);
   ASSERT_TRUE(mytest_struct_ok);
 
-  test_codegen_fns_ran = true;
+  test_generic_codegen_fns_ran = true;
+}
+
+static void test_x86_avx_abi_codegen_fns(MyASTConsumer *my) {
+  bool mytest_avx_fn_ok = false;
+  bool mytest_avx_method_ok = false;
+
+  CodeGen::CodeGenModule &CGM = my->Builder->CGM();
+  const ASTContext &Ctx = my->toplevel_decls.front()->getASTContext();
+
+  // First get the caller decl, which we need to determine call ABI
+  FunctionDecl *callerDecl = nullptr;
+  for (auto decl : my->toplevel_decls) {
+    if (FunctionDecl *fd = dyn_cast<FunctionDecl>(decl)) {
+      if (fd->getName() != "caller")
+        continue;
+
+      callerDecl = fd;
+      break;
+    }
+  }
+
+  for (auto decl : my->toplevel_decls) {
+    if (FunctionDecl *fd = dyn_cast<FunctionDecl>(decl)) {
+      if (fd->getName() != "mytest_avx_fn")
+        continue;
+
+      const auto *FPT = fd->getType()->castAs<FunctionProtoType>();
+      SmallVector<CanQualType, 4> ArgTypes;
+      for (const ParmVarDecl *Param : fd->parameters())
+        ArgTypes.push_back(Ctx.getCanonicalParamType(Param->getType()));
+
+      const CodeGen::CGFunctionInfo &FnInfo = CodeGen::arrangeFreeFunctionCall(
+          CGM, Ctx.getCanonicalType(FPT->getReturnType()), ArgTypes,
+          FPT->getExtInfo(), {},
+          CodeGen::RequiredArgs::forPrototypePlus(FPT, 0), callerDecl);
+      ASSERT_EQ(FnInfo.getX86AVXABILevel(), 1U);
+      ASSERT_TRUE(FnInfo.getReturnInfo().isDirect());
+      ASSERT_TRUE(FnInfo.arg_begin()->info.isDirect());
+      mytest_avx_fn_ok = true;
+    } else if (RecordDecl *rd = dyn_cast<RecordDecl>(decl)) {
+      if (rd->getName() != "mytest_avx_method_holder")
+        continue;
+
+      const auto *MethodRD = cast<CXXRecordDecl>(rd->getDefinition());
+      const auto *MD = cast<CXXMethodDecl>(*MethodRD->method_begin());
+      const auto *FPT = MD->getType()->castAs<FunctionProtoType>();
+      SmallVector<CanQualType, 4> ArgTypes;
+      ArgTypes.push_back(Ctx.getCanonicalParamType(MD->getThisType()));
+      for (const ParmVarDecl *Param : MD->parameters())
+        ArgTypes.push_back(Ctx.getCanonicalParamType(Param->getType()));
+
+      const CodeGen::CGFunctionInfo &FnInfo = CodeGen::arrangeCXXMethodCall(
+          CGM, Ctx.getCanonicalType(FPT->getReturnType()), ArgTypes,
+          FPT->getExtInfo(), {},
+          CodeGen::RequiredArgs::forPrototypePlus(FPT, 1), callerDecl);
+      ASSERT_EQ(FnInfo.getX86AVXABILevel(), 1u);
+      ASSERT_TRUE(FnInfo.getReturnInfo().isDirect());
+      ASSERT_TRUE(FnInfo.arg_begin()[1].info.isDirect());
+      mytest_avx_method_ok = true;
+    }
+  }
+
+  ASSERT_TRUE(mytest_avx_fn_ok);
+  ASSERT_TRUE(mytest_avx_method_ok);
+
+  test_x86_avx_abi_codegen_fns_ran = true;
 }
 
 TEST(CodeGenExternalTest, CodeGenExternalTest) {
@@ -262,14 +350,30 @@ TEST(CodeGenExternalTest, CodeGenExternalTest) {
   LO.CPlusPlus = 1;
   LO.CPlusPlus11 = 1;
   TestCompiler Compiler(LO);
-  auto CustomASTConsumer
-    = std::make_unique<MyASTConsumer>(std::move(Compiler.CG));
+  auto CustomASTConsumer = std::make_unique<MyASTConsumer>(
+      std::move(Compiler.CG), test_generic_codegen_fns);
+
+  Compiler.init(GenericTestProgram, std::move(CustomASTConsumer));
+
+  clang::ParseAST(Compiler.compiler.getSema(), false, false);
+
+  ASSERT_TRUE(test_generic_codegen_fns_ran);
+}
+
+TEST(CodeGenExternalTest, X86AVXABIQuery) {
+  clang::LangOptions LO;
+  LO.CPlusPlus = 1;
+  LO.CPlusPlus11 = 1;
+  TestCompiler Compiler(LO, clang::CodeGenOptions(),
+                        "x86_64-unknown-linux-gnu");
+  auto CustomASTConsumer = std::make_unique<MyASTConsumer>(
+      std::move(Compiler.CG), test_x86_avx_abi_codegen_fns);
 
-  Compiler.init(TestProgram, std::move(CustomASTConsumer));
+  Compiler.init(X86AVXABITestProgram, std::move(CustomASTConsumer));
 
   clang::ParseAST(Compiler.compiler.getSema(), false, false);
 
-  ASSERT_TRUE(test_codegen_fns_ran);
+  ASSERT_TRUE(test_x86_avx_abi_codegen_fns_ran);
 }
 
 } // end anonymous namespace
diff --git a/clang/unittests/CodeGen/TestCompiler.h b/clang/unittests/CodeGen/TestCompiler.h
index 18947584bd0b3..3ba839979b867 100644
--- a/clang/unittests/CodeGen/TestCompiler.h
+++ b/clang/unittests/CodeGen/TestCompiler.h
@@ -33,17 +33,21 @@ struct TestCompiler {
   unsigned PtrSize = 0;
 
   TestCompiler(clang::LangOptions LO,
-               clang::CodeGenOptions CGO = clang::CodeGenOptions()) {
+               clang::CodeGenOptions CGO = clang::CodeGenOptions(),
+               llvm::StringRef TripleStr = "") {
     compiler.getLangOpts() = LO;
     compiler.getCodeGenOpts() = CGO;
     compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem());
     compiler.createDiagnostics();
 
-    std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple());
-    llvm::Triple Tr(TrStr);
-    Tr.setOS(Triple::Linux);
-    Tr.setVendor(Triple::VendorType::UnknownVendor);
-    Tr.setEnvironment(Triple::EnvironmentType::UnknownEnvironment);
+    llvm::Triple Tr(TripleStr.empty()
+                        ? llvm::Triple::normalize(llvm::sys::getProcessTriple())
+                        : llvm::Triple::normalize(TripleStr));
+    if (TripleStr.empty()) {
+      Tr.setOS(Triple::Linux);
+      Tr.setVendor(Triple::VendorType::UnknownVendor);
+      Tr.setEnvironment(Triple::EnvironmentType::UnknownEnvironment);
+    }
     compiler.getTargetOpts().Triple = Tr.getTriple();
     compiler.setTarget(clang::TargetInfo::CreateTargetInfo(
         compiler.getDiagnostics(), compiler.getTargetOpts()));

>From 46f5c750839be2f37d09df170b41ca191ed9c1c8 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Thu, 14 May 2026 16:17:25 +0900
Subject: [PATCH 02/13] Pass caller or callee FunctionDecl down to
 ABIInfo::computeInfo to derive the correct per function AVX level instead of
 exposing AVX ABI details at higher levels, also allow targets other than
 x86_64 to customize ABI based on caller or callee FD

---
 clang/include/clang/CodeGen/CGFunctionInfo.h  | 19 ++--
 clang/lib/CodeGen/CGCall.cpp                  | 93 ++++++++-----------
 clang/lib/CodeGen/CGClass.cpp                 |  4 +-
 clang/lib/CodeGen/CGExpr.cpp                  |  2 +-
 clang/lib/CodeGen/CGExprCXX.cpp               | 16 ++--
 clang/lib/CodeGen/CodeGenABITypes.cpp         |  5 +-
 clang/lib/CodeGen/CodeGenFunction.cpp         |  6 +-
 clang/lib/CodeGen/CodeGenFunction.h           |  2 +-
 clang/lib/CodeGen/CodeGenTypes.h              | 31 +++----
 clang/lib/CodeGen/Targets/Mips.cpp            |  1 +
 clang/lib/CodeGen/Targets/X86.cpp             | 11 ++-
 .../unittests/CodeGen/CodeGenExternalTest.cpp |  4 +-
 12 files changed, 86 insertions(+), 108 deletions(-)

diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h
index a394d18780e6e..aa41b1dff367d 100644
--- a/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -653,9 +653,8 @@ class CGFunctionInfo final
   /// Log 2 of the maximum vector width.
   unsigned MaxVectorWidth : 4;
 
-  /// Effective x86 AVX ABI level used during ABI classification. Used to
-  /// support target attributes.
-  unsigned X86AVXABILevel : 2;
+  /// Declaration context used to derive target-specific ABI classification.
+  const FunctionDecl *ABIInfoFD = nullptr;
 
   RequiredArgs Required;
 
@@ -687,7 +686,7 @@ class CGFunctionInfo final
 public:
   static CGFunctionInfo *
   create(unsigned llvmCC, bool instanceMethod, bool chainCall,
-         bool delegateCall, unsigned X86AVXABILevel,
+         bool delegateCall, const FunctionDecl *ABIInfoFD,
          const FunctionType::ExtInfo &extInfo,
          ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
          ArrayRef<CanQualType> argTypes, RequiredArgs required);
@@ -814,11 +813,7 @@ class CGFunctionInfo final
     MaxVectorWidth = llvm::countr_zero(Width) + 1;
   }
 
-  unsigned getX86AVXABILevel() const { return X86AVXABILevel; }
-  void setX86AVXABILevel(unsigned Level) {
-    assert(Level <= 2 && "invalid AVX ABI level");
-    X86AVXABILevel = Level;
-  }
+  const FunctionDecl *getABIInfoFD() const { return ABIInfoFD; }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
     ID.AddInteger(getASTCallingConvention());
@@ -832,7 +827,7 @@ class CGFunctionInfo final
     ID.AddInteger(RegParm);
     ID.AddBoolean(NoCfCheck);
     ID.AddBoolean(CmseNSCall);
-    ID.AddInteger(X86AVXABILevel);
+    ID.AddPointer(ABIInfoFD);
     ID.AddInteger(Required.getOpaqueData());
     ID.AddBoolean(HasExtParameterInfos);
     if (HasExtParameterInfos) {
@@ -845,7 +840,7 @@ class CGFunctionInfo final
   }
   static void Profile(llvm::FoldingSetNodeID &ID, bool InstanceMethod,
                       bool ChainCall, bool IsDelegateCall,
-                      unsigned X86AVXABILevel,
+                      const FunctionDecl *ABIInfoFD,
                       const FunctionType::ExtInfo &info,
                       ArrayRef<ExtParameterInfo> paramInfos,
                       RequiredArgs required, CanQualType resultType,
@@ -861,7 +856,7 @@ class CGFunctionInfo final
     ID.AddInteger(info.getRegParm());
     ID.AddBoolean(info.getNoCfCheck());
     ID.AddBoolean(info.getCmseNSCall());
-    ID.AddInteger(X86AVXABILevel);
+    ID.AddPointer(ABIInfoFD);
     ID.AddInteger(required.getOpaqueData());
     ID.AddBoolean(!paramInfos.empty());
     if (!paramInfos.empty()) {
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 62270584a7022..61461885e4f01 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -504,15 +504,15 @@ getExtParameterInfosForCall(const FunctionProtoType *proto, unsigned prefixArgs,
 const CGFunctionInfo &CodeGenTypes::arrangeCXXConstructorCall(
     const CallArgList &args, const CXXConstructorDecl *D, CXXCtorType CtorKind,
     unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs, bool PassProtoArgs) {
-  return arrangeCXXConstructorCall(
-      args, D, CtorKind, ExtraPrefixArgs, ExtraSuffixArgs,
-      CGM.getDefaultX86AVXABILevel(), PassProtoArgs);
+  return arrangeCXXConstructorCall(args, D, CtorKind, ExtraPrefixArgs,
+                                   ExtraSuffixArgs,
+                                   /*FD=*/nullptr, PassProtoArgs);
 }
 
 const CGFunctionInfo &CodeGenTypes::arrangeCXXConstructorCall(
     const CallArgList &args, const CXXConstructorDecl *D, CXXCtorType CtorKind,
-    unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs, unsigned X86AVXABILevel,
-    bool PassProtoArgs) {
+    unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs,
+    const FunctionDecl *ABIInfoFD, bool PassProtoArgs) {
   CanQualTypeList ArgTypes;
   for (const auto &Arg : args)
     ArgTypes.push_back(Context.getCanonicalParamType(Arg.Ty));
@@ -544,7 +544,7 @@ const CGFunctionInfo &CodeGenTypes::arrangeCXXConstructorCall(
 
   return arrangeLLVMFunctionInfo(ResultType, FnInfoOpts::IsInstanceMethod,
                                  ArgTypes, Info, ParamInfos, Required,
-                                 X86AVXABILevel);
+                                 ABIInfoFD);
 }
 
 /// Arrange the argument and result information for the declaration or
@@ -642,7 +642,8 @@ CodeGenTypes::arrangeUnprototypedObjCMessageSend(QualType returnType,
   FunctionType::ExtInfo einfo;
 
   return arrangeLLVMFunctionInfo(GetReturnType(returnType), FnInfoOpts::None,
-                                 argTypes, einfo, {}, RequiredArgs::All);
+                                 argTypes, einfo, {}, RequiredArgs::All,
+                                 nullptr);
 }
 
 const CGFunctionInfo &CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) {
@@ -694,7 +695,7 @@ static const CGFunctionInfo &
 arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, CodeGenModule &CGM,
                             const CallArgList &args, const FunctionType *fnType,
                             unsigned numExtraRequiredArgs, bool chainCall,
-                            unsigned X86AVXABILevel) {
+                            const FunctionDecl *ABIInfoFD) {
   assert(args.size() >= numExtraRequiredArgs);
 
   ExtParameterInfoList paramInfos;
@@ -727,7 +728,7 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, CodeGenModule &CGM,
   FnInfoOpts opts = chainCall ? FnInfoOpts::IsChainCall : FnInfoOpts::None;
   return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()),
                                      opts, argTypes, fnType->getExtInfo(),
-                                     paramInfos, required, X86AVXABILevel);
+                                     paramInfos, required, ABIInfoFD);
 }
 
 /// Figure out the rules for calling a function with the given formal
@@ -736,17 +737,14 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, CodeGenModule &CGM,
 /// target-dependent in crazy ways.
 const CGFunctionInfo &CodeGenTypes::arrangeFreeFunctionCall(
     const CallArgList &args, const FunctionType *fnType, bool chainCall) {
-  return arrangeFreeFunctionCall(
-      args, fnType, chainCall,
-      static_cast<unsigned>(CGM.getDefaultX86AVXABILevel()));
+  return arrangeFreeFunctionCall(args, fnType, chainCall, /*FD=*/nullptr);
 }
 
-const CGFunctionInfo &
-CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
-                                      const FunctionType *fnType,
-                                      bool chainCall, unsigned X86AVXABILevel) {
-  return arrangeFreeFunctionLikeCall(
-      *this, CGM, args, fnType, chainCall ? 1 : 0, chainCall, X86AVXABILevel);
+const CGFunctionInfo &CodeGenTypes::arrangeFreeFunctionCall(
+    const CallArgList &args, const FunctionType *fnType, bool chainCall,
+    const FunctionDecl *ABIInfoFD) {
+  return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType,
+                                     chainCall ? 1 : 0, chainCall, ABIInfoFD);
 }
 
 /// A block function is essentially a free function with an
@@ -754,10 +752,8 @@ CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
 const CGFunctionInfo &
 CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args,
                                        const FunctionType *fnType) {
-  return arrangeFreeFunctionLikeCall(
-      *this, CGM, args, fnType, 1,
-      /*chainCall=*/false,
-      static_cast<unsigned>(CGM.getDefaultX86AVXABILevel()));
+  return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, 1,
+                                     /*chainCall=*/false, nullptr);
 }
 
 const CGFunctionInfo &
@@ -781,7 +777,7 @@ CodeGenTypes::arrangeBuiltinFunctionCall(QualType resultType,
     argTypes.push_back(Context.getCanonicalParamType(Arg.Ty));
   return arrangeLLVMFunctionInfo(GetReturnType(resultType), FnInfoOpts::None,
                                  argTypes, FunctionType::ExtInfo(),
-                                 /*paramInfos=*/{}, RequiredArgs::All);
+                                 /*paramInfos=*/{}, RequiredArgs::All, nullptr);
 }
 
 const CGFunctionInfo &
@@ -818,14 +814,14 @@ const CGFunctionInfo &CodeGenTypes::arrangeDeviceKernelCallerDeclaration(
 const CGFunctionInfo &CodeGenTypes::arrangeCXXMethodCall(
     const CallArgList &args, const FunctionProtoType *proto,
     RequiredArgs required, unsigned numPrefixArgs) {
-  return arrangeCXXMethodCall(
-      args, proto, required, numPrefixArgs,
-      static_cast<unsigned>(CGM.getDefaultX86AVXABILevel()));
+  return arrangeCXXMethodCall(args, proto, required, numPrefixArgs,
+                              /*FD=*/nullptr);
 }
 
 const CGFunctionInfo &CodeGenTypes::arrangeCXXMethodCall(
     const CallArgList &args, const FunctionProtoType *proto,
-    RequiredArgs required, unsigned numPrefixArgs, unsigned X86AVXABILevel) {
+    RequiredArgs required, unsigned numPrefixArgs,
+    const FunctionDecl *ABIInfoFD) {
   assert(numPrefixArgs + 1 <= args.size() &&
          "Emitting a call with less args than the required prefix?");
   // Add one to account for `this`. It's a bit awkward here, but we don't count
@@ -838,7 +834,7 @@ const CGFunctionInfo &CodeGenTypes::arrangeCXXMethodCall(
   FunctionType::ExtInfo info = proto->getExtInfo();
   return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()),
                                  FnInfoOpts::IsInstanceMethod, argTypes, info,
-                                 paramInfos, required, X86AVXABILevel);
+                                 paramInfos, required, ABIInfoFD);
 }
 
 const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
@@ -849,15 +845,15 @@ const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
 
 const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
                                                 const CallArgList &args) {
-  return arrangeCall(signature, args,
-                     static_cast<unsigned>(CGM.getDefaultX86AVXABILevel()));
+  return arrangeCall(signature, args, /*FD=*/nullptr);
 }
 
 const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
                                                 const CallArgList &args,
-                                                unsigned X86AVXABILevel) {
+                                                const FunctionDecl *ABIInfoFD) {
   assert(signature.arg_size() <= args.size());
-  if (signature.arg_size() == args.size())
+  if (signature.arg_size() == args.size() &&
+      signature.getABIInfoFD() == ABIInfoFD)
     return signature;
 
   ExtParameterInfoList paramInfos;
@@ -880,9 +876,8 @@ const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
 
   const CGFunctionInfo *newFI = findOrInsertCGFunctionInfo(
       signature.isInstanceMethod(), signature.isChainCall(),
-      signature.isDelegateCall(), X86AVXABILevel, signature.getExtInfo(),
-      paramInfos, signature.getRequiredArgs(), signature.getReturnType(),
-      argTypes);
+      signature.isDelegateCall(), ABIInfoFD, signature.getExtInfo(), paramInfos,
+      signature.getRequiredArgs(), signature.getReturnType(), argTypes);
   return *newFI;
 }
 
@@ -953,16 +948,6 @@ ABIArgInfo CodeGenModule::convertABIArgInfo(const llvm::abi::ArgInfo &AbiInfo,
   llvm_unreachable("Unexpected llvm::abi::ArgInfo kind");
 }
 
-const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
-    CanQualType resultType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
-    FunctionType::ExtInfo info,
-    ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
-    RequiredArgs required, const FunctionDecl *FD) {
-  return arrangeLLVMFunctionInfo(
-      resultType, opts, argTypes, info, paramInfos, required,
-      static_cast<unsigned>(CGM.getEffectiveX86AVXABILevel(FD)));
-}
-
 /// Arrange the argument and result information for an abstract value
 /// of a given function type.  This is the method which all of the
 /// above functions ultimately defer to.
@@ -970,7 +955,7 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
     CanQualType resultType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
     FunctionType::ExtInfo info,
     ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
-    RequiredArgs required, unsigned X86AVXABILevel) {
+    RequiredArgs required, const FunctionDecl *ABIInfoFD) {
   assert(llvm::all_of(argTypes,
                       [](CanQualType T) { return T.isCanonicalAsParam(); }));
 
@@ -984,21 +969,21 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
       (opts & FnInfoOpts::IsDelegateCall) == FnInfoOpts::IsDelegateCall;
 
   const CGFunctionInfo *newFI = findOrInsertCGFunctionInfo(
-      isInstanceMethod, isChainCall, isDelegateCall, X86AVXABILevel, info,
+      isInstanceMethod, isChainCall, isDelegateCall, ABIInfoFD, info,
       paramInfos, required, resultType, argTypes);
   return *newFI;
 }
 
 CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
     bool isInstanceMethod, bool isChainCall, bool isDelegateCall,
-    unsigned X86AVXABILevel, const FunctionType::ExtInfo &info,
+    const FunctionDecl *ABIInfoFD, const FunctionType::ExtInfo &info,
     ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
     RequiredArgs required, CanQualType resultType,
     ArrayRef<CanQualType> argTypes) {
   llvm::FoldingSetNodeID ID;
   CGFunctionInfo::Profile(ID, isInstanceMethod, isChainCall, isDelegateCall,
-                          X86AVXABILevel, info, paramInfos, required,
-                          resultType, argTypes);
+                          ABIInfoFD, info, paramInfos, required, resultType,
+                          argTypes);
 
   void *insertPos = nullptr;
   CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos);
@@ -1009,8 +994,8 @@ CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
 
   // Construct the function info.  We co-allocate the ArgInfos.
   FI = CGFunctionInfo::create(CC, isInstanceMethod, isChainCall, isDelegateCall,
-                              X86AVXABILevel, info, paramInfos, resultType,
-                              argTypes, required);
+                              ABIInfoFD, info, paramInfos, resultType, argTypes,
+                              required);
   FunctionInfos.InsertNode(FI, insertPos);
 
   bool inserted = FunctionsBeingProcessed.insert(FI).second;
@@ -1054,7 +1039,7 @@ CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
 
 CGFunctionInfo *CGFunctionInfo::create(
     unsigned llvmCC, bool instanceMethod, bool chainCall, bool delegateCall,
-    unsigned X86AVXABILevel, const FunctionType::ExtInfo &info,
+    const FunctionDecl *ABIInfoFD, const FunctionType::ExtInfo &info,
     ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
     ArrayRef<CanQualType> argTypes, RequiredArgs required) {
   assert(paramInfos.empty() || paramInfos.size() == argTypes.size());
@@ -1079,7 +1064,7 @@ CGFunctionInfo *CGFunctionInfo::create(
   FI->Required = required;
   FI->HasRegParm = info.getHasRegParm();
   FI->RegParm = info.getRegParm();
-  FI->X86AVXABILevel = X86AVXABILevel;
+  FI->ABIInfoFD = ABIInfoFD;
   FI->ArgStruct = nullptr;
   FI->ArgStructAlign = 0;
   FI->NumArgs = argTypes.size();
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 149fe1e71ffce..1ad6da0cee676 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -2317,7 +2317,7 @@ static bool canEmitDelegateCallArgs(CodeGenFunction &CGF,
 
     // Likewise if they're inalloca.
     const CGFunctionInfo &Info = CGF.CGM.getTypes().arrangeCXXConstructorCall(
-        Args, Ctor, Type, 0, 0, CGF.getCurrentFunctionX86AVXABILevel());
+        Args, Ctor, Type, 0, 0, CGF.getCurrentFunctionDecl());
     if (Info.usesInAlloca())
       return false;
   }
@@ -2378,7 +2378,7 @@ void CodeGenFunction::EmitCXXConstructorCall(
   llvm::Constant *CalleePtr = CGM.getAddrOfCXXStructor(GlobalDecl(D, Type));
   const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall(
       Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix,
-      getCurrentFunctionX86AVXABILevel(), PassPrototypeArgs);
+      getCurrentFunctionDecl(), PassPrototypeArgs);
   CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(D, Type));
   EmitCall(Info, Callee, ReturnValueSlot(), Args, CallOrInvoke, false, Loc);
 
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 5fda07432ca36..1c0f92da3b43c 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -7086,7 +7086,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
                E->getDirectCallee(), /*ParamsToSkip=*/0, Order);
 
   const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall(
-      Args, FnType, /*ChainCall=*/Chain, getCurrentFunctionX86AVXABILevel());
+      Args, FnType, /*ChainCall=*/Chain, getCurrentFunctionDecl());
 
   if (ResolvedFnInfo)
     *ResolvedFnInfo = &FnInfo;
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 58a58cf15a7b2..85965b9380384 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -93,7 +93,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
       *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs);
   auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall(
       Args, FPT, CallInfo.ReqArgs, CallInfo.PrefixSize,
-      getCurrentFunctionX86AVXABILevel());
+      getCurrentFunctionDecl());
   return EmitCall(FnInfo, Callee, ReturnValue, Args, CallOrInvoke,
                   CE && CE == MustTailCall,
                   CE ? CE->getExprLoc() : SourceLocation());
@@ -483,9 +483,9 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
 
   // And the rest of the call args
   EmitCallArgs(Args, FPT, E->arguments());
-  return EmitCall(CGM.getTypes().arrangeCXXMethodCall(
-                      Args, FPT, required,
-                      /*PrefixSize=*/0, getCurrentFunctionX86AVXABILevel()),
+  return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required,
+                                                      /*PrefixSize=*/0,
+                                                      getCurrentFunctionDecl()),
                   Callee, ReturnValue, Args, CallOrInvoke, E == MustTailCall,
                   E->getExprLoc());
 }
@@ -1343,10 +1343,10 @@ static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
   llvm::CallBase *CallOrInvoke;
   llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl);
   CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(CalleeDecl));
-  RValue RV = CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(
-                               Args, CalleeType, /*ChainCall=*/false,
-                               CGF.getCurrentFunctionX86AVXABILevel()),
-                           Callee, ReturnValueSlot(), Args, &CallOrInvoke);
+  RValue RV = CGF.EmitCall(
+      CGF.CGM.getTypes().arrangeFreeFunctionCall(
+          Args, CalleeType, /*ChainCall=*/false, CGF.getCurrentFunctionDecl()),
+      Callee, ReturnValueSlot(), Args, &CallOrInvoke);
 
   /// C++1y [expr.new]p10:
   ///   [In a new-expression,] an implementation is allowed to omit a call
diff --git a/clang/lib/CodeGen/CodeGenABITypes.cpp b/clang/lib/CodeGen/CodeGenABITypes.cpp
index 5713f9be37b60..a2f4c6fd9a26a 100644
--- a/clang/lib/CodeGen/CodeGenABITypes.cpp
+++ b/clang/lib/CodeGen/CodeGenABITypes.cpp
@@ -64,7 +64,7 @@ const CGFunctionInfo &CodeGen::arrangeCXXMethodCall(
     const FunctionDecl *CallerFD) {
   return CGM.getTypes().arrangeLLVMFunctionInfo(
       returnType, FnInfoOpts::IsInstanceMethod, argTypes, info, paramInfos,
-      args, static_cast<unsigned>(CGM.getEffectiveX86AVXABILevel(CallerFD)));
+      args, CallerFD);
 }
 
 const CGFunctionInfo &CodeGen::arrangeFreeFunctionCall(
@@ -73,8 +73,7 @@ const CGFunctionInfo &CodeGen::arrangeFreeFunctionCall(
     ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, RequiredArgs args,
     const FunctionDecl *CallerFD) {
   return CGM.getTypes().arrangeLLVMFunctionInfo(
-      returnType, FnInfoOpts::None, argTypes, info, paramInfos, args,
-      static_cast<unsigned>(CGM.getEffectiveX86AVXABILevel(CallerFD)));
+      returnType, FnInfoOpts::None, argTypes, info, paramInfos, args, CallerFD);
 }
 
 ImplicitCXXConstructorArgs
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 53cc191150e95..6e0916d11bee7 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -90,11 +90,11 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
   SetFastMathFlags(CurFPFeatures);
 }
 
-unsigned CodeGenFunction::getCurrentFunctionX86AVXABILevel() const {
+const FunctionDecl *CodeGenFunction::getCurrentFunctionDecl() const {
   const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl);
   if (!FD)
     FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl);
-  return static_cast<unsigned>(CGM.getEffectiveX86AVXABILevel(FD));
+  return FD;
 }
 
 CodeGenFunction::~CodeGenFunction() {
@@ -1618,7 +1618,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
     const FunctionType *FT = cast<FunctionType>(FD->getType());
     CGM.getTargetCodeGenInfo().setOCLKernelStubCallingConvention(FT);
     const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall(
-        CallArgs, FT, /*ChainCall=*/false);
+        CallArgs, FT, /*ChainCall=*/false, getCurrentFunctionDecl());
     llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FnInfo);
     llvm::Constant *GDStubFunctionPointer =
         CGM.getRawFunctionPointer(GDStub, FTy);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 71ac5254f1dd5..5b079a105ca0d 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2234,7 +2234,7 @@ class CodeGenFunction : public CodeGenTypeCache {
   const TargetCodeGenInfo &getTargetHooks() const {
     return CGM.getTargetCodeGenInfo();
   }
-  unsigned getCurrentFunctionX86AVXABILevel() const;
+  const FunctionDecl *getCurrentFunctionDecl() const;
 
   //===--------------------------------------------------------------------===//
   //                                  Cleanups
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 4d8627bc32276..88d6d1e5ea3be 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -33,6 +33,7 @@ template <typename> class CanQual;
 class CXXConstructorDecl;
 class CXXMethodDecl;
 class CodeGenOptions;
+class FunctionDecl;
 class FunctionProtoType;
 class QualType;
 class RecordDecl;
@@ -96,7 +97,7 @@ class CodeGenTypes {
   // Helper to insert CGFunctionInfo objects
   CGFunctionInfo *findOrInsertCGFunctionInfo(
       bool isInstanceMethod, bool isChainCall, bool isDelegateCall,
-      unsigned X86AVXABILevel, const FunctionType::ExtInfo &info,
+      const FunctionDecl *ABIInfoFD, const FunctionType::ExtInfo &info,
       ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
       RequiredArgs required, CanQualType resultType,
       ArrayRef<CanQualType> argTypes);
@@ -215,7 +216,7 @@ class CodeGenTypes {
                                     const CallArgList &args);
   const CGFunctionInfo &arrangeCall(const CGFunctionInfo &declFI,
                                     const CallArgList &args,
-                                    unsigned X86AVXABILevel);
+                                    const FunctionDecl *ABIInfoFD);
 
   /// Free functions are functions that are compatible with an ordinary
   /// C function pointer type.
@@ -226,7 +227,7 @@ class CodeGenTypes {
   const CGFunctionInfo &arrangeFreeFunctionCall(const CallArgList &Args,
                                                 const FunctionType *Ty,
                                                 bool ChainCall,
-                                                unsigned X86AVXABILevel);
+                                                const FunctionDecl *ABIInfoFD);
   const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty);
   const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty);
 
@@ -256,9 +257,9 @@ class CodeGenTypes {
   const CGFunctionInfo &arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD);
   const CGFunctionInfo &arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
                                                         QualType receiverType);
-  const CGFunctionInfo &arrangeUnprototypedObjCMessageSend(
-                                                     QualType returnType,
-                                                     const CallArgList &args);
+  const CGFunctionInfo &
+  arrangeUnprototypedObjCMessageSend(QualType returnType,
+                                     const CallArgList &args);
 
   /// Block invocation functions are C functions with an implicit parameter.
   const CGFunctionInfo &arrangeBlockFunctionDeclaration(
@@ -277,11 +278,10 @@ class CodeGenTypes {
                                                   unsigned ExtraSuffixArgs,
                                                   bool PassProtoArgs = true);
 
-  const CGFunctionInfo &
-  arrangeCXXConstructorCall(const CallArgList &Args,
-                            const CXXConstructorDecl *D, CXXCtorType CtorKind,
-                            unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs,
-                            unsigned X86AVXABILevel, bool PassProtoArgs = true);
+  const CGFunctionInfo &arrangeCXXConstructorCall(
+      const CallArgList &Args, const CXXConstructorDecl *D,
+      CXXCtorType CtorKind, unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs,
+      const FunctionDecl *ABIInfoFD, bool PassProtoArgs = true);
 
   const CGFunctionInfo &arrangeCXXMethodCall(const CallArgList &args,
                                              const FunctionProtoType *type,
@@ -291,7 +291,7 @@ class CodeGenTypes {
                                              const FunctionProtoType *type,
                                              RequiredArgs required,
                                              unsigned numPrefixArgs,
-                                             unsigned X86AVXABILevel);
+                                             const FunctionDecl *ABIInfoFD);
   const CGFunctionInfo &
   arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD);
   const CGFunctionInfo &arrangeMSCtorClosure(const CXXConstructorDecl *CD,
@@ -310,12 +310,7 @@ class CodeGenTypes {
       CanQualType returnType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
       FunctionType::ExtInfo info,
       ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
-      RequiredArgs args, unsigned X86AVXABILevel);
-  const CGFunctionInfo &arrangeLLVMFunctionInfo(
-      CanQualType returnType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
-      FunctionType::ExtInfo info,
-      ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
-      RequiredArgs args, const FunctionDecl *FD = nullptr);
+      RequiredArgs args, const FunctionDecl *ABIInfoFD = nullptr);
 
   /// Compute a new LLVM record layout object for the given record.
   std::unique_ptr<CGRecordLayout> ComputeRecordLayout(const RecordDecl *D,
diff --git a/clang/lib/CodeGen/Targets/Mips.cpp b/clang/lib/CodeGen/Targets/Mips.cpp
index 22fdcd95ea8fa..fee19181b94d6 100644
--- a/clang/lib/CodeGen/Targets/Mips.cpp
+++ b/clang/lib/CodeGen/Targets/Mips.cpp
@@ -8,6 +8,7 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
+#include "clang/AST/Decl.h"
 
 using namespace clang;
 using namespace clang::CodeGen;
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index b63c6ad9c2c60..5a0ea6112533e 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2966,10 +2966,13 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
       getContext().getLangOpts().getClangABICompat() >
           LangOptions::ClangABI::Ver22;
 
-  if (shouldRespectFunctionAVXLevel &&
-      FI.getX86AVXABILevel() != static_cast<unsigned>(AVXLevel)) {
-    auto EffectiveAVXLevel =
-        static_cast<X86AVXABILevel>(FI.getX86AVXABILevel());
+  X86AVXABILevel EffectiveAVXLevel = AVXLevel;
+  if (shouldRespectFunctionAVXLevel && FI.getABIInfoFD()) {
+    EffectiveAVXLevel = static_cast<X86AVXABILevel>(
+        CGT.getCGM().getEffectiveX86AVXABILevel(FI.getABIInfoFD()));
+  }
+
+  if (EffectiveAVXLevel != AVXLevel) {
     X86_64ABIInfo EffectiveABIInfo(CGT, EffectiveAVXLevel);
     EffectiveABIInfo.computeInfo(FI);
     return;
diff --git a/clang/unittests/CodeGen/CodeGenExternalTest.cpp b/clang/unittests/CodeGen/CodeGenExternalTest.cpp
index 2f622474ed98b..df5477e9f7f46 100644
--- a/clang/unittests/CodeGen/CodeGenExternalTest.cpp
+++ b/clang/unittests/CodeGen/CodeGenExternalTest.cpp
@@ -312,7 +312,7 @@ static void test_x86_avx_abi_codegen_fns(MyASTConsumer *my) {
           CGM, Ctx.getCanonicalType(FPT->getReturnType()), ArgTypes,
           FPT->getExtInfo(), {},
           CodeGen::RequiredArgs::forPrototypePlus(FPT, 0), callerDecl);
-      ASSERT_EQ(FnInfo.getX86AVXABILevel(), 1U);
+      ASSERT_EQ(FnInfo.getABIInfoFD(), callerDecl);
       ASSERT_TRUE(FnInfo.getReturnInfo().isDirect());
       ASSERT_TRUE(FnInfo.arg_begin()->info.isDirect());
       mytest_avx_fn_ok = true;
@@ -332,7 +332,7 @@ static void test_x86_avx_abi_codegen_fns(MyASTConsumer *my) {
           CGM, Ctx.getCanonicalType(FPT->getReturnType()), ArgTypes,
           FPT->getExtInfo(), {},
           CodeGen::RequiredArgs::forPrototypePlus(FPT, 1), callerDecl);
-      ASSERT_EQ(FnInfo.getX86AVXABILevel(), 1u);
+      ASSERT_EQ(FnInfo.getABIInfoFD(), callerDecl);
       ASSERT_TRUE(FnInfo.getReturnInfo().isDirect());
       ASSERT_TRUE(FnInfo.arg_begin()[1].info.isDirect());
       mytest_avx_method_ok = true;

>From d0816623e887eab223f5ed591d42e0f4a07eb592 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Fri, 15 May 2026 12:00:06 +0900
Subject: [PATCH 03/13] Replaced FunctionDecl * with ABIInfoKey on
 CGFunctionInfo object since caching on FunctionDecl * would produce more
 cache misses than required

---
 clang/include/clang/CodeGen/CGFunctionInfo.h  | 15 +++--
 clang/lib/CodeGen/ABIInfo.h                   |  9 +++
 clang/lib/CodeGen/CGCall.cpp                  | 22 ++++---
 clang/lib/CodeGen/CodeGenTypes.h              |  2 +-
 clang/lib/CodeGen/Targets/X86.cpp             | 59 ++++++++++++++-----
 .../unittests/CodeGen/CodeGenExternalTest.cpp | 27 ++++++---
 6 files changed, 91 insertions(+), 43 deletions(-)

diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h
index aa41b1dff367d..c55150b185290 100644
--- a/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -17,7 +17,6 @@
 
 #include "clang/AST/CanonicalType.h"
 #include "clang/AST/CharUnits.h"
-#include "clang/AST/Decl.h"
 #include "clang/AST/Type.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/ADT/FoldingSet.h"
@@ -653,8 +652,8 @@ class CGFunctionInfo final
   /// Log 2 of the maximum vector width.
   unsigned MaxVectorWidth : 4;
 
-  /// Declaration context used to derive target-specific ABI classification.
-  const FunctionDecl *ABIInfoFD = nullptr;
+  /// Target-specific ABI classification key.
+  unsigned ABIInfoKey = 0;
 
   RequiredArgs Required;
 
@@ -686,7 +685,7 @@ class CGFunctionInfo final
 public:
   static CGFunctionInfo *
   create(unsigned llvmCC, bool instanceMethod, bool chainCall,
-         bool delegateCall, const FunctionDecl *ABIInfoFD,
+         bool delegateCall, unsigned ABIInfoKey,
          const FunctionType::ExtInfo &extInfo,
          ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
          ArrayRef<CanQualType> argTypes, RequiredArgs required);
@@ -813,7 +812,7 @@ class CGFunctionInfo final
     MaxVectorWidth = llvm::countr_zero(Width) + 1;
   }
 
-  const FunctionDecl *getABIInfoFD() const { return ABIInfoFD; }
+  unsigned getABIInfoKey() const { return ABIInfoKey; }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
     ID.AddInteger(getASTCallingConvention());
@@ -827,7 +826,7 @@ class CGFunctionInfo final
     ID.AddInteger(RegParm);
     ID.AddBoolean(NoCfCheck);
     ID.AddBoolean(CmseNSCall);
-    ID.AddPointer(ABIInfoFD);
+    ID.AddInteger(ABIInfoKey);
     ID.AddInteger(Required.getOpaqueData());
     ID.AddBoolean(HasExtParameterInfos);
     if (HasExtParameterInfos) {
@@ -840,7 +839,7 @@ class CGFunctionInfo final
   }
   static void Profile(llvm::FoldingSetNodeID &ID, bool InstanceMethod,
                       bool ChainCall, bool IsDelegateCall,
-                      const FunctionDecl *ABIInfoFD,
+                      unsigned ABIInfoKey,
                       const FunctionType::ExtInfo &info,
                       ArrayRef<ExtParameterInfo> paramInfos,
                       RequiredArgs required, CanQualType resultType,
@@ -856,7 +855,7 @@ class CGFunctionInfo final
     ID.AddInteger(info.getRegParm());
     ID.AddBoolean(info.getNoCfCheck());
     ID.AddBoolean(info.getCmseNSCall());
-    ID.AddPointer(ABIInfoFD);
+    ID.AddInteger(ABIInfoKey);
     ID.AddInteger(required.getOpaqueData());
     ID.AddBoolean(!paramInfos.empty());
     if (!paramInfos.empty()) {
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h
index 576cf8f742446..9fce25d4e215b 100644
--- a/clang/lib/CodeGen/ABIInfo.h
+++ b/clang/lib/CodeGen/ABIInfo.h
@@ -26,6 +26,7 @@ class FixedVectorType;
 namespace clang {
 class ASTContext;
 class CodeGenOptions;
+class FunctionDecl;
 class TargetInfo;
 
 namespace CodeGen {
@@ -69,6 +70,14 @@ class ABIInfo {
   /// functions.
   llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
 
+  /// Return a target-specific key for ABI information that affects function
+  /// lowering but is not captured by the source signature.
+  virtual unsigned
+  getABIInfoKey(const FunctionDecl *,
+                const FunctionType::ExtInfo &) const {
+    return 0;
+  }
+
   virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const = 0;
 
   /// EmitVAArg - Emit the target dependent code to load a value of
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 61461885e4f01..f19271e8df99a 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -852,8 +852,10 @@ const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
                                                 const CallArgList &args,
                                                 const FunctionDecl *ABIInfoFD) {
   assert(signature.arg_size() <= args.size());
+  unsigned ABIInfoKey =
+      CGM.getABIInfo().getABIInfoKey(ABIInfoFD, signature.getExtInfo());
   if (signature.arg_size() == args.size() &&
-      signature.getABIInfoFD() == ABIInfoFD)
+      signature.getABIInfoKey() == ABIInfoKey)
     return signature;
 
   ExtParameterInfoList paramInfos;
@@ -876,8 +878,9 @@ const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
 
   const CGFunctionInfo *newFI = findOrInsertCGFunctionInfo(
       signature.isInstanceMethod(), signature.isChainCall(),
-      signature.isDelegateCall(), ABIInfoFD, signature.getExtInfo(), paramInfos,
-      signature.getRequiredArgs(), signature.getReturnType(), argTypes);
+      signature.isDelegateCall(), ABIInfoKey, signature.getExtInfo(),
+      paramInfos, signature.getRequiredArgs(), signature.getReturnType(),
+      argTypes);
   return *newFI;
 }
 
@@ -967,22 +970,23 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
       (opts & FnInfoOpts::IsChainCall) == FnInfoOpts::IsChainCall;
   bool isDelegateCall =
       (opts & FnInfoOpts::IsDelegateCall) == FnInfoOpts::IsDelegateCall;
+  unsigned ABIInfoKey = CGM.getABIInfo().getABIInfoKey(ABIInfoFD, info);
 
   const CGFunctionInfo *newFI = findOrInsertCGFunctionInfo(
-      isInstanceMethod, isChainCall, isDelegateCall, ABIInfoFD, info,
+      isInstanceMethod, isChainCall, isDelegateCall, ABIInfoKey, info,
       paramInfos, required, resultType, argTypes);
   return *newFI;
 }
 
 CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
     bool isInstanceMethod, bool isChainCall, bool isDelegateCall,
-    const FunctionDecl *ABIInfoFD, const FunctionType::ExtInfo &info,
+    unsigned ABIInfoKey, const FunctionType::ExtInfo &info,
     ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
     RequiredArgs required, CanQualType resultType,
     ArrayRef<CanQualType> argTypes) {
   llvm::FoldingSetNodeID ID;
   CGFunctionInfo::Profile(ID, isInstanceMethod, isChainCall, isDelegateCall,
-                          ABIInfoFD, info, paramInfos, required, resultType,
+                          ABIInfoKey, info, paramInfos, required, resultType,
                           argTypes);
 
   void *insertPos = nullptr;
@@ -994,7 +998,7 @@ CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
 
   // Construct the function info.  We co-allocate the ArgInfos.
   FI = CGFunctionInfo::create(CC, isInstanceMethod, isChainCall, isDelegateCall,
-                              ABIInfoFD, info, paramInfos, resultType, argTypes,
+                              ABIInfoKey, info, paramInfos, resultType, argTypes,
                               required);
   FunctionInfos.InsertNode(FI, insertPos);
 
@@ -1039,7 +1043,7 @@ CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
 
 CGFunctionInfo *CGFunctionInfo::create(
     unsigned llvmCC, bool instanceMethod, bool chainCall, bool delegateCall,
-    const FunctionDecl *ABIInfoFD, const FunctionType::ExtInfo &info,
+    unsigned ABIInfoKey, const FunctionType::ExtInfo &info,
     ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
     ArrayRef<CanQualType> argTypes, RequiredArgs required) {
   assert(paramInfos.empty() || paramInfos.size() == argTypes.size());
@@ -1064,7 +1068,7 @@ CGFunctionInfo *CGFunctionInfo::create(
   FI->Required = required;
   FI->HasRegParm = info.getHasRegParm();
   FI->RegParm = info.getRegParm();
-  FI->ABIInfoFD = ABIInfoFD;
+  FI->ABIInfoKey = ABIInfoKey;
   FI->ArgStruct = nullptr;
   FI->ArgStructAlign = 0;
   FI->NumArgs = argTypes.size();
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 88d6d1e5ea3be..a4c124e41c3b5 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -97,7 +97,7 @@ class CodeGenTypes {
   // Helper to insert CGFunctionInfo objects
   CGFunctionInfo *findOrInsertCGFunctionInfo(
       bool isInstanceMethod, bool isChainCall, bool isDelegateCall,
-      const FunctionDecl *ABIInfoFD, const FunctionType::ExtInfo &info,
+      unsigned ABIInfoKey, const FunctionType::ExtInfo &info,
       ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
       RequiredArgs required, CanQualType resultType,
       ArrayRef<CanQualType> argTypes);
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 5a0ea6112533e..1bbaf5542369e 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1210,6 +1210,17 @@ static unsigned getNativeVectorSizeForAVXABI(X86AVXABILevel AVXLevel) {
   llvm_unreachable("Unknown AVXLevel");
 }
 
+static unsigned getEffectiveX86AVXABILevelForCall(CodeGenTypes &CGT,
+                                                  X86AVXABILevel AVXLevel,
+                                                  const FunctionDecl *FD) {
+  if (CGT.getTarget().getTriple().isPS() ||
+      CGT.getContext().getLangOpts().getClangABICompat() <=
+          LangOptions::ClangABI::Ver22)
+    return static_cast<unsigned>(AVXLevel);
+
+  return CGT.getCGM().getEffectiveX86AVXABILevel(FD);
+}
+
 /// X86_64ABIInfo - The X86_64 ABI information.
 class X86_64ABIInfo : public ABIInfo {
   enum Class {
@@ -1384,6 +1395,8 @@ class X86_64ABIInfo : public ABIInfo {
   }
 
   void computeInfo(CGFunctionInfo &FI) const override;
+  unsigned getABIInfoKey(const FunctionDecl *FD,
+                         const FunctionType::ExtInfo &Info) const override;
 
   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
                    AggValueSlot Slot) const override;
@@ -1403,6 +1416,8 @@ class WinX86_64ABIInfo : public ABIInfo {
         IsMingw64(getTarget().getTriple().isWindowsGNUEnvironment()) {}
 
   void computeInfo(CGFunctionInfo &FI) const override;
+  unsigned getABIInfoKey(const FunctionDecl *FD,
+                         const FunctionType::ExtInfo &Info) const override;
 
   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
                    AggValueSlot Slot) const override;
@@ -2960,24 +2975,16 @@ X86_64ABIInfo::classifyRegCallStructType(QualType Ty, unsigned &NeededInt,
       llvm::StructType::get(getVMContext(), CoerceElts));
 }
 
-void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
-  bool shouldRespectFunctionAVXLevel =
-      !getTarget().getTriple().isPS() &&
-      getContext().getLangOpts().getClangABICompat() >
-          LangOptions::ClangABI::Ver22;
-
-  X86AVXABILevel EffectiveAVXLevel = AVXLevel;
-  if (shouldRespectFunctionAVXLevel && FI.getABIInfoFD()) {
-    EffectiveAVXLevel = static_cast<X86AVXABILevel>(
-        CGT.getCGM().getEffectiveX86AVXABILevel(FI.getABIInfoFD()));
-  }
+unsigned
+X86_64ABIInfo::getABIInfoKey(const FunctionDecl *FD,
+                             const FunctionType::ExtInfo &Info) const {
+  if (Info.getCC() == CC_Win64)
+    return 0;
 
-  if (EffectiveAVXLevel != AVXLevel) {
-    X86_64ABIInfo EffectiveABIInfo(CGT, EffectiveAVXLevel);
-    EffectiveABIInfo.computeInfo(FI);
-    return;
-  }
+  return getEffectiveX86AVXABILevelForCall(CGT, AVXLevel, FD);
+}
 
+void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
   const unsigned CallingConv = FI.getCallingConvention();
   // It is possible to force Win64 calling convention on any x86_64 target by
   // using __attribute__((ms_abi)). In such case to correctly emit Win64
@@ -2988,6 +2995,17 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
     return;
   }
 
+  assert(FI.getABIInfoKey() <=
+             static_cast<unsigned>(X86AVXABILevel::AVX512) &&
+         "Unexpected X86 AVX ABI key");
+  X86AVXABILevel EffectiveAVXLevel =
+      static_cast<X86AVXABILevel>(FI.getABIInfoKey());
+  if (EffectiveAVXLevel != AVXLevel) {
+    X86_64ABIInfo EffectiveABIInfo(CGT, EffectiveAVXLevel);
+    EffectiveABIInfo.computeInfo(FI);
+    return;
+  }
+
   bool IsRegCall = CallingConv == llvm::CallingConv::X86_RegCall;
 
   // Keep track of the number of assigned registers.
@@ -3491,6 +3509,15 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
   return ABIArgInfo::getDirect();
 }
 
+unsigned
+WinX86_64ABIInfo::getABIInfoKey(const FunctionDecl *FD,
+                                const FunctionType::ExtInfo &Info) const {
+  if (Info.getCC() != CC_X86_64SysV)
+    return 0;
+
+  return getEffectiveX86AVXABILevelForCall(CGT, AVXLevel, FD);
+}
+
 void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
   const unsigned CC = FI.getCallingConvention();
   bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
diff --git a/clang/unittests/CodeGen/CodeGenExternalTest.cpp b/clang/unittests/CodeGen/CodeGenExternalTest.cpp
index df5477e9f7f46..34404afe3d41a 100644
--- a/clang/unittests/CodeGen/CodeGenExternalTest.cpp
+++ b/clang/unittests/CodeGen/CodeGenExternalTest.cpp
@@ -187,7 +187,8 @@ const char X86AVXABITestProgram[] =
     "  mytest_avx_fn(hello);\n"
     "  mytest_avx_method_holder holder = mytest_avx_method_holder();\n"
     "  holder.method(hello);\n"
-    "}\n";
+    "}\n"
+    "__attribute__((target(\"avx\"))) void caller2() {}\n";
 
 static void test_generic_codegen_fns(MyASTConsumer *my) {
   bool mytest_fn_ok = false;
@@ -286,17 +287,20 @@ static void test_x86_avx_abi_codegen_fns(MyASTConsumer *my) {
   CodeGen::CodeGenModule &CGM = my->Builder->CGM();
   const ASTContext &Ctx = my->toplevel_decls.front()->getASTContext();
 
-  // First get the caller decl, which we need to determine call ABI
+  // First get the caller decls, which we need to determine call ABI.
   FunctionDecl *callerDecl = nullptr;
+  FunctionDecl *caller2Decl = nullptr;
   for (auto decl : my->toplevel_decls) {
     if (FunctionDecl *fd = dyn_cast<FunctionDecl>(decl)) {
-      if (fd->getName() != "caller")
-        continue;
-
-      callerDecl = fd;
-      break;
+      if (fd->getName() == "caller")
+        callerDecl = fd;
+      else if (fd->getName() == "caller2")
+        caller2Decl = fd;
     }
   }
+  ASSERT_TRUE(callerDecl);
+  ASSERT_TRUE(caller2Decl);
+  ASSERT_NE(callerDecl, caller2Decl);
 
   for (auto decl : my->toplevel_decls) {
     if (FunctionDecl *fd = dyn_cast<FunctionDecl>(decl)) {
@@ -312,7 +316,12 @@ static void test_x86_avx_abi_codegen_fns(MyASTConsumer *my) {
           CGM, Ctx.getCanonicalType(FPT->getReturnType()), ArgTypes,
           FPT->getExtInfo(), {},
           CodeGen::RequiredArgs::forPrototypePlus(FPT, 0), callerDecl);
-      ASSERT_EQ(FnInfo.getABIInfoFD(), callerDecl);
+      const CodeGen::CGFunctionInfo &FnInfo2 = CodeGen::arrangeFreeFunctionCall(
+          CGM, Ctx.getCanonicalType(FPT->getReturnType()), ArgTypes,
+          FPT->getExtInfo(), {},
+          CodeGen::RequiredArgs::forPrototypePlus(FPT, 0), caller2Decl);
+      ASSERT_EQ(&FnInfo, &FnInfo2);
+      ASSERT_EQ(FnInfo.getABIInfoKey(), 1u);
       ASSERT_TRUE(FnInfo.getReturnInfo().isDirect());
       ASSERT_TRUE(FnInfo.arg_begin()->info.isDirect());
       mytest_avx_fn_ok = true;
@@ -332,7 +341,7 @@ static void test_x86_avx_abi_codegen_fns(MyASTConsumer *my) {
           CGM, Ctx.getCanonicalType(FPT->getReturnType()), ArgTypes,
           FPT->getExtInfo(), {},
           CodeGen::RequiredArgs::forPrototypePlus(FPT, 1), callerDecl);
-      ASSERT_EQ(FnInfo.getABIInfoFD(), callerDecl);
+      ASSERT_EQ(FnInfo.getABIInfoKey(), 1u);
       ASSERT_TRUE(FnInfo.getReturnInfo().isDirect());
       ASSERT_TRUE(FnInfo.arg_begin()[1].info.isDirect());
       mytest_avx_method_ok = true;

>From c6cf7bbcb69faeeff7d1eeb3d8562fcaef71af1a Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Sat, 16 May 2026 08:05:32 +0900
Subject: [PATCH 04/13] Refactored ABIInfoKey into X86ABIAVXLevel because I
 think that names explains what we are using it for more clearly

---
 clang/include/clang/CodeGen/CGFunctionInfo.h  | 14 ++---
 clang/lib/CodeGen/ABIInfo.h                   |  7 ++-
 clang/lib/CodeGen/CGCall.cpp                  | 22 +++----
 clang/lib/CodeGen/CodeGenModule.cpp           | 19 ------
 clang/lib/CodeGen/CodeGenModule.h             |  3 -
 clang/lib/CodeGen/CodeGenTypes.h              |  2 +-
 clang/lib/CodeGen/Targets/X86.cpp             | 60 +++++++++++--------
 .../unittests/CodeGen/CodeGenExternalTest.cpp |  4 +-
 8 files changed, 60 insertions(+), 71 deletions(-)

diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h
index c55150b185290..49737797b1386 100644
--- a/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -652,8 +652,8 @@ class CGFunctionInfo final
   /// Log 2 of the maximum vector width.
   unsigned MaxVectorWidth : 4;
 
-  /// Target-specific ABI classification key.
-  unsigned ABIInfoKey = 0;
+  /// X86 AVX Level, can be different from global / module level AVX level because of target attributes
+  unsigned X86ABIAVXLevel = 0;
 
   RequiredArgs Required;
 
@@ -685,7 +685,7 @@ class CGFunctionInfo final
 public:
   static CGFunctionInfo *
   create(unsigned llvmCC, bool instanceMethod, bool chainCall,
-         bool delegateCall, unsigned ABIInfoKey,
+         bool delegateCall, unsigned X86ABIAVXLevel,
          const FunctionType::ExtInfo &extInfo,
          ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
          ArrayRef<CanQualType> argTypes, RequiredArgs required);
@@ -812,7 +812,7 @@ class CGFunctionInfo final
     MaxVectorWidth = llvm::countr_zero(Width) + 1;
   }
 
-  unsigned getABIInfoKey() const { return ABIInfoKey; }
+  unsigned getX86ABIAVXLevel() const { return X86ABIAVXLevel; }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
     ID.AddInteger(getASTCallingConvention());
@@ -826,7 +826,7 @@ class CGFunctionInfo final
     ID.AddInteger(RegParm);
     ID.AddBoolean(NoCfCheck);
     ID.AddBoolean(CmseNSCall);
-    ID.AddInteger(ABIInfoKey);
+    ID.AddInteger(X86ABIAVXLevel);
     ID.AddInteger(Required.getOpaqueData());
     ID.AddBoolean(HasExtParameterInfos);
     if (HasExtParameterInfos) {
@@ -839,7 +839,7 @@ class CGFunctionInfo final
   }
   static void Profile(llvm::FoldingSetNodeID &ID, bool InstanceMethod,
                       bool ChainCall, bool IsDelegateCall,
-                      unsigned ABIInfoKey,
+                      unsigned X86ABIAVXLevel,
                       const FunctionType::ExtInfo &info,
                       ArrayRef<ExtParameterInfo> paramInfos,
                       RequiredArgs required, CanQualType resultType,
@@ -855,7 +855,7 @@ class CGFunctionInfo final
     ID.AddInteger(info.getRegParm());
     ID.AddBoolean(info.getNoCfCheck());
     ID.AddBoolean(info.getCmseNSCall());
-    ID.AddInteger(ABIInfoKey);
+    ID.AddInteger(X86ABIAVXLevel);
     ID.AddInteger(required.getOpaqueData());
     ID.AddBoolean(!paramInfos.empty());
     if (!paramInfos.empty()) {
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h
index 9fce25d4e215b..2e1cf6c222d9d 100644
--- a/clang/lib/CodeGen/ABIInfo.h
+++ b/clang/lib/CodeGen/ABIInfo.h
@@ -70,10 +70,11 @@ class ABIInfo {
   /// functions.
   llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
 
-  /// Return a target-specific key for ABI information that affects function
-  /// lowering but is not captured by the source signature.
+  // Get X86ABIAVXLevel for the given FunctionDecl and ExtInfo.
+  // This can be different than the global / module level X86ABIAVXLevel 
+  // due to function attributes.
   virtual unsigned
-  getABIInfoKey(const FunctionDecl *,
+  getX86ABIAVXLevel(const FunctionDecl *,
                 const FunctionType::ExtInfo &) const {
     return 0;
   }
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index f19271e8df99a..5538a24370c3f 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -852,10 +852,10 @@ const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
                                                 const CallArgList &args,
                                                 const FunctionDecl *ABIInfoFD) {
   assert(signature.arg_size() <= args.size());
-  unsigned ABIInfoKey =
-      CGM.getABIInfo().getABIInfoKey(ABIInfoFD, signature.getExtInfo());
+  unsigned X86ABIAVXLevel =
+      CGM.getABIInfo().getX86ABIAVXLevel(ABIInfoFD, signature.getExtInfo());
   if (signature.arg_size() == args.size() &&
-      signature.getABIInfoKey() == ABIInfoKey)
+      signature.getX86ABIAVXLevel() == X86ABIAVXLevel)
     return signature;
 
   ExtParameterInfoList paramInfos;
@@ -878,7 +878,7 @@ const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
 
   const CGFunctionInfo *newFI = findOrInsertCGFunctionInfo(
       signature.isInstanceMethod(), signature.isChainCall(),
-      signature.isDelegateCall(), ABIInfoKey, signature.getExtInfo(),
+      signature.isDelegateCall(), X86ABIAVXLevel, signature.getExtInfo(),
       paramInfos, signature.getRequiredArgs(), signature.getReturnType(),
       argTypes);
   return *newFI;
@@ -970,23 +970,23 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
       (opts & FnInfoOpts::IsChainCall) == FnInfoOpts::IsChainCall;
   bool isDelegateCall =
       (opts & FnInfoOpts::IsDelegateCall) == FnInfoOpts::IsDelegateCall;
-  unsigned ABIInfoKey = CGM.getABIInfo().getABIInfoKey(ABIInfoFD, info);
+  unsigned X86ABIAVXLevel = CGM.getABIInfo().getX86ABIAVXLevel(ABIInfoFD, info);
 
   const CGFunctionInfo *newFI = findOrInsertCGFunctionInfo(
-      isInstanceMethod, isChainCall, isDelegateCall, ABIInfoKey, info,
+      isInstanceMethod, isChainCall, isDelegateCall, X86ABIAVXLevel, info,
       paramInfos, required, resultType, argTypes);
   return *newFI;
 }
 
 CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
     bool isInstanceMethod, bool isChainCall, bool isDelegateCall,
-    unsigned ABIInfoKey, const FunctionType::ExtInfo &info,
+    unsigned X86ABIAVXLevel, const FunctionType::ExtInfo &info,
     ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
     RequiredArgs required, CanQualType resultType,
     ArrayRef<CanQualType> argTypes) {
   llvm::FoldingSetNodeID ID;
   CGFunctionInfo::Profile(ID, isInstanceMethod, isChainCall, isDelegateCall,
-                          ABIInfoKey, info, paramInfos, required, resultType,
+                          X86ABIAVXLevel, info, paramInfos, required, resultType,
                           argTypes);
 
   void *insertPos = nullptr;
@@ -998,7 +998,7 @@ CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
 
   // Construct the function info.  We co-allocate the ArgInfos.
   FI = CGFunctionInfo::create(CC, isInstanceMethod, isChainCall, isDelegateCall,
-                              ABIInfoKey, info, paramInfos, resultType, argTypes,
+                              X86ABIAVXLevel, info, paramInfos, resultType, argTypes,
                               required);
   FunctionInfos.InsertNode(FI, insertPos);
 
@@ -1043,7 +1043,7 @@ CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
 
 CGFunctionInfo *CGFunctionInfo::create(
     unsigned llvmCC, bool instanceMethod, bool chainCall, bool delegateCall,
-    unsigned ABIInfoKey, const FunctionType::ExtInfo &info,
+    unsigned X86ABIAVXLevel, const FunctionType::ExtInfo &info,
     ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType,
     ArrayRef<CanQualType> argTypes, RequiredArgs required) {
   assert(paramInfos.empty() || paramInfos.size() == argTypes.size());
@@ -1068,7 +1068,7 @@ CGFunctionInfo *CGFunctionInfo::create(
   FI->Required = required;
   FI->HasRegParm = info.getHasRegParm();
   FI->RegParm = info.getRegParm();
-  FI->ABIInfoKey = ABIInfoKey;
+  FI->X86ABIAVXLevel = X86ABIAVXLevel;
   FI->ArgStruct = nullptr;
   FI->ArgStructAlign = 0;
   FI->NumArgs = argTypes.size();
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 2df2bc35ff678..6df78b6478240 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -6278,25 +6278,6 @@ const ABIInfo &CodeGenModule::getABIInfo() {
   return getTargetCodeGenInfo().getABIInfo();
 }
 
-unsigned CodeGenModule::getDefaultX86AVXABILevel() const {
-  return static_cast<unsigned>(::getDefaultX86AVXABILevel(Target));
-}
-
-unsigned
-CodeGenModule::getEffectiveX86AVXABILevel(const FunctionDecl *FD) const {
-  X86AVXABILevel Level = ::getDefaultX86AVXABILevel(Target);
-  if (!FD)
-    return static_cast<unsigned>(Level);
-
-  llvm::StringMap<bool> FeatureMap;
-  Context.getFunctionFeatureMap(FeatureMap, FD);
-  if (FeatureMap.lookup("avx512f"))
-    return static_cast<unsigned>(std::max(Level, X86AVXABILevel::AVX512));
-  if (FeatureMap.lookup("avx"))
-    return static_cast<unsigned>(std::max(Level, X86AVXABILevel::AVX));
-  return static_cast<unsigned>(Level);
-}
-
 /// Pass IsTentative as true if you want to create a tentative definition.
 void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
                                             bool IsTentative) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 48a4485f76a39..5e5e73d9c4c44 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -919,9 +919,6 @@ class CodeGenModule : public CodeGenTypeCache {
   /// in classification, and write the results back into FI.
   void computeABIInfoUsingLib(CGFunctionInfo &FI);
 
-  unsigned getDefaultX86AVXABILevel() const;
-  unsigned getEffectiveX86AVXABILevel(const FunctionDecl *FD) const;
-
   CGCXXABI &getCXXABI() const { return *ABI; }
   llvm::LLVMContext &getLLVMContext() { return VMContext; }
 
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index a4c124e41c3b5..7821f47c39d1b 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -97,7 +97,7 @@ class CodeGenTypes {
   // Helper to insert CGFunctionInfo objects
   CGFunctionInfo *findOrInsertCGFunctionInfo(
       bool isInstanceMethod, bool isChainCall, bool isDelegateCall,
-      unsigned ABIInfoKey, const FunctionType::ExtInfo &info,
+      unsigned X86ABIAVXLevel, const FunctionType::ExtInfo &info,
       ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
       RequiredArgs required, CanQualType resultType,
       ArrayRef<CanQualType> argTypes);
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 1bbaf5542369e..337aa277343e5 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -9,6 +9,7 @@
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
 #include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/Specifiers.h"
 #include "llvm/ADT/SmallBitVector.h"
 
 using namespace clang;
@@ -1210,17 +1211,6 @@ static unsigned getNativeVectorSizeForAVXABI(X86AVXABILevel AVXLevel) {
   llvm_unreachable("Unknown AVXLevel");
 }
 
-static unsigned getEffectiveX86AVXABILevelForCall(CodeGenTypes &CGT,
-                                                  X86AVXABILevel AVXLevel,
-                                                  const FunctionDecl *FD) {
-  if (CGT.getTarget().getTriple().isPS() ||
-      CGT.getContext().getLangOpts().getClangABICompat() <=
-          LangOptions::ClangABI::Ver22)
-    return static_cast<unsigned>(AVXLevel);
-
-  return CGT.getCGM().getEffectiveX86AVXABILevel(FD);
-}
-
 /// X86_64ABIInfo - The X86_64 ABI information.
 class X86_64ABIInfo : public ABIInfo {
   enum Class {
@@ -1395,7 +1385,7 @@ class X86_64ABIInfo : public ABIInfo {
   }
 
   void computeInfo(CGFunctionInfo &FI) const override;
-  unsigned getABIInfoKey(const FunctionDecl *FD,
+  unsigned getX86ABIAVXLevel(const FunctionDecl *FD,
                          const FunctionType::ExtInfo &Info) const override;
 
   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
@@ -1416,7 +1406,7 @@ class WinX86_64ABIInfo : public ABIInfo {
         IsMingw64(getTarget().getTriple().isWindowsGNUEnvironment()) {}
 
   void computeInfo(CGFunctionInfo &FI) const override;
-  unsigned getABIInfoKey(const FunctionDecl *FD,
+  unsigned getX86ABIAVXLevel(const FunctionDecl *FD,
                          const FunctionType::ExtInfo &Info) const override;
 
   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
@@ -1774,6 +1764,27 @@ void X86_64ABIInfo::postMerge(unsigned AggregateSize, Class &Lo,
     Hi = SSE;
 }
 
+static X86AVXABILevel getEffectiveX86AVXABILevel(CodeGenTypes &CGT, X86AVXABILevel GlobalAVXLevel, const FunctionDecl *FD) {
+  // Always return global AVX level on PlayStation
+  if (CGT.getTarget().getTriple().isPS() ||
+      CGT.getContext().getLangOpts().getClangABICompat() <=
+          LangOptions::ClangABI::Ver22) {
+            return GlobalAVXLevel;
+          }
+
+  X86AVXABILevel Level = GlobalAVXLevel;
+  if (!FD)
+    return Level;
+
+  llvm::StringMap<bool> FeatureMap;
+  CGT.getCGM().getContext().getFunctionFeatureMap(FeatureMap, FD);
+  if (FeatureMap.lookup("avx512f"))
+    return std::max(Level, X86AVXABILevel::AVX512);
+  if (FeatureMap.lookup("avx"))
+    return std::max(Level, X86AVXABILevel::AVX);
+  return Level;
+}
+
 X86_64ABIInfo::Class X86_64ABIInfo::merge(Class Accum, Class Field) {
   // AMD64-ABI 3.2.3p2: Rule 4. Each field of an object is
   // classified recursively so that always two fields are
@@ -2976,12 +2987,9 @@ X86_64ABIInfo::classifyRegCallStructType(QualType Ty, unsigned &NeededInt,
 }
 
 unsigned
-X86_64ABIInfo::getABIInfoKey(const FunctionDecl *FD,
+X86_64ABIInfo::getX86ABIAVXLevel(const FunctionDecl *FD,
                              const FunctionType::ExtInfo &Info) const {
-  if (Info.getCC() == CC_Win64)
-    return 0;
-
-  return getEffectiveX86AVXABILevelForCall(CGT, AVXLevel, FD);
+  return static_cast<unsigned>(getEffectiveX86AVXABILevel(CGT, AVXLevel, FD));
 }
 
 void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
@@ -2995,11 +3003,11 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
     return;
   }
 
-  assert(FI.getABIInfoKey() <=
+  assert(FI.getX86ABIAVXLevel() <=
              static_cast<unsigned>(X86AVXABILevel::AVX512) &&
-         "Unexpected X86 AVX ABI key");
+         "Unexpected X86 AVX ABI level");
   X86AVXABILevel EffectiveAVXLevel =
-      static_cast<X86AVXABILevel>(FI.getABIInfoKey());
+      static_cast<X86AVXABILevel>(FI.getX86ABIAVXLevel());
   if (EffectiveAVXLevel != AVXLevel) {
     X86_64ABIInfo EffectiveABIInfo(CGT, EffectiveAVXLevel);
     EffectiveABIInfo.computeInfo(FI);
@@ -3510,12 +3518,14 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
 }
 
 unsigned
-WinX86_64ABIInfo::getABIInfoKey(const FunctionDecl *FD,
+WinX86_64ABIInfo::getX86ABIAVXLevel(const FunctionDecl *FD,
                                 const FunctionType::ExtInfo &Info) const {
-  if (Info.getCC() != CC_X86_64SysV)
-    return 0;
+  if (Info.getCC() == CC_X86_64SysV)
+  {
+    return static_cast<unsigned>(getEffectiveX86AVXABILevel(CGT, AVXLevel, FD));
+  }
 
-  return getEffectiveX86AVXABILevelForCall(CGT, AVXLevel, FD);
+  return static_cast<unsigned>(AVXLevel);
 }
 
 void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
diff --git a/clang/unittests/CodeGen/CodeGenExternalTest.cpp b/clang/unittests/CodeGen/CodeGenExternalTest.cpp
index 34404afe3d41a..cf70ff32d9e67 100644
--- a/clang/unittests/CodeGen/CodeGenExternalTest.cpp
+++ b/clang/unittests/CodeGen/CodeGenExternalTest.cpp
@@ -321,7 +321,7 @@ static void test_x86_avx_abi_codegen_fns(MyASTConsumer *my) {
           FPT->getExtInfo(), {},
           CodeGen::RequiredArgs::forPrototypePlus(FPT, 0), caller2Decl);
       ASSERT_EQ(&FnInfo, &FnInfo2);
-      ASSERT_EQ(FnInfo.getABIInfoKey(), 1u);
+      ASSERT_EQ(FnInfo.getX86ABIAVXLevel(), 1u);
       ASSERT_TRUE(FnInfo.getReturnInfo().isDirect());
       ASSERT_TRUE(FnInfo.arg_begin()->info.isDirect());
       mytest_avx_fn_ok = true;
@@ -341,7 +341,7 @@ static void test_x86_avx_abi_codegen_fns(MyASTConsumer *my) {
           CGM, Ctx.getCanonicalType(FPT->getReturnType()), ArgTypes,
           FPT->getExtInfo(), {},
           CodeGen::RequiredArgs::forPrototypePlus(FPT, 1), callerDecl);
-      ASSERT_EQ(FnInfo.getABIInfoKey(), 1u);
+      ASSERT_EQ(FnInfo.getX86ABIAVXLevel(), 1u);
       ASSERT_TRUE(FnInfo.getReturnInfo().isDirect());
       ASSERT_TRUE(FnInfo.arg_begin()[1].info.isDirect());
       mytest_avx_method_ok = true;

>From cfc5534f184c8f44aad1febf6cbb151cc7c05e67 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Sat, 16 May 2026 08:06:57 +0900
Subject: [PATCH 05/13] clang format

---
 clang/include/clang/CodeGen/CGFunctionInfo.h |  5 +++--
 clang/lib/CodeGen/ABIInfo.h                  |  7 +++----
 clang/lib/CodeGen/CGCall.cpp                 |  8 ++++----
 clang/lib/CodeGen/Targets/X86.cpp            | 19 ++++++++++---------
 4 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h
index 49737797b1386..d92ad767d04ef 100644
--- a/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -18,8 +18,8 @@
 #include "clang/AST/CanonicalType.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/Type.h"
-#include "llvm/IR/DerivedTypes.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/IR/DerivedTypes.h"
 #include "llvm/Support/TrailingObjects.h"
 #include <cassert>
 
@@ -652,7 +652,8 @@ class CGFunctionInfo final
   /// Log 2 of the maximum vector width.
   unsigned MaxVectorWidth : 4;
 
-  /// X86 AVX Level, can be different from global / module level AVX level because of target attributes
+  /// X86 AVX Level, can be different from global / module level AVX level
+  /// because of target attributes
   unsigned X86ABIAVXLevel = 0;
 
   RequiredArgs Required;
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h
index 2e1cf6c222d9d..ece2743de8170 100644
--- a/clang/lib/CodeGen/ABIInfo.h
+++ b/clang/lib/CodeGen/ABIInfo.h
@@ -71,11 +71,10 @@ class ABIInfo {
   llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
 
   // Get X86ABIAVXLevel for the given FunctionDecl and ExtInfo.
-  // This can be different than the global / module level X86ABIAVXLevel 
+  // This can be different than the global / module level X86ABIAVXLevel
   // due to function attributes.
-  virtual unsigned
-  getX86ABIAVXLevel(const FunctionDecl *,
-                const FunctionType::ExtInfo &) const {
+  virtual unsigned getX86ABIAVXLevel(const FunctionDecl *,
+                                     const FunctionType::ExtInfo &) const {
     return 0;
   }
 
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 5538a24370c3f..7ed20b1c1b625 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -986,8 +986,8 @@ CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
     ArrayRef<CanQualType> argTypes) {
   llvm::FoldingSetNodeID ID;
   CGFunctionInfo::Profile(ID, isInstanceMethod, isChainCall, isDelegateCall,
-                          X86ABIAVXLevel, info, paramInfos, required, resultType,
-                          argTypes);
+                          X86ABIAVXLevel, info, paramInfos, required,
+                          resultType, argTypes);
 
   void *insertPos = nullptr;
   CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos);
@@ -998,8 +998,8 @@ CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo(
 
   // Construct the function info.  We co-allocate the ArgInfos.
   FI = CGFunctionInfo::create(CC, isInstanceMethod, isChainCall, isDelegateCall,
-                              X86ABIAVXLevel, info, paramInfos, resultType, argTypes,
-                              required);
+                              X86ABIAVXLevel, info, paramInfos, resultType,
+                              argTypes, required);
   FunctionInfos.InsertNode(FI, insertPos);
 
   bool inserted = FunctionsBeingProcessed.insert(FI).second;
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 337aa277343e5..22b5b4eae188d 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1386,7 +1386,7 @@ class X86_64ABIInfo : public ABIInfo {
 
   void computeInfo(CGFunctionInfo &FI) const override;
   unsigned getX86ABIAVXLevel(const FunctionDecl *FD,
-                         const FunctionType::ExtInfo &Info) const override;
+                             const FunctionType::ExtInfo &Info) const override;
 
   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
                    AggValueSlot Slot) const override;
@@ -1407,7 +1407,7 @@ class WinX86_64ABIInfo : public ABIInfo {
 
   void computeInfo(CGFunctionInfo &FI) const override;
   unsigned getX86ABIAVXLevel(const FunctionDecl *FD,
-                         const FunctionType::ExtInfo &Info) const override;
+                             const FunctionType::ExtInfo &Info) const override;
 
   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
                    AggValueSlot Slot) const override;
@@ -1764,13 +1764,15 @@ void X86_64ABIInfo::postMerge(unsigned AggregateSize, Class &Lo,
     Hi = SSE;
 }
 
-static X86AVXABILevel getEffectiveX86AVXABILevel(CodeGenTypes &CGT, X86AVXABILevel GlobalAVXLevel, const FunctionDecl *FD) {
+static X86AVXABILevel getEffectiveX86AVXABILevel(CodeGenTypes &CGT,
+                                                 X86AVXABILevel GlobalAVXLevel,
+                                                 const FunctionDecl *FD) {
   // Always return global AVX level on PlayStation
   if (CGT.getTarget().getTriple().isPS() ||
       CGT.getContext().getLangOpts().getClangABICompat() <=
           LangOptions::ClangABI::Ver22) {
-            return GlobalAVXLevel;
-          }
+    return GlobalAVXLevel;
+  }
 
   X86AVXABILevel Level = GlobalAVXLevel;
   if (!FD)
@@ -2988,7 +2990,7 @@ X86_64ABIInfo::classifyRegCallStructType(QualType Ty, unsigned &NeededInt,
 
 unsigned
 X86_64ABIInfo::getX86ABIAVXLevel(const FunctionDecl *FD,
-                             const FunctionType::ExtInfo &Info) const {
+                                 const FunctionType::ExtInfo &Info) const {
   return static_cast<unsigned>(getEffectiveX86AVXABILevel(CGT, AVXLevel, FD));
 }
 
@@ -3519,9 +3521,8 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
 
 unsigned
 WinX86_64ABIInfo::getX86ABIAVXLevel(const FunctionDecl *FD,
-                                const FunctionType::ExtInfo &Info) const {
-  if (Info.getCC() == CC_X86_64SysV)
-  {
+                                    const FunctionType::ExtInfo &Info) const {
+  if (Info.getCC() == CC_X86_64SysV) {
     return static_cast<unsigned>(getEffectiveX86AVXABILevel(CGT, AVXLevel, FD));
   }
 

>From 1343962de74d6e7164b548b1d9699063c13abe90 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Mon, 18 May 2026 07:32:17 -0700
Subject: [PATCH 06/13] removed spurious include

---
 clang/lib/CodeGen/Targets/Mips.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/Mips.cpp b/clang/lib/CodeGen/Targets/Mips.cpp
index fee19181b94d6..22fdcd95ea8fa 100644
--- a/clang/lib/CodeGen/Targets/Mips.cpp
+++ b/clang/lib/CodeGen/Targets/Mips.cpp
@@ -8,7 +8,6 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
-#include "clang/AST/Decl.h"
 
 using namespace clang;
 using namespace clang::CodeGen;

>From 256f6aa32e89011f84377ee6395f7d5c162488a3 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Mon, 18 May 2026 07:43:36 -0700
Subject: [PATCH 07/13] removed getDefaultX86AVXABILevel from CodeGenModule.cpp
 since we don't need it anymore

---
 clang/lib/CodeGen/CodeGenModule.cpp | 19 ++++---------------
 1 file changed, 4 insertions(+), 15 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 6df78b6478240..236738e9975d3 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -111,8 +111,6 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
   llvm_unreachable("invalid C++ ABI kind");
 }
 
-static X86AVXABILevel getDefaultX86AVXABILevel(const TargetInfo &Target);
-
 static std::unique_ptr<TargetCodeGenInfo>
 createTargetCodeGenInfo(CodeGenModule &CGM) {
   const TargetInfo &Target = CGM.getTarget();
@@ -270,7 +268,10 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
   }
 
   case llvm::Triple::x86_64: {
-    X86AVXABILevel AVXLevel = getDefaultX86AVXABILevel(Target);
+    StringRef ABI = Target.getABI();
+    X86AVXABILevel AVXLevel = (ABI == "avx512" ? X86AVXABILevel::AVX512
+                               : ABI == "avx"  ? X86AVXABILevel::AVX
+                                               : X86AVXABILevel::None);
 
     switch (Triple.getOS()) {
     case llvm::Triple::UEFI:
@@ -332,18 +333,6 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
   }
 }
 
-static X86AVXABILevel getDefaultX86AVXABILevel(const TargetInfo &Target) {
-  X86AVXABILevel Level = X86AVXABILevel::None;
-  if (Target.getTriple().isX86_64()) {
-    StringRef ABI = Target.getABI();
-    if (ABI == "avx512")
-      Level = X86AVXABILevel::AVX512;
-    else if (ABI == "avx")
-      Level = X86AVXABILevel::AVX;
-  }
-  return Level;
-}
-
 const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
   if (!TheTargetCodeGenInfo)
     TheTargetCodeGenInfo = createTargetCodeGenInfo(*this);

>From 96f07365494405bde3b4ea1c1b23db580bc718d1 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Mon, 18 May 2026 07:47:00 -0700
Subject: [PATCH 08/13] another spurious include

---
 clang/lib/CodeGen/Targets/X86.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 22b5b4eae188d..462ca50a7b3b7 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -9,7 +9,6 @@
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
 #include "clang/Basic/DiagnosticFrontend.h"
-#include "clang/Basic/Specifiers.h"
 #include "llvm/ADT/SmallBitVector.h"
 
 using namespace clang;

>From fbb9c9a301460d0d6a9a41128651a6e3a6613143 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Wed, 20 May 2026 10:28:05 -0700
Subject: [PATCH 09/13] Got rid of arrangeCXXMethodCall overrload that passed
 nullptr for ABIInfoFD & fixed up callsites

---
 clang/lib/CodeGen/CGCall.cpp        | 7 -------
 clang/lib/CodeGen/CGVTables.cpp     | 5 +++--
 clang/lib/CodeGen/CodeGenTypes.h    | 4 ----
 clang/lib/CodeGen/ItaniumCXXABI.cpp | 2 +-
 4 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 7ed20b1c1b625..2919c3e3b19bb 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -811,13 +811,6 @@ const CGFunctionInfo &CodeGenTypes::arrangeDeviceKernelCallerDeclaration(
 ///
 /// numPrefixArgs is the number of ABI-specific prefix arguments we have. It
 /// does not count `this`.
-const CGFunctionInfo &CodeGenTypes::arrangeCXXMethodCall(
-    const CallArgList &args, const FunctionProtoType *proto,
-    RequiredArgs required, unsigned numPrefixArgs) {
-  return arrangeCXXMethodCall(args, proto, required, numPrefixArgs,
-                              /*FD=*/nullptr);
-}
-
 const CGFunctionInfo &CodeGenTypes::arrangeCXXMethodCall(
     const CallArgList &args, const FunctionProtoType *proto,
     RequiredArgs required, unsigned numPrefixArgs,
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 1254c708cd8e1..5decb91ea86fb 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -381,10 +381,11 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::FunctionCallee Callee,
 
 #ifndef NDEBUG
   const CGFunctionInfo &CallFnInfo = CGM.getTypes().arrangeCXXMethodCall(
-      CallArgs, FPT, RequiredArgs::forPrototypePlus(FPT, 1), PrefixArgs);
+      CallArgs, FPT, RequiredArgs::forPrototypePlus(FPT, 1), PrefixArgs, MD);
   assert(CallFnInfo.getRegParm() == CurFnInfo->getRegParm() &&
          CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() &&
-         CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention());
+         CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention() &&
+         CallFnInfo.getX86ABIAVXLevel() == CurFnInfo->getX86ABIAVXLevel());
   assert(isa<CXXDestructorDecl>(MD) || // ignore dtor return types
          similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(),
                  CurFnInfo->getReturnInfo(), CurFnInfo->getReturnType()));
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 7821f47c39d1b..cffa794a15e87 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -283,10 +283,6 @@ class CodeGenTypes {
       CXXCtorType CtorKind, unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs,
       const FunctionDecl *ABIInfoFD, bool PassProtoArgs = true);
 
-  const CGFunctionInfo &arrangeCXXMethodCall(const CallArgList &args,
-                                             const FunctionProtoType *type,
-                                             RequiredArgs required,
-                                             unsigned numPrefixArgs);
   const CGFunctionInfo &arrangeCXXMethodCall(const CallArgList &args,
                                              const FunctionProtoType *type,
                                              RequiredArgs required,
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 6069d39f520ef..9126944215470 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3519,7 +3519,7 @@ ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) {
   const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
   RequiredArgs Required = RequiredArgs::forPrototypePlus(FPT, /*this*/ 1);
   const CGFunctionInfo &CallInfo =
-      CGM.getTypes().arrangeCXXMethodCall(CallArgs, FPT, Required, 0);
+      CGM.getTypes().arrangeCXXMethodCall(CallArgs, FPT, Required, 0, MD);
   CGCallee Callee = CGCallee::forVirtual(nullptr, GlobalDecl(MD),
                                          getThisAddress(CGF), ThunkTy);
   llvm::CallBase *CallOrInvoke;

>From 8093b184fc81e63aa75c69df30b6289308e1b36b Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Thu, 21 May 2026 11:21:09 -0700
Subject: [PATCH 10/13] clang format

---
 clang/lib/CodeGen/CGVTables.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 5decb91ea86fb..a70fede669c5d 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -384,7 +384,8 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::FunctionCallee Callee,
       CallArgs, FPT, RequiredArgs::forPrototypePlus(FPT, 1), PrefixArgs, MD);
   assert(CallFnInfo.getRegParm() == CurFnInfo->getRegParm() &&
          CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() &&
-         CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention() &&
+         CallFnInfo.getCallingConvention() ==
+             CurFnInfo->getCallingConvention() &&
          CallFnInfo.getX86ABIAVXLevel() == CurFnInfo->getX86ABIAVXLevel());
   assert(isa<CXXDestructorDecl>(MD) || // ignore dtor return types
          similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(),

>From dd5b6d09a09a2c426a657db6e3c95fbdb94f580b Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Thu, 25 Jun 2026 15:59:42 -0700
Subject: [PATCH 11/13] Update clang/lib/CodeGen/Targets/X86.cpp

Co-authored-by: Aaron Ballman <aaron at aaronballman.com>
---
 clang/lib/CodeGen/Targets/X86.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 462ca50a7b3b7..3d9ff48ec84d2 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1766,7 +1766,7 @@ void X86_64ABIInfo::postMerge(unsigned AggregateSize, Class &Lo,
 static X86AVXABILevel getEffectiveX86AVXABILevel(CodeGenTypes &CGT,
                                                  X86AVXABILevel GlobalAVXLevel,
                                                  const FunctionDecl *FD) {
-  // Always return global AVX level on PlayStation
+  // Always return global AVX level on PlayStation.
   if (CGT.getTarget().getTriple().isPS() ||
       CGT.getContext().getLangOpts().getClangABICompat() <=
           LangOptions::ClangABI::Ver22) {

>From 8c1a23fb5d8d78e3686b169693c9f341d2050165 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Thu, 25 Jun 2026 15:59:50 -0700
Subject: [PATCH 12/13] Update clang/include/clang/CodeGen/CGFunctionInfo.h

Co-authored-by: Aaron Ballman <aaron at aaronballman.com>
---
 clang/include/clang/CodeGen/CGFunctionInfo.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h
index d92ad767d04ef..d1fc80337d859 100644
--- a/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -653,7 +653,7 @@ class CGFunctionInfo final
   unsigned MaxVectorWidth : 4;
 
   /// X86 AVX Level, can be different from global / module level AVX level
-  /// because of target attributes
+  /// because of target attributes.
   unsigned X86ABIAVXLevel = 0;
 
   RequiredArgs Required;

>From 15a7edf84c4d94148db3f7179c05f0d5abad6ce0 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Thu, 25 Jun 2026 15:59:59 -0700
Subject: [PATCH 13/13] Update clang/include/clang/Basic/ABIVersions.def

Co-authored-by: Aaron Ballman <aaron at aaronballman.com>
---
 clang/include/clang/Basic/ABIVersions.def | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/ABIVersions.def b/clang/include/clang/Basic/ABIVersions.def
index bc083b19dd4a5..686687ca499ef 100644
--- a/clang/include/clang/Basic/ABIVersions.def
+++ b/clang/include/clang/Basic/ABIVersions.def
@@ -135,10 +135,10 @@ ABI_VER_MAJOR(20)
 ///    operator delete.
 ABI_VER_MAJOR(21)
 
-/// Attempt to be ABI-compatible with code generated by Clang 22.0.x.
+/// Attempt to be ABI-compatible with code generated by Clang 23.0.x.
 /// This causes clang to:
 ///   - Not ignore function __attribute(__target(...)) directives that change the ABI
-ABI_VER_MAJOR(22)
+ABI_VER_MAJOR(23)
 
 /// Conform to the underlying platform's C and C++ ABIs as closely as we can.
 ABI_VER_LATEST(Latest)



More information about the cfe-commits mailing list