Index: llvm/include/llvm/Analysis/TargetTransformInfo.h =================================================================== --- llvm/include/llvm/Analysis/TargetTransformInfo.h +++ llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -1320,6 +1320,9 @@ bool isLegalToVectorizeStoreChain(unsigned ChainSizeInBytes, Align Alignment, unsigned AddrSpace) const; + /// \returns True if it is legal to vectorize the given element type. + bool isLegalToVectorizeType(Type *Ty) const; + /// \returns True if it is legal to vectorize the given reduction kind. bool isLegalToVectorizeReduction(RecurrenceDescriptor RdxDesc, ElementCount VF) const; @@ -1704,6 +1707,7 @@ virtual bool isLegalToVectorizeStoreChain(unsigned ChainSizeInBytes, Align Alignment, unsigned AddrSpace) const = 0; + virtual bool isLegalToVectorizeType(Type *Ty) const = 0; virtual bool isLegalToVectorizeReduction(RecurrenceDescriptor RdxDesc, ElementCount VF) const = 0; virtual unsigned getLoadVectorFactor(unsigned VF, unsigned LoadSize, @@ -2253,6 +2257,9 @@ return Impl.isLegalToVectorizeStoreChain(ChainSizeInBytes, Alignment, AddrSpace); } + bool isLegalToVectorizeType(Type *Ty) const override { + return Impl.isLegalToVectorizeType(Ty); + } bool isLegalToVectorizeReduction(RecurrenceDescriptor RdxDesc, ElementCount VF) const override { return Impl.isLegalToVectorizeReduction(RdxDesc, VF); Index: llvm/include/llvm/Analysis/TargetTransformInfoImpl.h =================================================================== --- llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -715,6 +715,10 @@ return true; } + bool isLegalToVectorizeType(Type *Ty) const { + return true; + } + bool isLegalToVectorizeReduction(RecurrenceDescriptor RdxDesc, ElementCount VF) const { return true; Index: llvm/lib/Analysis/TargetTransformInfo.cpp =================================================================== --- llvm/lib/Analysis/TargetTransformInfo.cpp +++ llvm/lib/Analysis/TargetTransformInfo.cpp @@ -997,6 +997,10 @@ AddrSpace); } +bool TargetTransformInfo::isLegalToVectorizeType(Type *Ty) const { + return TTIImpl->isLegalToVectorizeType(Ty); +} + bool TargetTransformInfo::isLegalToVectorizeReduction( RecurrenceDescriptor RdxDesc, ElementCount VF) const { return TTIImpl->isLegalToVectorizeReduction(RdxDesc, VF); Index: llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h =================================================================== --- llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h +++ llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h @@ -288,6 +288,8 @@ bool supportsScalableVectors() const { return ST->hasSVE(); } + bool isLegalToVectorizeType(Type *Ty) const; + bool isLegalToVectorizeReduction(RecurrenceDescriptor RdxDesc, ElementCount VF) const; Index: llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -1501,6 +1501,17 @@ return Considerable; } +bool AArch64TTIImpl::isLegalToVectorizeType(Type *Ty) const { + if (Ty->isVoidTy() || Ty->isIntegerTy(1)) + return true; + + if (supportsScalableVectors()) { + return isLegalElementTypeForSVE(Ty); + } + + return true; +} + bool AArch64TTIImpl::isLegalToVectorizeReduction(RecurrenceDescriptor RdxDesc, ElementCount VF) const { if (!VF.isScalable()) Index: llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp =================================================================== --- llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp +++ llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp @@ -719,6 +719,7 @@ // Also, we can't vectorize extractelement instructions. if ((!VectorType::isValidElementType(I.getType()) && !I.getType()->isVoidTy()) || + !TTI->isLegalToVectorizeType(I.getType()) || isa(I)) { reportVectorizationFailure("Found unvectorizable type", "instruction return type cannot be vectorized", Index: llvm/test/Transforms/LoopVectorize/AArch64/scalable-reductions.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/scalable-reductions.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/scalable-reductions.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -loop-vectorize -pass-remarks=loop-vectorize -pass-remarks-analysis=loop-vectorize -pass-remarks-missed=loop-vectorize -mtriple aarch64-unknown-linux-gnu -mattr=+sve -S 2>%t | FileCheck %s -check-prefix=CHECK +; RUN: opt < %s -loop-vectorize -pass-remarks=loop-vectorize -pass-remarks-analysis=loop-vectorize -pass-remarks-missed=loop-vectorize -mtriple aarch64-unknown-linux-gnu -mattr=+sve,+bf16 -S 2>%t | FileCheck %s -check-prefix=CHECK ; RUN: cat %t | FileCheck %s -check-prefix=CHECK-REMARK ; Reduction can be vectorized Index: llvm/test/Transforms/LoopVectorize/AArch64/sve-illegal-type.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/LoopVectorize/AArch64/sve-illegal-type.ll @@ -0,0 +1,70 @@ +; RUN: opt < %s -loop-vectorize -mtriple aarch64-linux-gnu -force-vector-width=4 -pass-remarks-analysis=loop-vectorize -S | FileCheck %s --check-prefix=CHECK-NO-SVE +; RUN: opt < %s -loop-vectorize -mtriple aarch64-linux-gnu -mattr=+sve -pass-remarks-analysis=loop-vectorize -S 2>%t | FileCheck %s -check-prefix=CHECK-SVE +; RUN: cat %t | FileCheck %s -check-prefix=CHECK-REMARKS + +; CHECK-REMARKS: loop not vectorized: instruction return type cannot be vectorized +define dso_local void @loop_sve_i128(i128* nocapture %ptr, i64 %N) { +; CHECK-SVE-LABEL: @loop_sve_i128 +; CHECK-SVE-NOT: vector.body +entry: + br label %for.body + +for.body: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] + %arrayidx = getelementptr inbounds i128, i128* %ptr, i64 %iv + %0 = load i128, i128* %arrayidx, align 16 + %add = add nsw i128 %0, 42 + store i128 %add, i128* %arrayidx, align 16 + %iv.next = add i64 %iv, 1 + %exitcond.not = icmp eq i64 %iv.next, %N + br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 + +for.end: + ret void +} + +; CHECK-REMARKS: loop not vectorized: instruction return type cannot be vectorized +define dso_local void @loop_sve_f128(fp128* nocapture %ptr, i64 %N) { +; CHECK-SVE-LABEL: @loop_sve_f128 +; CHECK-SVE-NOT: vector.body +entry: + br label %for.body + +for.body: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] + %arrayidx = getelementptr inbounds fp128, fp128* %ptr, i64 %iv + %0 = load fp128, fp128* %arrayidx, align 16 + %add = fsub fp128 %0, 0xL00000000000000008000000000000000 + store fp128 %add, fp128* %arrayidx, align 16 + %iv.next = add nuw nsw i64 %iv, 1 + %exitcond.not = icmp eq i64 %iv.next, %N + br i1 %exitcond.not, label %for.end, label %for.body, !llvm.loop !0 + +for.end: + ret void +} + +define dso_local void @loop_fixed_width_i128(i128* nocapture %ptr, i64 %N) { +; CHECK-NO-SVE-LABEL: @loop_fixed_width_i128 +; CHECK-NO-SVE:load <4 x i128>, <4 x i128>* +; CHECK-NO-SVE: add nsw <4 x i128> {{.*}}, +; CHECK-NO-SVE: store <4 x i128> {{.*}} <4 x i128>* +entry: + br label %for.body + +for.body: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] + %arrayidx = getelementptr inbounds i128, i128* %ptr, i64 %iv + %0 = load i128, i128* %arrayidx, align 16 + %add = add nsw i128 %0, 42 + store i128 %add, i128* %arrayidx, align 16 + %iv.next = add i64 %iv, 1 + %exitcond.not = icmp eq i64 %iv.next, %N + br i1 %exitcond.not, label %for.end, label %for.body + +for.end: + ret void +} + +!0 = distinct !{!0, !1} +!1 = !{!"llvm.loop.vectorize.scalable.enable", i1 true}