https://github.com/efriedma-quic updated 
https://github.com/llvm/llvm-project/pull/144611

>From c28804a471a9fe6be24479ffbfd7d4aa6c774125 Mon Sep 17 00:00:00 2001
From: Eli Friedman <efrie...@quicinc.com>
Date: Tue, 17 Jun 2025 11:48:47 -0700
Subject: [PATCH 1/2] [AArch64] Add option -msve-streaming-vector-bits= .

This is similar to -msve-vector-bits, but for streaming mode: it
constrains the legal values of "vscale", allowing optimizations based on
that constraint.

This also fixes conversions between SVE vectors and fixed-width vectors
in streaming functions with -msve-vector-bits and
-msve-streaming-vector-bits.

This currently doesn't touch the __ARM_FEATURE_SVE_BITS define or the
arm_sve_vector_bits attribute.
---
 clang/include/clang/AST/ASTContext.h          |  9 --
 clang/include/clang/Basic/LangOptions.def     |  3 +
 clang/include/clang/Driver/Options.td         | 19 ++++
 clang/include/clang/Sema/SemaARM.h            |  9 ++
 clang/lib/AST/ASTContext.cpp                  | 81 ----------------
 clang/lib/Basic/Targets/AArch64.cpp           |  8 +-
 clang/lib/Driver/ToolChains/Clang.cpp         | 29 ++++--
 clang/lib/Frontend/CompilerInvocation.cpp     |  5 +
 clang/lib/Sema/SemaARM.cpp                    | 97 +++++++++++++++++++
 clang/lib/Sema/SemaChecking.cpp               | 16 +--
 clang/lib/Sema/SemaExpr.cpp                   |  5 +-
 clang/lib/Sema/SemaOverload.cpp               |  9 +-
 .../arm-sve-vector-bits-vscale-range.c        | 58 ++++++++---
 clang/test/Driver/aarch64-sve-vector-bits.c   |  4 +
 ...rch64-streaming-sve-vector-conversions.cpp | 53 ++++++++++
 15 files changed, 277 insertions(+), 128 deletions(-)
 create mode 100644 
clang/test/SemaCXX/aarch64-streaming-sve-vector-conversions.cpp

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 3abb49312255a..64d4c5547341e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2486,15 +2486,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
   /// types.
   bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
 
-  /// Return true if the given types are an SVE builtin and a VectorType that
-  /// is a fixed-length representation of the SVE builtin for a specific
-  /// vector-length.
-  bool areCompatibleSveTypes(QualType FirstType, QualType SecondType);
-
-  /// Return true if the given vector types are lax-compatible SVE vector 
types,
-  /// false otherwise.
-  bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType);
-
   /// Return true if the given types are an RISC-V vector builtin type and a
   /// VectorType that is a fixed-length representation of the RISC-V vector
   /// builtin type for a specific vector-length.
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 789761c1f3647..8054be1bb4e88 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -503,6 +503,9 @@ LANGOPT(OmitVTableRTTI, 1, 0,
 LANGOPT(VScaleMin, 32, 0, "Minimum vscale value")
 LANGOPT(VScaleMax, 32, 0, "Maximum vscale value")
 
+LANGOPT(VScaleStreamingMin, 32, 0, "Minimum streaming vscale value")
+LANGOPT(VScaleStreamingMax, 32, 0, "Maximum streaming vscale value")
+
 ENUM_LANGOPT(ExtendIntArgs, ExtendArgsKind, 1, ExtendArgsKind::ExtendTo32,
              "Controls how scalar integer arguments are extended in calls "
              "to unprototyped and varargs functions")
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 152df89118a6a..2e8d5b18483d7 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5173,6 +5173,14 @@ def msve_vector_bits_EQ : Joined<["-"], 
"msve-vector-bits=">, Group<m_aarch64_Fe
   Visibility<[ClangOption, FlangOption]>,
   HelpText<"Specify the size in bits of an SVE vector register. Defaults to 
the"
            " vector length agnostic value of \"scalable\". (AArch64 only)">;
+def msve_streaming_vector_bits_EQ
+    : Joined<["-"], "msve-streaming-vector-bits=">,
+      Group<m_aarch64_Features_Group>,
+      Visibility<[ClangOption, FlangOption]>,
+      HelpText<
+          "Specify the size in bits of an SVE vector register in streaming "
+          "mode. Defaults to the vector length agnostic value of "
+          "\"scalable\". (AArch64 only)">;
 } // let Flags = [TargetSpecific]
 
 def mvscale_min_EQ : Joined<["-"], "mvscale-min=">,
@@ -5184,6 +5192,17 @@ def mvscale_max_EQ : Joined<["-"], "mvscale-max=">,
   HelpText<"Specify the vscale maximum. Defaults to the"
            " vector length agnostic value of \"0\". (AArch64/RISC-V only)">,
   MarshallingInfoInt<LangOpts<"VScaleMax">>;
+def mvscale_streaming_min_EQ
+    : Joined<["-"], "mvscale-streaming-min=">,
+      Visibility<[CC1Option, FC1Option]>,
+      HelpText<"Specify the vscale minimum. Defaults to \"1\". (AArch64 
only)">,
+      MarshallingInfoInt<LangOpts<"VScaleStreamingMin">>;
+def mvscale_streaming_max_EQ
+    : Joined<["-"], "mvscale-streaming-max=">,
+      Visibility<[CC1Option, FC1Option]>,
+      HelpText<"Specify the vscale maximum. Defaults to the"
+               " vector length agnostic value of \"0\". (AArch64 only)">,
+      MarshallingInfoInt<LangOpts<"VScaleStreamingMax">>;
 
 def msign_return_address_EQ : Joined<["-"], "msign-return-address=">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/include/clang/Sema/SemaARM.h 
b/clang/include/clang/Sema/SemaARM.h
index ce79e94ebdd9b..788a7abf5f9c1 100644
--- a/clang/include/clang/Sema/SemaARM.h
+++ b/clang/include/clang/Sema/SemaARM.h
@@ -82,6 +82,15 @@ class SemaARM : public SemaBase {
   void handleInterruptSaveFPAttr(Decl *D, const ParsedAttr &AL);
 
   void CheckSMEFunctionDefAttributes(const FunctionDecl *FD);
+
+  /// Return true if the given types are an SVE builtin and a VectorType that
+  /// is a fixed-length representation of the SVE builtin for a specific
+  /// vector-length.
+  bool areCompatibleSveTypes(QualType FirstType, QualType SecondType);
+
+  /// Return true if the given vector types are lax-compatible SVE vector 
types,
+  /// false otherwise.
+  bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType);
 };
 
 SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 4d44f23c0f503..d785b5a5006cc 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -10443,87 +10443,6 @@ bool ASTContext::areCompatibleVectorTypes(QualType 
FirstVec,
   return false;
 }
 
