diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -252,6 +252,16 @@ Res = CastInst::Create( static_cast(Opc), I->getOperand(0), Ty); break; + case Instruction::Call: + if (const IntrinsicInst *II = dyn_cast(I)) { + if (II->getIntrinsicID() == Intrinsic::vscale) { + Function *Fn = + Intrinsic::getDeclaration(I->getModule(), Intrinsic::vscale, {Ty}); + Res = CallInst::Create(Fn->getFunctionType(), Fn); + break; + } + } + LLVM_FALLTHROUGH; default: // TODO: Can handle more cases here. llvm_unreachable("Unreachable!"); @@ -1217,6 +1227,13 @@ return false; return true; } + case Instruction::Call: + // llvm.vscale() can always be executed in larger type, because the + // value is automatically zero-extended. + if (const IntrinsicInst *II = dyn_cast(I)) + if (II->getIntrinsicID() == Intrinsic::vscale) + return true; + return false; default: // TODO: Can handle more cases here. return false; diff --git a/llvm/test/Transforms/InstCombine/AArch64/vscale.ll b/llvm/test/Transforms/InstCombine/AArch64/vscale.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/AArch64/vscale.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes='instcombine' -S < %s | FileCheck %s +target triple = "aarch64" +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + +define i64 @free_zext_vscale_i32_to_i64() #0 { +; CHECK-LABEL: @free_zext_vscale_i32_to_i64( +; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: ret i64 [[VSCALE]] +; + %vscale = call i32 @llvm.vscale.i32() + %ext = zext i32 %vscale to i64 + ret i64 %ext +} + +define i64 @free_zext_vscale_shl_i32_to_i64() #0 { +; CHECK-LABEL: @free_zext_vscale_shl_i32_to_i64( +; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i64 [[VSCALE]], 3 +; CHECK-NEXT: ret i64 [[SHL]] +; + %vscale = call i32 @llvm.vscale.i32() + %shl = shl i32 %vscale, 3 + %ext = zext i32 %shl to i64 + ret i64 %ext +} + +declare i32 @llvm.vscale.i32() + +attributes #0 = { vscale_range(1,16) "target-features"="+sve" }