mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@144536 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			478 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			478 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===-- 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
 | |
| 
 | |
| #include "llvm/ADT/DenseMap.h"
 | |
| #include "llvm/ADT/SmallVector.h"
 | |
| #include "llvm/Support/Allocator.h"
 | |
| #include "llvm/Support/Debug.h"
 | |
| #include "llvm/Support/ValueHandle.h"
 | |
| 
 | |
| namespace llvm {
 | |
| 
 | |
| class CastInst;
 | |
| class PHINode;
 | |
| 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
 |