//===-- SSAUpdaterImpl.h - SSA Updater Implementation -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file provides a template that implements the core algorithm for the // SSAUpdater and MachineSSAUpdater. // //===----------------------------------------------------------------------===// #ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATERIMPL_H #define LLVM_TRANSFORMS_UTILS_SSAUPDATERIMPL_H namespace llvm { template<typename T> class SSAUpdaterTraits; template<typename UpdaterT> class SSAUpdaterImpl { private: UpdaterT *Updater; typedef SSAUpdaterTraits<UpdaterT> Traits; typedef typename Traits::BlkT BlkT; typedef typename Traits::ValT ValT; typedef typename Traits::PhiT PhiT; /// BBInfo - Per-basic block information used internally by SSAUpdaterImpl. /// The predecessors of each block are cached here since pred_iterator is /// slow and we need to iterate over the blocks at least a few times. class BBInfo { public: BlkT *BB; // Back-pointer to the corresponding block. ValT AvailableVal; // Value to use in this block. BBInfo *DefBB; // Block that defines the available value. int BlkNum; // Postorder number. BBInfo *IDom; // Immediate dominator. unsigned NumPreds; // Number of predecessor blocks. BBInfo **Preds; // Array[NumPreds] of predecessor blocks. PhiT *PHITag; // Marker for existing PHIs that match. BBInfo(BlkT *ThisBB, ValT V) : BB(ThisBB), AvailableVal(V), DefBB(V ? this : 0), BlkNum(0), IDom(0), NumPreds(0), Preds(0), PHITag(0) { } }; typedef DenseMap<BlkT*, ValT> AvailableValsTy; AvailableValsTy *AvailableVals; SmallVectorImpl<PhiT*> *InsertedPHIs; typedef SmallVectorImpl<BBInfo*> BlockListTy; typedef DenseMap<BlkT*, BBInfo*> BBMapTy; BBMapTy BBMap; BumpPtrAllocator Allocator; public: explicit SSAUpdaterImpl(UpdaterT *U, AvailableValsTy *A, SmallVectorImpl<PhiT*> *Ins) : Updater(U), AvailableVals(A), InsertedPHIs(Ins) { } /// GetValue - Check to see if AvailableVals has an entry for the specified /// BB and if so, return it. If not, construct SSA form by first /// calculating the required placement of PHIs and then inserting new PHIs /// where needed. ValT GetValue(BlkT *BB) { SmallVector<BBInfo*, 100> BlockList; BBInfo *PseudoEntry = BuildBlockList(BB, &BlockList); // Special case: bail out if BB is unreachable. if (BlockList.size() == 0) { ValT V = Traits::GetUndefVal(BB, Updater); (*AvailableVals)[BB] = V; return V; } FindDominators(&BlockList, PseudoEntry); FindPHIPlacement(&BlockList); FindAvailableVals(&BlockList); return BBMap[BB]->DefBB->AvailableVal; } /// BuildBlockList - Starting from the specified basic block, traverse back /// through its predecessors until reaching blocks with known values. /// Create BBInfo structures for the blocks and append them to the block /// list. BBInfo *BuildBlockList(BlkT *BB, BlockListTy *BlockList) { SmallVector<BBInfo*, 10> RootList; SmallVector<BBInfo*, 64> WorkList; BBInfo *Info = new (Allocator) BBInfo(BB, 0); BBMap[BB] = Info; WorkList.push_back(Info); // Search backward from BB, creating BBInfos along the way and stopping // when reaching blocks that define the value. Record those defining // blocks on the RootList. SmallVector<BlkT*, 10> Preds; while (!WorkList.empty()) { Info = WorkList.pop_back_val(); Preds.clear(); Traits::FindPredecessorBlocks(Info->BB, &Preds); Info->NumPreds = Preds.size(); if (Info->NumPreds == 0) Info->Preds = 0; else Info->Preds = static_cast<BBInfo**> (Allocator.Allocate(Info->NumPreds * sizeof(BBInfo*), AlignOf<BBInfo*>::Alignment)); for (unsigned p = 0; p != Info->NumPreds; ++p) { BlkT *Pred = Preds[p]; // Check if BBMap already has a BBInfo for the predecessor block. typename BBMapTy::value_type &BBMapBucket = BBMap.FindAndConstruct(Pred); if (BBMapBucket.second) { Info->Preds[p] = BBMapBucket.second; continue; } // Create a new BBInfo for the predecessor. ValT PredVal = AvailableVals->lookup(Pred); BBInfo *PredInfo = new (Allocator) BBInfo(Pred, PredVal); BBMapBucket.second = PredInfo; Info->Preds[p] = PredInfo; if (PredInfo->AvailableVal) { RootList.push_back(PredInfo); continue; } WorkList.push_back(PredInfo); } } // Now that we know what blocks are backwards-reachable from the starting // block, do a forward depth-first traversal to assign postorder numbers // to those blocks. BBInfo *PseudoEntry = new (Allocator) BBInfo(0, 0); unsigned BlkNum = 1; // Initialize the worklist with the roots from the backward traversal. while (!RootList.empty()) { Info = RootList.pop_back_val(); Info->IDom = PseudoEntry; Info->BlkNum = -1; WorkList.push_back(Info); } while (!WorkList.empty()) { Info = WorkList.back(); if (Info->BlkNum == -2) { // All the successors have been handled; assign the postorder number. Info->BlkNum = BlkNum++; // If not a root, put it on the BlockList. if (!Info->AvailableVal) BlockList->push_back(Info); WorkList.pop_back(); continue; } // Leave this entry on the worklist, but set its BlkNum to mark that its // successors have been put on the worklist. When it returns to the top // the list, after handling its successors, it will be assigned a // number. Info->BlkNum = -2; // Add unvisited successors to the work list. for (typename Traits::BlkSucc_iterator SI = Traits::BlkSucc_begin(Info->BB), E = Traits::BlkSucc_end(Info->BB); SI != E; ++SI) { BBInfo *SuccInfo = BBMap[*SI]; if (!SuccInfo || SuccInfo->BlkNum) continue; SuccInfo->BlkNum = -1; WorkList.push_back(SuccInfo); } } PseudoEntry->BlkNum = BlkNum; return PseudoEntry; } /// IntersectDominators - This is the dataflow lattice "meet" operation for /// finding dominators. Given two basic blocks, it walks up the dominator /// tree until it finds a common dominator of both. It uses the postorder /// number of the blocks to determine how to do that. BBInfo *IntersectDominators(BBInfo *Blk1, BBInfo *Blk2) { while (Blk1 != Blk2) { while (Blk1->BlkNum < Blk2->BlkNum) { Blk1 = Blk1->IDom; if (!Blk1) return Blk2; } while (Blk2->BlkNum < Blk1->BlkNum) { Blk2 = Blk2->IDom; if (!Blk2) return Blk1; } } return Blk1; } /// FindDominators - Calculate the dominator tree for the subset of the CFG /// corresponding to the basic blocks on the BlockList. This uses the /// algorithm from: "A Simple, Fast Dominance Algorithm" by Cooper, Harvey /// and Kennedy, published in Software--Practice and Experience, 2001, /// 4:1-10. Because the CFG subset does not include any edges leading into /// blocks that define the value, the results are not the usual dominator /// tree. The CFG subset has a single pseudo-entry node with edges to a set /// of root nodes for blocks that define the value. The dominators for this /// subset CFG are not the standard dominators but they are adequate for /// placing PHIs within the subset CFG. void FindDominators(BlockListTy *BlockList, BBInfo *PseudoEntry) { bool Changed; do { Changed = false; // Iterate over the list in reverse order, i.e., forward on CFG edges. for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(), E = BlockList->rend(); I != E; ++I) { BBInfo *Info = *I; BBInfo *NewIDom = 0; // Iterate through the block's predecessors. for (unsigned p = 0; p != Info->NumPreds; ++p) { BBInfo *Pred = Info->Preds[p]; // Treat an unreachable predecessor as a definition with 'undef'. if (Pred->BlkNum == 0) { Pred->AvailableVal = Traits::GetUndefVal(Pred->BB, Updater); (*AvailableVals)[Pred->BB] = Pred->AvailableVal; Pred->DefBB = Pred; Pred->BlkNum = PseudoEntry->BlkNum; PseudoEntry->BlkNum++; } if (!NewIDom) NewIDom = Pred; else NewIDom = IntersectDominators(NewIDom, Pred); } // Check if the IDom value has changed. if (NewIDom && NewIDom != Info->IDom) { Info->IDom = NewIDom; Changed = true; } } } while (Changed); } /// IsDefInDomFrontier - Search up the dominator tree from Pred to IDom for /// any blocks containing definitions of the value. If one is found, then /// the successor of Pred is in the dominance frontier for the definition, /// and this function returns true. bool IsDefInDomFrontier(const BBInfo *Pred, const BBInfo *IDom) { for (; Pred != IDom; Pred = Pred->IDom) { if (Pred->DefBB == Pred) return true; } return false; } /// FindPHIPlacement - PHIs are needed in the iterated dominance frontiers /// of the known definitions. Iteratively add PHIs in the dom frontiers /// until nothing changes. Along the way, keep track of the nearest /// dominating definitions for non-PHI blocks. void FindPHIPlacement(BlockListTy *BlockList) { bool Changed; do { Changed = false; // Iterate over the list in reverse order, i.e., forward on CFG edges. for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(), E = BlockList->rend(); I != E; ++I) { BBInfo *Info = *I; // If this block already needs a PHI, there is nothing to do here. if (Info->DefBB == Info) continue; // Default to use the same def as the immediate dominator. BBInfo *NewDefBB = Info->IDom->DefBB; for (unsigned p = 0; p != Info->NumPreds; ++p) { if (IsDefInDomFrontier(Info->Preds[p], Info->IDom)) { // Need a PHI here. NewDefBB = Info; break; } } // Check if anything changed. if (NewDefBB != Info->DefBB) { Info->DefBB = NewDefBB; Changed = true; } } } while (Changed); } /// FindAvailableVal - If this block requires a PHI, first check if an /// existing PHI matches the PHI placement and reaching definitions computed /// earlier, and if not, create a new PHI. Visit all the block's /// predecessors to calculate the available value for each one and fill in /// the incoming values for a new PHI. void FindAvailableVals(BlockListTy *BlockList) { // Go through the worklist in forward order (i.e., backward through the CFG) // and check if existing PHIs can be used. If not, create empty PHIs where // they are needed. for (typename BlockListTy::iterator I = BlockList->begin(), E = BlockList->end(); I != E; ++I) { BBInfo *Info = *I; // Check if there needs to be a PHI in BB. if (Info->DefBB != Info) continue; // Look for an existing PHI. FindExistingPHI(Info->BB, BlockList); if (Info->AvailableVal) continue; ValT PHI = Traits::CreateEmptyPHI(Info->BB, Info->NumPreds, Updater); Info->AvailableVal = PHI; (*AvailableVals)[Info->BB] = PHI; } // Now go back through the worklist in reverse order to fill in the // arguments for any new PHIs added in the forward traversal. for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(), E = BlockList->rend(); I != E; ++I) { BBInfo *Info = *I; if (Info->DefBB != Info) { // Record the available value at join nodes to speed up subsequent // uses of this SSAUpdater for the same value. if (Info->NumPreds > 1) (*AvailableVals)[Info->BB] = Info->DefBB->AvailableVal; continue; } // Check if this block contains a newly added PHI. PhiT *PHI = Traits::ValueIsNewPHI(Info->AvailableVal, Updater); if (!PHI) continue; // Iterate through the block's predecessors. for (unsigned p = 0; p != Info->NumPreds; ++p) { BBInfo *PredInfo = Info->Preds[p]; BlkT *Pred = PredInfo->BB; // Skip to the nearest preceding definition. if (PredInfo->DefBB != PredInfo) PredInfo = PredInfo->DefBB; Traits::AddPHIOperand(PHI, PredInfo->AvailableVal, Pred); } DEBUG(dbgs() << " Inserted PHI: " << *PHI << "\n"); // If the client wants to know about all new instructions, tell it. if (InsertedPHIs) InsertedPHIs->push_back(PHI); } } /// FindExistingPHI - Look through the PHI nodes in a block to see if any of /// them match what is needed. void FindExistingPHI(BlkT *BB, BlockListTy *BlockList) { for (typename BlkT::iterator BBI = BB->begin(), BBE = BB->end(); BBI != BBE; ++BBI) { PhiT *SomePHI = Traits::InstrIsPHI(BBI); if (!SomePHI) break; if (CheckIfPHIMatches(SomePHI)) { RecordMatchingPHI(SomePHI); break; } // Match failed: clear all the PHITag values. for (typename BlockListTy::iterator I = BlockList->begin(), E = BlockList->end(); I != E; ++I) (*I)->PHITag = 0; } } /// CheckIfPHIMatches - Check if a PHI node matches the placement and values /// in the BBMap. bool CheckIfPHIMatches(PhiT *PHI) { SmallVector<PhiT*, 20> WorkList; WorkList.push_back(PHI); // Mark that the block containing this PHI has been visited. BBMap[PHI->getParent()]->PHITag = PHI; while (!WorkList.empty()) { PHI = WorkList.pop_back_val(); // Iterate through the PHI's incoming values. for (typename Traits::PHI_iterator I = Traits::PHI_begin(PHI), E = Traits::PHI_end(PHI); I != E; ++I) { ValT IncomingVal = I.getIncomingValue(); BBInfo *PredInfo = BBMap[I.getIncomingBlock()]; // Skip to the nearest preceding definition. if (PredInfo->DefBB != PredInfo) PredInfo = PredInfo->DefBB; // Check if it matches the expected value. if (PredInfo->AvailableVal) { if (IncomingVal == PredInfo->AvailableVal) continue; return false; } // Check if the value is a PHI in the correct block. PhiT *IncomingPHIVal = Traits::ValueIsPHI(IncomingVal, Updater); if (!IncomingPHIVal || IncomingPHIVal->getParent() != PredInfo->BB) return false; // If this block has already been visited, check if this PHI matches. if (PredInfo->PHITag) { if (IncomingPHIVal == PredInfo->PHITag) continue; return false; } PredInfo->PHITag = IncomingPHIVal; WorkList.push_back(IncomingPHIVal); } } return true; } /// RecordMatchingPHI - For a PHI node that matches, record it and its input /// PHIs in both the BBMap and the AvailableVals mapping. void RecordMatchingPHI(PhiT *PHI) { SmallVector<PhiT*, 20> WorkList; WorkList.push_back(PHI); // Record this PHI. BlkT *BB = PHI->getParent(); ValT PHIVal = Traits::GetPHIValue(PHI); (*AvailableVals)[BB] = PHIVal; BBMap[BB]->AvailableVal = PHIVal; while (!WorkList.empty()) { PHI = WorkList.pop_back_val(); // Iterate through the PHI's incoming values. for (typename Traits::PHI_iterator I = Traits::PHI_begin(PHI), E = Traits::PHI_end(PHI); I != E; ++I) { ValT IncomingVal = I.getIncomingValue(); PhiT *IncomingPHI = Traits::ValueIsPHI(IncomingVal, Updater); if (!IncomingPHI) continue; BB = IncomingPHI->getParent(); BBInfo *Info = BBMap[BB]; if (!Info || Info->AvailableVal) continue; // Record the PHI and add it to the worklist. (*AvailableVals)[BB] = IncomingVal; Info->AvailableVal = IncomingVal; WorkList.push_back(IncomingPHI); } } } }; } // End llvm namespace #endif