-/// getSVETypeSize - Return SVE vector or predicate register size.
-static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty) {
-  assert(Ty->isSveVLSBuiltinType() && "Invalid SVE Type");
-  if (Ty->getKind() == BuiltinType::SveBool ||
-      Ty->getKind() == BuiltinType::SveCount)
-    return (Context.getLangOpts().VScaleMin * 128) / Context.getCharWidth();
-  return Context.getLangOpts().VScaleMin * 128;
-}
-
-bool ASTContext::areCompatibleSveTypes(QualType FirstType,
-                                       QualType SecondType) {
-  auto IsValidCast = [this](QualType FirstType, QualType SecondType) {
-    if (const auto *BT = FirstType->getAs<BuiltinType>()) {
-      if (const auto *VT = SecondType->getAs<VectorType>()) {
-        // Predicates have the same representation as uint8 so we also have to
-        // check the kind to make these types incompatible.
-        if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate)
-          return BT->getKind() == BuiltinType::SveBool;
-        else if (VT->getVectorKind() == VectorKind::SveFixedLengthData)
-          return VT->getElementType().getCanonicalType() ==
-                 FirstType->getSveEltType(*this);
-        else if (VT->getVectorKind() == VectorKind::Generic)
-          return getTypeSize(SecondType) == getSVETypeSize(*this, BT) &&
-                 hasSameType(VT->getElementType(),
-                             getBuiltinVectorTypeInfo(BT).ElementType);
-      }
-    }
-    return false;
-  };
-
-  return IsValidCast(FirstType, SecondType) ||
-         IsValidCast(SecondType, FirstType);
-}
-
-bool ASTContext::areLaxCompatibleSveTypes(QualType FirstType,
-                                          QualType SecondType) {
-  auto IsLaxCompatible = [this](QualType FirstType, QualType SecondType) {
-    const auto *BT = FirstType->getAs<BuiltinType>();
-    if (!BT)
-      return false;
-
-    const auto *VecTy = SecondType->getAs<VectorType>();
-    if (VecTy && (VecTy->getVectorKind() == VectorKind::SveFixedLengthData ||
-                  VecTy->getVectorKind() == VectorKind::Generic)) {
-      const LangOptions::LaxVectorConversionKind LVCKind =
-          getLangOpts().getLaxVectorConversions();
-
-      // Can not convert between sve predicates and sve vectors because of
-      // different size.
-      if (BT->getKind() == BuiltinType::SveBool &&
-          VecTy->getVectorKind() == VectorKind::SveFixedLengthData)
-        return false;
-
-      // If __ARM_FEATURE_SVE_BITS != N do not allow GNU vector lax conversion.
-      // "Whenever __ARM_FEATURE_SVE_BITS==N, GNUT implicitly
-      // converts to VLAT and VLAT implicitly converts to GNUT."
-      // ACLE Spec Version 00bet6, 3.7.3.2. Behavior common to vectors and
-      // predicates.
-      if (VecTy->getVectorKind() == VectorKind::Generic &&
-          getTypeSize(SecondType) != getSVETypeSize(*this, BT))
-        return false;
-
-      // If -flax-vector-conversions=all is specified, the types are
-      // certainly compatible.
-      if (LVCKind == LangOptions::LaxVectorConversionKind::All)
-        return true;
-
-      // If -flax-vector-conversions=integer is specified, the types are
-      // compatible if the elements are integer types.
-      if (LVCKind == LangOptions::LaxVectorConversionKind::Integer)
-        return VecTy->getElementType().getCanonicalType()->isIntegerType() &&
-               FirstType->getSveEltType(*this)->isIntegerType();
-    }
-
-    return false;
-  };
-
-  return IsLaxCompatible(FirstType, SecondType) ||
-         IsLaxCompatible(SecondType, FirstType);
-}
-
 /// getRVVTypeSize - Return RVV vector register size.
 static uint64_t getRVVTypeSize(ASTContext &Context, const BuiltinType *Ty) {
   assert(Ty->isRVVVLSBuiltinType() && "Invalid RVV Type");
diff --git a/clang/lib/Basic/Targets/AArch64.cpp 
b/clang/lib/Basic/Targets/AArch64.cpp
index e8abdf9aafd82..c5935390137b1 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -822,10 +822,16 @@ std::optional<std::pair<unsigned, unsigned>>
 AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts,
                                   bool IsArmStreamingFunction,
                                   llvm::StringMap<bool> *FeatureMap) const {
-  if (LangOpts.VScaleMin || LangOpts.VScaleMax)
+  if (!IsArmStreamingFunction && (LangOpts.VScaleMin || LangOpts.VScaleMax))
     return std::pair<unsigned, unsigned>(
         LangOpts.VScaleMin ? LangOpts.VScaleMin : 1, LangOpts.VScaleMax);
 
+  if (IsArmStreamingFunction &&
+      (LangOpts.VScaleStreamingMin || LangOpts.VScaleStreamingMax))
+    return std::pair<unsigned, unsigned>(
+        LangOpts.VScaleStreamingMin ? LangOpts.VScaleStreamingMin : 1,
+        LangOpts.VScaleStreamingMax);
+
   if (hasFeature("sve") || (FeatureMap && (FeatureMap->lookup("sve"))))
     return std::pair<unsigned, unsigned>(1, 16);
 
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 1d11be1d82be8..24ec25601881f 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1666,7 +1666,7 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
   }
 
   // Handle -msve_vector_bits=<bits>
-  if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) {
+  auto HandleVectorBits = [&](Arg *A, bool Streaming) {
     StringRef Val = A->getValue();
     const Driver &D = getToolChain().getDriver();
     if (Val == "128" || Val == "256" || Val == "512" || Val == "1024" ||
@@ -1674,22 +1674,35 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
         Val == "1024+" || Val == "2048+") {
       unsigned Bits = 0;
       if (!Val.consume_back("+")) {
-        bool Invalid = Val.getAsInteger(10, Bits); (void)Invalid;
+        bool Invalid = Val.getAsInteger(10, Bits);
+        (void)Invalid;
         assert(!Invalid && "Failed to parse value");
+        StringRef VScaleMax =
+            Streaming ? "-mvscale-streaming-max=" : "-mvscale-max=";
         CmdArgs.push_back(
-            Args.MakeArgString("-mvscale-max=" + llvm::Twine(Bits / 128)));
+            Args.MakeArgString(VScaleMax + llvm::Twine(Bits / 128)));
       }
 
-      bool Invalid = Val.getAsInteger(10, Bits); (void)Invalid;
+      bool Invalid = Val.getAsInteger(10, Bits);
+      (void)Invalid;
       assert(!Invalid && "Failed to parse value");
+
+      StringRef VScaleMin =
+          Streaming ? "-mvscale-streaming-min=" : "-mvscale-min=";
       CmdArgs.push_back(
-          Args.MakeArgString("-mvscale-min=" + llvm::Twine(Bits / 128)));
-    // Silently drop requests for vector-length agnostic code as it's implied.
-    } else if (Val != "scalable")
+          Args.MakeArgString(VScaleMin + llvm::Twine(Bits / 128)));
+    } else if (Val == "scalable") {
+      // Silently drop requests for vector-length agnostic code as it's 
implied.
+    } else {
       // Handle the unsupported values passed to msve-vector-bits.
       D.Diag(diag::err_drv_unsupported_option_argument)
           << A->getSpelling() << Val;
-  }
+    }
+  };
+  if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ))
+    HandleVectorBits(A, /*Streaming*/ false);
+  if (Arg *A = Args.getLastArg(options::OPT_msve_streaming_vector_bits_EQ))
+    HandleVectorBits(A, /*Streaming*/ true);
 
   AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
 
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 2c02719121c73..b3334b1bc560a 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4558,6 +4558,11 @@ bool CompilerInvocation::ParseLangArgs(LangOptions 
&Opts, ArgList &Args,
     if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)
       Diags.Report(diag::err_cc1_unbounded_vscale_min);
   }
