[libc-commits] [clang] [libc] [libcxx] [clang][X86] Emit AVX level mismatch psABI warnings on function definitions (PR #199091)

Benjamin Luke via libc-commits libc-commits at lists.llvm.org
Thu May 21 11:58:24 PDT 2026


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

>From f4f2c695e7c6e0a5b2cbc1ef045908353caf9069 Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Wed, 20 May 2026 11:53:38 -0700
Subject: [PATCH 1/2] [clang][X86] Emit AVX level mismatch psABI warnings on
 function definitions

Emit -WpsABI for x86_64 function definitions whose return type or
parameter type uses a vector wider than 128 bits without the required ABI
feature enabled. 256-bit vectors require avx, and 512-bit vectors require
avx512f.

Previously this diagnostic was only emitted at call sites, so definitions
with wide vector signatures could be introduced without a warning until
they were called. Use the function feature map so
attribute(target("avx/avx512f")) definitions are accepted, and emit no
warnings for prototype-only declarations.
---
 clang/lib/CodeGen/Targets/X86.cpp             | 51 +++++++++++++++++++
 clang/test/CodeGen/X86/mmx-inline-asm-error.c |  2 +
 clang/test/CodeGen/target-builtin-error-3.c   |  6 +++
 clang/test/CodeGen/target-features-error-2.c  |  1 +
 clang/test/CodeGenCXX/target-avx-abi-diag.cpp | 37 ++++++++++++++
 libc/src/mathvec/generic/CMakeLists.txt       |  2 +
 libcxx/utils/libcxx/test/params.py            |  3 ++
 7 files changed, 102 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/target-avx-abi-diag.cpp

diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 61ab591f55be9..6ea4df1bc5438 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/SourceLocation.h"
 #include "llvm/ADT/SmallBitVector.h"
 
 using namespace clang;
@@ -1509,6 +1510,9 @@ class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
                             const FunctionDecl *Caller,
                             const FunctionDecl *Callee, const CallArgList &Args,
                             QualType ReturnType) const override;
+
+  void checkFunctionABI(CodeGenModule &CGM,
+                        const FunctionDecl *FD) const override;
 };
 } // namespace
 
@@ -1571,6 +1575,53 @@ static bool checkAVXParam(DiagnosticsEngine &Diag, ASTContext &Ctx,
   return false;
 }
 
+void X86_64TargetCodeGenInfo::checkFunctionABI(CodeGenModule &CGM,
+                                               const FunctionDecl *FD) const {
+  auto GetReturnTypeLoc = [](const FunctionDecl *FD) {
+    if (const TypeSourceInfo *TSI = FD->getTypeSourceInfo()) {
+      TypeLoc TL = TSI->getTypeLoc();
+
+      if (auto FTL = TL.IgnoreParens().getAs<FunctionTypeLoc>())
+        return FTL.getReturnLoc().getBeginLoc();
+    }
+
+    return FD->getLocation();
+  };
+
+  auto Check = [&](QualType Ty, SourceLocation Loc, bool IsReturn) {
+    if (!Ty->isVectorType())
+      return false;
+    if (CGM.getContext().getTypeSize(Ty) <= 128)
+      return false;
+
+    StringRef Feature =
+        CGM.getContext().getTypeSize(Ty) > 256 ? "avx512f" : "avx";
+
+    llvm::StringMap<bool> FeatureMap;
+    CGM.getContext().getFunctionFeatureMap(FeatureMap, FD);
+    if (!FeatureMap.lookup(Feature)) {
+      CGM.getDiags().Report(Loc, diag::warn_avx_calling_convention)
+          << !IsReturn << Ty << Feature;
+      return true;
+    }
+
+    return false;
+  };
+
+  // First check the return type and emit diagnostic if required
+  Check(FD->getReturnType(), GetReturnTypeLoc(FD), true);
+
+  // Go through the parameters and emit a warning for the first vector found
+  // without the matching function AVX level attribute
+  for (const ParmVarDecl *P : FD->parameters()) {
+    SourceLocation Loc = P->getLocation();
+    if (Loc.isInvalid())
+      Loc = P->getBeginLoc();
+    if (Check(P->getType(), Loc, false))
+      return;
+  }
+}
+
 void X86_64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
                                                    SourceLocation CallLoc,
                                                    const FunctionDecl *Caller,
diff --git a/clang/test/CodeGen/X86/mmx-inline-asm-error.c b/clang/test/CodeGen/X86/mmx-inline-asm-error.c
index 8a2f991a537a2..7f7f53a553057 100644
--- a/clang/test/CodeGen/X86/mmx-inline-asm-error.c
+++ b/clang/test/CodeGen/X86/mmx-inline-asm-error.c
@@ -2,6 +2,8 @@
 // RUN: %clang_cc1 -verify=omp -triple x86_64-unknown-unknown -emit-llvm-only -fopenmp %s
 typedef int vec256 __attribute__((ext_vector_type(8)));
 
