@@ -1019,6 +1019,14 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
10191019 TypeInfo.inferScalarType (R.getOperand (1 )) ==
10201020 TypeInfo.inferScalarType (R.getVPSingleValue ()))
10211021 return R.getVPSingleValue ()->replaceAllUsesWith (R.getOperand (1 ));
1022+
1023+ if (match (&R, m_VPInstruction<VPInstruction::WideIVStep>(m_VPValue (X),
1024+ m_SpecificInt (1 )))) {
1025+ Type *WideStepTy = TypeInfo.inferScalarType (R.getVPSingleValue ());
1026+ if (TypeInfo.inferScalarType (X) != WideStepTy)
1027+ X = VPBuilder (&R).createWidenCast (Instruction::Trunc, X, WideStepTy);
1028+ R.getVPSingleValue ()->replaceAllUsesWith (X);
1029+ }
10221030}
10231031
10241032void VPlanTransforms::simplifyRecipes (VPlan &Plan, Type &CanonicalIVTy) {
@@ -2367,23 +2375,71 @@ void VPlanTransforms::createInterleaveGroups(
23672375 }
23682376}
23692377
2370- void VPlanTransforms::convertToConcreteRecipes (VPlan &Plan) {
2378+ void VPlanTransforms::convertToConcreteRecipes (VPlan &Plan,
2379+ Type &CanonicalIVTy) {
2380+ using namespace llvm ::VPlanPatternMatch;
2381+
2382+ VPTypeAnalysis TypeInfo (&CanonicalIVTy);
2383+ SmallVector<VPRecipeBase *> ToRemove;
23712384 for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
23722385 vp_depth_first_deep (Plan.getEntry ()))) {
2373- for (VPRecipeBase &R : make_early_inc_range (VPBB->phis ())) {
2374- if (!isa<VPCanonicalIVPHIRecipe, VPEVLBasedIVPHIRecipe>(&R))
2386+ for (VPRecipeBase &R : make_early_inc_range (*VPBB)) {
2387+ if (isa<VPCanonicalIVPHIRecipe, VPEVLBasedIVPHIRecipe>(&R)) {
2388+ auto *PhiR = cast<VPHeaderPHIRecipe>(&R);
2389+ StringRef Name =
2390+ isa<VPCanonicalIVPHIRecipe>(PhiR) ? " index" : " evl.based.iv" ;
2391+ auto *ScalarR = new VPInstruction (
2392+ Instruction::PHI, {PhiR->getStartValue (), PhiR->getBackedgeValue ()},
2393+ PhiR->getDebugLoc (), Name);
2394+ ScalarR->insertBefore (PhiR);
2395+ PhiR->replaceAllUsesWith (ScalarR);
2396+ ToRemove.push_back (PhiR);
23752397 continue ;
2376- auto *PhiR = cast<VPHeaderPHIRecipe>(&R);
2377- StringRef Name =
2378- isa<VPCanonicalIVPHIRecipe>(PhiR) ? " index" : " evl.based.iv" ;
2379- auto *ScalarR = new VPInstruction (
2380- Instruction::PHI, {PhiR->getStartValue (), PhiR->getBackedgeValue ()},
2381- PhiR->getDebugLoc (), Name);
2382- ScalarR->insertBefore (PhiR);
2383- PhiR->replaceAllUsesWith (ScalarR);
2384- PhiR->eraseFromParent ();
2398+ }
2399+
2400+ VPValue *VectorStep;
2401+ VPValue *ScalarStep;
2402+ if (!match (&R, m_VPInstruction<VPInstruction::WideIVStep>(
2403+ m_VPValue (VectorStep), m_VPValue (ScalarStep))))
2404+ continue ;
2405+
2406+ // Expand WideIVStep.
2407+ auto *VPI = cast<VPInstruction>(&R);
2408+ VPBuilder Builder (VPI);
2409+ Type *IVTy = TypeInfo.inferScalarType (VPI);
2410+ if (TypeInfo.inferScalarType (VectorStep) != IVTy) {
2411+ Instruction::CastOps CastOp = IVTy->isFloatingPointTy ()
2412+ ? Instruction::UIToFP
2413+ : Instruction::Trunc;
2414+ VectorStep = Builder.createWidenCast (CastOp, VectorStep, IVTy);
2415+ }
2416+
2417+ auto *ConstStep =
2418+ ScalarStep->isLiveIn ()
2419+ ? dyn_cast<ConstantInt>(ScalarStep->getLiveInIRValue ())
2420+ : nullptr ;
2421+ assert (!ConstStep || ConstStep->getValue () != 1 );
2422+ if (TypeInfo.inferScalarType (ScalarStep) != IVTy) {
2423+ ScalarStep =
2424+ Builder.createWidenCast (Instruction::Trunc, ScalarStep, IVTy);
2425+ }
2426+
2427+ std::optional<FastMathFlags> FMFs;
2428+ if (IVTy->isFloatingPointTy ())
2429+ FMFs = VPI->getFastMathFlags ();
2430+
2431+ unsigned MulOpc =
2432+ IVTy->isFloatingPointTy () ? Instruction::FMul : Instruction::Mul;
2433+ VPInstruction *Mul = Builder.createNaryOp (
2434+ MulOpc, {VectorStep, ScalarStep}, FMFs, R.getDebugLoc ());
2435+ VectorStep = Mul;
2436+ VPI->replaceAllUsesWith (VectorStep);
2437+ ToRemove.push_back (VPI);
23852438 }
23862439 }
2440+
2441+ for (VPRecipeBase *R : ToRemove)
2442+ R->eraseFromParent ();
23872443}
23882444
23892445void VPlanTransforms::handleUncountableEarlyExit (
0 commit comments