Skip to content

Conversation

@MacDue
Copy link
Member

@MacDue MacDue commented Nov 13, 2025

This prevents the backend from crashing for basic uses of __SVCount_t type (e.g., as function arguments), without +sve2p1 or +sme2.

Fixes #167462

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Nov 13, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 13, 2025

@llvm/pr-subscribers-backend-aarch64

@llvm/pr-subscribers-clang

Author: Benjamin Maxwell (MacDue)

Changes

__SVCount_t is currently only supported on targets with sme2 or sve2p1, and will crash in the backend if used on targets without these features.

Unfortunately, there is quite a bit of churn with this change, as there are a couple of large tests for the built-in guards. These tests no longer really test the guard, as the clang bails out earlier, as the __SVCount_t type is not supported in the testing configurations. I spent some time trying to update these tests, but they now boil down to checking that the __SVCount_t type is illegal, so I simplified them to that.

This fixes the frontend side of #167462


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

10 Files Affected:

  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+1-1)
  • (modified) clang/include/clang/Sema/Sema.h (+6)
  • (modified) clang/lib/Sema/Sema.cpp (+26-9)
  • (modified) clang/lib/Sema/SemaDecl.cpp (+12-16)
  • (modified) clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp (+2-2)
  • (modified) clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp (+1-1)
  • (modified) clang/test/DebugInfo/AArch64/sve-vector-types.c (+1-1)
  • (modified) clang/test/Sema/AArch64/arm_sve_feature_dependent_sve_AND_sve2p1___sme_AND_LP_sve2p1_OR_sme2_RP.c (+7-2113)
  • (modified) clang/test/Sema/AArch64/arm_sve_streaming_only_sme_AND_sme2.c (+2-209)
  • (modified) clang/test/Sema/arm-sve-target.cpp (+21-1)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3e864475f22a1..8515c2af45012 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3354,7 +3354,7 @@ def warn_attribute_arm_zt0_builtin_no_zt0_state : Warning<
   "builtin call is not valid when calling from a function without active ZT0 state">,
   InGroup<DiagGroup<"undefined-arm-zt0">>;
 def err_sve_vector_in_non_sve_target : Error<
-  "SVE vector type %0 cannot be used in a target without sve">;
+  "SVE vector type %0 cannot be used in a target without %1 or %2">;
 def err_sve_vector_in_non_streaming_function : Error<
   "SVE vector type %0 cannot be used in a non-streaming function">;
 def err_sve_fixed_vector_in_streaming_function
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 163ab32fafa48..a533c0aaa4808 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7871,6 +7871,12 @@ class Sema final : public SemaBase {
   /// the perspective of SVE bitcasts.
   bool isValidSveBitcast(QualType srcType, QualType destType);
 
+  // Returns true if \p Ty is supported on the target, otherwise emits a
+  // diagnostic.
+  bool isSupportedSVETypeOrEmitDiag(QualType Ty, SourceLocation Loc,
+                                    const FunctionDecl *FD,
+                                    bool &HasRequiredSVEFeature);
+
   /// Are the two types matrix types and do they have the same dimensions i.e.
   /// do they have the same number of rows and the same number of columns?
   bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 46addea232b03..ce860d7e9b501 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -2115,6 +2115,26 @@ Sema::targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD) {
                                FD, *this);
 }
 
+bool Sema::isSupportedSVETypeOrEmitDiag(QualType Ty, SourceLocation Loc,
+                                        const FunctionDecl *FD,
+                                        bool &HasRequiredSVEFeature) {
+  const auto *BT = Ty->castAs<BuiltinType>();
+  auto [RequiredSVEFeature, RequiredSMEFeature] =
+      BT->isSVECount() ? std::make_pair("sve2p1", "sme2")
+                       : std::make_pair("sve", "sme");
+  llvm::StringMap<bool> CallerFeatureMap;
+  Context.getFunctionFeatureMap(CallerFeatureMap, FD);
+  HasRequiredSVEFeature = Builtin::evaluateRequiredTargetFeatures(
+      RequiredSVEFeature, CallerFeatureMap);
+  if (!HasRequiredSVEFeature && !Builtin::evaluateRequiredTargetFeatures(
+                                    RequiredSMEFeature, CallerFeatureMap)) {
+    Diag(Loc, diag::err_sve_vector_in_non_sve_target)
+        << Ty << RequiredSVEFeature << RequiredSMEFeature;
+    return false;
+  }
+  return true;
+}
+
 void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
   if (isUnevaluatedContext() || Ty.isNull())
     return;
