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,20 @@ Res = CastInst::Create( static_cast(Opc), I->getOperand(0), Ty); break; + case Instruction::Call: + if (const IntrinsicInst *II = dyn_cast(I)) { + switch (II->getIntrinsicID()) { + default: + llvm_unreachable("Unsupported call!"); + case Intrinsic::vscale: { + Function *Fn = + Intrinsic::getDeclaration(I->getModule(), Intrinsic::vscale, {Ty}); + Res = CallInst::Create(Fn->getFunctionType(), Fn); + break; + } + } + } + break; default: // TODO: Can handle more cases here. llvm_unreachable("Unreachable!"); @@ -1217,6 +1231,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/vscale.ll b/llvm/test/Transforms/InstCombine/vscale.ll --- a/llvm/test/Transforms/InstCombine/vscale.ll +++ b/llvm/test/Transforms/InstCombine/vscale.ll @@ -4,8 +4,8 @@ define i64 @promote_vscale_i32_to_i64() { ; CHECK-LABEL: @promote_vscale_i32_to_i64( -; CHECK-NEXT: [[VSCALE:%.*]] = call i32 @llvm.vscale.i32() -; CHECK-NEXT: [[EXT:%.*]] = zext i32 [[VSCALE]] to i64 +; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[EXT:%.*]] = and i64 [[VSCALE]], 4294967295 ; CHECK-NEXT: ret i64 [[EXT]] ; %vscale = call i32 @llvm.vscale.i32() @@ -15,9 +15,9 @@ define i64 @pomote_zext_shl_vscale_i32_to_i64() { ; CHECK-LABEL: @pomote_zext_shl_vscale_i32_to_i64( -; CHECK-NEXT: [[VSCALE:%.*]] = call i32 @llvm.vscale.i32() -; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[VSCALE]], 3 -; CHECK-NEXT: [[EXT:%.*]] = zext i32 [[SHL]] to i64 +; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[VSCALE]], 3 +; CHECK-NEXT: [[EXT:%.*]] = and i64 [[SHL]], 4294967288 ; CHECK-NEXT: ret i64 [[EXT]] ; %vscale = call i32 @llvm.vscale.i32() @@ -30,10 +30,9 @@ ; vscale_range attribute so that the 'and' is folded away. define i64 @free_zext_vscale_shl_i32_to_i64() #0 { ; CHECK-LABEL: @free_zext_vscale_shl_i32_to_i64( -; CHECK-NEXT: [[VSCALE:%.*]] = call i32 @llvm.vscale.i32() -; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[VSCALE]], 3 -; CHECK-NEXT: [[EXT:%.*]] = zext i32 [[SHL]] to i64 -; CHECK-NEXT: ret i64 [[EXT]] +; 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