@@ -614,17 +614,60 @@ void VPBasicBlock::print(raw_ostream &O, const Twine &Indent,
614
614
printSuccessors (O, Indent);
615
615
}
616
616
#endif
617
+ static void cloneCFG (VPBlockBase *Entry,
618
+ DenseMap<VPBlockBase *, VPBlockBase *> &Old2NewVPBlocks);
619
+
620
+ static VPBlockBase *cloneVPB (VPBlockBase *BB) {
621
+ if (auto *VPBB = dyn_cast<VPBasicBlock>(BB)) {
622
+ auto *NewBlock = new VPBasicBlock (VPBB->getName ());
623
+ for (VPRecipeBase &R : *VPBB)
624
+ NewBlock->appendRecipe (R.clone ());
625
+ return NewBlock;
626
+ }
617
627
618
- VPBlockBase * VPRegionBlock::clone () {
619
- DenseMap<VPBlockBase *, VPBlockBase *> Old2New ;
628
+ auto *VPR = cast< VPRegionBlock>(BB);
629
+ DenseMap<VPBlockBase *, VPBlockBase *> Old2NewVPBlocks ;
620
630
DenseMap<VPValue *, VPValue *> Old2NewVPValues;
621
- VPBlockBase *NewEntry =
622
- VPBlockUtils::cloneCFG (Entry, Old2New, Old2NewVPValues);
623
- auto *NewR =
624
- new VPRegionBlock (NewEntry, Old2New[Exiting], getName (), isReplicator ());
631
+ cloneCFG (VPR->getEntry (), Old2NewVPBlocks);
632
+ VPBlockBase *NewEntry = Old2NewVPBlocks[VPR->getEntry ()];
633
+ auto *NewRegion =
634
+ new VPRegionBlock (NewEntry, Old2NewVPBlocks[VPR->getExiting ()],
635
+ VPR->getName (), VPR->isReplicator ());
625
636
for (VPBlockBase *Block : vp_depth_first_shallow (NewEntry))
626
- Block->setParent (NewR);
627
- return NewR;
637
+ Block->setParent (NewRegion);
638
+ return NewRegion;
639
+ }
640
+
641
+ // Clone the CFG for all nodes reachable from \p Entry, this includes cloning
642
+ // the blocks and their recipes. Operands of cloned recipes will NOT be updated.
643
+ // Remapping of operands must be done separately.
644
+ static void cloneCFG (VPBlockBase *Entry,
645
+ DenseMap<VPBlockBase *, VPBlockBase *> &Old2NewVPBlocks) {
646
+ ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>> RPOT (
647
+ Entry);
648
+ for (VPBlockBase *BB : RPOT) {
649
+ VPBlockBase *NewBB = cloneVPB (BB);
650
+ for (VPBlockBase *Pred : BB->getPredecessors ())
651
+ VPBlockUtils::connectBlocks (Old2NewVPBlocks[Pred], NewBB);
652
+
653
+ Old2NewVPBlocks[BB] = NewBB;
654
+ }
655
+
656
+ #if !defined(NDEBUG)
657
+ // Verify that the order of predecessors and successors matches in the cloned
658
+ // version.
659
+ ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>>
660
+ NewRPOT (Old2NewVPBlocks[Entry]);
661
+ for (const auto &[OldBB, NewBB] : zip (RPOT, NewRPOT)) {
662
+ for (const auto &[OldPred, NewPred] :
663
+ zip (OldBB->getPredecessors (), NewBB->getPredecessors ()))
664
+ assert (NewPred == Old2NewVPBlocks[OldPred] && " Different predecessors" );
665
+
666
+ for (const auto &[OldSucc, NewSucc] :
667
+ zip (OldBB->successors (), NewBB->successors ()))
668
+ assert (NewSucc == Old2NewVPBlocks[OldSucc] && " Different successors" );
669
+ }
670
+ #endif
628
671
}
629
672
630
673
void VPRegionBlock::dropAllReferences (VPValue *NewValue) {
@@ -994,62 +1037,91 @@ void VPlan::updateDominatorTree(DominatorTree *DT, BasicBlock *LoopHeaderBB,
994
1037
assert (DT->verify (DominatorTree::VerificationLevel::Fast));
995
1038
}
996
1039
997
- static void remapVPValues (VPBasicBlock *OldBB, VPBasicBlock *NewBB,
998
- DenseMap<VPValue *, VPValue *> &Old2NewVPValues,
999
- bool Full = false ) {
1000
- for (const auto &[OldR, NewR] : zip (*OldBB, *NewBB)) {
1001
- for (unsigned I = 0 , E = NewR.getNumOperands (); I != E; ++I) {
1002
- VPValue *NewOp = Old2NewVPValues.lookup (OldR.getOperand (I));
1003
- if (!Full)
1004
- continue ;
1005
- NewR.setOperand (I, NewOp);
1040
+ static void remapOperands (VPBlockBase *Entry, VPBlockBase *NewEntry,
1041
+ DenseMap<VPValue *, VPValue *> &Old2NewVPValues) {
1042
+ // Update the operands of all cloned recipes starting at NewEntry. This
1043
+ // traverses all reachable blocks. This is done in two steps, to handle cycles
1044
+ // in PHI recipes.
1045
+ ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>>
1046
+ OldDeepRPOT (Entry);
1047
+ ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>>
1048
+ NewDeepRPOT (NewEntry);
1049
+ // First, collect all mappings from old to new VPValues defined by cloned
1050
+ // recipes.
1051
+ for (const auto &[OldBB, NewBB] :
1052
+ zip (VPBlockUtils::blocksOnly<VPBasicBlock>(OldDeepRPOT),
1053
+ VPBlockUtils::blocksOnly<VPBasicBlock>(NewDeepRPOT))) {
1054
+ assert (OldBB->getRecipeList ().size () == NewBB->getRecipeList ().size () &&
1055
+ " blocks must have the same number of recipes" );
1056
+
1057
+ for (const auto &[OldR, NewR] : zip (*OldBB, *NewBB)) {
1058
+ assert (OldR.getNumOperands () == NewR.getNumOperands () &&
1059
+ " recipes must have the same number of operands" );
1060
+ assert (OldR.getNumDefinedValues () == NewR.getNumDefinedValues () &&
1061
+ " recipes must define the same number of operands" );
1062
+ for (const auto &[OldV, NewV] :
1063
+ zip (OldR.definedValues (), NewR.definedValues ()))
1064
+ Old2NewVPValues[OldV] = NewV;
1006
1065
}
1007
- for (const auto &[OldV, NewV] :
1008
- zip (OldR.definedValues (), NewR.definedValues ()))
1009
- Old2NewVPValues[OldV] = NewV;
1066
+ }
1067
+
1068
+ // Update all operands to use cloned VPValues.
1069
+ for (VPBasicBlock *NewBB :
1070
+ VPBlockUtils::blocksOnly<VPBasicBlock>(NewDeepRPOT)) {
1071
+ for (VPRecipeBase &NewR : *NewBB)
1072
+ for (unsigned I = 0 , E = NewR.getNumOperands (); I != E; ++I) {
1073
+ VPValue *NewOp = Old2NewVPValues.lookup (NewR.getOperand (I));
1074
+ NewR.setOperand (I, NewOp);
1075
+ }
1010
1076
}
1011
1077
}
1012
1078
1013
1079
VPlan *VPlan::clone () {
1014
- DenseMap<VPBlockBase *, VPBlockBase *> Old2New ;
1080
+ DenseMap<VPBlockBase *, VPBlockBase *> Old2NewVPBlocks ;
1015
1081
DenseMap<VPValue *, VPValue *> Old2NewVPValues;
1016
1082
1017
1083
auto *NewPlan = new VPlan ();
1084
+
1085
+ // Clone live-ins.
1018
1086
SmallVector<VPValue *, 16 > NewLiveIns;
1019
- for (VPValue *LI : VPLiveInsToFree) {
1020
- VPValue *NewLI = new VPValue (LI ->getLiveInIRValue ());
1021
- NewPlan->VPLiveInsToFree .push_back (NewLI );
1022
- Old2NewVPValues[LI ] = NewLI ;
1087
+ for (VPValue *OldLiveIn : VPLiveInsToFree) {
1088
+ VPValue *NewLiveIn = new VPValue (OldLiveIn ->getLiveInIRValue ());
1089
+ NewPlan->VPLiveInsToFree .push_back (NewLiveIn );
1090
+ Old2NewVPValues[OldLiveIn ] = NewLiveIn ;
1023
1091
}
1024
-
1025
1092
Old2NewVPValues[&VectorTripCount] = &NewPlan->VectorTripCount ;
1026
1093
Old2NewVPValues[&VFxUF] = &NewPlan->VFxUF ;
1027
1094
if (BackedgeTakenCount) {
1028
- Old2NewVPValues[ BackedgeTakenCount] = new VPValue ();
1029
- NewPlan-> BackedgeTakenCount = Old2NewVPValues[ BackedgeTakenCount] ;
1095
+ NewPlan-> BackedgeTakenCount = new VPValue ();
1096
+ Old2NewVPValues[ BackedgeTakenCount] = NewPlan-> BackedgeTakenCount ;
1030
1097
}
1031
-
1032
- auto NewPH = cast<VPBasicBlock>(Preheader->clone ());
1033
- remapVPValues (cast<VPBasicBlock>(Preheader), cast<VPBasicBlock>(NewPH),
1034
- Old2NewVPValues, /* Full*/ true );
1035
- VPValue *NewTC = Old2NewVPValues.lookup (TripCount);
1036
- if (!NewTC)
1098
+ assert (TripCount && " trip count must be set" );
1099
+ if (TripCount->isLiveIn ())
1037
1100
Old2NewVPValues[TripCount] = new VPValue (TripCount->getLiveInIRValue ());
1038
- NewPlan->TripCount = Old2NewVPValues[TripCount];
1039
1101
1040
- auto *NewEntry = cast<VPBasicBlock>(VPBlockUtils::cloneCFG (
1041
- getEntry (), Old2New, Old2NewVPValues, /* FullRemapping*/ true ));
1102
+ // Clone blocks.
1103
+ cloneCFG (Preheader, Old2NewVPBlocks);
1104
+ cloneCFG (getEntry (), Old2NewVPBlocks);
1105
+
1106
+ auto *NewPreheader = cast<VPBasicBlock>(Old2NewVPBlocks[Preheader]);
1107
+ remapOperands (Preheader, NewPreheader, Old2NewVPValues);
1108
+ auto *NewEntry = cast<VPBasicBlock>(Old2NewVPBlocks[Entry]);
1109
+ remapOperands (Entry, NewEntry, Old2NewVPValues);
1110
+
1111
+ // Clone live-outs.
1112
+ for (const auto &[_, LO] : LiveOuts)
1113
+ NewPlan->addLiveOut (LO->getPhi (), Old2NewVPValues[LO->getOperand (0 )]);
1042
1114
1115
+ // Initialize fields of cloned VPlan.
1043
1116
NewPlan->Entry = NewEntry;
1044
- NewPlan->Preheader = NewPH ;
1117
+ NewPlan->Preheader = NewPreheader ;
1045
1118
NewEntry->setPlan (NewPlan);
1046
- NewPH ->setPlan (NewPlan);
1119
+ NewPreheader ->setPlan (NewPlan);
1047
1120
NewPlan->VFs = VFs;
1048
1121
NewPlan->UFs = UFs;
1122
+ // TODO: Adjust names.
1049
1123
NewPlan->Name = Name;
1050
-
1051
- for (const auto &[_, LO] : LiveOuts)
1052
- NewPlan->addLiveOut (LO->getPhi (), Old2NewVPValues[LO->getOperand (0 )]);
1124
+ NewPlan->TripCount = Old2NewVPValues[TripCount];
1053
1125
return NewPlan;
1054
1126
}
1055
1127
@@ -1271,59 +1343,6 @@ void VPUser::printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const {
1271
1343
}
1272
1344
#endif
1273
1345
1274
- VPBlockBase *VPBlockUtils::cloneCFG (
1275
- VPBlockBase *Entry, DenseMap<VPBlockBase *, VPBlockBase *> &Old2New,
1276
- DenseMap<VPValue *, VPValue *> &Old2NewVPValues, bool FullRemapping) {
1277
- ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>> RPOT (
1278
- Entry);
1279
- VPBlockBase *NewEntry = nullptr ;
1280
- for (VPBlockBase *BB : RPOT) {
1281
- VPBlockBase *NewBB = BB->clone ();
1282
- if (!NewEntry)
1283
- NewEntry = NewBB;
1284
-
1285
- for (VPBlockBase *Pred : BB->getPredecessors ())
1286
- connectBlocks (Old2New[Pred], NewBB);
1287
-
1288
- Old2New[BB] = NewBB;
1289
-
1290
- if (!isa<VPBasicBlock>(BB))
1291
- continue ;
1292
- }
1293
-
1294
- // Update the operands of all cloned recipes starting at NewEntry. This
1295
- // traverses all reachable blocks. This is done in two steps, to handle cycles
1296
- // in PHI recipes.
1297
- ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>>
1298
- OldDeepRPOT (Entry);
1299
- ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>>
1300
- NewDeepRPOT (NewEntry);
1301
- // First, collect all mappings from old to new VPValues defined by cloned
1302
- // recipes.
1303
- for (const auto &[OldBB, NewBB] :
1304
- zip (VPBlockUtils::blocksOnly<VPBasicBlock>(OldDeepRPOT),
1305
- VPBlockUtils::blocksOnly<VPBasicBlock>(NewDeepRPOT))) {
1306
- for (const auto &[OldR, NewR] : zip (*OldBB, *NewBB))
1307
- for (const auto &[OldV, NewV] :
1308
- zip (OldR.definedValues (), NewR.definedValues ()))
1309
- Old2NewVPValues[OldV] = NewV;
1310
- }
1311
-
1312
- // Update all operands to use cloned VPValues.
1313
- for (VPBasicBlock *NewBB :
1314
- VPBlockUtils::blocksOnly<VPBasicBlock>(NewDeepRPOT)) {
1315
- for (VPRecipeBase &NewR : *NewBB)
1316
- for (unsigned I = 0 , E = NewR.getNumOperands (); I != E; ++I) {
1317
- VPValue *NewOp = Old2NewVPValues.lookup (NewR.getOperand (I));
1318
- if (!FullRemapping)
1319
- continue ;
1320
- NewR.setOperand (I, NewOp);
1321
- }
1322
- }
1323
-
1324
- return NewEntry;
1325
- }
1326
-
1327
1346
void VPInterleavedAccessInfo::visitRegion (VPRegionBlock *Region,
1328
1347
Old2NewTy &Old2New,
1329
1348
InterleavedAccessInfo &IAI) {
0 commit comments