@@ -498,15 +498,18 @@ static void removeDeadRecipes(VPlan &Plan) {
498
498
}
499
499
}
500
500
501
- static VPValue *createScalarIVSteps (VPlan &Plan, const InductionDescriptor &ID,
501
+ static VPValue *createScalarIVSteps (VPlan &Plan,
502
+ InductionDescriptor::InductionKind Kind,
503
+ Instruction::BinaryOps InductionOpcode,
504
+ FPMathOperator *FPBinOp,
502
505
ScalarEvolution &SE, Instruction *TruncI,
503
506
VPValue *StartV, VPValue *Step,
504
507
VPBasicBlock::iterator IP) {
505
508
VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion ()->getEntryBasicBlock ();
506
509
VPCanonicalIVPHIRecipe *CanonicalIV = Plan.getCanonicalIV ();
507
510
VPSingleDefRecipe *BaseIV = CanonicalIV;
508
- if (!CanonicalIV->isCanonical (ID. getKind () , StartV, Step)) {
509
- BaseIV = new VPDerivedIVRecipe (ID , StartV, CanonicalIV, Step);
511
+ if (!CanonicalIV->isCanonical (Kind , StartV, Step)) {
512
+ BaseIV = new VPDerivedIVRecipe (Kind, FPBinOp , StartV, CanonicalIV, Step);
510
513
HeaderVPBB->insert (BaseIV, IP);
511
514
}
512
515
@@ -536,21 +539,56 @@ static VPValue *createScalarIVSteps(VPlan &Plan, const InductionDescriptor &ID,
536
539
VecPreheader->appendRecipe (Step->getDefiningRecipe ());
537
540
}
538
541
539
- VPScalarIVStepsRecipe *Steps = new VPScalarIVStepsRecipe (ID, BaseIV, Step);
542
+ VPScalarIVStepsRecipe *Steps = new VPScalarIVStepsRecipe (
543
+ BaseIV, Step, InductionOpcode,
544
+ FPBinOp ? FPBinOp->getFastMathFlags () : FastMathFlags ());
540
545
HeaderVPBB->insert (Steps, IP);
541
546
return Steps;
542
547
}
543
548
544
- // / If any user of a VPWidenIntOrFpInductionRecipe needs scalar values,
545
- // / provide them by building scalar steps off of the canonical scalar IV and
546
- // / update the original IV's users. This is an optional optimization to reduce
547
- // / the needs of vector extracts.
548
- static void optimizeInductions (VPlan &Plan, ScalarEvolution &SE) {
549
+ // / Legalize VPWidenPointerInductionRecipe, by replacing it with a PtrAdd
550
+ // / (IndStart, ScalarIVSteps (0, Step)) if only its scalar values are used, as
551
+ // / VPWidenPointerInductionRecipe will generate vectors only. If some users
552
+ // / require vectors while other require scalars, the scalar uses need to extract
553
+ // / the scalars from the generated vectors (Note that this is different to how
554
+ // / int/fp inductions are handled). Also optimize VPWidenIntOrFpInductionRecipe,
555
+ // / if any of its users needs scalar values, by providing them scalar steps
556
+ // / built on the canonical scalar IV and update the original IV's users. This is
557
+ // / an optional optimization to reduce the needs of vector extracts.
558
+ static void legalizeAndOptimizeInductions (VPlan &Plan, ScalarEvolution &SE) {
549
559
SmallVector<VPRecipeBase *> ToRemove;
550
560
VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion ()->getEntryBasicBlock ();
551
561
bool HasOnlyVectorVFs = !Plan.hasVF (ElementCount::getFixed (1 ));
552
562
VPBasicBlock::iterator InsertPt = HeaderVPBB->getFirstNonPhi ();
553
563
for (VPRecipeBase &Phi : HeaderVPBB->phis ()) {
564
+ // Replace wide pointer inductions which have only their scalars used by
565
+ // PtrAdd(IndStart, ScalarIVSteps (0, Step)).
566
+ if (auto *PtrIV = dyn_cast<VPWidenPointerInductionRecipe>(&Phi)) {
567
+ if (!PtrIV->onlyScalarsGenerated (Plan.hasScalableVF ()))
568
+ continue ;
569
+
570
+ const InductionDescriptor &ID = PtrIV->getInductionDescriptor ();
571
+ VPValue *StartV = Plan.getVPValueOrAddLiveIn (
572
+ ConstantInt::get (ID.getStep ()->getType (), 0 ));
573
+ VPValue *StepV = PtrIV->getOperand (1 );
574
+ VPRecipeBase *Steps =
575
+ createScalarIVSteps (Plan, InductionDescriptor::IK_IntInduction,
576
+ Instruction::Add, nullptr , SE, nullptr , StartV,
577
+ StepV, InsertPt)
578
+ ->getDefiningRecipe ();
579
+
580
+ auto *Recipe =
581
+ new VPInstruction (VPInstruction::PtrAdd,
582
+ {PtrIV->getStartValue (), Steps->getVPSingleValue ()},
583
+ PtrIV->getDebugLoc (), " next.gep" );
584
+
585
+ Recipe->insertAfter (Steps);
586
+ PtrIV->replaceAllUsesWith (Recipe);
587
+ continue ;
588
+ }
589
+
590
+ // Replace widened induction with scalar steps for users that only use
591
+ // scalars.
554
592
auto *WideIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(&Phi);
555
593
if (!WideIV)
556
594
continue ;
@@ -560,9 +598,11 @@ static void optimizeInductions(VPlan &Plan, ScalarEvolution &SE) {
560
598
continue ;
561
599
562
600
const InductionDescriptor &ID = WideIV->getInductionDescriptor ();
563
- VPValue *Steps = createScalarIVSteps (Plan, ID, SE, WideIV->getTruncInst (),
564
- WideIV->getStartValue (),
565
- WideIV->getStepValue (), InsertPt);
601
+ VPValue *Steps = createScalarIVSteps (
602
+ Plan, ID.getKind (), ID.getInductionOpcode (),
603
+ dyn_cast_or_null<FPMathOperator>(ID.getInductionBinOp ()), SE,
604
+ WideIV->getTruncInst (), WideIV->getStartValue (), WideIV->getStepValue (),
605
+ InsertPt);
566
606
567
607
// Update scalar users of IV to use Step instead.
568
608
if (!HasOnlyVectorVFs)
@@ -1025,7 +1065,7 @@ void VPlanTransforms::optimize(VPlan &Plan, ScalarEvolution &SE) {
1025
1065
removeRedundantInductionCasts (Plan);
1026
1066
1027
1067
simplifyRecipes (Plan, SE.getContext ());
1028
- optimizeInductions (Plan, SE);
1068
+ legalizeAndOptimizeInductions (Plan, SE);
1029
1069
removeDeadRecipes (Plan);
1030
1070
1031
1071
createAndOptimizeReplicateRegions (Plan);
0 commit comments