@@ -768,10 +768,17 @@ static std::pair<VPBlockBase *, VPBlockBase *> cloneFrom(VPBlockBase *Entry) {
768
768
769
769
VPRegionBlock *VPRegionBlock::clone () {
770
770
const auto &[NewEntry, NewExiting] = cloneFrom (getEntry ());
771
- auto *NewRegion = getPlan ()-> createVPRegionBlock (NewEntry, NewExiting,
772
- getName (), isReplicator ());
771
+ auto *NewRegion =
772
+ getPlan ()-> createVPRegionBlock (NewEntry, NewExiting, getName ());
773
773
for (VPBlockBase *Block : vp_depth_first_shallow (NewEntry))
774
774
Block->setParent (NewRegion);
775
+
776
+ if (CanIVInfo.CanIV ) {
777
+ NewRegion->CanIVInfo .CanIV = new VPRegionValue ();
778
+ NewRegion->CanIVInfo .HasNUW = CanIVInfo.HasNUW ;
779
+ NewRegion->CanIVInfo .DL = CanIVInfo.DL ;
780
+ }
781
+
775
782
return NewRegion;
776
783
}
777
784
@@ -856,6 +863,11 @@ void VPRegionBlock::print(raw_ostream &O, const Twine &Indent,
856
863
VPSlotTracker &SlotTracker) const {
857
864
O << Indent << (isReplicator () ? " <xVFxUF> " : " <x1> " ) << getName () << " : {" ;
858
865
auto NewIndent = Indent + " " ;
866
+ if (auto *CanIV = getCanonicalIV ()) {
867
+ O << ' \n ' ;
868
+ CanIV->print (O, SlotTracker);
869
+ O << ' \n ' ;
870
+ }
859
871
for (auto *BlockBase : vp_depth_first_shallow (Entry)) {
860
872
O << ' \n ' ;
861
873
BlockBase->print (O, NewIndent, SlotTracker);
@@ -868,18 +880,37 @@ void VPRegionBlock::print(raw_ostream &O, const Twine &Indent,
868
880
869
881
void VPRegionBlock::dissolveToCFGLoop () {
870
882
auto *Header = cast<VPBasicBlock>(getEntry ());
871
- if (auto *CanIV = dyn_cast<VPCanonicalIVPHIRecipe>(&Header->front ())) {
872
- assert (this == getPlan ()->getVectorLoopRegion () &&
873
- " Canonical IV must be in the entry of the top-level loop region" );
874
- auto *ScalarR = VPBuilder (CanIV).createScalarPhi (
875
- {CanIV->getStartValue (), CanIV->getBackedgeValue ()},
876
- CanIV->getDebugLoc (), " index" );
883
+ auto *ExitingLatch = cast<VPBasicBlock>(getExiting ());
884
+ VPValue *CanIV = getCanonicalIV ();
885
+ if (CanIV && CanIV->getNumUsers () > 0 ) {
886
+ auto *ExitingTerm = ExitingLatch->getTerminator ();
887
+ VPInstruction *CanIVInc = nullptr ;
888
+ // Check if there's a canonical IV increment via an existing terminator.
889
+ if (match (ExitingTerm,
890
+ m_BranchOnCount (m_VPInstruction (CanIVInc), m_VPValue ()))) {
891
+ assert (match (CanIVInc,
892
+ m_Add (m_CombineOr (m_Specific (CanIV),
893
+ m_Add (m_Specific (CanIV), m_LiveIn ())),
894
+ m_VPValue ())) &&
895
+ " invalid existing IV increment" );
896
+ }
897
+ VPlan &Plan = *getPlan ();
898
+ if (!CanIVInc) {
899
+ CanIVInc = VPBuilder (ExitingTerm)
900
+ .createOverflowingOp (
901
+ Instruction::Add, {CanIV, &Plan.getVFxUF ()},
902
+ {CanIVInfo.HasNUW , false }, CanIVInfo.DL , " index.next" );
903
+ }
904
+ Type *CanIVTy = VPTypeAnalysis (Plan).inferScalarType (CanIV);
905
+ auto *ScalarR =
906
+ VPBuilder (Header, Header->begin ())
907
+ .createScalarPhi (
908
+ {Plan.getOrAddLiveIn (ConstantInt::get (CanIVTy, 0 )), CanIVInc},
909
+ CanIVInfo.DL , " index" );
877
910
CanIV->replaceAllUsesWith (ScalarR);
878
- CanIV->eraseFromParent ();
879
911
}
880
912
881
913
VPBlockBase *Preheader = getSinglePredecessor ();
882
- auto *ExitingLatch = cast<VPBasicBlock>(getExiting ());
883
914
VPBlockBase *Middle = getSingleSuccessor ();
884
915
VPBlockUtils::disconnectBlocks (Preheader, this );
885
916
VPBlockUtils::disconnectBlocks (this , Middle);
@@ -916,7 +947,10 @@ VPlan::~VPlan() {
916
947
for (unsigned I = 0 , E = R.getNumOperands (); I != E; I++)
917
948
R.setOperand (I, &DummyValue);
918
949
}
950
+ } else if (auto *CanIV = cast<VPRegionBlock>(VPB)->getCanonicalIV ()) {
951
+ CanIV->replaceAllUsesWith (&DummyValue);
919
952
}
953
+
920
954
delete VPB;
921
955
}
922
956
for (VPValue *VPV : getLiveIns ())
@@ -1224,6 +1258,11 @@ VPlan *VPlan::duplicate() {
1224
1258
// else NewTripCount will be created and inserted into Old2NewVPValues when
1225
1259
// TripCount is cloned. In any case NewPlan->TripCount is updated below.
1226
1260
1261
+ if (auto *LoopRegion = getVectorLoopRegion ()) {
1262
+ Old2NewVPValues[LoopRegion->getCanonicalIV ()] =
1263
+ NewPlan->getVectorLoopRegion ()->getCanonicalIV ();
1264
+ }
1265
+
1227
1266
remapOperands (Entry, NewEntry, Old2NewVPValues);
1228
1267
1229
1268
// Initialize remaining fields of cloned VPlan.
@@ -1404,6 +1443,8 @@ void VPlanPrinter::dumpRegion(const VPRegionBlock *Region) {
1404
1443
// / Returns true if there is a vector loop region and \p VPV is defined in a
1405
1444
// / loop region.
1406
1445
static bool isDefinedInsideLoopRegions (const VPValue *VPV) {
1446
+ if (isa<VPRegionValue>(VPV))
1447
+ return true ;
1407
1448
const VPRecipeBase *DefR = VPV->getDefiningRecipe ();
1408
1449
return DefR && (!DefR->getParent ()->getPlan ()->getVectorLoopRegion () ||
1409
1450
DefR->getParent ()->getEnclosingLoopRegion ());
@@ -1513,9 +1554,12 @@ void VPSlotTracker::assignNames(const VPlan &Plan) {
1513
1554
1514
1555
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<const VPBlockBase *>>
1515
1556
RPOT (VPBlockDeepTraversalWrapper<const VPBlockBase *>(Plan.getEntry ()));
1516
- for (const VPBasicBlock *VPBB :
1517
- VPBlockUtils::blocksOnly<const VPBasicBlock>(RPOT))
1518
- assignNames (VPBB);
1557
+ for (const VPBlockBase *VPB : RPOT) {
1558
+ if (auto *VPBB = dyn_cast<VPBasicBlock>(VPB)) {
1559
+ assignNames (VPBB);
1560
+ } else if (auto *CanIV = cast<VPRegionBlock>(VPB)->getCanonicalIV ())
1561
+ assignName (CanIV);
1562
+ }
1519
1563
}
1520
1564
1521
1565
void VPSlotTracker::assignNames (const VPBasicBlock *VPBB) {
0 commit comments