#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
-#include "llvm/LLVMContext.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CFG.h"
-#include "llvm/Support/Compiler.h"
#include <algorithm>
using namespace llvm;
STATISTIC(NumDeadAlloca, "Number of dead alloca's removed");
STATISTIC(NumPHIInsert, "Number of PHI nodes inserted");
-// Provide DenseMapInfo for all pointers.
namespace llvm {
template<>
struct DenseMapInfo<std::pair<BasicBlock*, unsigned> > {
static bool isEqual(const EltTy &LHS, const EltTy &RHS) {
return LHS == RHS;
}
- static bool isPod() { return true; }
};
}
struct AllocaInfo;
// Data package used by RenamePass()
- class VISIBILITY_HIDDEN RenamePassData {
+ class RenamePassData {
public:
typedef std::vector<Value *> ValVector;
- RenamePassData() {}
+ RenamePassData() : BB(NULL), Pred(NULL), Values() {}
RenamePassData(BasicBlock *B, BasicBlock *P,
const ValVector &V) : BB(B), Pred(P), Values(V) {}
BasicBlock *BB;
///
/// This functionality is important because it avoids scanning large basic
/// blocks multiple times when promoting many allocas in the same block.
- class VISIBILITY_HIDDEN LargeBlockInfo {
+ class LargeBlockInfo {
/// InstNumbers - For each instruction that we track, keep the index of the
/// instruction. The index starts out as the number of the instruction from
/// the start of the block.
}
};
- struct VISIBILITY_HIDDEN PromoteMem2Reg {
+ struct PromoteMem2Reg {
/// Allocas - The alloca instructions being promoted.
///
std::vector<AllocaInst*> Allocas;
///
AliasSetTracker *AST;
- LLVMContext &Context;
-
/// AllocaLookup - Reverse mapping of Allocas.
///
std::map<AllocaInst*, unsigned> AllocaLookup;
DenseMap<const BasicBlock*, unsigned> BBNumPreds;
public:
PromoteMem2Reg(const std::vector<AllocaInst*> &A, DominatorTree &dt,
- DominanceFrontier &df, AliasSetTracker *ast,
- LLVMContext &C)
- : Allocas(A), DT(dt), DF(df), AST(ast), Context(C) {}
+ DominanceFrontier &df, AliasSetTracker *ast)
+ : Allocas(A), DT(dt), DF(df), AST(ast) {}
void run();
// As we scan the uses of the alloca instruction, keep track of stores,
// and decide whether all of the loads and stores to the alloca are within
// the same basic block.
- for (Value::use_iterator U = AI->use_begin(), E = AI->use_end();
- U != E;) {
- Instruction *User = cast<Instruction>(*U);
- ++U;
+ for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();
+ UI != E;) {
+ Instruction *User = cast<Instruction>(*UI++);
if (BitCastInst *BC = dyn_cast<BitCastInst>(User)) {
// Remove any uses of this alloca in DbgInfoInstrinsics.
assert(BC->hasOneUse() && "Unexpected alloca uses!");
BC->eraseFromParent();
continue;
}
- else if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
+
+ if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
// Remember the basic blocks which define new values for the alloca
DefiningBlocks.push_back(SI->getParent());
AllocaPointerVal = SI->getOperand(0);
PHINode *PN = I->second;
// If this PHI node merges one value and/or undefs, get the value.
- if (Value *V = PN->hasConstantValue(true)) {
- if (!isa<Instruction>(V) ||
- properlyDominates(cast<Instruction>(V), PN)) {
- if (AST && isa<PointerType>(PN->getType()))
- AST->deleteValue(PN);
- PN->replaceAllUsesWith(V);
- PN->eraseFromParent();
- NewPhiNodes.erase(I++);
- EliminatedAPHI = true;
- continue;
- }
+ if (Value *V = PN->hasConstantValue(&DT)) {
+ if (AST && isa<PointerType>(PN->getType()))
+ AST->deleteValue(PN);
+ PN->replaceAllUsesWith(V);
+ PN->eraseFromParent();
+ NewPhiNodes.erase(I++);
+ EliminatedAPHI = true;
+ continue;
}
++I;
}
LiveInBlockWorklist.pop_back();
--i, --e;
break;
- } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
+ }
+
+ if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
if (LI->getOperand(0) != AI) continue;
// Okay, we found a load before a store to the alloca. It is actually
}
// Otherwise, we *can* safely rewrite this load.
- LI->replaceAllUsesWith(OnlyStore->getOperand(0));
+ Value *ReplVal = OnlyStore->getOperand(0);
+ // If the replacement value is the load, this must occur in unreachable
+ // code.
+ if (ReplVal == LI)
+ ReplVal = UndefValue::get(LI->getType());
+ LI->replaceAllUsesWith(ReplVal);
if (AST && isa<PointerType>(LI->getType()))
AST->deleteValue(LI);
LI->eraseFromParent();
///
void llvm::PromoteMemToReg(const std::vector<AllocaInst*> &Allocas,
DominatorTree &DT, DominanceFrontier &DF,
- LLVMContext &Context, AliasSetTracker *AST) {
+ AliasSetTracker *AST) {
// If there is nothing to do, bail out...
if (Allocas.empty()) return;
- PromoteMem2Reg(Allocas, DT, DF, AST, Context).run();
+ PromoteMem2Reg(Allocas, DT, DF, AST).run();
}