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@21427 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			630 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			630 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===- PRE.cpp - Partial Redundancy Elimination ---------------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file was developed by the LLVM research group and is distributed under
 | |
| // the University of Illinois Open Source License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file implements the well-known Partial Redundancy Elimination
 | |
| // optimization, using an SSA formulation based on e-paths.  See this paper for
 | |
| // more information:
 | |
| //
 | |
| //  E-path_PRE: partial redundancy elimination made easy
 | |
| //  By: Dhananjay M. Dhamdhere   In: ACM SIGPLAN Notices. Vol 37, #8, 2002
 | |
| //    http://doi.acm.org/10.1145/596992.597004
 | |
| //
 | |
| // This file actually implements a sparse version of the algorithm, using SSA
 | |
| // and CFG properties instead of bit-vectors.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "llvm/Pass.h"
 | |
| #include "llvm/Function.h"
 | |
| #include "llvm/Type.h"
 | |
| #include "llvm/Instructions.h"
 | |
| #include "llvm/Support/CFG.h"
 | |
| #include "llvm/Analysis/Dominators.h"
 | |
| #include "llvm/Analysis/PostDominators.h"
 | |
| #include "llvm/Analysis/ValueNumbering.h"
 | |
| #include "llvm/Transforms/Scalar.h"
 | |
| #include "llvm/Support/Debug.h"
 | |
| #include "llvm/ADT/DepthFirstIterator.h"
 | |
| #include "llvm/ADT/PostOrderIterator.h"
 | |
| #include "llvm/ADT/Statistic.h"
 | |
| #include "llvm/ADT/hash_set"
 | |
| #include "llvm/ADT/hash_map"
 | |
| using namespace llvm;
 | |
| 
 | |
| namespace {
 | |
|   Statistic<> NumExprsEliminated("pre", "Number of expressions constantified");
 | |
|   Statistic<> NumRedundant      ("pre", "Number of redundant exprs eliminated");
 | |
|   Statistic<> NumInserted       ("pre", "Number of expressions inserted");
 | |
| 
 | |
|   struct PRE : public FunctionPass {
 | |
|     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
 | |
|       AU.addRequiredID(BreakCriticalEdgesID);  // No critical edges for now!
 | |
|       AU.addRequired<PostDominatorTree>();
 | |
|       AU.addRequired<PostDominanceFrontier>();
 | |
|       AU.addRequired<DominatorSet>();
 | |
|       AU.addRequired<DominatorTree>();
 | |
|       AU.addRequired<DominanceFrontier>();
 | |
|       AU.addRequired<ValueNumbering>();
 | |
|     }
 | |
|     virtual bool runOnFunction(Function &F);
 | |
| 
 | |
|   private:
 | |
|     // Block information - Map basic blocks in a function back and forth to
 | |
|     // unsigned integers.
 | |
|     std::vector<BasicBlock*> BlockMapping;
 | |
|     hash_map<BasicBlock*, unsigned> BlockNumbering;
 | |
| 
 | |
|     // ProcessedExpressions - Keep track of which expressions have already been
 | |
|     // processed.
 | |
|     hash_set<Instruction*> ProcessedExpressions;
 | |
| 
 | |
|     // Provide access to the various analyses used...
 | |
|     DominatorSet      *DS;
 | |
|     DominatorTree     *DT; PostDominatorTree *PDT;
 | |
|     DominanceFrontier *DF; PostDominanceFrontier *PDF;
 | |
|     ValueNumbering    *VN;
 | |
| 
 | |
|     // AvailableBlocks - Contain a mapping of blocks with available expression
 | |
|     // values to the expression value itself.  This can be used as an efficient
 | |
|     // way to find out if the expression is available in the block, and if so,
 | |
|     // which version to use.  This map is only used while processing a single
 | |
|     // expression.
 | |
|     //
 | |
|     typedef hash_map<BasicBlock*, Instruction*> AvailableBlocksTy;
 | |
|     AvailableBlocksTy AvailableBlocks;
 | |
| 
 | |
|     bool ProcessBlock(BasicBlock *BB);
 | |
| 
 | |
|     // Anticipatibility calculation...
 | |
|     void MarkPostDominatingBlocksAnticipatible(PostDominatorTree::Node *N,
 | |
|                                                std::vector<char> &AntBlocks,
 | |
|                                                Instruction *Occurrence);
 | |
|     void CalculateAnticipatiblityForOccurrence(unsigned BlockNo,
 | |
|                                               std::vector<char> &AntBlocks,
 | |
|                                               Instruction *Occurrence);
 | |
|     void CalculateAnticipatibleBlocks(const std::map<unsigned, Instruction*> &D,
 | |
|                                       std::vector<char> &AnticipatibleBlocks);
 | |
| 
 | |
|     // PRE for an expression
 | |
|     void MarkOccurrenceAvailableInAllDominatedBlocks(Instruction *Occurrence,
 | |
|                                                      BasicBlock *StartBlock);
 | |
|     void ReplaceDominatedAvailableOccurrencesWith(Instruction *NewOcc,
 | |
|                                                   DominatorTree::Node *N);
 | |
|     bool ProcessExpression(Instruction *I);
 | |
|   };
 | |
| 
 | |
|   RegisterOpt<PRE> Z("pre", "Partial Redundancy Elimination");
 | |
| }
 | |
| 
 | |
| FunctionPass* llvm::createPREPass() { return new PRE(); }
 | |
| 
 | |
| bool PRE::runOnFunction(Function &F) {
 | |
|   VN  = &getAnalysis<ValueNumbering>();
 | |
|   DS  = &getAnalysis<DominatorSet>();
 | |
|   DT  = &getAnalysis<DominatorTree>();
 | |
|   DF  = &getAnalysis<DominanceFrontier>();
 | |
|   PDT = &getAnalysis<PostDominatorTree>();
 | |
|   PDF = &getAnalysis<PostDominanceFrontier>();
 | |
| 
 | |
|   DEBUG(std::cerr << "\n*** Running PRE on func '" << F.getName() << "'...\n");
 | |
| 
 | |
|   // Number the basic blocks based on a reverse post-order traversal of the CFG
 | |
|   // so that all predecessors of a block (ignoring back edges) are visited
 | |
|   // before a block is visited.
 | |
|   //
 | |
|   BlockMapping.reserve(F.size());
 | |
|   {
 | |
|     ReversePostOrderTraversal<Function*> RPOT(&F);
 | |
|     DEBUG(std::cerr << "Block order: ");
 | |
|     for (ReversePostOrderTraversal<Function*>::rpo_iterator I = RPOT.begin(),
 | |
|            E = RPOT.end(); I != E; ++I) {
 | |
|       // Keep track of mapping...
 | |
|       BasicBlock *BB = *I;
 | |
|       BlockNumbering.insert(std::make_pair(BB, BlockMapping.size()));
 | |
|       BlockMapping.push_back(BB);
 | |
|       DEBUG(std::cerr << BB->getName() << " ");
 | |
|     }
 | |
|     DEBUG(std::cerr << "\n");
 | |
|   }
 | |
| 
 | |
|   // Traverse the current function depth-first in dominator-tree order.  This
 | |
|   // ensures that we see all definitions before their uses (except for PHI
 | |
|   // nodes), allowing us to hoist dependent expressions correctly.
 | |
|   bool Changed = false;
 | |
|   for (unsigned i = 0, e = BlockMapping.size(); i != e; ++i)
 | |
|     Changed |= ProcessBlock(BlockMapping[i]);
 | |
| 
 | |
|   // Free memory
 | |
|   BlockMapping.clear();
 | |
|   BlockNumbering.clear();
 | |
|   ProcessedExpressions.clear();
 | |
|   return Changed;
 | |
| }
 | |
| 
 | |
| 
 | |
| // ProcessBlock - Process any expressions first seen in this block...
 | |
| //
 | |
| bool PRE::ProcessBlock(BasicBlock *BB) {
 | |
|   bool Changed = false;
 | |
| 
 | |
|   // DISABLED: This pass invalidates iterators and then uses them.
 | |
|   return false;
 | |
| 
 | |
|   // PRE expressions first defined in this block...
 | |
|   for (BasicBlock::iterator I = BB->begin(); I != BB->end(); )
 | |
|     if (ProcessExpression(I++))
 | |
|       Changed = true;
 | |
| 
 | |
|   return Changed;
 | |
| }
 | |
| 
 | |
