diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -654,6 +654,10 @@ bool isOverflowIntrinsicNoWrap(const WithOverflowInst *WO, const DominatorTree &DT); +/// Determine the possible constant range of vscale with the given bit width, +/// based on the vscale_range function attribute. +ConstantRange getVScaleRange(const Function *F, unsigned BitWidth); + /// Determine the possible constant range of an integer or vector of integer /// value. This is intended as a cheap, non-recursive check. ConstantRange computeConstantRange(const Value *V, bool ForSigned, diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -6600,7 +6600,7 @@ case scConstant: llvm_unreachable("Already handled above."); case scVScale: - return setRange(S, SignHint, std::move(ConservativeResult)); + return setRange(S, SignHint, getVScaleRange(&F, BitWidth)); case scTruncate: { const SCEVTruncateExpr *Trunc = cast(S); ConstantRange X = getRangeRef(Trunc->getOperand(), SignHint, Depth + 1); @@ -8007,6 +8007,8 @@ // A start_loop_iterations or llvm.annotation or llvm.prt.annotation is // just eqivalent to the first operand for SCEV purposes. return getSCEV(II->getArgOperand(0)); + case Intrinsic::vscale: + return getVScale(II->getType()); default: break; } diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1152,7 +1152,7 @@ Query(DL, AC, safeCxtI(I, CxtI), DT, UseInstrInfo, ORE)); } -static ConstantRange getVScaleRange(const Function *F, unsigned BitWidth) { +ConstantRange llvm::getVScaleRange(const Function *F, unsigned BitWidth) { Attribute Attr = F->getFnAttribute(Attribute::VScaleRange); // Without vscale_range, we only know that vscale is non-zero. if (!Attr.isValid()) diff --git a/llvm/test/Analysis/ScalarEvolution/scalable-vector.ll b/llvm/test/Analysis/ScalarEvolution/scalable-vector.ll --- a/llvm/test/Analysis/ScalarEvolution/scalable-vector.ll +++ b/llvm/test/Analysis/ScalarEvolution/scalable-vector.ll @@ -19,9 +19,9 @@ ; CHECK-LABEL: 'vscale_gep_range' ; CHECK-NEXT: Classifying expressions for: @vscale_gep_range ; CHECK-NEXT: %1 = getelementptr , ptr null, i32 3 -; CHECK-NEXT: --> ((48 * vscale) + null) U: [0,-15) S: [-9223372036854775808,9223372036854775793) +; CHECK-NEXT: --> ((48 * vscale) + null) U: [96,769) S: [96,769) ; CHECK-NEXT: %2 = getelementptr , ptr %p, i32 1 -; CHECK-NEXT: --> ((8 * vscale) + %p) U: full-set S: full-set +; CHECK-NEXT: --> ((8 * vscale) + %p) U: full-set S: full-set ; CHECK-NEXT: Determining loop execution counts for: @vscale_gep_range ; getelementptr , ptr null, i32 3 @@ -33,7 +33,7 @@ ; CHECK-LABEL: 'vscale_no_range' ; CHECK-NEXT: Classifying expressions for: @vscale_no_range ; CHECK-NEXT: %vscale = call i64 @llvm.vscale.i64() -; CHECK-NEXT: --> %vscale U: [1,0) S: [1,0) +; CHECK-NEXT: --> vscale U: [1,0) S: [1,0) ; CHECK-NEXT: Determining loop execution counts for: @vscale_no_range ; %vscale = call i64 @llvm.vscale.i64() @@ -44,7 +44,7 @@ ; CHECK-LABEL: 'vscale_min_max_range' ; CHECK-NEXT: Classifying expressions for: @vscale_min_max_range ; CHECK-NEXT: %vscale = call i64 @llvm.vscale.i64() -; CHECK-NEXT: --> %vscale U: [1,32) S: [1,32) +; CHECK-NEXT: --> vscale U: [2,17) S: [2,17) ; CHECK-NEXT: Determining loop execution counts for: @vscale_min_max_range ; %vscale = call i64 @llvm.vscale.i64() @@ -55,7 +55,7 @@ ; CHECK-LABEL: 'vscale_min_range' ; CHECK-NEXT: Classifying expressions for: @vscale_min_range ; CHECK-NEXT: %vscale = call i64 @llvm.vscale.i64() -; CHECK-NEXT: --> %vscale U: [1,0) S: [1,0) +; CHECK-NEXT: --> vscale U: [2,0) S: [2,0) ; CHECK-NEXT: Determining loop execution counts for: @vscale_min_range ; %vscale = call i64 @llvm.vscale.i64() @@ -66,7 +66,7 @@ ; CHECK-LABEL: 'vscale_exact_range' ; CHECK-NEXT: Classifying expressions for: @vscale_exact_range ; CHECK-NEXT: %vscale = call i64 @llvm.vscale.i64() -; CHECK-NEXT: --> %vscale U: [2,3) S: [2,3) +; CHECK-NEXT: --> vscale U: [2,3) S: [2,3) ; CHECK-NEXT: Determining loop execution counts for: @vscale_exact_range ; %vscale = call i64 @llvm.vscale.i64()