This pass has never worked correctly. Remove.
authorChris Lattner <sabre@nondot.org>
Mon, 16 Jan 2006 01:06:00 +0000 (01:06 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 16 Jan 2006 01:06:00 +0000 (01:06 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25349 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/PRE.cpp [deleted file]

diff --git a/lib/Transforms/Scalar/PRE.cpp b/lib/Transforms/Scalar/PRE.cpp
deleted file mode 100644 (file)
index 1ee923a..0000000
+++ /dev/null
@@ -1,629 +0,0 @@
-//===- 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;
-}
-