| void PRE::MarkPostDominatingBlocksAnticipatible(PostDominatorTree::Node *N,
 | |
|                                                 std::vector<char> &AntBlocks,
 | |
|                                                 Instruction *Occurrence) {
 | |
|   unsigned BlockNo = BlockNumbering[N->getBlock()];
 | |
| 
 | |
|   if (AntBlocks[BlockNo]) return;  // Already known to be anticipatible??
 | |
| 
 | |
|   // Check to see if any of the operands are defined in this block, if so, the
 | |
|   // entry of this block does not anticipate the expression.  This computes
 | |
|   // "transparency".
 | |
|   for (unsigned i = 0, e = Occurrence->getNumOperands(); i != e; ++i)
 | |
|     if (Instruction *I = dyn_cast<Instruction>(Occurrence->getOperand(i)))
 | |
|       if (I->getParent() == N->getBlock())  // Operand is defined in this block!
 | |
|         return;
 | |
| 
 | |
|   if (isa<LoadInst>(Occurrence))
 | |
|     return;        // FIXME: compute transparency for load instructions using AA
 | |
| 
 | |
|   // Insert block into AntBlocks list...
 | |
|   AntBlocks[BlockNo] = true;
 | |
| 
 | |
|   for (PostDominatorTree::Node::iterator I = N->begin(), E = N->end(); I != E;
 | |
|        ++I)
 | |
|     MarkPostDominatingBlocksAnticipatible(*I, AntBlocks, Occurrence);
 | |
| }
 | |
| 
 | |
