https://github.com/efriedma-quic created https://github.com/llvm/llvm-project/pull/144611
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. >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] [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}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits