================ @@ -982,6 +1037,94 @@ void VPlan::updateDominatorTree(DominatorTree *DT, BasicBlock *LoopHeaderBB, assert(DT->verify(DominatorTree::VerificationLevel::Fast)); } +static void remapOperands(VPBlockBase *Entry, VPBlockBase *NewEntry, + DenseMap<VPValue *, VPValue *> &Old2NewVPValues) { + // Update the operands of all cloned recipes starting at NewEntry. This + // traverses all reachable blocks. This is done in two steps, to handle cycles + // in PHI recipes. + ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> + OldDeepRPOT(Entry); + ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> + NewDeepRPOT(NewEntry); + // First, collect all mappings from old to new VPValues defined by cloned + // recipes. + for (const auto &[OldBB, NewBB] : + zip(VPBlockUtils::blocksOnly<VPBasicBlock>(OldDeepRPOT), + VPBlockUtils::blocksOnly<VPBasicBlock>(NewDeepRPOT))) { + assert(OldBB->getRecipeList().size() == NewBB->getRecipeList().size() && + "blocks must have the same number of recipes"); + + for (const auto &[OldR, NewR] : zip(*OldBB, *NewBB)) { + assert(OldR.getNumOperands() == NewR.getNumOperands() && + "recipes must have the same number of operands"); + assert(OldR.getNumDefinedValues() == NewR.getNumDefinedValues() && + "recipes must define the same number of operands"); + for (const auto &[OldV, NewV] : + zip(OldR.definedValues(), NewR.definedValues())) + Old2NewVPValues[OldV] = NewV; + } + } + + // Update all operands to use cloned VPValues. + for (VPBasicBlock *NewBB : + VPBlockUtils::blocksOnly<VPBasicBlock>(NewDeepRPOT)) { + for (VPRecipeBase &NewR : *NewBB) + for (unsigned I = 0, E = NewR.getNumOperands(); I != E; ++I) { + VPValue *NewOp = Old2NewVPValues.lookup(NewR.getOperand(I)); + NewR.setOperand(I, NewOp); + } + } +} + +VPlan *VPlan::clone() { + DenseMap<VPBlockBase *, VPBlockBase *> Old2NewVPBlocks; + DenseMap<VPValue *, VPValue *> Old2NewVPValues; + + auto *NewPlan = new VPlan(); + + // Clone live-ins. + SmallVector<VPValue *, 16> NewLiveIns; + for (VPValue *OldLiveIn : VPLiveInsToFree) { + VPValue *NewLiveIn = new VPValue(OldLiveIn->getLiveInIRValue()); + NewPlan->VPLiveInsToFree.push_back(NewLiveIn); + Old2NewVPValues[OldLiveIn] = NewLiveIn; + } + Old2NewVPValues[&VectorTripCount] = &NewPlan->VectorTripCount; + Old2NewVPValues[&VFxUF] = &NewPlan->VFxUF; + if (BackedgeTakenCount) { + NewPlan->BackedgeTakenCount = new VPValue(); + Old2NewVPValues[BackedgeTakenCount] = NewPlan->BackedgeTakenCount; + } + assert(TripCount && "trip count must be set"); + if (TripCount->isLiveIn()) + Old2NewVPValues[TripCount] = new VPValue(TripCount->getLiveInIRValue()); + + // Clone blocks. + cloneCFG(Preheader, Old2NewVPBlocks); + cloneCFG(getEntry(), Old2NewVPBlocks); + + auto *NewPreheader = cast<VPBasicBlock>(Old2NewVPBlocks[Preheader]); + remapOperands(Preheader, NewPreheader, Old2NewVPValues); + auto *NewEntry = cast<VPBasicBlock>(Old2NewVPBlocks[Entry]); + remapOperands(Entry, NewEntry, Old2NewVPValues); + + // Clone live-outs. + for (const auto &[_, LO] : LiveOuts) + NewPlan->addLiveOut(LO->getPhi(), Old2NewVPValues[LO->getOperand(0)]); + + // Initialize fields of cloned VPlan. + NewPlan->Entry = NewEntry; + NewPlan->Preheader = NewPreheader; + NewEntry->setPlan(NewPlan); + NewPreheader->setPlan(NewPlan); + NewPlan->VFs = VFs; + NewPlan->UFs = UFs; + // TODO: Adjust names. + NewPlan->Name = Name; + NewPlan->TripCount = Old2NewVPValues[TripCount]; ---------------- ayalz wrote:
nit: can assert that Old2NewVPValues contains TripCount. https://github.com/llvm/llvm-project/pull/73158 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits