/// Update the dominator tree after if-conversion erased some blocks. void AArch64ConditionalCompares::updateDomTree( ArrayRef<MachineBasicBlock *> Removed) { // convert() removes CmpBB which was previously dominated by Head. // CmpBB children should be transferred to Head. MachineDomTreeNode *HeadNode = DomTree->getNode(CmpConv.Head); for (unsigned i = 0, e = Removed.size(); i != e; ++i) { MachineDomTreeNode *Node = DomTree->getNode(Removed[i]); assert(Node != HeadNode && "Cannot erase the head node"); assert(Node->getIDom() == HeadNode && "CmpBB should be dominated by Head"); while (Node->getNumChildren()) DomTree->changeImmediateDominator(Node->getChildren().back(), HeadNode); DomTree->eraseNode(Removed[i]); } }
/// computeDFS - Computes the DFS-in and DFS-out numbers of the dominator tree /// of the given MachineFunction. These numbers are then used in other parts /// of the PHI elimination process. void StrongPHIElimination::computeDFS(MachineFunction& MF) { SmallPtrSet<MachineDomTreeNode*, 8> frontier; SmallPtrSet<MachineDomTreeNode*, 8> visited; unsigned time = 0; MachineDominatorTree& DT = getAnalysis<MachineDominatorTree>(); MachineDomTreeNode* node = DT.getRootNode(); std::vector<MachineDomTreeNode*> worklist; worklist.push_back(node); while (!worklist.empty()) { MachineDomTreeNode* currNode = worklist.back(); if (!frontier.count(currNode)) { frontier.insert(currNode); ++time; preorder.insert(std::make_pair(currNode->getBlock(), time)); } bool inserted = false; for (MachineDomTreeNode::iterator I = currNode->begin(), E = currNode->end(); I != E; ++I) if (!frontier.count(*I) && !visited.count(*I)) { worklist.push_back(*I); inserted = true; break; } if (!inserted) { frontier.erase(currNode); visited.insert(currNode); maxpreorder.insert(std::make_pair(currNode->getBlock(), time)); worklist.pop_back(); } } }
bool MachineCSE::PerformCSE(MachineDomTreeNode *Node) { SmallVector<MachineDomTreeNode*, 32> Scopes; SmallVector<MachineDomTreeNode*, 8> WorkList; DenseMap<MachineDomTreeNode*, MachineDomTreeNode*> ParentMap; DenseMap<MachineDomTreeNode*, unsigned> OpenChildren; CurrVN = 0; // Perform a DFS walk to determine the order of visit. WorkList.push_back(Node); do { Node = WorkList.pop_back_val(); Scopes.push_back(Node); const std::vector<MachineDomTreeNode*> &Children = Node->getChildren(); unsigned NumChildren = Children.size(); OpenChildren[Node] = NumChildren; for (unsigned i = 0; i != NumChildren; ++i) { MachineDomTreeNode *Child = Children[i]; ParentMap[Child] = Node; WorkList.push_back(Child); } } while (!WorkList.empty()); // Now perform CSE. bool Changed = false; for (unsigned i = 0, e = Scopes.size(); i != e; ++i) { MachineDomTreeNode *Node = Scopes[i]; MachineBasicBlock *MBB = Node->getBlock(); EnterScope(MBB); Changed |= ProcessBlock(MBB); // If it's a leaf node, it's done. Traverse upwards to pop ancestors. ExitScopeIfDone(Node, OpenChildren, ParentMap); } return Changed; }
// This is essentially the same iterative algorithm that SSAUpdater uses, // except we already have a dominator tree, so we don't have to recompute it. void LiveRangeCalc::updateSSA() { assert(Indexes && "Missing SlotIndexes"); assert(DomTree && "Missing dominator tree"); // Interate until convergence. unsigned Changes; do { Changes = 0; // Propagate live-out values down the dominator tree, inserting phi-defs // when necessary. for (SmallVectorImpl<LiveInBlock>::iterator I = LiveIn.begin(), E = LiveIn.end(); I != E; ++I) { MachineDomTreeNode *Node = I->DomNode; // Skip block if the live-in value has already been determined. if (!Node) continue; MachineBasicBlock *MBB = Node->getBlock(); MachineDomTreeNode *IDom = Node->getIDom(); LiveOutPair IDomValue; // We need a live-in value to a block with no immediate dominator? // This is probably an unreachable block that has survived somehow. bool needPHI = !IDom || !Seen.test(IDom->getBlock()->getNumber()); // IDom dominates all of our predecessors, but it may not be their // immediate dominator. Check if any of them have live-out values that are // properly dominated by IDom. If so, we need a phi-def here. if (!needPHI) { IDomValue = LiveOut[IDom->getBlock()]; // Cache the DomTree node that defined the value. if (IDomValue.first && !IDomValue.second) LiveOut[IDom->getBlock()].second = IDomValue.second = DomTree->getNode(Indexes->getMBBFromIndex(IDomValue.first->def)); for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), PE = MBB->pred_end(); PI != PE; ++PI) { LiveOutPair &Value = LiveOut[*PI]; if (!Value.first || Value.first == IDomValue.first) continue; // Cache the DomTree node that defined the value. if (!Value.second) Value.second = DomTree->getNode(Indexes->getMBBFromIndex(Value.first->def)); // This predecessor is carrying something other than IDomValue. // It could be because IDomValue hasn't propagated yet, or it could be // because MBB is in the dominance frontier of that value. if (DomTree->dominates(IDom, Value.second)) { needPHI = true; break; } } } // The value may be live-through even if Kill is set, as can happen when // we are called from extendRange. In that case LiveOutSeen is true, and // LiveOut indicates a foreign or missing value. LiveOutPair &LOP = LiveOut[MBB]; // Create a phi-def if required. if (needPHI) { ++Changes; assert(Alloc && "Need VNInfo allocator to create PHI-defs"); SlotIndex Start, End; tie(Start, End) = Indexes->getMBBRange(MBB); VNInfo *VNI = I->LI->getNextValue(Start, *Alloc); I->Value = VNI; // This block is done, we know the final value. I->DomNode = 0; // Add liveness since updateLiveIns now skips this node. if (I->Kill.isValid()) I->LI->addRange(LiveRange(Start, I->Kill, VNI)); else { I->LI->addRange(LiveRange(Start, End, VNI)); LOP = LiveOutPair(VNI, Node); } } else if (IDomValue.first) { // No phi-def here. Remember incoming value. I->Value = IDomValue.first; // If the IDomValue is killed in the block, don't propagate through. if (I->Kill.isValid()) continue; // Propagate IDomValue if it isn't killed: // MBB is live-out and doesn't define its own value. if (LOP.first == IDomValue.first) continue; ++Changes; LOP = IDomValue; } } } while (Changes); }
/// Walk the specified loop in the CFG (defined by all blocks dominated by the /// specified header block, and that are in the current loop) in depth first /// order w.r.t the DominatorTree. This allows us to visit definitions before /// uses, allowing us to hoist a loop body in one pass without iteration. /// void MachineLICM::HoistOutOfLoop(MachineDomTreeNode *HeaderN) { MachineBasicBlock *Preheader = getCurPreheader(); if (!Preheader) return; SmallVector<MachineDomTreeNode*, 32> Scopes; SmallVector<MachineDomTreeNode*, 8> WorkList; DenseMap<MachineDomTreeNode*, MachineDomTreeNode*> ParentMap; DenseMap<MachineDomTreeNode*, unsigned> OpenChildren; // Perform a DFS walk to determine the order of visit. WorkList.push_back(HeaderN); while (!WorkList.empty()) { MachineDomTreeNode *Node = WorkList.pop_back_val(); assert(Node && "Null dominator tree node?"); MachineBasicBlock *BB = Node->getBlock(); // If the header of the loop containing this basic block is a landing pad, // then don't try to hoist instructions out of this loop. const MachineLoop *ML = MLI->getLoopFor(BB); if (ML && ML->getHeader()->isEHPad()) continue; // If this subregion is not in the top level loop at all, exit. if (!CurLoop->contains(BB)) continue; Scopes.push_back(Node); const std::vector<MachineDomTreeNode*> &Children = Node->getChildren(); unsigned NumChildren = Children.size(); // Don't hoist things out of a large switch statement. This often causes // code to be hoisted that wasn't going to be executed, and increases // register pressure in a situation where it's likely to matter. if (BB->succ_size() >= 25) NumChildren = 0; OpenChildren[Node] = NumChildren; // Add children in reverse order as then the next popped worklist node is // the first child of this node. This means we ultimately traverse the // DOM tree in exactly the same order as if we'd recursed. for (int i = (int)NumChildren-1; i >= 0; --i) { MachineDomTreeNode *Child = Children[i]; ParentMap[Child] = Node; WorkList.push_back(Child); } } if (Scopes.size() == 0) return; // Compute registers which are livein into the loop headers. RegSeen.clear(); BackTrace.clear(); InitRegPressure(Preheader); // Now perform LICM. for (MachineDomTreeNode *Node : Scopes) { MachineBasicBlock *MBB = Node->getBlock(); EnterScope(MBB); // Process the block SpeculationState = SpeculateUnknown; for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end(); MII != E; ) { MachineBasicBlock::iterator NextMII = MII; ++NextMII; MachineInstr *MI = &*MII; if (!Hoist(MI, Preheader)) UpdateRegPressure(MI); MII = NextMII; } // If it's a leaf node, it's done. Traverse upwards to pop ancestors. ExitScopeIfDone(Node, OpenChildren, ParentMap); } }
// This is essentially the same iterative algorithm that SSAUpdater uses, // except we already have a dominator tree, so we don't have to recompute it. void LiveRangeCalc::updateSSA() { assert(Indexes && "Missing SlotIndexes"); assert(DomTree && "Missing dominator tree"); // Interate until convergence. bool Changed; do { Changed = false; // Propagate live-out values down the dominator tree, inserting phi-defs // when necessary. for (LiveInBlock &I : LiveIn) { MachineDomTreeNode *Node = I.DomNode; // Skip block if the live-in value has already been determined. if (!Node) continue; MachineBasicBlock *MBB = Node->getBlock(); MachineDomTreeNode *IDom = Node->getIDom(); LiveOutPair IDomValue; // We need a live-in value to a block with no immediate dominator? // This is probably an unreachable block that has survived somehow. bool needPHI = !IDom || !Seen.test(IDom->getBlock()->getNumber()); // IDom dominates all of our predecessors, but it may not be their // immediate dominator. Check if any of them have live-out values that are // properly dominated by IDom. If so, we need a phi-def here. if (!needPHI) { IDomValue = Map[IDom->getBlock()]; // Cache the DomTree node that defined the value. if (IDomValue.first && IDomValue.first != &UndefVNI && !IDomValue.second) { Map[IDom->getBlock()].second = IDomValue.second = DomTree->getNode(Indexes->getMBBFromIndex(IDomValue.first->def)); } for (MachineBasicBlock *Pred : MBB->predecessors()) { LiveOutPair &Value = Map[Pred]; if (!Value.first || Value.first == IDomValue.first) continue; if (Value.first == &UndefVNI) { needPHI = true; break; } // Cache the DomTree node that defined the value. if (!Value.second) Value.second = DomTree->getNode(Indexes->getMBBFromIndex(Value.first->def)); // This predecessor is carrying something other than IDomValue. // It could be because IDomValue hasn't propagated yet, or it could be // because MBB is in the dominance frontier of that value. if (DomTree->dominates(IDom, Value.second)) { needPHI = true; break; } } } // The value may be live-through even if Kill is set, as can happen when // we are called from extendRange. In that case LiveOutSeen is true, and // LiveOut indicates a foreign or missing value. LiveOutPair &LOP = Map[MBB]; // Create a phi-def if required. if (needPHI) { Changed = true; assert(Alloc && "Need VNInfo allocator to create PHI-defs"); SlotIndex Start, End; std::tie(Start, End) = Indexes->getMBBRange(MBB); LiveRange &LR = I.LR; VNInfo *VNI = LR.getNextValue(Start, *Alloc); I.Value = VNI; // This block is done, we know the final value. I.DomNode = nullptr; // Add liveness since updateFromLiveIns now skips this node. if (I.Kill.isValid()) { if (VNI) LR.addSegment(LiveInterval::Segment(Start, I.Kill, VNI)); } else { if (VNI) LR.addSegment(LiveInterval::Segment(Start, End, VNI)); LOP = LiveOutPair(VNI, Node); } } else if (IDomValue.first && IDomValue.first != &UndefVNI) { // No phi-def here. Remember incoming value. I.Value = IDomValue.first; // If the IDomValue is killed in the block, don't propagate through. if (I.Kill.isValid()) continue; // Propagate IDomValue if it isn't killed: // MBB is live-out and doesn't define its own value. if (LOP.first == IDomValue.first) continue; Changed = true; LOP = IDomValue; } } } while (Changed); }