Index: clang/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticDriverKinds.td +++ clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -592,4 +592,7 @@ "generated arguments parse failed in round-trip">; def err_cc1_round_trip_mismatch : Error< "generated arguments do not match in round-trip">; + +def err_cc1_unbounded_vscale_min : Error< + "minimum vscale must be an unsigned integer greater than 0">; } Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -3337,8 +3337,7 @@ def mvscale_min_EQ : Joined<["-"], "mvscale-min=">, Group, Flags<[NoXarchOption,CC1Option]>, - HelpText<"Specify the vscale minimum. Defaults to the" - " vector length agnostic value of \"0\". (AArch64 only)">, + HelpText<"Specify the vscale minimum. Defaults to \"1\". (AArch64 only)">, MarshallingInfoInt>; def mvscale_max_EQ : Joined<["-"], "mvscale-max=">, Group, Flags<[NoXarchOption,CC1Option]>, Index: clang/lib/Basic/Targets/AArch64.cpp =================================================================== --- clang/lib/Basic/Targets/AArch64.cpp +++ clang/lib/Basic/Targets/AArch64.cpp @@ -474,10 +474,13 @@ Optional> AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts) const { if (LangOpts.VScaleMin || LangOpts.VScaleMax) - return std::pair(LangOpts.VScaleMin, - LangOpts.VScaleMax); + return std::pair( + LangOpts.VScaleMin ? LangOpts.VScaleMin : 1, LangOpts.VScaleMax); + if (hasFeature("sve")) - return std::pair(0, 16); + return std::pair( + LangOpts.VScaleMin ? LangOpts.VScaleMin : 1, 16); + return None; } Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -4125,6 +4125,14 @@ {std::string(Split.first), std::string(Split.second)}); } + // Error if -mvscale-min is unbounded. + if (Arg *A = Args.getLastArg(options::OPT_mvscale_min_EQ)) { + unsigned VScaleMin; + if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || + (VScaleMin == 0)) + Diags.Report(diag::err_cc1_unbounded_vscale_min); + } + return Diags.getNumErrors() == NumErrorsBefore; } Index: clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c =================================================================== --- clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c +++ clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c @@ -10,12 +10,13 @@ // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -mvscale-min=4 -S -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 -S -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 -S -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=0 -mvscale-max=0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-NONE -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -mvscale-min=0 -mvscale-max=0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-NONE +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2 -mvscale-min=1 -mvscale-max=0 -S -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 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-UNBOUNDED // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-NONE // CHECK-LABEL: @func() #0 // CHECK: attributes #0 = { {{.*}} vscale_range([[#VBITS]],[[#VBITS]]) {{.*}} } // CHECK-NOMAX: attributes #0 = { {{.*}} vscale_range([[#VBITS]],0) {{.*}} } -// CHECK-NONE: attributes #0 = { {{.*}} vscale_range(0,16) {{.*}} } +// CHECK-UNBOUNDED: attributes #0 = { {{.*}} vscale_range(1,0) {{.*}} } +// CHECK-NONE: attributes #0 = { {{.*}} vscale_range(1,16) {{.*}} } void func() {} Index: clang/test/Frontend/aarch64-vscale-min.c =================================================================== --- /dev/null +++ clang/test/Frontend/aarch64-vscale-min.c @@ -0,0 +1,10 @@ +// ----------------------------------------------------------------------------- +// Tests for the -mvscale-min flag +// ----------------------------------------------------------------------------- + +// Error out if value is unbounded. +// ----------------------------------------------------------------------------- +// RUN: not %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \ +// RUN: -mvscale-min=0 2>&1 | FileCheck %s + +// CHECK: error: minimum vscale must be an unsigned integer greater than 0 Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -2134,9 +2134,10 @@ duplicate definitions are linked together with differing values. ``vscale_range([, ])`` This attribute indicates the minimum and maximum vscale value for the given - function. A value of 0 means unbounded. If the optional max value is omitted - then max is set to the value of min. If the attribute is not present, no - assumptions are made about the range of vscale. + function. The min must be greater than 0. A maximum value of 0 means + unbounded. If the optional max value is omitted then max is set to the + value of min. If the attribute is not present, no assumptions are made + about the range of vscale. Call Site Attributes ---------------------- Index: llvm/include/llvm/IR/Attributes.h =================================================================== --- llvm/include/llvm/IR/Attributes.h +++ llvm/include/llvm/IR/Attributes.h @@ -217,7 +217,7 @@ /// if not known). std::pair> getAllocSizeArgs() const; - /// Returns the argument numbers for the vscale_range attribute (or pair(0, 0) + /// Returns the argument numbers for the vscale_range attribute (or pair(1, 0) /// if not known). std::pair getVScaleRangeArgs() const; @@ -1055,7 +1055,7 @@ std::pair> getAllocSizeArgs() const; /// Retrieve the vscale_range args, if the vscale_range attribute exists. If - /// it doesn't exist, pair(0, 0) is returned. + /// it doesn't exist, pair(1, 0) is returned. std::pair getVScaleRangeArgs() const; /// Add integer attribute with raw value (packed/encoded if necessary). Index: llvm/lib/IR/Attributes.cpp =================================================================== --- llvm/lib/IR/Attributes.cpp +++ llvm/lib/IR/Attributes.cpp @@ -719,7 +719,7 @@ std::pair AttributeSet::getVScaleRangeArgs() const { return SetNode ? SetNode->getVScaleRangeArgs() - : std::pair(0, 0); + : std::pair(1, 0); } std::string AttributeSet::getAsString(bool InAttrGrp) const { @@ -900,7 +900,7 @@ std::pair AttributeSetNode::getVScaleRangeArgs() const { if (auto A = findEnumAttribute(Attribute::VScaleRange)) return A->getVScaleRangeArgs(); - return std::make_pair(0, 0); + return std::make_pair(1, 0); } std::string AttributeSetNode::getAsString(bool InAttrGrp) const { Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -2060,6 +2060,9 @@ std::pair Args = Attrs.getFnAttrs().getVScaleRangeArgs(); + if (Args.first == 0) + CheckFailed("'vscale_range' minimum must be greater than 0", V); + if (Args.first > Args.second && Args.second != 0) CheckFailed("'vscale_range' minimum cannot be greater than maximum", V); } Index: llvm/test/Analysis/CostModel/AArch64/sve-gather.ll =================================================================== --- llvm/test/Analysis/CostModel/AArch64/sve-gather.ll +++ llvm/test/Analysis/CostModel/AArch64/sve-gather.ll @@ -104,8 +104,8 @@ ret void } -attributes #0 = { "target-features"="+sve" vscale_range(0, 8) } -attributes #1 = { "target-features"="+sve" vscale_range(0, 16) "tune-cpu"="generic" } +attributes #0 = { "target-features"="+sve" vscale_range(1, 8) } +attributes #1 = { "target-features"="+sve" vscale_range(1, 16) "tune-cpu"="generic" } attributes #2 = { "target-features"="+sve" } declare @llvm.masked.gather.nxv4i32(, i32, , ) Index: llvm/test/Analysis/CostModel/AArch64/sve-scatter.ll =================================================================== --- llvm/test/Analysis/CostModel/AArch64/sve-scatter.ll +++ llvm/test/Analysis/CostModel/AArch64/sve-scatter.ll @@ -104,8 +104,8 @@ ret void } -attributes #0 = { "target-features"="+sve" vscale_range(0, 8) } -attributes #1 = { "target-features"="+sve" vscale_range(0, 16) "tune-cpu"="generic" } +attributes #0 = { "target-features"="+sve" vscale_range(1, 8) } +attributes #1 = { "target-features"="+sve" vscale_range(1, 16) "tune-cpu"="generic" } attributes #2 = { "target-features"="+sve" } declare void @llvm.masked.scatter.nxv4i32(, , i32, ) Index: llvm/test/Bitcode/attributes.ll =================================================================== --- llvm/test/Bitcode/attributes.ll +++ llvm/test/Bitcode/attributes.ll @@ -440,13 +440,6 @@ ret void } -; CHECK: define void @f75() -; CHECK-NOT: define void @f75() # -define void @f75() vscale_range(0,0) -{ - ret void -} - ; CHECK: define void @f76(i8* swiftasync %0) define void @f76(i8* swiftasync %0) { Index: llvm/test/Transforms/InstCombine/icmp-vscale.ll =================================================================== --- llvm/test/Transforms/InstCombine/icmp-vscale.ll +++ llvm/test/Transforms/InstCombine/icmp-vscale.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -instcombine -S < %s | FileCheck %s -define i1 @ugt_vscale64_x_32() vscale_range(0,16) { +define i1 @ugt_vscale64_x_32() vscale_range(1,16) { ; CHECK-LABEL: @ugt_vscale64_x_32( ; CHECK-NEXT: entry: ; CHECK-NEXT: ret i1 false @@ -13,7 +13,7 @@ ret i1 %res } -define i1 @ugt_vscale64_x_31() vscale_range(0,16) { +define i1 @ugt_vscale64_x_31() vscale_range(1,16) { ; CHECK-LABEL: @ugt_vscale64_x_31( ; CHECK-NEXT: entry: ; CHECK-NEXT: ret i1 false @@ -25,7 +25,7 @@ ret i1 %res } -define i1 @ugt_vscale16_x_32() vscale_range(0,16) { +define i1 @ugt_vscale16_x_32() vscale_range(1,16) { ; CHECK-LABEL: @ugt_vscale16_x_32( ; CHECK-NEXT: entry: ; CHECK-NEXT: ret i1 false @@ -37,7 +37,7 @@ ret i1 %res } -define i1 @ult_vscale16() vscale_range(0,16) { +define i1 @ult_vscale16() vscale_range(1,16) { ; CHECK-LABEL: @ult_vscale16( ; CHECK-NEXT: entry: ; CHECK-NEXT: ret i1 false @@ -48,7 +48,7 @@ ret i1 %res } -define i1 @ule_vscale64() vscale_range(0,16) { +define i1 @ule_vscale64() vscale_range(1,16) { ; CHECK-LABEL: @ule_vscale64( ; CHECK-NEXT: entry: ; CHECK-NEXT: ret i1 false @@ -70,7 +70,7 @@ ret i1 %res } -define i1 @ne_vscale64_x_32() vscale_range(0,16) { +define i1 @ne_vscale64_x_32() vscale_range(1,16) { ; CHECK-LABEL: @ne_vscale64_x_32( ; CHECK-NEXT: entry: ; CHECK-NEXT: ret i1 true Index: llvm/test/Transforms/InstCombine/vscale_sext_and_zext.ll =================================================================== --- llvm/test/Transforms/InstCombine/vscale_sext_and_zext.ll +++ llvm/test/Transforms/InstCombine/vscale_sext_and_zext.ll @@ -5,7 +5,7 @@ ; Sign-extend ; -define i32 @vscale_SExt_i8toi32() vscale_range(0, 127) { +define i32 @vscale_SExt_i8toi32() vscale_range(1, 127) { ; CHECK-LABEL: @vscale_SExt_i8toi32( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.vscale.i32() @@ -17,7 +17,7 @@ ret i32 %1 } -define i32 @vscale_SExt_i8toi32_poison() vscale_range(0, 128) { +define i32 @vscale_SExt_i8toi32_poison() vscale_range(1, 128) { ; CHECK-LABEL: @vscale_SExt_i8toi32_poison( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.vscale.i8() @@ -34,7 +34,7 @@ ; Zero-extend ; -define i32 @vscale_ZExt_i8toi32() vscale_range(0, 128) { +define i32 @vscale_ZExt_i8toi32() vscale_range(1, 128) { ; CHECK-LABEL: @vscale_ZExt_i8toi32( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.vscale.i32() @@ -46,7 +46,7 @@ ret i32 %1 } -define i32 @vscale_ZExt_i8toi32_poison() vscale_range(0, 256) { +define i32 @vscale_ZExt_i8toi32_poison() vscale_range(1, 256) { ; CHECK-LABEL: @vscale_ZExt_i8toi32_poison( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.vscale.i8() @@ -80,7 +80,7 @@ ; unbounded vscale_range maximum (0) ; -define i32 @vscale_SExt_i8toi32_unbounded() vscale_range(0, 0) { +define i32 @vscale_SExt_i8toi32_unbounded() vscale_range(1, 0) { ; CHECK-LABEL: @vscale_SExt_i8toi32_unbounded( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.vscale.i8() @@ -93,7 +93,7 @@ ret i32 %1 } -define i32 @vscale_ZExt_i8toi32_unbounded() vscale_range(0, 0) { +define i32 @vscale_ZExt_i8toi32_unbounded() vscale_range(1, 0) { ; CHECK-LABEL: @vscale_ZExt_i8toi32_unbounded( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.vscale.i8() Index: llvm/test/Transforms/InstCombine/vscale_trunc.ll =================================================================== --- llvm/test/Transforms/InstCombine/vscale_trunc.ll +++ llvm/test/Transforms/InstCombine/vscale_trunc.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S | FileCheck %s -define i8 @vscale_trunc_i32toi8() vscale_range(0, 255) { +define i8 @vscale_trunc_i32toi8() vscale_range(1, 255) { ; CHECK-LABEL: @vscale_trunc_i32toi8( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.vscale.i8() @@ -13,7 +13,7 @@ } -define i8 @vscale_trunc_i32toi8_poison() vscale_range(0, 256) { +define i8 @vscale_trunc_i32toi8_poison() vscale_range(1, 256) { ; CHECK-LABEL: @vscale_trunc_i32toi8_poison( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.vscale.i32() Index: llvm/test/Transforms/LoopVectorize/AArch64/first-order-recurrence.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/first-order-recurrence.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/first-order-recurrence.ll @@ -100,6 +100,6 @@ ret void } -attributes #0 = { vscale_range(0, 16) } +attributes #0 = { vscale_range(1, 16) } !0 = distinct !{!0, !1} !1 = !{!"llvm.loop.vectorize.scalable.enable", i1 true} Index: llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll @@ -390,7 +390,7 @@ ret float %rdx } -attributes #0 = { vscale_range(0, 16) } +attributes #0 = { vscale_range(1, 16) } !0 = distinct !{!0, !3, !6, !8} !1 = distinct !{!1, !3, !7, !8} !2 = distinct !{!2, !4, !6, !8} Index: llvm/test/Transforms/LoopVectorize/AArch64/scalable-vectorization.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/scalable-vectorization.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/scalable-vectorization.ll @@ -173,4 +173,4 @@ ret void } -attributes #0 = { vscale_range(0, 16) } +attributes #0 = { vscale_range(1, 16) } Index: llvm/test/Transforms/LoopVectorize/AArch64/scalable-vf-hint.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/scalable-vf-hint.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/scalable-vf-hint.ll @@ -378,7 +378,7 @@ ret void } -attributes #0 = { vscale_range(0, 16) } +attributes #0 = { vscale_range(1, 16) } !21 = !{!21, !22, !23} !22 = !{!"llvm.loop.vectorize.width", i32 4} !23 = !{!"llvm.loop.vectorize.scalable.enable", i1 true} Index: llvm/test/Transforms/LoopVectorize/AArch64/sve-cond-inv-loads.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/sve-cond-inv-loads.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/sve-cond-inv-loads.ll @@ -117,7 +117,7 @@ ret void } -attributes #0 = { vscale_range(0, 16) } +attributes #0 = { vscale_range(1, 16) } !0 = distinct !{!0, !1, !2, !3, !4, !5} !1 = !{!"llvm.loop.mustprogress"} !2 = !{!"llvm.loop.vectorize.width", i32 4} Index: llvm/test/Transforms/LoopVectorize/AArch64/sve-gather-scatter.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/sve-gather-scatter.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/sve-gather-scatter.ll @@ -153,7 +153,7 @@ ret void } -attributes #0 = { vscale_range(0, 16) } +attributes #0 = { vscale_range(1, 16) } !0 = distinct !{!0, !1, !2, !3, !4, !5} !1 = !{!"llvm.loop.mustprogress"} Index: llvm/test/Transforms/LoopVectorize/AArch64/sve-inv-store.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/sve-inv-store.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/sve-inv-store.ll @@ -59,7 +59,7 @@ ret void } -attributes #0 = { "target-features"="+neon,+sve" vscale_range(0, 16) } +attributes #0 = { "target-features"="+neon,+sve" vscale_range(1, 16) } !0 = distinct !{!0, !1, !2, !3, !4, !5} !1 = !{!"llvm.loop.mustprogress"} Index: llvm/test/Transforms/LoopVectorize/AArch64/sve-large-strides.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/sve-large-strides.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/sve-large-strides.ll @@ -90,7 +90,7 @@ ret void } -attributes #0 = { vscale_range(0, 16) } +attributes #0 = { vscale_range(1, 16) } !0 = distinct !{!0, !1, !2, !3, !4, !5} !1 = !{!"llvm.loop.mustprogress"} !2 = !{!"llvm.loop.vectorize.width", i32 4} Index: llvm/test/Transforms/LoopVectorize/AArch64/sve-strict-fadd-cost.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/sve-strict-fadd-cost.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/sve-strict-fadd-cost.ll @@ -53,7 +53,7 @@ ret double %add } -attributes #0 = { "target-features"="+sve" vscale_range(0, 16) } +attributes #0 = { "target-features"="+sve" vscale_range(1, 16) } !0 = distinct !{!0, !1} !1 = !{!"llvm.loop.vectorize.scalable.enable", i1 true} Index: llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-phi.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-phi.ll +++ llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-phi.ll @@ -175,7 +175,7 @@ ret i32 %tmp5 } -attributes #0 = { vscale_range(0, 16) } +attributes #0 = { vscale_range(1, 16) } !0 = distinct !{!0, !1, !2, !3, !4, !5} !1 = !{!"llvm.loop.mustprogress"} !2 = !{!"llvm.loop.vectorize.width", i32 4} Index: llvm/test/Verifier/vscale_range.ll =================================================================== --- llvm/test/Verifier/vscale_range.ll +++ llvm/test/Verifier/vscale_range.ll @@ -1,4 +1,7 @@ ; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s +; CHECK: 'vscale_range' minimum must be greater than 0 +declare i8* @a(i32*) vscale_range(0, 1) + ; CHECK: 'vscale_range' minimum cannot be greater than maximum declare i8* @b(i32*) vscale_range(8, 1)