+ /// \brief Helper structure used to hold all the basic blocks
+ /// involved in the split of a critical edge.
+ struct CriticalEdge {
+ MachineBasicBlock *FromBB;
+ MachineBasicBlock *ToBB;
+ MachineBasicBlock *NewBB;
+ CriticalEdge(MachineBasicBlock *FromBB, MachineBasicBlock *ToBB,
+ MachineBasicBlock *NewBB)
+ : FromBB(FromBB), ToBB(ToBB), NewBB(NewBB) {}
+ };
+
+ /// \brief Pile up all the critical edges to be split.
+ /// The splitting of a critical edge is local and thus, it is possible
+ /// to apply several of those changes at the same time.
+ mutable SmallVector<CriticalEdge, 32> CriticalEdgesToSplit;
+ /// \brief Remember all the basic blocks that are inserted during
+ /// edge splitting.
+ /// Invariant: NewBBs == all the basic blocks contained in the NewBB
+ /// field of all the elements of CriticalEdgesToSplit.
+ /// I.e., forall elt in CriticalEdgesToSplit, it exists BB in NewBBs
+ /// such as BB == elt.NewBB.
+ mutable SmallSet<MachineBasicBlock *, 32> NewBBs;
+
+ /// \brief Apply all the recorded critical edges to the DT.
+ /// This updates the underlying DT information in a way that uses
+ /// the fast query path of DT as much as possible.
+ ///
+ /// \post CriticalEdgesToSplit.empty().
+ void applySplitCriticalEdges() const {
+ // Bail out early if there is nothing to do.
+ if (CriticalEdgesToSplit.empty())
+ return;
+
+ // For each element in CriticalEdgesToSplit, remember whether or
+ // not element is the new immediate domminator of its successor.
+ // The mapping is done by index, i.e., the information for the ith
+ // element of CriticalEdgesToSplit is the ith element of IsNewIDom.
+ SmallVector<bool, 32> IsNewIDom;
+ IsNewIDom.resize(CriticalEdgesToSplit.size());
+ size_t Idx = 0;
+
+ // Collect all the dominance properties info, before invalidating
+ // the underlying DT.
+ for (CriticalEdge &Edge : CriticalEdgesToSplit) {
+ // Update dominator information.
+ MachineBasicBlock *Succ = Edge.ToBB;
+ MachineDomTreeNode *SucccDTNode = DT->getNode(Succ);
+
+ IsNewIDom[Idx] = true;
+ for (MachineBasicBlock *PredBB : Succ->predecessors()) {
+ if (PredBB == Edge.NewBB)
+ continue;
+ // If we are in this situation:
+ // FromBB1 FromBB2
+ // + +
+ // + + + +
+ // + + + +
+ // ... Split1 Split2 ...
+ // + +
+ // + +
+ // +
+ // Succ
+ // Instead of checking the domiance property with Split2, we
+ // check it with FromBB2 since Split2 is still unknown of the
+ // underlying DT structure.
+ if (NewBBs.count(PredBB)) {
+ assert(PredBB->pred_size() == 1 && "A basic block resulting from a "
+ "critical edge split has more "
+ "than one predecessor!");
+ PredBB = *PredBB->pred_begin();
+ }
+ if (!DT->dominates(SucccDTNode, DT->getNode(PredBB))) {
+ IsNewIDom[Idx] = false;
+ break;
+ }
+ }
+ ++Idx;
+ }
+
+ // Now, update DT with the collected dominance properties info.
+ Idx = 0;
+ for (CriticalEdge &Edge : CriticalEdgesToSplit) {
+ // We know FromBB dominates NewBB.
+ MachineDomTreeNode *NewDTNode = DT->addNewBlock(Edge.NewBB, Edge.FromBB);
+ MachineDomTreeNode *SucccDTNode = DT->getNode(Edge.ToBB);
+
+ // If all the other predecessors of "Succ" are dominated by "Succ" itself
+ // then the new block is the new immediate dominator of "Succ". Otherwise,
+ // the new block doesn't dominate anything.
+ if (IsNewIDom[Idx])
+ DT->changeImmediateDominator(SucccDTNode, NewDTNode);
+ ++Idx;
+ }
+ NewBBs.clear();
+ CriticalEdgesToSplit.clear();
+ }
+