diff options
Diffstat (limited to 'llvm/lib/Transforms/Scalar/GVN.cpp')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/GVN.cpp | 52 | 
1 files changed, 39 insertions, 13 deletions
| diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index f350b9bbde5..996996dc55d 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -45,6 +45,7 @@  #include "llvm/Target/TargetLibraryInfo.h"  #include "llvm/Transforms/Utils/BasicBlockUtils.h"  #include "llvm/Transforms/Utils/SSAUpdater.h" +#include <vector>  using namespace llvm;  using namespace PatternMatch; @@ -692,6 +693,7 @@ namespace {      void cleanupGlobalSets();      void verifyRemoved(const Instruction *I) const;      bool splitCriticalEdges(); +    BasicBlock *splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ);      unsigned replaceAllDominatedUsesWith(Value *From, Value *To,                                           const BasicBlockEdge &Root);      bool propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root); @@ -1513,7 +1515,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,    for (unsigned i = 0, e = UnavailableBlocks.size(); i != e; ++i)      FullyAvailableBlocks[UnavailableBlocks[i]] = false; -  SmallVector<std::pair<TerminatorInst*, unsigned>, 4> NeedToSplit; +  SmallVector<BasicBlock *, 4> CriticalEdgePred;    for (pred_iterator PI = pred_begin(LoadBB), E = pred_end(LoadBB);         PI != E; ++PI) {      BasicBlock *Pred = *PI; @@ -1536,20 +1538,14 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,          return false;        } -      unsigned SuccNum = GetSuccessorNumber(Pred, LoadBB); -      NeedToSplit.push_back(std::make_pair(Pred->getTerminator(), SuccNum)); +      CriticalEdgePred.push_back(Pred);      }    } -  if (!NeedToSplit.empty()) { -    toSplit.append(NeedToSplit.begin(), NeedToSplit.end()); -    return false; -  } -    // Decide whether PRE is profitable for this load.    unsigned NumUnavailablePreds = PredLoads.size();    assert(NumUnavailablePreds != 0 && -         "Fully available value should be eliminated above!"); +         "Fully available value should already be eliminated!");    // If this load is unavailable in multiple predecessors, reject it.    // FIXME: If we could restructure the CFG, we could make a common pred with @@ -1558,6 +1554,17 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,    if (NumUnavailablePreds != 1)        return false; +  // Split critical edges, and update the unavailable predecessors accordingly. +  for (SmallVector<BasicBlock *, 4>::iterator I = CriticalEdgePred.begin(),  +         E = CriticalEdgePred.end(); I != E; I++) { +    BasicBlock *OrigPred = *I; +    BasicBlock *NewPred = splitCriticalEdges(OrigPred, LoadBB); +    PredLoads.erase(OrigPred); +    PredLoads[NewPred] = 0; +    DEBUG(dbgs() << "Split critical edge " << OrigPred->getName() << "->" +                 << LoadBB->getName() << '\n'); +  } +    // Check if the load can safely be moved to all the unavailable predecessors.    bool CanDoPRE = true;    SmallVector<Instruction*, 8> NewInsts; @@ -1594,7 +1601,9 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,        if (MD) MD->removeInstruction(I);        I->eraseFromParent();      } -    return false; +    // HINT:Don't revert the edge-splitting as following transformation may  +    // also need to split these critial edges. +    return !CriticalEdgePred.empty();    }    // Okay, we can eliminate this load by inserting a reload in the predecessor @@ -2297,8 +2306,6 @@ bool GVN::runOnFunction(Function& F) {    while (ShouldContinue) {      DEBUG(dbgs() << "GVN iteration: " << Iteration << "\n");      ShouldContinue = iterateOnFunction(F); -    if (splitCriticalEdges()) -      ShouldContinue = true;      Changed |= ShouldContinue;      ++Iteration;    } @@ -2310,6 +2317,7 @@ bool GVN::runOnFunction(Function& F) {        Changed |= PREChanged;      }    } +    // FIXME: Should perform GVN again after PRE does something.  PRE can move    // computations into blocks where they become fully redundant.  Note that    // we can't do this until PRE's critical edge splitting updates memdep. @@ -2543,6 +2551,15 @@ bool GVN::performPRE(Function &F) {    return Changed;  } +/// Split the critical edge connecting the given two blocks, and return +/// the block inserted to the critical edge. +BasicBlock *GVN::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) { +  BasicBlock *BB = SplitCriticalEdge(Pred, Succ, this); +  if (MD) +    MD->invalidateCachedPredecessors(); +  return BB; +} +  /// splitCriticalEdges - Split critical edges found during the previous  /// iteration that may enable further optimization.  bool GVN::splitCriticalEdges() { @@ -2569,9 +2586,18 @@ bool GVN::iterateOnFunction(Function &F) {         RE = RPOT.end(); RI != RE; ++RI)      Changed |= processBlock(*RI);  #else +  // Save the blocks this function have before transformation begins. GVN may +  // split critical edge, and hence may invalidate the RPO/DT iterator. +  // +  std::vector<BasicBlock *> BBVect; +  BBVect.reserve(256);    for (df_iterator<DomTreeNode*> DI = df_begin(DT->getRootNode()),         DE = df_end(DT->getRootNode()); DI != DE; ++DI) -    Changed |= processBlock(DI->getBlock()); +    BBVect.push_back(DI->getBlock()); + +  for (std::vector<BasicBlock *>::iterator I = BBVect.begin(), E = BBVect.end(); +       I != E; I++) +    Changed |= processBlock(*I);  #endif    return Changed; | 