+// omp-warning at +2 {{AVX vector return of type 'vec256' (vector of 8 'int' values) without 'avx' enabled changes the ABI}}
+// omp-warning at +1 {{AVX vector argument of type 'vec256' (vector of 8 'int' values) without 'avx' enabled changes the ABI}}
 vec256 foo(vec256 in) {
   vec256 out;
 
diff --git a/clang/test/CodeGen/target-builtin-error-3.c b/clang/test/CodeGen/target-builtin-error-3.c
index 056dc940f7a93..840ca7534905d 100644
--- a/clang/test/CodeGen/target-builtin-error-3.c
+++ b/clang/test/CodeGen/target-builtin-error-3.c
@@ -17,32 +17,38 @@ typedef __attribute__ ((ext_vector_type(16),__aligned__( 64))) float float16;
 static inline half8 __attribute__((__overloadable__)) convert_half( float8 a ) {
   return __extension__ ({ __m256 __a = (a); (__m128i)__builtin_ia32_vcvtps2ph256((__v8sf)__a, (0x00)); }); // expected-error {{'__builtin_ia32_vcvtps2ph256' needs target feature f16c}}
 }
+// expected-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
 static inline half16 __attribute__((__overloadable__)) convert_half( float16 a ) {
   half16 r;
   r.lo = convert_half(a.lo);
   return r;
 }
+// expected-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
 void avx_test( uint16_t *destData, float16 argbF)
 {
   ((half16U *)destData)[0] = convert_half(argbF);
 }
 
+// expected-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
 half16 test( float16 a ) {
   half16 r;
   r.lo = convert_half(a.lo);
   return r;
 }
+// expected-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
 void avx_test2( uint16_t *destData, float16 argbF)
 {
   // expected-warning at +1{{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
   ((half16U *)destData)[0] = test(argbF);
 }
 
+// expected-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
 __attribute__((always_inline)) half16 test2( float16 a ) {
   half16 r;
   r.lo = convert_half(a.lo);
   return r;
 }
+// expected-warning at +1 {{AVX vector argument of type 'float16' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
 void avx_test3( uint16_t *destData, float16 argbF)
 {
   ((half16U *)destData)[0] = test2(argbF);
diff --git a/clang/test/CodeGen/target-features-error-2.c b/clang/test/CodeGen/target-features-error-2.c
index 1599b0135b747..8f2ef35b8a931 100644
--- a/clang/test/CodeGen/target-features-error-2.c
+++ b/clang/test/CodeGen/target-features-error-2.c
@@ -8,6 +8,7 @@
 #include <x86intrin.h>
 
 #if NEED_AVX_1
+// expected-warning at +1 {{AVX vector argument of type '__m256i' (vector of 4 'long long' values) without 'avx' enabled changes the ABI}}
 int baz(__m256i a) {
   return _mm256_extract_epi32(a, 3); // expected-error {{'__builtin_ia32_vec_ext_v8si' needs target feature avx}}
 }
diff --git a/clang/test/CodeGenCXX/target-avx-abi-diag.cpp b/clang/test/CodeGenCXX/target-avx-abi-diag.cpp
new file mode 100644
index 0000000000000..5048cb092e67f
--- /dev/null
+++ b/clang/test/CodeGenCXX/target-avx-abi-diag.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -emit-llvm -disable-llvm-passes -verify=noavx,noavx512 -o - %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -target-feature +avx -emit-llvm -disable-llvm-passes -verify=noavx512 -o - %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -target-feature +avx512f -emit-llvm -disable-llvm-passes -verify=both -o - %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -Wno-psabi -emit-llvm -disable-llvm-passes -verify=suppressed -o - %s
+// REQUIRES: x86-registered-target
+
+// both-no-diagnostics
+// suppressed-no-diagnostics
+
+typedef float v8f __attribute__((vector_size(32)));
+typedef float v16f __attribute__((vector_size(64)));
+
+// Prototype-only declarations do not warn.
+v8f proto256(v8f);
+v16f proto512(v16f);
+
+// noavx-warning at +2 {{AVX vector return of type 'v8f' (vector of 8 'float' values) without 'avx' enabled changes the ABI}}
+// noavx-warning at +1 {{AVX vector argument of type 'v8f' (vector of 8 'float' values) without 'avx' enabled changes the ABI}}
+v8f def256(v8f x) {
+  return x;
+}
+
+// noavx512-warning at +2 {{AVX vector return of type 'v16f' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
+// noavx512-warning at +1 {{AVX vector argument of type 'v16f' (vector of 16 'float' values) without 'avx512f' enabled changes the ABI}}
+v16f def512(v16f x) {
+  return x;
+}
+
+__attribute__((target("avx")))
+v8f def256_avx(v8f x) {
+  return x;
+}
+
+__attribute__((target("avx512f")))
+v16f def512_avx512(v16f x) {
+  return x;
+}
diff --git a/libc/src/mathvec/generic/CMakeLists.txt b/libc/src/mathvec/generic/CMakeLists.txt
index d5d94d5ed56b5..0592ec1258cbf 100644
--- a/libc/src/mathvec/generic/CMakeLists.txt
+++ b/libc/src/mathvec/generic/CMakeLists.txt
@@ -7,6 +7,8 @@ add_entrypoint_object(
   DEPENDS
     libc.src.__support.macros.properties.cpu_features
     libc.src.__support.mathvec.expf
+  COMPILE_OPTIONS
+    -Wno-psabi
   FLAGS
     ROUND_OPT
     FMA_OPT
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index d0bb38ab84df4..2c78a32b1449b 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -76,6 +76,9 @@
     # We're not annotating all the APIs, since that's a lot of annotations compared to how many we actually care about
     "-Wno-nullability-completeness",
 
+    # Adding this for now to get the build to pass but needs more detailed review
+    "-Wno-psabi",
+
     # Technically not a warning flag, but might as well be:
     "-flax-vector-conversions=none",
 ]

>From 2f8a49024db0e5bd83e4816bbe6403505950de1f Mon Sep 17 00:00:00 2001
From: Benjamin Luke <benjamin.luke at sony.com>
Date: Thu, 21 May 2026 11:57:54 -0700
Subject: [PATCH 2/2] darker format

---
 libcxx/utils/libcxx/test/params.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index 2c78a32b1449b..c9e6f767679fa 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -75,7 +75,6 @@
 
     # We're not annotating all the APIs, since that's a lot of annotations compared to how many we actually care about
     "-Wno-nullability-completeness",
-
     # Adding this for now to get the build to pass but needs more detailed review
     "-Wno-psabi",
 



More information about the libc-commits mailing list