+++ /dev/null
-//===- 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;
-}
-