+  if (Arg *A = Args.getLastArg(options::OPT_mvscale_streaming_min_EQ)) {
+    unsigned VScaleMin;
+    if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)
+      Diags.Report(diag::err_cc1_unbounded_vscale_min);
+  }
 
   if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) {
     std::ifstream SeedFile(A->getValue(0));
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index e992a1012fde0..ec892a5d82421 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -1409,4 +1409,101 @@ void SemaARM::CheckSMEFunctionDefAttributes(const 
FunctionDecl *FD) {
   }
 }
 
+/// getSVETypeSize - Return SVE vector or predicate register size.
+static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty,
+                               bool IsStreaming) {
+  assert(Ty->isSveVLSBuiltinType() && "Invalid SVE Type");
+  uint64_t VScale = IsStreaming ? Context.getLangOpts().VScaleStreamingMin
+                                : Context.getLangOpts().VScaleMin;
+  if (Ty->getKind() == BuiltinType::SveBool ||
+      Ty->getKind() == BuiltinType::SveCount)
+    return (VScale * 128) / Context.getCharWidth();
+  return VScale * 128;
+}
+
+bool SemaARM::areCompatibleSveTypes(QualType FirstType, QualType SecondType) {
+  bool IsStreaming = false;
+  if (const FunctionDecl *FD = 
SemaRef.getCurFunctionDecl(/*AllowLambda=*/true))
+    if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
+      IsStreaming = true;
+  auto IsValidCast = [&](QualType FirstType, QualType SecondType) {
+    if (const auto *BT = FirstType->getAs<BuiltinType>()) {
+      if (const auto *VT = SecondType->getAs<VectorType>()) {
+        // Predicates have the same representation as uint8 so we also have to
+        // check the kind to make these types incompatible.
+        ASTContext &Context = getASTContext();
+        if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate)
+          return BT->getKind() == BuiltinType::SveBool;
+        else if (VT->getVectorKind() == VectorKind::SveFixedLengthData)
+          return VT->getElementType().getCanonicalType() ==
+                 FirstType->getSveEltType(Context);
+        else if (VT->getVectorKind() == VectorKind::Generic)
+          return Context.getTypeSize(SecondType) ==
+                     getSVETypeSize(Context, BT, IsStreaming) &&
+                 Context.hasSameType(
+                     VT->getElementType(),
+                     Context.getBuiltinVectorTypeInfo(BT).ElementType);
+      }
+    }
+    return false;
+  };
+
+  return IsValidCast(FirstType, SecondType) ||
+         IsValidCast(SecondType, FirstType);
+}
+
+bool SemaARM::areLaxCompatibleSveTypes(QualType FirstType,
+                                       QualType SecondType) {
+  bool IsStreaming = false;
+  if (const FunctionDecl *FD = 
SemaRef.getCurFunctionDecl(/*AllowLambda=*/true))
+    if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
+      IsStreaming = true;
+
+  auto IsLaxCompatible = [&](QualType FirstType, QualType SecondType) {
+    const auto *BT = FirstType->getAs<BuiltinType>();
+    if (!BT)
+      return false;
+
+    const auto *VecTy = SecondType->getAs<VectorType>();
+    if (VecTy && (VecTy->getVectorKind() == VectorKind::SveFixedLengthData ||
+                  VecTy->getVectorKind() == VectorKind::Generic)) {
+      const LangOptions::LaxVectorConversionKind LVCKind =
+          getLangOpts().getLaxVectorConversions();
+      ASTContext &Context = getASTContext();
+
+      // Can not convert between sve predicates and sve vectors because of
+      // different size.
+      if (BT->getKind() == BuiltinType::SveBool &&
+          VecTy->getVectorKind() == VectorKind::SveFixedLengthData)
+        return false;
+
+      // If __ARM_FEATURE_SVE_BITS != N do not allow GNU vector lax conversion.
+      // "Whenever __ARM_FEATURE_SVE_BITS==N, GNUT implicitly
+      // converts to VLAT and VLAT implicitly converts to GNUT."
+      // ACLE Spec Version 00bet6, 3.7.3.2. Behavior common to vectors and
+      // predicates.
+      if (VecTy->getVectorKind() == VectorKind::Generic &&
+          Context.getTypeSize(SecondType) !=
+              getSVETypeSize(Context, BT, IsStreaming))
+        return false;
+
+      // If -flax-vector-conversions=all is specified, the types are
+      // certainly compatible.
+      if (LVCKind == LangOptions::LaxVectorConversionKind::All)
+        return true;
+
+      // If -flax-vector-conversions=integer is specified, the types are
+      // compatible if the elements are integer types.
+      if (LVCKind == LangOptions::LaxVectorConversionKind::Integer)
+        return VecTy->getElementType().getCanonicalType()->isIntegerType() &&
+               FirstType->getSveEltType(Context)->isIntegerType();
+    }
+
+    return false;
+  };
+
+  return IsLaxCompatible(FirstType, SecondType) ||
+         IsLaxCompatible(SecondType, FirstType);
+}
+
 } // namespace clang
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 8f8e1ceb7197e..bae4cc67da98f 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -12057,10 +12057,10 @@ void Sema::CheckImplicitConversion(Expr *E, QualType 
T, SourceLocation CC,
   // Strip vector types.
   if (isa<VectorType>(Source)) {
     if (Target->isSveVLSBuiltinType() &&
-        (Context.areCompatibleSveTypes(QualType(Target, 0),
-                                       QualType(Source, 0)) ||
-         Context.areLaxCompatibleSveTypes(QualType(Target, 0),
-                                          QualType(Source, 0))))
+        (ARM().areCompatibleSveTypes(QualType(Target, 0),
+                                     QualType(Source, 0)) ||
+         ARM().areLaxCompatibleSveTypes(QualType(Target, 0),
+                                        QualType(Source, 0))))
       return;
 
     if (Target->isRVVVLSBuiltinType() &&
@@ -12120,10 +12120,10 @@ void Sema::CheckImplicitConversion(Expr *E, QualType 
T, SourceLocation CC,
     const Type *OriginalTarget = Context.getCanonicalType(T).getTypePtr();
     // Handle conversion from scalable to fixed when msve-vector-bits is
     // specified
-    if (Context.areCompatibleSveTypes(QualType(OriginalTarget, 0),
-                                      QualType(Source, 0)) ||
-        Context.areLaxCompatibleSveTypes(QualType(OriginalTarget, 0),
-                                         QualType(Source, 0)))
+    if (ARM().areCompatibleSveTypes(QualType(OriginalTarget, 0),
+                                    QualType(Source, 0)) ||
+        ARM().areLaxCompatibleSveTypes(QualType(OriginalTarget, 0),
+                                       QualType(Source, 0)))
       return;
 
     // If the vector cast is cast between two vectors of the same size, it is
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c7abbbd6993de..087db40573ef6 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -51,6 +51,7 @@
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaARM.h"
 #include "clang/Sema/SemaCUDA.h"
 #include "clang/Sema/SemaFixItUtils.h"
 #include "clang/Sema/SemaHLSL.h"
@@ -9533,8 +9534,8 @@ AssignConvertType 
Sema::CheckAssignmentConstraints(QualType LHSType,
     // Allow assignments between fixed-length and sizeless SVE vectors.
     if ((LHSType->isSVESizelessBuiltinType() && RHSType->isVectorType()) ||
         (LHSType->isVectorType() && RHSType->isSVESizelessBuiltinType()))
-      if (Context.areCompatibleSveTypes(LHSType, RHSType) ||
-          Context.areLaxCompatibleSveTypes(LHSType, RHSType)) {
+      if (ARM().areCompatibleSveTypes(LHSType, RHSType) ||
+          ARM().areLaxCompatibleSveTypes(LHSType, RHSType)) {
         Kind = CK_BitCast;
         return AssignConvertType::Compatible;
       }
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 89e86f49a3ca8..4d5964c1a93b0 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -30,6 +30,7 @@
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Overload.h"
+#include "clang/Sema/SemaARM.h"
 #include "clang/Sema/SemaCUDA.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/Template.h"
@@ -2180,8 +2181,8 @@ static bool IsVectorConversion(Sema &S, QualType 
FromType, QualType ToType,
 
   if (ToType->isSVESizelessBuiltinType() ||
       FromType->isSVESizelessBuiltinType())
-    if (S.Context.areCompatibleSveTypes(FromType, ToType) ||
-        S.Context.areLaxCompatibleSveTypes(FromType, ToType)) {
+    if (S.ARM().areCompatibleSveTypes(FromType, ToType) ||
+        S.ARM().areLaxCompatibleSveTypes(FromType, ToType)) {
       ICK = ICK_SVE_Vector_Conversion;
       return true;
     }
@@ -4735,9 +4736,9 @@ CompareStandardConversionSequences(Sema &S, 
SourceLocation Loc,
   if (SCS1.Second == ICK_SVE_Vector_Conversion &&
       SCS2.Second == ICK_SVE_Vector_Conversion) {
     bool SCS1IsCompatibleSVEVectorConversion =
-        S.Context.areCompatibleSveTypes(SCS1.getFromType(), SCS1.getToType(2));
+        S.ARM().areCompatibleSveTypes(SCS1.getFromType(), SCS1.getToType(2));
     bool SCS2IsCompatibleSVEVectorConversion =
-        S.Context.areCompatibleSveTypes(SCS2.getFromType(), SCS2.getToType(2));
+        S.ARM().areCompatibleSveTypes(SCS2.getFromType(), SCS2.getToType(2));
 
     if (SCS1IsCompatibleSVEVectorConversion !=
         SCS2IsCompatibleSVEVectorConversion)
diff --git a/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c 
b/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c
index bd424172a1865..47e745aece191 100644
--- a/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c
+++ b/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c
@@ -1,22 +1,50 @@
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=1 -mvscale-max=1 -emit-llvm -o - %s | FileCheck %s -D#VBITS=1
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=2 -mvscale-max=2 -emit-llvm -o - %s | FileCheck %s -D#VBITS=2
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=4 -mvscale-max=4 -emit-llvm -o - %s | FileCheck %s -D#VBITS=4
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=8 -mvscale-max=8 -emit-llvm -o - %s | FileCheck %s -D#VBITS=8
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=16 -mvscale-max=16 -emit-llvm -o - %s | FileCheck %s -D#VBITS=16
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 
-mvscale-min=1 -mvscale-max=1 -emit-llvm -o - %s | FileCheck %s -D#VBITS=1
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 
-mvscale-min=2 -mvscale-max=2 -emit-llvm -o - %s | FileCheck %s -D#VBITS=2
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=1 -emit-llvm -o - %s | FileCheck %s -D#VBITS=1 
--check-prefix=CHECK-NOMAX
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=2 -emit-llvm -o - %s | FileCheck %s -D#VBITS=2 
--check-prefix=CHECK-NOMAX
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=4 -emit-llvm -o - %s | FileCheck %s -D#VBITS=4 
--check-prefix=CHECK-NOMAX
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=8 -emit-llvm -o - %s | FileCheck %s -D#VBITS=8 
--check-prefix=CHECK-NOMAX
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=16 -emit-llvm -o - %s | FileCheck %s -D#VBITS=16 
--check-prefix=CHECK-NOMAX
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 
-mvscale-min=1 -mvscale-max=0 -emit-llvm -o - %s | FileCheck %s 
--check-prefix=CHECK-UNBOUNDED
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-mvscale-min=1 -mvscale-max=0 -emit-llvm -o - %s | FileCheck %s 
--check-prefix=CHECK-UNBOUNDED
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-NONE
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=1 -mvscale-max=1 -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=1
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=2 -mvscale-max=2 -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=2
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=4 -mvscale-max=4 -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=4
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=8 -mvscale-max=8 -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=8
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=16 -mvscale-max=16 -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=16
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 
-target-feature +sme -mvscale-min=1 -mvscale-max=1 -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=1
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 
-target-feature +sme -mvscale-min=2 -mvscale-max=2 -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=2
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=1 -emit-llvm -o - %s | \
+// RUN: FileCheck %s -D#VBITS=1 --check-prefixes=CHECK-NOMAX,CHECK-NOSTREAMING
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=2 -emit-llvm -o - %s | \
+// RUN:  FileCheck %s -D#VBITS=2 --check-prefixes=CHECK-NOMAX,CHECK-NOSTREAMING
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=4 -emit-llvm -o - %s | \
+// RUN: FileCheck %s -D#VBITS=4 --check-prefixes=CHECK-NOMAX,CHECK-NOSTREAMING
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=8 -emit-llvm -o - %s | \
+// RUN: FileCheck %s -D#VBITS=8 --check-prefixes=CHECK-NOMAX,CHECK-NOSTREAMING
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=16 -emit-llvm -o - %s | \
+// RUN: FileCheck %s -D#VBITS=16 --check-prefixes=CHECK-NOMAX,CHECK-NOSTREAMING
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 
-target-feature +sme -mvscale-min=1 -mvscale-max=0 -emit-llvm -o - %s | \
+// RUN:  FileCheck %s --check-prefixes=CHECK-UNBOUNDED,CHECK-NOSTREAMING
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=1 -mvscale-max=0 -emit-llvm -o - %s | \
+// RUN:  FileCheck %s --check-prefixes=CHECK-UNBOUNDED,CHECK-NOSTREAMING
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK-NONE,CHECK-NOSTREAMING
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -target-feature +sme -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK-NONE,CHECK-NOSTREAMING
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -target-feature +sme -mvscale-streaming-min=1 
-mvscale-streaming-max=1 -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK-NONE,CHECK-STREAMING 
-D#STREAMINGVBITS=1
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -target-feature +sme -mvscale-streaming-min=4 
-mvscale-streaming-max=4 -emit-llvm -o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK-NONE,CHECK-STREAMING 
-D#STREAMINGVBITS=4
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -target-feature +sme -mvscale-streaming-min=4 -emit-llvm 
-o - %s | \
+// RUN: FileCheck %s --check-prefixes=CHECK-NONE,CHECK-STREAMING-NOMAX 
-D#STREAMINGVBITS=4
 
 // CHECK-LABEL: @func() #0
+// CHECK-LABEL: @func2() #1
 // CHECK: attributes #0 = { {{.*}} vscale_range([[#VBITS]],[[#VBITS]]) {{.*}} }
 // CHECK-NOMAX: attributes #0 = { {{.*}} vscale_range([[#VBITS]],0) {{.*}} }
 // CHECK-UNBOUNDED: attributes #0 = { {{.*}} vscale_range(1,0) {{.*}} }
 // CHECK-NONE: attributes #0 = { {{.*}} vscale_range(1,16) {{.*}} }
+// CHECK-STREAMING: attributes #1 = { {{.*}} 
vscale_range([[#STREAMINGVBITS]],[[#STREAMINGVBITS]])
+// CHECK-STREAMING-NOMAX: attributes #1 = { {{.*}} 
vscale_range([[#STREAMINGVBITS]],0)
+// CHECK-NOSTREAMING: attributes #1 = { {{.*}} vscale_range(1,16) {{.*}} }
 void func(void) {}
+__arm_locally_streaming void func2(void) {}
diff --git a/clang/test/Driver/aarch64-sve-vector-bits.c 
b/clang/test/Driver/aarch64-sve-vector-bits.c
index 535b0f157019a..f54cd94764bfb 100644
--- a/clang/test/Driver/aarch64-sve-vector-bits.c
+++ b/clang/test/Driver/aarch64-sve-vector-bits.c
@@ -24,6 +24,8 @@
 // RUN:  -msve-vector-bits=2048+ 2>&1 | FileCheck --check-prefix=CHECK-2048P %s
 // RUN: %clang -c %s -### --target=aarch64-none-linux-gnu -march=armv8-a+sve \
 // RUN:  -msve-vector-bits=scalable 2>&1 | FileCheck 
--check-prefix=CHECK-SCALABLE %s
+// RUN: %clang -c %s -### --target=aarch64-none-linux-gnu 
-march=armv8-a+sve+sme \
+// RUN:  -msve-streaming-vector-bits=128 2>&1 | FileCheck 
--check-prefix=STREAMING-128 %s
 
 // CHECK-128: "-mvscale-max=1" "-mvscale-min=1"
 // CHECK-256: "-mvscale-max=2" "-mvscale-min=2"
@@ -44,6 +46,8 @@
 // CHECK-SCALABLE-NOT: "-mvscale-min=
 // CHECK-SCALABLE-NOT: "-mvscale-max=
 
+// STREAMING-128: "-mvscale-streaming-max=1" "-mvscale-streaming-min=1"
+
 // Error out if an unsupported value is passed to -msve-vector-bits.
 // 
-----------------------------------------------------------------------------
 // RUN: not %clang -c %s -### --target=aarch64-none-linux-gnu 
-march=armv8-a+sve \
diff --git a/clang/test/SemaCXX/aarch64-streaming-sve-vector-conversions.cpp 
b/clang/test/SemaCXX/aarch64-streaming-sve-vector-conversions.cpp
new file mode 100644
index 0000000000000..7498aaa9982f9
--- /dev/null
+++ b/clang/test/SemaCXX/aarch64-streaming-sve-vector-conversions.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=1 -mvscale-max=1 -mvscale-streaming-min=2 
-mvscale-streaming-max=2 -flax-vector-conversions=integer -ffreestanding 
-fsyntax-only -verify %s
+// REQUIRES: aarch64-registered-target
+
+#include <arm_sve.h>
+
+#define SVE_BITS 128
+#define SVE_FIXED_ATTR __attribute__((arm_sve_vector_bits(SVE_BITS)))
+#define GNU_FIXED_ATTR __attribute__((vector_size(SVE_BITS / 8)))
+#define GNU_BOOL_FIXED_ATTR __attribute__((vector_size(SVE_BITS / 64)))
+#define STREAMING_BITS 256
+#define GNU_FIXED_STREAMING_ATTR __attribute__((vector_size(STREAMING_BITS / 
8)))
+#define GNU_BOOL_FIXED_STREAMING_ATTR 
__attribute__((vector_size(STREAMING_BITS / 64)))
+
+typedef svfloat32_t sve_fixed_float32_t SVE_FIXED_ATTR;
+typedef svint32_t sve_fixed_int32_t SVE_FIXED_ATTR;
+typedef svbool_t sve_fixed_bool_t SVE_FIXED_ATTR;
+typedef float gnu_fixed_float32_t GNU_FIXED_ATTR;
+typedef int gnu_fixed_int32_t GNU_FIXED_ATTR;
+typedef int8_t gnu_fixed_bool_t GNU_BOOL_FIXED_ATTR;
+
+typedef float gnu_fixed_float32_t_streaming GNU_FIXED_STREAMING_ATTR;
+typedef int gnu_fixed_int32_t_streaming GNU_FIXED_STREAMING_ATTR;
+typedef int8_t gnu_fixed_bool_t_streaming GNU_BOOL_FIXED_STREAMING_ATTR;
+
+void sve_fixed() {
+  gnu_fixed_int32_t fi;
+  gnu_fixed_float32_t_streaming fi_wrong;
+  gnu_fixed_float32_t ff;
+  gnu_fixed_float32_t_streaming ff_wrong;
+  gnu_fixed_bool_t fb;
+  gnu_fixed_bool_t_streaming fb_wrong;
+  *(volatile svint32_t*)0 = fi;
+  *(volatile svint32_t*)0 = fi_wrong; // expected-error {{incompatible}}
+  *(volatile svfloat32_t*)0 = ff;
+  *(volatile svfloat32_t*)0 = ff_wrong; // expected-error {{incompatible}}
+  *(volatile svbool_t*)0 = fb;
+  *(volatile svbool_t*)0 = fb_wrong; // expected-error {{incompatible}}
+}
+
+__arm_locally_streaming void streaming_fixed() {
+  gnu_fixed_int32_t_streaming fi;
+  gnu_fixed_float32_t fi_wrong;
+  gnu_fixed_float32_t_streaming ff;
+  gnu_fixed_float32_t ff_wrong;
+  gnu_fixed_bool_t_streaming fb;
+  gnu_fixed_bool_t fb_wrong;
+  *(volatile svint32_t*)0 = fi;
+  *(volatile svint32_t*)0 = fi_wrong; // expected-error {{incompatible}}
+  *(volatile svfloat32_t*)0 = ff;
+  *(volatile svfloat32_t*)0 = ff_wrong; // expected-error {{incompatible}}
+  *(volatile svbool_t*)0 = fb;
+  *(volatile svbool_t*)0 = fb_wrong; // expected-error {{incompatible}}
+}

>From cb8936f185ae113905221a685ec84f226d817b70 Mon Sep 17 00:00:00 2001
From: Eli Friedman <efrie...@quicinc.com>
Date: Wed, 18 Jun 2025 17:09:06 -0700
Subject: [PATCH 2/2] Fix interaction with streaming-compatible functions.

---
 clang/include/clang/Basic/TargetInfo.h        |  9 +++-
 clang/lib/AST/ASTContext.cpp                  |  4 +-
 clang/lib/AST/ItaniumMangle.cpp               |  3 +-
 clang/lib/Basic/Targets/AArch64.cpp           |  9 ++--
 clang/lib/Basic/Targets/AArch64.h             |  3 +-
 clang/lib/Basic/Targets/RISCV.cpp             |  4 +-
 clang/lib/Basic/Targets/RISCV.h               |  3 +-
 clang/lib/CodeGen/CodeGenFunction.cpp         | 10 ++++-
 clang/lib/CodeGen/Targets/RISCV.cpp           |  2 +-
 clang/lib/Sema/SemaARM.cpp                    | 21 ++++++++-
 clang/lib/Sema/SemaType.cpp                   |  4 +-
 .../arm-sve-vector-bits-vscale-range.c        | 43 ++++++++++---------
 ...rch64-streaming-sve-vector-conversions.cpp | 16 +++++++
 13 files changed, 92 insertions(+), 39 deletions(-)

diff --git a/clang/include/clang/Basic/TargetInfo.h 
b/clang/include/clang/Basic/TargetInfo.h
index c3bce6e807f34..00e6f88d648ca 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1034,9 +1034,16 @@ class TargetInfo : public TransferrableTargetInfo,
   /// set of primary and secondary targets.
   virtual llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const = 0;
 
+  enum class ArmStreamingKind {
+    NotStreaming,
+    StreamingCompatible,
+    Streaming,
+  };
+
   /// Returns target-specific min and max values VScale_Range.
   virtual std::optional<std::pair<unsigned, unsigned>>
-  getVScaleRange(const LangOptions &LangOpts, bool IsArmStreamingFunction,
+  getVScaleRange(const LangOptions &LangOpts,
+                 ArmStreamingKind IsArmStreamingFunction,
                  llvm::StringMap<bool> *FeatureMap = nullptr) const {
     return std::nullopt;
   }
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index d785b5a5006cc..07c70ea770d66 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -10446,8 +10446,8 @@ bool ASTContext::areCompatibleVectorTypes(QualType 
FirstVec,
 /// getRVVTypeSize - Return RVV vector register size.
 static uint64_t getRVVTypeSize(ASTContext &Context, const BuiltinType *Ty) {
   assert(Ty->isRVVVLSBuiltinType() && "Invalid RVV Type");
-  auto VScale =
-      Context.getTargetInfo().getVScaleRange(Context.getLangOpts(), false);
+  auto VScale = Context.getTargetInfo().getVScaleRange(
+      Context.getLangOpts(), TargetInfo::ArmStreamingKind::NotStreaming);
   if (!VScale)
     return 0;
 
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index ecf5be220439b..40da699f052f9 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4273,7 +4273,8 @@ void CXXNameMangler::mangleRISCVFixedRVVVectorType(const 
VectorType *T) {
 
   // Apend the LMUL suffix.
   auto VScale = getASTContext().getTargetInfo().getVScaleRange(
-      getASTContext().getLangOpts(), false);
+      getASTContext().getLangOpts(),
+      TargetInfo::ArmStreamingKind::NotStreaming);
   unsigned VLen = VScale->first * llvm::RISCV::RVVBitsPerBlock;
 
   if (T->getVectorKind() == VectorKind::RVVFixedLengthData) {
diff --git a/clang/lib/Basic/Targets/AArch64.cpp 
b/clang/lib/Basic/Targets/AArch64.cpp
index c5935390137b1..2e4234f0b5fae 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -820,13 +820,14 @@ AArch64TargetInfo::getTargetBuiltins() const {
 
 std::optional<std::pair<unsigned, unsigned>>
 AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts,
-                                  bool IsArmStreamingFunction,
+                                  ArmStreamingKind IsArmStreamingFunction,
                                   llvm::StringMap<bool> *FeatureMap) const {
-  if (!IsArmStreamingFunction && (LangOpts.VScaleMin || LangOpts.VScaleMax))
+  if (IsArmStreamingFunction == ArmStreamingKind::NotStreaming &&
+      (LangOpts.VScaleMin || LangOpts.VScaleMax))
     return std::pair<unsigned, unsigned>(
         LangOpts.VScaleMin ? LangOpts.VScaleMin : 1, LangOpts.VScaleMax);
 
-  if (IsArmStreamingFunction &&
+  if (IsArmStreamingFunction == ArmStreamingKind::Streaming &&
       (LangOpts.VScaleStreamingMin || LangOpts.VScaleStreamingMax))
     return std::pair<unsigned, unsigned>(
         LangOpts.VScaleStreamingMin ? LangOpts.VScaleStreamingMin : 1,
@@ -835,7 +836,7 @@ AArch64TargetInfo::getVScaleRange(const LangOptions 
&LangOpts,
   if (hasFeature("sve") || (FeatureMap && (FeatureMap->lookup("sve"))))
     return std::pair<unsigned, unsigned>(1, 16);
 
-  if (IsArmStreamingFunction &&
+  if (IsArmStreamingFunction == ArmStreamingKind::Streaming &&
       (hasFeature("sme") || (FeatureMap && (FeatureMap->lookup("sme")))))
     return std::pair<unsigned, unsigned>(1, 16);
 
diff --git a/clang/lib/Basic/Targets/AArch64.h 
b/clang/lib/Basic/Targets/AArch64.h
index a4c65361105e4..6dc96ad6cb3d2 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -197,7 +197,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public 
TargetInfo {
   llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
 
   std::optional<std::pair<unsigned, unsigned>>
-  getVScaleRange(const LangOptions &LangOpts, bool IsArmStreamingFunction,
+  getVScaleRange(const LangOptions &LangOpts,
+                 ArmStreamingKind IsArmStreamingFunction,
                  llvm::StringMap<bool> *FeatureMap = nullptr) const override;
   bool doesFeatureAffectCodeGen(StringRef Name) const override;
   bool validateCpuSupports(StringRef FeatureStr) const override;
diff --git a/clang/lib/Basic/Targets/RISCV.cpp 
b/clang/lib/Basic/Targets/RISCV.cpp
index 2098449dd83a3..8a28c0788aad7 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -222,7 +222,7 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions 
&Opts,
   // Currently we support the v1.0 RISC-V V intrinsics.
   Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(1, 0)));
 
-  auto VScale = getVScaleRange(Opts, false);
+  auto VScale = getVScaleRange(Opts, ArmStreamingKind::NotStreaming);
   if (VScale && VScale->first && VScale->first == VScale->second)
     Builder.defineMacro("__riscv_v_fixed_vlen",
                         Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock));
@@ -367,7 +367,7 @@ bool RISCVTargetInfo::initFeatureMap(
 
 std::optional<std::pair<unsigned, unsigned>>
 RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts,
-                                bool IsArmStreamingFunction,
+                                ArmStreamingKind IsArmStreamingFunction,
                                 llvm::StringMap<bool> *FeatureMap) const {
   // RISCV::RVVBitsPerBlock is 64.
   unsigned VScaleMin = ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 0b36c9d5d9cc8..2779538e5b741 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -99,7 +99,8 @@ class RISCVTargetInfo : public TargetInfo {
                  const std::vector<std::string> &FeaturesVec) const override;
 
   std::optional<std::pair<unsigned, unsigned>>
-  getVScaleRange(const LangOptions &LangOpts, bool IsArmStreamingFunction,
+  getVScaleRange(const LangOptions &LangOpts,
+                 ArmStreamingKind IsArmStreamingFunction,
                  llvm::StringMap<bool> *FeatureMap = nullptr) const override;
 
   bool hasFeature(StringRef Feature) const override;
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index 56562002e7194..52707a1fd9f75 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1108,10 +1108,16 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
 
   // Add vscale_range attribute if appropriate.
   llvm::StringMap<bool> FeatureMap;
-  bool IsArmStreaming = false;
+  auto IsArmStreaming = TargetInfo::ArmStreamingKind::NotStreaming;
   if (FD) {
     getContext().getFunctionFeatureMap(FeatureMap, FD);
-    IsArmStreaming = IsArmStreamingFunction(FD, true);
+    if (const auto *T = FD->getType()->getAs<FunctionProtoType>())
+      if (T->getAArch64SMEAttributes() &
+          FunctionType::SME_PStateSMCompatibleMask)
+        IsArmStreaming = TargetInfo::ArmStreamingKind::StreamingCompatible;
+
+    if (IsArmStreamingFunction(FD, true))
+      IsArmStreaming = TargetInfo::ArmStreamingKind::Streaming;
   }
   std::optional<std::pair<unsigned, unsigned>> VScaleRange =
       getContext().getTargetInfo().getVScaleRange(getLangOpts(), 
IsArmStreaming,
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp 
b/clang/lib/CodeGen/Targets/RISCV.cpp
index 14d4cee7c61d3..cc3d487da83b5 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -544,7 +544,7 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty, 
unsigned ABIVLen) const {
   assert(VT->getElementType()->isBuiltinType() && "expected builtin type!");
 
   auto VScale = getContext().getTargetInfo().getVScaleRange(
-      getContext().getLangOpts(), false);
+      getContext().getLangOpts(), TargetInfo::ArmStreamingKind::NotStreaming);
 
   unsigned NumElts = VT->getNumElements();
   llvm::Type *EltType = llvm::Type::getInt1Ty(getVMContext());
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index ec892a5d82421..dd52400cf77ce 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -1423,9 +1423,18 @@ static uint64_t getSVETypeSize(ASTContext &Context, 
const BuiltinType *Ty,
 
 bool SemaARM::areCompatibleSveTypes(QualType FirstType, QualType SecondType) {
   bool IsStreaming = false;
-  if (const FunctionDecl *FD = 
SemaRef.getCurFunctionDecl(/*AllowLambda=*/true))
+  if (const FunctionDecl *FD =
+          SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
+    // For streaming-compatible functions, we don't know vector length.
+    if (const auto *T = FD->getType()->getAs<FunctionProtoType>())
+      if (T->getAArch64SMEAttributes() &
+          FunctionType::SME_PStateSMCompatibleMask)
+        return false;
+
     if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
       IsStreaming = true;
+  }
+
   auto IsValidCast = [&](QualType FirstType, QualType SecondType) {
     if (const auto *BT = FirstType->getAs<BuiltinType>()) {
       if (const auto *VT = SecondType->getAs<VectorType>()) {
@@ -1455,9 +1464,17 @@ bool SemaARM::areCompatibleSveTypes(QualType FirstType, 
QualType SecondType) {
 bool SemaARM::areLaxCompatibleSveTypes(QualType FirstType,
                                        QualType SecondType) {
   bool IsStreaming = false;
-  if (const FunctionDecl *FD = 
SemaRef.getCurFunctionDecl(/*AllowLambda=*/true))
+  if (const FunctionDecl *FD =
+          SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
+    // For streaming-compatible functions, we don't know vector length.
+    if (const auto *T = FD->getType()->getAs<FunctionProtoType>())
+      if (T->getAArch64SMEAttributes() &
+          FunctionType::SME_PStateSMCompatibleMask)
+        return false;
+
     if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
       IsStreaming = true;
+  }
 
   auto IsLaxCompatible = [&](QualType FirstType, QualType SecondType) {
     const auto *BT = FirstType->getAs<BuiltinType>();
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index a0cd2d1615243..2039d27b32464 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8522,8 +8522,8 @@ static void HandleRISCVRVVVectorBitsTypeAttr(QualType 
&CurType,
     return;
   }
 
-  auto VScale =
-      S.Context.getTargetInfo().getVScaleRange(S.getLangOpts(), false);
+  auto VScale = S.Context.getTargetInfo().getVScaleRange(
+      S.getLangOpts(), TargetInfo::ArmStreamingKind::NotStreaming);
   if (!VScale || !VScale->first || VScale->first != VScale->second) {
     S.Diag(Attr.getLoc(), diag::err_attribute_riscv_rvv_bits_unsupported)
         << Attr;
diff --git a/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c 
b/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c
index 47e745aece191..252d40e7d1f75 100644
--- a/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c
+++ b/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c
@@ -1,50 +1,53 @@
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=1 -mvscale-max=1 -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=1
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-MINMAX,CHECK-NOSTREAMING 
-D#VBITS=1
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=2 -mvscale-max=2 -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=2
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-MINMAX,CHECK-NOSTREAMING 
-D#VBITS=2
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=4 -mvscale-max=4 -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=4
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-MINMAX,CHECK-NOSTREAMING 
-D#VBITS=4
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=8 -mvscale-max=8 -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=8
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-MINMAX,CHECK-NOSTREAMING 
-D#VBITS=8
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=16 -mvscale-max=16 -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=16
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-MINMAX,CHECK-NOSTREAMING 
-D#VBITS=16
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 
-target-feature +sme -mvscale-min=1 -mvscale-max=1 -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=1
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-MINMAX,CHECK-NOSTREAMING 
-D#VBITS=1
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 
-target-feature +sme -mvscale-min=2 -mvscale-max=2 -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOSTREAMING -D#VBITS=2
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-MINMAX,CHECK-NOSTREAMING 
-D#VBITS=2
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=1 -emit-llvm -o - %s | \
-// RUN: FileCheck %s -D#VBITS=1 --check-prefixes=CHECK-NOMAX,CHECK-NOSTREAMING
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOMAX,CHECK-NOSTREAMING 
-D#VBITS=1
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=2 -emit-llvm -o - %s | \
-// RUN:  FileCheck %s -D#VBITS=2 --check-prefixes=CHECK-NOMAX,CHECK-NOSTREAMING
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOMAX,CHECK-NOSTREAMING 
-D#VBITS=2
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=4 -emit-llvm -o - %s | \
-// RUN: FileCheck %s -D#VBITS=4 --check-prefixes=CHECK-NOMAX,CHECK-NOSTREAMING
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOMAX,CHECK-NOSTREAMING 
-D#VBITS=4
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=8 -emit-llvm -o - %s | \
-// RUN: FileCheck %s -D#VBITS=8 --check-prefixes=CHECK-NOMAX,CHECK-NOSTREAMING
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOMAX,CHECK-NOSTREAMING 
-D#VBITS=8
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=16 -emit-llvm -o - %s | \
-// RUN: FileCheck %s -D#VBITS=16 --check-prefixes=CHECK-NOMAX,CHECK-NOSTREAMING
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOMAX,CHECK-NOSTREAMING 
-D#VBITS=16
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 
-target-feature +sme -mvscale-min=1 -mvscale-max=0 -emit-llvm -o - %s | \
-// RUN:  FileCheck %s --check-prefixes=CHECK-UNBOUNDED,CHECK-NOSTREAMING
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-UNBOUNDED,CHECK-NOSTREAMING
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -mvscale-min=1 -mvscale-max=0 -emit-llvm -o - %s | \
-// RUN:  FileCheck %s --check-prefixes=CHECK-UNBOUNDED,CHECK-NOSTREAMING
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-UNBOUNDED,CHECK-NOSTREAMING
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK-NONE,CHECK-NOSTREAMING
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NONE,CHECK-NOSTREAMING
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -target-feature +sme -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK-NONE,CHECK-NOSTREAMING
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NONE,CHECK-NOSTREAMING
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -target-feature +sme -mvscale-streaming-min=1 
-mvscale-streaming-max=1 -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK-NONE,CHECK-STREAMING 
-D#STREAMINGVBITS=1
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NONE,CHECK-STREAMING 
-D#STREAMINGVBITS=1
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -target-feature +sme -mvscale-streaming-min=4 
-mvscale-streaming-max=4 -emit-llvm -o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK-NONE,CHECK-STREAMING 
-D#STREAMINGVBITS=4
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NONE,CHECK-STREAMING 
-D#STREAMINGVBITS=4
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve 
-target-feature +sme -target-feature +sme -mvscale-streaming-min=4 -emit-llvm 
-o - %s | \
-// RUN: FileCheck %s --check-prefixes=CHECK-NONE,CHECK-STREAMING-NOMAX 
-D#STREAMINGVBITS=4
+// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NONE,CHECK-STREAMING-NOMAX 
-D#STREAMINGVBITS=4
 
 // CHECK-LABEL: @func() #0
 // CHECK-LABEL: @func2() #1
-// CHECK: attributes #0 = { {{.*}} vscale_range([[#VBITS]],[[#VBITS]]) {{.*}} }
+// CHECK-LABEL: @func3() #2
+// CHECK-MINMAX: attributes #0 = { {{.*}} vscale_range([[#VBITS]],[[#VBITS]]) 
{{.*}} }
 // CHECK-NOMAX: attributes #0 = { {{.*}} vscale_range([[#VBITS]],0) {{.*}} }
 // CHECK-UNBOUNDED: attributes #0 = { {{.*}} vscale_range(1,0) {{.*}} }
 // CHECK-NONE: attributes #0 = { {{.*}} vscale_range(1,16) {{.*}} }
 // CHECK-STREAMING: attributes #1 = { {{.*}} 
vscale_range([[#STREAMINGVBITS]],[[#STREAMINGVBITS]])
 // CHECK-STREAMING-NOMAX: attributes #1 = { {{.*}} 
vscale_range([[#STREAMINGVBITS]],0)
 // CHECK-NOSTREAMING: attributes #1 = { {{.*}} vscale_range(1,16) {{.*}} }
+// CHECK: attributes #2 = { {{.*}} vscale_range(1,16) {{.*}} }
 void func(void) {}
 __arm_locally_streaming void func2(void) {}
+void func3(void) __arm_streaming_compatible {}
diff --git a/clang/test/SemaCXX/aarch64-streaming-sve-vector-conversions.cpp 
b/clang/test/SemaCXX/aarch64-streaming-sve-vector-conversions.cpp
index 7498aaa9982f9..1520e2b572ce6 100644
--- a/clang/test/SemaCXX/aarch64-streaming-sve-vector-conversions.cpp
+++ b/clang/test/SemaCXX/aarch64-streaming-sve-vector-conversions.cpp
@@ -51,3 +51,19 @@ __arm_locally_streaming void streaming_fixed() {
   *(volatile svbool_t*)0 = fb;
   *(volatile svbool_t*)0 = fb_wrong; // expected-error {{incompatible}}
 }
+
+void streaming_compatible() __arm_streaming_compatible {
+  gnu_fixed_int32_t fi_ns;
+  gnu_fixed_float32_t_streaming fi_s;
+  gnu_fixed_float32_t ff_ns;
+  gnu_fixed_float32_t_streaming ff_s;
+  gnu_fixed_bool_t fb_ns;
+  gnu_fixed_bool_t_streaming fb_s;
+  *(volatile svint32_t*)0 = fi_ns; // expected-error {{incompatible}}
+  *(volatile svint32_t*)0 = fi_s; // expected-error {{incompatible}}
+  *(volatile svfloat32_t*)0 = ff_ns; // expected-error {{incompatible}}
+  *(volatile svfloat32_t*)0 = ff_s; // expected-error {{incompatible}}
+  *(volatile svbool_t*)0 = fb_ns; // expected-error {{incompatible}}
+  *(volatile svbool_t*)0 = fb_s; // expected-error {{incompatible}}
+}
+

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to