diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2013-04-08 18:41:23 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2013-04-08 18:41:23 +0000 | 
| commit | 4a16efa3e43e35f0cc9efe3a67f620f0017c3d36 (patch) | |
| tree | 06099edc18d30894081a822b756f117cbe0b8207 /lib/Transforms/Utils/Local.cpp | |
| parent | 482e7bddf617ae804dc47133cb07eb4aa81e45de (diff) | |
Diffstat (limited to 'lib/Transforms/Utils/Local.cpp')
| -rw-r--r-- | lib/Transforms/Utils/Local.cpp | 101 | 
1 files changed, 86 insertions, 15 deletions
| diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index a954d82c05bf..be80d34d960f 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -13,33 +13,34 @@  //===----------------------------------------------------------------------===//  #include "llvm/Transforms/Utils/Local.h" -#include "llvm/Constants.h" -#include "llvm/DIBuilder.h" -#include "llvm/DebugInfo.h" -#include "llvm/DerivedTypes.h" -#include "llvm/GlobalAlias.h" -#include "llvm/GlobalVariable.h" -#include "llvm/IRBuilder.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Intrinsics.h" -#include "llvm/MDBuilder.h" -#include "llvm/Metadata.h" -#include "llvm/Operator.h"  #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/SmallPtrSet.h"  #include "llvm/Analysis/Dominators.h"  #include "llvm/Analysis/InstructionSimplify.h"  #include "llvm/Analysis/MemoryBuiltins.h"  #include "llvm/Analysis/ProfileInfo.h"  #include "llvm/Analysis/ValueTracking.h" +#include "llvm/DIBuilder.h" +#include "llvm/DebugInfo.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Operator.h"  #include "llvm/Support/CFG.h"  #include "llvm/Support/Debug.h"  #include "llvm/Support/GetElementPtrTypeIterator.h"  #include "llvm/Support/MathExtras.h"  #include "llvm/Support/ValueHandle.h"  #include "llvm/Support/raw_ostream.h" -#include "llvm/DataLayout.h"  using namespace llvm;  //===----------------------------------------------------------------------===// @@ -604,7 +605,7 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) {    // possible to handle such cases, but difficult: it requires checking whether    // BB dominates Succ, which is non-trivial to calculate in the case where    // Succ has multiple predecessors.  Also, it requires checking whether -  // constructing the necessary self-referential PHI node doesn't intoduce any +  // constructing the necessary self-referential PHI node doesn't introduce any    // conflicts; this isn't too difficult, but the previous code for doing this    // was incorrect.    // @@ -928,3 +929,73 @@ DbgDeclareInst *llvm::FindAllocaDbgDeclare(Value *V) {    return 0;  } + +bool llvm::replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, +                                      DIBuilder &Builder) { +  DbgDeclareInst *DDI = FindAllocaDbgDeclare(AI); +  if (!DDI) +    return false; +  DIVariable DIVar(DDI->getVariable()); +  if (!DIVar.Verify()) +    return false; + +  // Create a copy of the original DIDescriptor for user variable, appending +  // "deref" operation to a list of address elements, as new llvm.dbg.declare +  // will take a value storing address of the memory for variable, not +  // alloca itself. +  Type *Int64Ty = Type::getInt64Ty(AI->getContext()); +  SmallVector<Value*, 4> NewDIVarAddress; +  if (DIVar.hasComplexAddress()) { +    for (unsigned i = 0, n = DIVar.getNumAddrElements(); i < n; ++i) { +      NewDIVarAddress.push_back( +          ConstantInt::get(Int64Ty, DIVar.getAddrElement(i))); +    } +  } +  NewDIVarAddress.push_back(ConstantInt::get(Int64Ty, DIBuilder::OpDeref)); +  DIVariable NewDIVar = Builder.createComplexVariable( +      DIVar.getTag(), DIVar.getContext(), DIVar.getName(), +      DIVar.getFile(), DIVar.getLineNumber(), DIVar.getType(), +      NewDIVarAddress, DIVar.getArgNumber()); + +  // Insert llvm.dbg.declare in the same basic block as the original alloca, +  // and remove old llvm.dbg.declare. +  BasicBlock *BB = AI->getParent(); +  Builder.insertDeclare(NewAllocaAddress, NewDIVar, BB); +  DDI->eraseFromParent(); +  return true; +} + +bool llvm::removeUnreachableBlocks(Function &F) { +  SmallPtrSet<BasicBlock*, 16> Reachable; +  SmallVector<BasicBlock*, 128> Worklist; +  Worklist.push_back(&F.getEntryBlock()); +  Reachable.insert(&F.getEntryBlock()); +  do { +    BasicBlock *BB = Worklist.pop_back_val(); +    for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) +      if (Reachable.insert(*SI)) +        Worklist.push_back(*SI); +  } while (!Worklist.empty()); + +  if (Reachable.size() == F.size()) +    return false; + +  assert(Reachable.size() < F.size()); +  for (Function::iterator I = llvm::next(F.begin()), E = F.end(); I != E; ++I) { +    if (Reachable.count(I)) +      continue; + +    for (succ_iterator SI = succ_begin(I), SE = succ_end(I); SI != SE; ++SI) +      if (Reachable.count(*SI)) +        (*SI)->removePredecessor(I); +    I->dropAllReferences(); +  } + +  for (Function::iterator I = llvm::next(F.begin()), E=F.end(); I != E;) +    if (!Reachable.count(I)) +      I = F.getBasicBlockList().erase(I); +    else +      ++I; + +  return true; +} | 