| void PRE::CalculateAnticipatiblityForOccurrence(unsigned BlockNo,
 | |
|                                                 std::vector<char> &AntBlocks,
 | |
|                                                 Instruction *Occurrence) {
 | |
|   if (AntBlocks[BlockNo]) return;  // Block already anticipatible!
 | |
| 
 | |
|   BasicBlock *BB = BlockMapping[BlockNo];
 | |
| 
 | |
|   // For each occurrence, mark all post-dominated blocks as anticipatible...
 | |
|   MarkPostDominatingBlocksAnticipatible(PDT->getNode(BB), AntBlocks,
 | |
|                                         Occurrence);
 | |
| 
 | |
|   // Next, mark any blocks in the post-dominance frontier as anticipatible iff
 | |
|   // all successors are anticipatible.
 | |
|   //
 | |
|   PostDominanceFrontier::iterator PDFI = PDF->find(BB);
 | |
|   if (PDFI != DF->end())
 | |
|     for (std::set<BasicBlock*>::iterator DI = PDFI->second.begin();
 | |
|          DI != PDFI->second.end(); ++DI) {
 | |
|       BasicBlock *PDFBlock = *DI;
 | |
|       bool AllSuccessorsAnticipatible = true;
 | |
|       for (succ_iterator SI = succ_begin(PDFBlock), SE = succ_end(PDFBlock);
 | |
|            SI != SE; ++SI)
 | |
|         if (!AntBlocks[BlockNumbering[*SI]]) {
 | |
|           AllSuccessorsAnticipatible = false;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|       if (AllSuccessorsAnticipatible)
 | |
|         CalculateAnticipatiblityForOccurrence(BlockNumbering[PDFBlock],
 | |
|                                               AntBlocks, Occurrence);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| void PRE::CalculateAnticipatibleBlocks(const std::map<unsigned,
 | |
|                                                       Instruction*> &Defs,
 | |
|                                        std::vector<char> &AntBlocks) {
 | |
|   // Initialize to zeros...
 | |
|   AntBlocks.resize(BlockMapping.size());
 | |
| 
 | |
|   // Loop over all of the expressions...
 | |
|   for (std::map<unsigned, Instruction*>::const_iterator I = Defs.begin(),
 | |
|          E = Defs.end(); I != E; ++I)
 | |
|     CalculateAnticipatiblityForOccurrence(I->first, AntBlocks, I->second);
 | |
| }
 | |
| 
 | |
| /// MarkOccurrenceAvailableInAllDominatedBlocks - Add entries to AvailableBlocks
 | |
| /// for all nodes dominated by the occurrence to indicate that it is now the
 | |
| /// available occurrence to use in any of these blocks.
 | |
| ///
 | |
| void PRE::MarkOccurrenceAvailableInAllDominatedBlocks(Instruction *Occurrence,
 | |
|                                                       BasicBlock *BB) {
 | |
|   // FIXME: There are much more efficient ways to get the blocks dominated
 | |
|   // by a block.  Use them.
 | |
|   //
 | |
|   DominatorTree::Node *N = DT->getNode(Occurrence->getParent());
 | |
|   for (df_iterator<DominatorTree::Node*> DI = df_begin(N), E = df_end(N);
 | |
|        DI != E; ++DI)
 | |
|     AvailableBlocks[(*DI)->getBlock()] = Occurrence;
 | |
| }
 | |
| 
 | |
| /// ReplaceDominatedAvailableOccurrencesWith - This loops over the region
 | |
| /// dominated by N, replacing any available expressions with NewOcc.
 | |
| void PRE::ReplaceDominatedAvailableOccurrencesWith(Instruction *NewOcc,
 | |
|                                                    DominatorTree::Node *N) {
 | |
|   BasicBlock *BB = N->getBlock();
 | |
|   Instruction *&ExistingAvailableVal = AvailableBlocks[BB];
 | |
| 
 | |
|   // If there isn't a definition already active in this node, make this the new
 | |
|   // active definition...
 | |
|   if (ExistingAvailableVal == 0) {
 | |
|     ExistingAvailableVal = NewOcc;
 | |
| 
 | |
|     for (DominatorTree::Node::iterator I = N->begin(), E = N->end(); I != E;++I)
 | |
|       ReplaceDominatedAvailableOccurrencesWith(NewOcc, *I);
 | |
|   } else {
 | |
|     // If there is already an active definition in this block, replace it with
 | |
|     // NewOcc, and force it into all dominated blocks.
 | |
|     DEBUG(std::cerr << "  Replacing dominated occ %"
 | |
|           << ExistingAvailableVal->getName() << " with %" << NewOcc->getName()
 | |
|           << "\n");
 | |
|     assert(ExistingAvailableVal != NewOcc && "NewOcc already inserted??");
 | |
|     ExistingAvailableVal->replaceAllUsesWith(NewOcc);
 | |
|     ++NumRedundant;
 | |
| 
 | |
|     assert(ExistingAvailableVal->getParent() == BB &&
 | |
|            "OldOcc not defined in current block?");
 | |
|     BB->getInstList().erase(ExistingAvailableVal);
 | |
| 
 | |
|     // Mark NewOCC as the Available expression in all blocks dominated by BB
 | |
|     for (df_iterator<DominatorTree::Node*> DI = df_begin(N), E = df_end(N);
 | |
|          DI != E; ++DI)
 | |
|       AvailableBlocks[(*DI)->getBlock()] = NewOcc;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /// ProcessExpression - Given an expression (instruction) process the
 | |
| /// instruction to remove any partial redundancies induced by equivalent
 | |
| /// computations.  Note that we only need to PRE each expression once, so we
 | |
| /// keep track of whether an expression has been PRE'd already, and don't PRE an
 | |
| /// expression again.  Expressions may be seen multiple times because process
 | |
| /// the entire equivalence class at once, which may leave expressions later in
 | |
| /// the control path.
 | |
| ///
 | |
| bool PRE::ProcessExpression(Instruction *Expr) {
 | |
|   if (Expr->mayWriteToMemory() || Expr->getType() == Type::VoidTy ||
 | |
|       isa<PHINode>(Expr))
 | |
|     return false;         // Cannot move expression
 | |
|   if (ProcessedExpressions.count(Expr)) return false; // Already processed.
 | |
| 
 | |
|   // Ok, this is the first time we have seen the expression.  Build a set of
 | |
|   // equivalent expressions using SSA def/use information.  We consider
 | |
|   // expressions to be equivalent if they are the same opcode and have
 | |
|   // equivalent operands.  As a special case for SSA, values produced by PHI
 | |
|   // nodes are considered to be equivalent to all of their operands.
 | |
|   //
 | |
|   std::vector<Value*> Values;
 | |
|   VN->getEqualNumberNodes(Expr, Values);
 | |
| 
 | |
| #if 0
 | |
|   // FIXME: This should handle PHI nodes correctly.  To do this, we need to
 | |
|   // consider expressions of the following form equivalent to this set of
 | |
|   // expressions:
 | |
|   //
 | |
|   // If an operand is a PHI node, add any occurrences of the expression with the
 | |
|   // PHI operand replaced with the PHI node operands.  This is only valid if the
 | |
|   // PHI operand occurrences exist in blocks post-dominated by the incoming edge
 | |
|   // of the PHI node.
 | |
| #endif
 | |
| 
 | |
|   // We have to be careful to handle expression definitions which dominated by
 | |
|   // other expressions.  These can be directly eliminated in favor of their
 | |
|   // dominating value.  Keep track of which blocks contain definitions (the key)
 | |
|   // and if a block contains a definition, which instruction it is.
 | |
|   //
 | |
|   std::map<unsigned, Instruction*> Definitions;
 | |
|   Definitions.insert(std::make_pair(BlockNumbering[Expr->getParent()], Expr));
 | |
| 
 | |
|   bool Changed = false;
 | |
| 
 | |
|   // Look at all of the equal values.  If any of the values is not an
 | |
|   // instruction, replace all other expressions immediately with it (it must be
 | |
|   // an argument or a constant or something). Otherwise, convert the list of
 | |
|   // values into a list of expression (instruction) definitions ordering
 | |
|   // according to their dominator tree ordering.
 | |
|   //
 | |
|   Value *NonInstValue = 0;
 | |
|   for (unsigned i = 0, e = Values.size(); i != e; ++i)
 | |
|     if (Instruction *I = dyn_cast<Instruction>(Values[i])) {
 | |
|       Instruction *&BlockInst = Definitions[BlockNumbering[I->getParent()]];
 | |
|       if (BlockInst && BlockInst != I) {    // Eliminate direct redundancy
 | |
|         if (DS->dominates(I, BlockInst)) {  // I dom BlockInst
 | |
|           BlockInst->replaceAllUsesWith(I);
 | |
|           BlockInst->getParent()->getInstList().erase(BlockInst);
 | |
|         } else {                            // BlockInst dom I
 | |
|           I->replaceAllUsesWith(BlockInst);
 | |
|           I->getParent()->getInstList().erase(I);
 | |
|           I = BlockInst;
 | |
|         }
 | |
|         ++NumRedundant;
 | |
|       }
 | |
|       BlockInst = I;
 | |
|     } else {
 | |
|       NonInstValue = Values[i];
 | |
|     }
 | |
| 
 | |
|   std::vector<Value*>().swap(Values);  // Done with the values list
 | |
| 
 | |
|   if (NonInstValue) {
 | |
|     // This is the good, though unlikely, case where we find out that this
 | |
|     // expression is equal to a constant or argument directly.  We can replace
 | |
|     // this and all of the other equivalent instructions with the value
 | |
|     // directly.
 | |
|     //
 | |
|     for (std::map<unsigned, Instruction*>::iterator I = Definitions.begin(),
 | |
|            E = Definitions.end(); I != E; ++I) {
 | |
|       Instruction *Inst = I->second;
 | |
|       // Replace the value with the specified non-instruction value.
 | |
|       Inst->replaceAllUsesWith(NonInstValue);       // Fixup any uses
 | |
|       Inst->getParent()->getInstList().erase(Inst); // Erase the instruction
 | |
|     }
 | |
|     NumExprsEliminated += Definitions.size();
 | |
|     return true;   // Program modified!
 | |
|   }
 | |
| 
 | |
|   // There are no expressions equal to this one.  Exit early.
 | |
|   assert(!Definitions.empty() && "no equal expressions??");
 | |
| #if 0
 | |
|   if (Definitions.size() == 1) {
 | |
|     ProcessedExpressions.insert(Definitions.begin()->second);
 | |
|     return Changed;
 | |
|   }
 | |
| #endif
 | |
|   DEBUG(std::cerr << "\n====--- Expression: " << *Expr);
 | |
|   const Type *ExprType = Expr->getType();
 | |
| 
 | |
|   // AnticipatibleBlocks - Blocks where the current expression is anticipatible.
 | |
|   // This is logically std::vector<bool> but using 'char' for performance.
 | |
|   std::vector<char> AnticipatibleBlocks;
 | |
| 
 | |
|   // Calculate all of the blocks which the current expression is anticipatible.
 | |
|   CalculateAnticipatibleBlocks(Definitions, AnticipatibleBlocks);
 | |
| 
 | |
|   // Print out anticipatible blocks...
 | |
|   DEBUG(std::cerr << "AntBlocks: ";
 | |
|         for (unsigned i = 0, e = AnticipatibleBlocks.size(); i != e; ++i)
 | |
|           if (AnticipatibleBlocks[i])
 | |
|             std::cerr << BlockMapping[i]->getName() <<" ";
 | |
|         std::cerr << "\n";);
 | |
| 
 | |
| 
 | |
| 
 | |
|   // AvailabilityFrontier - Calculates the availability frontier for the current
 | |
|   // expression.  The availability frontier contains the blocks on the dominance
 | |
|   // frontier of the current available expressions, iff they anticipate a
 | |
|   // definition of the expression.
 | |
|   hash_set<unsigned> AvailabilityFrontier;
 | |
| 
 | |
|   Instruction *NonPHIOccurrence = 0;
 | |
| 
 | |
|   while (!Definitions.empty() || !AvailabilityFrontier.empty()) {
 | |
|     if (!Definitions.empty() &&
 | |
|         (AvailabilityFrontier.empty() ||
 | |
|          Definitions.begin()->first < *AvailabilityFrontier.begin())) {
 | |
|       Instruction *Occurrence = Definitions.begin()->second;
 | |
|       BasicBlock *BB = Occurrence->getParent();
 | |
|       Definitions.erase(Definitions.begin());
 | |
| 
 | |
|       DEBUG(std::cerr << "PROCESSING Occurrence: " << *Occurrence);
 | |
| 
 | |
|       // Check to see if there is already an incoming value for this block...
 | |
|       AvailableBlocksTy::iterator LBI = AvailableBlocks.find(BB);
 | |
|       if (LBI != AvailableBlocks.end()) {
 | |
|         // Yes, there is a dominating definition for this block.  Replace this
 | |
|         // occurrence with the incoming value.
 | |
|         if (LBI->second != Occurrence) {
 | |
|           DEBUG(std::cerr << "  replacing with: " << *LBI->second);
 | |
|           Occurrence->replaceAllUsesWith(LBI->second);
 | |
|           BB->getInstList().erase(Occurrence);   // Delete instruction
 | |
|           ++NumRedundant;
 | |
|         }
 | |
|       } else {
 | |
|         ProcessedExpressions.insert(Occurrence);
 | |
|         if (!isa<PHINode>(Occurrence))
 | |
|           NonPHIOccurrence = Occurrence;  // Keep an occurrence of this expr
 | |
| 
 | |
|         // Okay, there is no incoming value for this block, so this expression
 | |
|         // is a new definition that is good for this block and all blocks
 | |
|         // dominated by it.  Add this information to the AvailableBlocks map.
 | |
|         //
 | |
|         MarkOccurrenceAvailableInAllDominatedBlocks(Occurrence, BB);
 | |
| 
 | |
|         // Update the dominance frontier for the definitions so far... if a node
 | |
|         // in the dominator frontier now has all of its predecessors available,
 | |
|         // and the block is in an anticipatible region, we can insert a PHI node
 | |
|         // in that block.
 | |
|         DominanceFrontier::iterator DFI = DF->find(BB);
 | |
|         if (DFI != DF->end()) {
 | |
|           for (std::set<BasicBlock*>::iterator DI = DFI->second.begin();
 | |
|                DI != DFI->second.end(); ++DI) {
 | |
|             BasicBlock *DFBlock = *DI;
 | |
|             unsigned DFBlockID = BlockNumbering[DFBlock];
 | |
|             if (AnticipatibleBlocks[DFBlockID]) {
 | |
|               // Check to see if any of the predecessors of this block on the
 | |
|               // frontier are not available...
 | |
|               bool AnyNotAvailable = false;
 | |
|               for (pred_iterator PI = pred_begin(DFBlock),
 | |
|                      PE = pred_end(DFBlock); PI != PE; ++PI)
 | |
|                 if (!AvailableBlocks.count(*PI)) {
 | |
|                   AnyNotAvailable = true;
 | |
|                   break;
 | |
|                 }
 | |
| 
 | |
|               // If any predecessor blocks are not available, add the node to
 | |
|               // the current expression dominance frontier.
 | |
|               if (AnyNotAvailable) {
 | |
|                 AvailabilityFrontier.insert(DFBlockID);
 | |
|               } else {
 | |
|                 // This block is no longer in the availability frontier, it IS
 | |
|                 // available.
 | |
|                 AvailabilityFrontier.erase(DFBlockID);
 | |
| 
 | |
|                 // If all of the predecessor blocks are available (and the block
 | |
|                 // anticipates a definition along the path to the exit), we need
 | |
|                 // to insert a new PHI node in this block.  This block serves as
 | |
|                 // a new definition for the expression, extending the available
 | |
|                 // region.
 | |
|                 //
 | |
|                 PHINode *PN = new PHINode(ExprType, Expr->getName()+".pre",
 | |
|                                           DFBlock->begin());
 | |
|                 ProcessedExpressions.insert(PN);
 | |
| 
 | |
|                 DEBUG(std::cerr << "  INSERTING PHI on frontier: " << *PN);
 | |
| 
 | |
|                 // Add the incoming blocks for the PHI node
 | |
|                 for (pred_iterator PI = pred_begin(DFBlock),
 | |
|                        PE = pred_end(DFBlock); PI != PE; ++PI)
 | |
|                   if (*PI != DFBlock)
 | |
|                     PN->addIncoming(AvailableBlocks[*PI], *PI);
 | |
|                   else                          // edge from the current block
 | |
|                     PN->addIncoming(PN, DFBlock);
 | |
| 
 | |
|                 Instruction *&BlockOcc = Definitions[DFBlockID];
 | |
|                 if (BlockOcc) {
 | |
|                   DEBUG(std::cerr <<"    PHI superceeds occurrence: "<<
 | |
|                         *BlockOcc);
 | |
|                   BlockOcc->replaceAllUsesWith(PN);
 | |
|                   BlockOcc->getParent()->getInstList().erase(BlockOcc);
 | |
|                   ++NumRedundant;
 | |
|                 }
 | |
|                 BlockOcc = PN;
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|     } else {
 | |
|       // Otherwise we must be looking at a node in the availability frontier!
 | |
|       unsigned AFBlockID = *AvailabilityFrontier.begin();
 | |
|       AvailabilityFrontier.erase(AvailabilityFrontier.begin());
 | |
|       BasicBlock *AFBlock = BlockMapping[AFBlockID];
 | |
| 
 | |
|       // We eliminate the partial redundancy on this frontier by inserting a PHI
 | |
|       // node into this block, merging any incoming available versions into the
 | |
|       // PHI and inserting a new computation into predecessors without an
 | |
|       // incoming value.  Note that we would have to insert the expression on
 | |
|       // the edge if the predecessor didn't anticipate the expression and we
 | |
|       // didn't break critical edges.
 | |
|       //
 | |
|       PHINode *PN = new PHINode(ExprType, Expr->getName()+".PRE",
 | |
|                                 AFBlock->begin());
 | |
|       DEBUG(std::cerr << "INSERTING PHI for PR: " << *PN);
 | |
| 
 | |
|       // If there is a pending occurrence in this block, make sure to replace it
 | |
|       // with the PHI node...
 | |
|       std::map<unsigned, Instruction*>::iterator EDFI =
 | |
|         Definitions.find(AFBlockID);
 | |
|       if (EDFI != Definitions.end()) {
 | |
|         // There is already an occurrence in this block.  Replace it with PN and
 | |
|         // remove it.
 | |
|         Instruction *OldOcc = EDFI->second;
 | |
|         DEBUG(std::cerr << "  Replaces occurrence: " << *OldOcc);
 | |
|         OldOcc->replaceAllUsesWith(PN);
 | |
|         AFBlock->getInstList().erase(OldOcc);
 | |
|         Definitions.erase(EDFI);
 | |
|         ++NumRedundant;
 | |
|       }
 | |
| 
 | |
|       for (pred_iterator PI = pred_begin(AFBlock), PE = pred_end(AFBlock);
 | |
|            PI != PE; ++PI) {
 | |
|         BasicBlock *Pred = *PI;
 | |
|         AvailableBlocksTy::iterator LBI = AvailableBlocks.find(Pred);
 | |
|         if (LBI != AvailableBlocks.end()) {    // If there is a available value
 | |
|           PN->addIncoming(LBI->second, Pred);  // for this pred, use it.
 | |
|         } else {                         // No available value yet...
 | |
|           unsigned PredID = BlockNumbering[Pred];
 | |
| 
 | |
|           // Is the predecessor the same block that we inserted the PHI into?
 | |
|           // (self loop)
 | |
|           if (Pred == AFBlock) {
 | |
|             // Yes, reuse the incoming value here...
 | |
|             PN->addIncoming(PN, Pred);
 | |
|           } else {
 | |
|             // No, we must insert a new computation into this block and add it
 | |
|             // to the definitions list...
 | |
|             assert(NonPHIOccurrence && "No non-phi occurrences seen so far???");
 | |
|             Instruction *New = NonPHIOccurrence->clone();
 | |
|             New->setName(NonPHIOccurrence->getName() + ".PRE-inserted");
 | |
|             ProcessedExpressions.insert(New);
 | |
| 
 | |
|             DEBUG(std::cerr << "  INSERTING OCCURRRENCE: " << *New);
 | |
| 
 | |
|             // Insert it into the bottom of the predecessor, right before the
 | |
|             // terminator instruction...
 | |
|             Pred->getInstList().insert(Pred->getTerminator(), New);
 | |
| 
 | |
|             // Make this block be the available definition for any blocks it
 | |
|             // dominates.  The ONLY case that this can affect more than just the
 | |
|             // block itself is when we are moving a computation to a loop
 | |
|             // header.  In all other cases, because we don't have critical
 | |
|             // edges, the node is guaranteed to only dominate itself.
 | |
|             //
 | |
|             ReplaceDominatedAvailableOccurrencesWith(New, DT->getNode(Pred));
 | |
| 
 | |
|             // Add it as an incoming value on this edge to the PHI node
 | |
|             PN->addIncoming(New, Pred);
 | |
|             NonPHIOccurrence = New;
 | |
|             NumInserted++;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       // Find out if there is already an available value in this block.  If so,
 | |
|       // we need to replace the available value with the PHI node.  This can
 | |
|       // only happen when we just inserted a PHI node on a backedge.
 | |
|       //
 | |
|       AvailableBlocksTy::iterator LBBlockAvailableValIt =
 | |
|         AvailableBlocks.find(AFBlock);
 | |
|       if (LBBlockAvailableValIt != AvailableBlocks.end()) {
 | |
|         if (LBBlockAvailableValIt->second->getParent() == AFBlock) {
 | |
|           Instruction *OldVal = LBBlockAvailableValIt->second;
 | |
|           OldVal->replaceAllUsesWith(PN);        // Use the new PHI node now
 | |
|           ++NumRedundant;
 | |
|           DEBUG(std::cerr << "  PHI replaces available value: %"
 | |
|                 << OldVal->getName() << "\n");
 | |
| 
 | |
|           // Loop over all of the blocks dominated by this PHI node, and change
 | |
|           // the AvailableBlocks entries to be the PHI node instead of the old
 | |
|           // instruction.
 | |
|           MarkOccurrenceAvailableInAllDominatedBlocks(PN, AFBlock);
 | |
| 
 | |
|           AFBlock->getInstList().erase(OldVal);  // Delete old instruction!
 | |
| 
 | |
|           // The resultant PHI node is a new definition of the value!
 | |
|           Definitions.insert(std::make_pair(AFBlockID, PN));
 | |
|         } else {
 | |
|           // If the value is not defined in this block, that means that an
 | |
|           // inserted occurrence in a predecessor is now the live value for the
 | |
|           // region (occurs when hoisting loop invariants, f.e.).  In this case,
 | |
|           // the PHI node should actually just be removed.
 | |
|           assert(PN->use_empty() && "No uses should exist for dead PHI node!");
 | |
|           PN->getParent()->getInstList().erase(PN);
 | |
|         }
 | |
|       } else {
 | |
|         // The resultant PHI node is a new definition of the value!
 | |
|         Definitions.insert(std::make_pair(AFBlockID, PN));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   AvailableBlocks.clear();
 | |
| 
 | |
|   return Changed;
 | |
| }
 | |
| 
 |