diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -5772,13 +5772,31 @@ static Value *simplifyIntrinsic(CallBase *Call, const SimplifyQuery &Q) { - // Intrinsics with no operands have some kind of side effect. Don't simplify. unsigned NumOperands = Call->getNumArgOperands(); - if (!NumOperands) - return nullptr; - Function *F = cast(Call->getCalledFunction()); Intrinsic::ID IID = F->getIntrinsicID(); + + // Most of the intrinsics with no operands have some kind of side effect. + // Don't simplify. + if (!NumOperands) { + switch (IID) { + case Intrinsic::vscale: { + auto Attr = Call->getFunction()->getFnAttribute(Attribute::VScaleRange); + if (!Attr.isValid()) + return nullptr; + unsigned MinScalarVectorSize, MaxScalarVectorSize; + std::tie(MinScalarVectorSize, MaxScalarVectorSize) = + Attr.getVScaleRangeArgs(); + if (MinScalarVectorSize == MaxScalarVectorSize && + MaxScalarVectorSize != 0) + return ConstantInt::get(F->getReturnType(), MinScalarVectorSize); + return nullptr; + } + default: + return nullptr; + } + } + if (NumOperands == 1) return simplifyUnaryIntrinsic(F, Call->getArgOperand(0), Q); diff --git a/llvm/test/Transforms/InstSimplify/fold-vscale.ll b/llvm/test/Transforms/InstSimplify/fold-vscale.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/fold-vscale.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instsimplify -S | FileCheck %s + +define i64 @vscale_i64() #1 { +; CHECK-LABEL: @vscale_i64( +; CHECK-NEXT: ret i64 1 +; + %out = call i64 @llvm.vscale.i64() + ret i64 %out +} + +define i32 @vscale_i32() #2 { +; CHECK-LABEL: @vscale_i32( +; CHECK-NEXT: ret i32 2 +; + %out = call i32 @llvm.vscale.i32() + ret i32 %out +} + +define i64 @vscale_i64_diff() #3 { +; CHECK-LABEL: @vscale_i64_diff( +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.vscale.i64() + ret i64 %out +} + +; Function Attrs: nofree nosync nounwind readnone willreturn +declare i64 @llvm.vscale.i64() #0 + +; Function Attrs: nofree nosync nounwind readnone willreturn +declare i32 @llvm.vscale.i32() #0 + +attributes #0 = { nofree nosync nounwind readnone willreturn } +attributes #1 = { mustprogress nofree nosync nounwind uwtable vscale_range(1,1) } +attributes #2 = { mustprogress nofree nosync nounwind uwtable vscale_range(2,2) } +attributes #3 = { mustprogress nofree nosync nounwind uwtable vscale_range(2,4) } + +