@@ -2255,15 +2275,12 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
 
     // Don't allow SVE types in functions without a SVE target.
     if (Ty->isSVESizelessBuiltinType() && FD && !FD->getType().isNull()) {
-      llvm::StringMap<bool> CallerFeatureMap;
-      Context.getFunctionFeatureMap(CallerFeatureMap, FD);
-      if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap)) {
-        if (!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap))
-          Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty;
-        else if (!IsArmStreamingFunction(FD,
-                                         /*IncludeLocallyStreaming=*/true))
-          Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;
-      }
+      bool HasRequiredSVEFeature = false;
+      if (isSupportedSVETypeOrEmitDiag(Ty, Loc, FD, HasRequiredSVEFeature) &&
+          !HasRequiredSVEFeature &&
+          !IsArmStreamingFunction(FD,
+                                  /*IncludeLocallyStreaming=*/true))
+        Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;
     }
 
     if (auto *VT = Ty->getAs<VectorType>();
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 25b89d65847ad..2c28ea3cb1d82 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9124,22 +9124,18 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
   // Check that SVE types are only used in functions with SVE available.
   if (T->isSVESizelessBuiltinType() && isa<FunctionDecl>(CurContext)) {
     const FunctionDecl *FD = cast<FunctionDecl>(CurContext);
-    llvm::StringMap<bool> CallerFeatureMap;
-    Context.getFunctionFeatureMap(CallerFeatureMap, FD);
-
-    if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap)) {
-      if (!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap)) {
-        Diag(NewVD->getLocation(), diag::err_sve_vector_in_non_sve_target) << T;
-        NewVD->setInvalidDecl();
-        return;
-      } else if (!IsArmStreamingFunction(FD,
-                                         /*IncludeLocallyStreaming=*/true)) {
-        Diag(NewVD->getLocation(),
-             diag::err_sve_vector_in_non_streaming_function)
-            << T;
-        NewVD->setInvalidDecl();
-        return;
-      }
+    bool HasRequiredSVEFeature = false;
+    if (!isSupportedSVETypeOrEmitDiag(T, NewVD->getLocation(), FD,
+                                      HasRequiredSVEFeature)) {
+      NewVD->setInvalidDecl();
+      return;
+    } else if (!HasRequiredSVEFeature &&
+               !IsArmStreamingFunction(FD,
+                                       /*IncludeLocallyStreaming=*/true)) {
+      Diag(NewVD->getLocation(), diag::err_sve_vector_in_non_streaming_function)
+          << T;
+      NewVD->setInvalidDecl();
+      return;
     }
   }
 
diff --git a/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp b/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp
index 1709c88563267..d316fec529212 100644
--- a/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp
+++ b/clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp
@@ -1,8 +1,8 @@
 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3
 // RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu %s -emit-llvm -o - \
-// RUN:   -target-feature +sve -target-feature +bf16 | FileCheck %s
+// RUN:   -target-feature +sve -target-feature +sve2p1 -target-feature +bf16 | FileCheck %s
 // RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu %s -emit-llvm -o - \
-// RUN:   -target-feature +sve -target-feature +bf16 -fclang-abi-compat=17 | FileCheck %s --check-prefix=COMPAT_17
+// RUN:   -target-feature +sve -target-feature +sve2p1 -target-feature +bf16 -fclang-abi-compat=17 | FileCheck %s --check-prefix=COMPAT_17
 
 void f(__SVInt8_t, __SVInt8_t);
 void f(__SVInt16_t, __SVInt16_t);
diff --git a/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp b/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp
index bb71eb5636652..e5ac6c4d543ce 100644
--- a/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp
+++ b/clang/test/CodeGenCXX/aarch64-sve-vector-init.cpp
@@ -1,5 +1,5 @@
 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2
-// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu -target-feature +sve -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2p1 -emit-llvm -o - %s | FileCheck %s
 
 // CHECK-LABEL: define dso_local void @_Z11test_localsv
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
diff --git a/clang/test/DebugInfo/AArch64/sve-vector-types.c b/clang/test/DebugInfo/AArch64/sve-vector-types.c
index ed1dbd1d80e0a..cc5d9edf99977 100644
--- a/clang/test/DebugInfo/AArch64/sve-vector-types.c
+++ b/clang/test/DebugInfo/AArch64/sve-vector-types.c
@@ -1,4 +1,4 @@
-// RUN:  %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \
+// RUN:  %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2p1 \
 // RUN:  -emit-llvm -o - %s -debug-info-kind=limited 2>&1 | FileCheck %s
 
 void test_locals(void) {
diff --git a/clang/test/Sema/AArch64/arm_sve_feature_dependent_sve_AND_sve2p1___sme_AND_LP_sve2p1_OR_sme2_RP.c b/clang/test/Sema/AArch64/arm_sve_feature_dependent_sve_AND_sve2p1___sme_AND_LP_sve2p1_OR_sme2_RP.c
index 07e275a5a2432..c1e4107970ee7 100644
--- a/clang/test/Sema/AArch64/arm_sve_feature_dependent_sve_AND_sve2p1___sme_AND_LP_sve2p1_OR_sme2_RP.c
+++ b/clang/test/Sema/AArch64/arm_sve_feature_dependent_sve_AND_sve2p1___sme_AND_LP_sve2p1_OR_sme2_RP.c
@@ -10,6 +10,11 @@
 // Properties: guard="sve,sve2p1" streaming_guard="sme,(sve2p1|sme2)" flags="feature-dependent"
 
 void test(void) {
+  // streaming-guard-error@+1 {{SVE vector type 'svcount_t' (aka '__SVCount_t') cannot be used in a non-streaming function}}
+  svcount_t svcount_t_val;
+}
+
+void test_streaming(void) __arm_streaming{
   bfloat16_t * bfloat16_t_ptr_val;
   float16_t * float16_t_ptr_val;
   float32_t * float32_t_ptr_val;
@@ -55,2625 +60,514 @@ void test(void) {
   uint64_t * uint64_t_ptr_val;
   uint64_t uint64_t_val;
 
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svcntp_c8(svcount_t_val, 2);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svcntp_c16(svcount_t_val, 2);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svcntp_c32(svcount_t_val, 2);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svcntp_c64(svcount_t_val, 2);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_bf16_x2(svcount_t_val, bfloat16_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_bf16_x4(svcount_t_val, bfloat16_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_f16_x2(svcount_t_val, float16_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_f16_x4(svcount_t_val, float16_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_f32_x2(svcount_t_val, float32_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_f32_x4(svcount_t_val, float32_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_f64_x2(svcount_t_val, float64_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_f64_x4(svcount_t_val, float64_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_mf8_x2(svcount_t_val, mfloat8_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_mf8_x4(svcount_t_val, mfloat8_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_s8_x2(svcount_t_val, int8_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_s8_x4(svcount_t_val, int8_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_s16_x2(svcount_t_val, int16_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_s16_x4(svcount_t_val, int16_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_s32_x2(svcount_t_val, int32_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_s32_x4(svcount_t_val, int32_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_s64_x2(svcount_t_val, int64_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_s64_x4(svcount_t_val, int64_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_u8_x2(svcount_t_val, uint8_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_u8_x4(svcount_t_val, uint8_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_u16_x2(svcount_t_val, uint16_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_u16_x4(svcount_t_val, uint16_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_u32_x2(svcount_t_val, uint32_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_u32_x4(svcount_t_val, uint32_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_u64_x2(svcount_t_val, uint64_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_u64_x4(svcount_t_val, uint64_t_ptr_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_bf16_x2(svcount_t_val, bfloat16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_bf16_x4(svcount_t_val, bfloat16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_f16_x2(svcount_t_val, float16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_f16_x4(svcount_t_val, float16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_f32_x2(svcount_t_val, float32_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_f32_x4(svcount_t_val, float32_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_f64_x2(svcount_t_val, float64_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_f64_x4(svcount_t_val, float64_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_mf8_x2(svcount_t_val, mfloat8_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_mf8_x4(svcount_t_val, mfloat8_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_s8_x2(svcount_t_val, int8_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_s8_x4(svcount_t_val, int8_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_s16_x2(svcount_t_val, int16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_s16_x4(svcount_t_val, int16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_s32_x2(svcount_t_val, int32_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_s32_x4(svcount_t_val, int32_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_s64_x2(svcount_t_val, int64_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_s64_x4(svcount_t_val, int64_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_u8_x2(svcount_t_val, uint8_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_u8_x4(svcount_t_val, uint8_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_u16_x2(svcount_t_val, uint16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_u16_x4(svcount_t_val, uint16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_u32_x2(svcount_t_val, uint32_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_u32_x4(svcount_t_val, uint32_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_u64_x2(svcount_t_val, uint64_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_u64_x4(svcount_t_val, uint64_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, bfloat16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, float16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, float32_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, float64_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, int8_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, int16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, int32_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, int64_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, mfloat8_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, uint8_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, uint16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, uint32_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x2(svcount_t_val, uint64_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x4(svcount_t_val, bfloat16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x4(svcount_t_val, float16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x4(svcount_t_val, float32_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x4(svcount_t_val, float64_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x4(svcount_t_val, int8_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{builtin can only be called from a streaming function}}
   svld1_vnum_x4(svcount_t_val, int16_t_ptr_val, int64_t_val);
-  // streaming-guard-error@+1 {{bui...
[truncated]

@paulwalker-arm
Copy link
Collaborator

Where possible you don't want to protect types by feature flags because it makes them hard to use. In this instance svcount_t does not introduce architectural state that's not already available to SVE and so it's really only the builtins that need protecting.

As far as I know when SVE is available we should be able to allocate, zero, load, store and bitcast this type so I don't see a need to restrict the type. This is the approach we took for svbfloat_t so perhaps there are just code generation bugs to fix?

This prevents the backend from crashing for basic uses of the
__SVCount_t type (e.g., as function arguments), without +sve2p1 or +sme2.

Fixes llvm#167462
@MacDue MacDue changed the title [clang][AArch64] Restrict __SVCount_t to targets with sme2 or sve2p1 [AArch64][SVE] Allow basic use of target("aarch64.svcount") with +sve Nov 13, 2025
Copy link
Collaborator

@paulwalker-arm paulwalker-arm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we need a new test file but otherwise this looks good to me.

@MacDue MacDue enabled auto-merge (squash) November 13, 2025 16:02
@MacDue MacDue merged commit 12322b2 into llvm:main Nov 13, 2025
9 of 10 checks passed
@MacDue MacDue deleted the svcount_check branch November 13, 2025 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:AArch64 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[AArch64] Assertion `DAG.getTargetLoweringInfo().isTypeLegal(PartVT) && "Copying to an illegal type!"' failed.

3 participants