Newer
Older
//===- GVN.cpp - Eliminate redundant values and loads ---------------------===//
Owen Anderson
committed
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
Owen Anderson
committed
//
//===----------------------------------------------------------------------===//
//
// This pass performs global value numbering to eliminate fully redundant
// instructions. It also performs simple dead load elimination.
//
// Note that this pass does the value numbering itself; it does not use the
Matthijs Kooijman
committed
// ValueNumbering analysis passes.
//
Owen Anderson
committed
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "gvn"
#include "llvm/Transforms/Scalar.h"
#include "llvm/BasicBlock.h"
#include "llvm/Constants.h"
Owen Anderson
committed
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/LLVMContext.h"
#include "llvm/Operator.h"
#include "llvm/Value.h"
Owen Anderson
committed
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
Owen Anderson
committed
#include "llvm/ADT/PostOrderIterator.h"
Owen Anderson
committed
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/AliasAnalysis.h"
Victor Hernandez
committed
#include "llvm/Analysis/MallocHelper.h"
Owen Anderson
committed
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
Daniel Dunbar
committed
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
Owen Anderson
committed
using namespace llvm;
STATISTIC(NumGVNInstr, "Number of instructions deleted");
STATISTIC(NumGVNLoad, "Number of loads deleted");
STATISTIC(NumGVNPRE, "Number of instructions PRE'd");
Owen Anderson
committed
STATISTIC(NumGVNBlocks, "Number of blocks merged");
STATISTIC(NumPRELoad, "Number of loads PRE'd");
static cl::opt<bool> EnablePRE("enable-pre",
cl::init(true), cl::Hidden);
static cl::opt<bool> EnableLoadPRE("enable-load-pre", cl::init(true));
Owen Anderson
committed
//===----------------------------------------------------------------------===//
// ValueTable Class
//===----------------------------------------------------------------------===//
/// This class holds the mapping between values and value numbers. It is used
/// as an efficient mechanism to determine the expression-wise equivalence of
/// two values.
namespace {
struct Expression {
enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL,
UDIV, SDIV, FDIV, UREM, SREM,
FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ,
ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE,
ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ,
FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE,
FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE,
Owen Anderson
committed
FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT,
SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI,
FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT,
PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, CONSTANT,
Owen Anderson
committed
EMPTY, TOMBSTONE };
Owen Anderson
committed
ExpressionOpcode opcode;
const Type* type;
uint32_t firstVN;
uint32_t secondVN;
uint32_t thirdVN;
SmallVector<uint32_t, 4> varargs;
Owen Anderson
committed
Expression() { }
Expression(ExpressionOpcode o) : opcode(o) { }
Owen Anderson
committed
bool operator==(const Expression &other) const {
if (opcode != other.opcode)
return false;
else if (opcode == EMPTY || opcode == TOMBSTONE)
return true;
else if (type != other.type)
return false;
else if (function != other.function)
return false;
Owen Anderson
committed
else if (firstVN != other.firstVN)
return false;
else if (secondVN != other.secondVN)
return false;
else if (thirdVN != other.thirdVN)
return false;
else {
if (varargs.size() != other.varargs.size())
return false;
Owen Anderson
committed
for (size_t i = 0; i < varargs.size(); ++i)
if (varargs[i] != other.varargs[i])
return false;
Owen Anderson
committed
return true;
}
}
Owen Anderson
committed
bool operator!=(const Expression &other) const {
Bill Wendling
committed
return !(*this == other);
Owen Anderson
committed
}
};
class ValueTable {
Owen Anderson
committed
private:
DenseMap<Value*, uint32_t> valueNumbering;
DenseMap<Expression, uint32_t> expressionNumbering;
AliasAnalysis* AA;
MemoryDependenceAnalysis* MD;
DominatorTree* DT;
Owen Anderson
committed
uint32_t nextValueNumber;
Owen Anderson
committed
Expression::ExpressionOpcode getOpcode(BinaryOperator* BO);
Expression::ExpressionOpcode getOpcode(CmpInst* C);
Expression::ExpressionOpcode getOpcode(CastInst* C);
Expression create_expression(BinaryOperator* BO);
Expression create_expression(CmpInst* C);
Expression create_expression(ShuffleVectorInst* V);
Expression create_expression(ExtractElementInst* C);
Expression create_expression(InsertElementInst* V);
Expression create_expression(SelectInst* V);
Expression create_expression(CastInst* C);
Expression create_expression(GetElementPtrInst* G);
Expression create_expression(CallInst* C);
Expression create_expression(Constant* C);
Owen Anderson
committed
public:
ValueTable() : nextValueNumber(1) { }
uint32_t lookup_or_add(Value *V);
uint32_t lookup(Value *V) const;
void add(Value *V, uint32_t num);
Owen Anderson
committed
void clear();
Owen Anderson
committed
unsigned size();
void setAliasAnalysis(AliasAnalysis* A) { AA = A; }
AliasAnalysis *getAliasAnalysis() const { return AA; }
void setMemDep(MemoryDependenceAnalysis* M) { MD = M; }
void setDomTree(DominatorTree* D) { DT = D; }
Owen Anderson
committed
uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
Bill Wendling
committed
void verifyRemoved(const Value *) const;
Owen Anderson
committed
};
}
namespace llvm {
template <> struct DenseMapInfo<Expression> {
static inline Expression getEmptyKey() {
return Expression(Expression::EMPTY);
}
static inline Expression getTombstoneKey() {
return Expression(Expression::TOMBSTONE);
}
Owen Anderson
committed
static unsigned getHashValue(const Expression e) {
unsigned hash = e.opcode;
Owen Anderson
committed
hash = e.firstVN + hash * 37;
hash = e.secondVN + hash * 37;
hash = e.thirdVN + hash * 37;
hash = ((unsigned)((uintptr_t)e.type >> 4) ^
(unsigned)((uintptr_t)e.type >> 9)) +
hash * 37;
for (SmallVector<uint32_t, 4>::const_iterator I = e.varargs.begin(),
E = e.varargs.end(); I != E; ++I)
Owen Anderson
committed
hash = *I + hash * 37;
hash = ((unsigned)((uintptr_t)e.function >> 4) ^
(unsigned)((uintptr_t)e.function >> 9)) +
hash * 37;
Owen Anderson
committed
return hash;
}
static bool isEqual(const Expression &LHS, const Expression &RHS) {
return LHS == RHS;
}
Owen Anderson
committed
static bool isPod() { return true; }
};
}
//===----------------------------------------------------------------------===//
// ValueTable Internal Functions
//===----------------------------------------------------------------------===//
Expression::ExpressionOpcode ValueTable::getOpcode(BinaryOperator* BO) {
Owen Anderson
committed
switch(BO->getOpcode()) {
default: // THIS SHOULD NEVER HAPPEN
llvm_unreachable("Binary operator with unknown opcode?");
case Instruction::Add: return Expression::ADD;
case Instruction::FAdd: return Expression::FADD;
case Instruction::Sub: return Expression::SUB;
case Instruction::FSub: return Expression::FSUB;
case Instruction::Mul: return Expression::MUL;
case Instruction::FMul: return Expression::FMUL;
case Instruction::UDiv: return Expression::UDIV;
case Instruction::SDiv: return Expression::SDIV;
case Instruction::FDiv: return Expression::FDIV;
case Instruction::URem: return Expression::UREM;
case Instruction::SRem: return Expression::SREM;
case Instruction::FRem: return Expression::FREM;
case Instruction::Shl: return Expression::SHL;
case Instruction::LShr: return Expression::LSHR;
case Instruction::AShr: return Expression::ASHR;
case Instruction::And: return Expression::AND;
case Instruction::Or: return Expression::OR;
case Instruction::Xor: return Expression::XOR;
Owen Anderson
committed
}
}
Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) {
if (isa<ICmpInst>(C)) {
Owen Anderson
committed
switch (C->getPredicate()) {
default: // THIS SHOULD NEVER HAPPEN
llvm_unreachable("Comparison with unknown predicate?");
case ICmpInst::ICMP_EQ: return Expression::ICMPEQ;
case ICmpInst::ICMP_NE: return Expression::ICMPNE;
case ICmpInst::ICMP_UGT: return Expression::ICMPUGT;
case ICmpInst::ICMP_UGE: return Expression::ICMPUGE;
case ICmpInst::ICMP_ULT: return Expression::ICMPULT;
case ICmpInst::ICMP_ULE: return Expression::ICMPULE;
case ICmpInst::ICMP_SGT: return Expression::ICMPSGT;
case ICmpInst::ICMP_SGE: return Expression::ICMPSGE;
case ICmpInst::ICMP_SLT: return Expression::ICMPSLT;
case ICmpInst::ICMP_SLE: return Expression::ICMPSLE;
Owen Anderson
committed
}
} else {
switch (C->getPredicate()) {
default: // THIS SHOULD NEVER HAPPEN
llvm_unreachable("Comparison with unknown predicate?");
case FCmpInst::FCMP_OEQ: return Expression::FCMPOEQ;
case FCmpInst::FCMP_OGT: return Expression::FCMPOGT;
case FCmpInst::FCMP_OGE: return Expression::FCMPOGE;
case FCmpInst::FCMP_OLT: return Expression::FCMPOLT;
case FCmpInst::FCMP_OLE: return Expression::FCMPOLE;
case FCmpInst::FCMP_ONE: return Expression::FCMPONE;
case FCmpInst::FCMP_ORD: return Expression::FCMPORD;
case FCmpInst::FCMP_UNO: return Expression::FCMPUNO;
case FCmpInst::FCMP_UEQ: return Expression::FCMPUEQ;
case FCmpInst::FCMP_UGT: return Expression::FCMPUGT;
case FCmpInst::FCMP_UGE: return Expression::FCMPUGE;
case FCmpInst::FCMP_ULT: return Expression::FCMPULT;
case FCmpInst::FCMP_ULE: return Expression::FCMPULE;
case FCmpInst::FCMP_UNE: return Expression::FCMPUNE;
}
Owen Anderson
committed
}
Expression::ExpressionOpcode ValueTable::getOpcode(CastInst* C) {
Owen Anderson
committed
switch(C->getOpcode()) {
default: // THIS SHOULD NEVER HAPPEN
llvm_unreachable("Cast operator with unknown opcode?");
case Instruction::Trunc: return Expression::TRUNC;
case Instruction::ZExt: return Expression::ZEXT;
case Instruction::SExt: return Expression::SEXT;
case Instruction::FPToUI: return Expression::FPTOUI;
case Instruction::FPToSI: return Expression::FPTOSI;
case Instruction::UIToFP: return Expression::UITOFP;
case Instruction::SIToFP: return Expression::SITOFP;
case Instruction::FPTrunc: return Expression::FPTRUNC;
case Instruction::FPExt: return Expression::FPEXT;
case Instruction::PtrToInt: return Expression::PTRTOINT;
case Instruction::IntToPtr: return Expression::INTTOPTR;
case Instruction::BitCast: return Expression::BITCAST;
Owen Anderson
committed
}
}
Expression ValueTable::create_expression(CallInst* C) {
Expression e;
e.type = C->getType();
e.firstVN = 0;
e.secondVN = 0;
e.thirdVN = 0;
e.function = C->getCalledFunction();
e.opcode = Expression::CALL;
for (CallInst::op_iterator I = C->op_begin()+1, E = C->op_end();
I != E; ++I)
Owen Anderson
committed
e.varargs.push_back(lookup_or_add(*I));
return e;
}
Owen Anderson
committed
Expression ValueTable::create_expression(BinaryOperator* BO) {
Expression e;
Owen Anderson
committed
e.firstVN = lookup_or_add(BO->getOperand(0));
e.secondVN = lookup_or_add(BO->getOperand(1));
Owen Anderson
committed
e.thirdVN = 0;
e.function = 0;
Owen Anderson
committed
e.type = BO->getType();
e.opcode = getOpcode(BO);
Owen Anderson
committed
return e;
}
Expression ValueTable::create_expression(CmpInst* C) {
Expression e;
Owen Anderson
committed
e.firstVN = lookup_or_add(C->getOperand(0));
e.secondVN = lookup_or_add(C->getOperand(1));
Owen Anderson
committed
e.thirdVN = 0;
e.function = 0;
Owen Anderson
committed
e.type = C->getType();
e.opcode = getOpcode(C);
Owen Anderson
committed
return e;
}
Expression ValueTable::create_expression(CastInst* C) {
Expression e;
Owen Anderson
committed
e.firstVN = lookup_or_add(C->getOperand(0));
Owen Anderson
committed
e.secondVN = 0;
e.thirdVN = 0;
e.function = 0;
Owen Anderson
committed
e.type = C->getType();
e.opcode = getOpcode(C);
Owen Anderson
committed
return e;
}
Expression ValueTable::create_expression(ShuffleVectorInst* S) {
Expression e;
Owen Anderson
committed
e.firstVN = lookup_or_add(S->getOperand(0));
e.secondVN = lookup_or_add(S->getOperand(1));
e.thirdVN = lookup_or_add(S->getOperand(2));
e.function = 0;
Owen Anderson
committed
e.type = S->getType();
e.opcode = Expression::SHUFFLE;
Owen Anderson
committed
return e;
}
Expression ValueTable::create_expression(ExtractElementInst* E) {
Expression e;
Owen Anderson
committed
e.firstVN = lookup_or_add(E->getOperand(0));
e.secondVN = lookup_or_add(E->getOperand(1));
Owen Anderson
committed
e.thirdVN = 0;
e.function = 0;
Owen Anderson
committed
e.type = E->getType();
e.opcode = Expression::EXTRACT;
Owen Anderson
committed
return e;
}
Expression ValueTable::create_expression(InsertElementInst* I) {
Expression e;
Owen Anderson
committed
e.firstVN = lookup_or_add(I->getOperand(0));
e.secondVN = lookup_or_add(I->getOperand(1));
e.thirdVN = lookup_or_add(I->getOperand(2));
e.function = 0;
Owen Anderson
committed
e.type = I->getType();
e.opcode = Expression::INSERT;
Owen Anderson
committed
return e;
}
Expression ValueTable::create_expression(SelectInst* I) {
Expression e;
Owen Anderson
committed
e.firstVN = lookup_or_add(I->getCondition());
e.secondVN = lookup_or_add(I->getTrueValue());
e.thirdVN = lookup_or_add(I->getFalseValue());
e.function = 0;
Owen Anderson
committed
e.type = I->getType();
e.opcode = Expression::SELECT;
Owen Anderson
committed
return e;
}
Expression ValueTable::create_expression(GetElementPtrInst* G) {
Expression e;
Owen Anderson
committed
e.firstVN = lookup_or_add(G->getPointerOperand());
Owen Anderson
committed
e.secondVN = 0;
e.thirdVN = 0;
e.function = 0;
Owen Anderson
committed
e.type = G->getType();
e.opcode = Expression::GEP;
Owen Anderson
committed
for (GetElementPtrInst::op_iterator I = G->idx_begin(), E = G->idx_end();
I != E; ++I)
Owen Anderson
committed
e.varargs.push_back(lookup_or_add(*I));
Owen Anderson
committed
return e;
}
//===----------------------------------------------------------------------===//
// ValueTable External Functions
//===----------------------------------------------------------------------===//
Owen Anderson
committed
/// add - Insert a value into the table with a specified value number.
void ValueTable::add(Value *V, uint32_t num) {
Owen Anderson
committed
valueNumbering.insert(std::make_pair(V, num));
}
Owen Anderson
committed
/// lookup_or_add - Returns the value number for the specified value, assigning
/// it a new number if it did not have one before.
uint32_t ValueTable::lookup_or_add(Value *V) {
Owen Anderson
committed
DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V);
if (VI != valueNumbering.end())
return VI->second;
if (CallInst* C = dyn_cast<CallInst>(V)) {
Owen Anderson
committed
if (AA->doesNotAccessMemory(C)) {
Expression e = create_expression(C);
DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
if (EI != expressionNumbering.end()) {
valueNumbering.insert(std::make_pair(V, EI->second));
return EI->second;
} else {
expressionNumbering.insert(std::make_pair(e, nextValueNumber));
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
} else if (AA->onlyReadsMemory(C)) {
Expression e = create_expression(C);
if (expressionNumbering.find(e) == expressionNumbering.end()) {
expressionNumbering.insert(std::make_pair(e, nextValueNumber));
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
MemDepResult local_dep = MD->getDependency(C);
if (!local_dep.isDef() && !local_dep.isNonLocal()) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
if (local_dep.isDef()) {
CallInst* local_cdep = cast<CallInst>(local_dep.getInst());
if (local_cdep->getNumOperands() != C->getNumOperands()) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
for (unsigned i = 1; i < C->getNumOperands(); ++i) {
uint32_t c_vn = lookup_or_add(C->getOperand(i));
uint32_t cd_vn = lookup_or_add(local_cdep->getOperand(i));
if (c_vn != cd_vn) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
}
uint32_t v = lookup_or_add(local_cdep);
valueNumbering.insert(std::make_pair(V, v));
return v;
}
const MemoryDependenceAnalysis::NonLocalDepInfo &deps =
MD->getNonLocalCallDependency(CallSite(C));
// FIXME: call/call dependencies for readonly calls should return def, not
// clobber! Move the checking logic to MemDep!
CallInst* cdep = 0;
// Check to see if we have a single dominating call instruction that is
// identical to C.
for (unsigned i = 0, e = deps.size(); i != e; ++i) {
const MemoryDependenceAnalysis::NonLocalDepEntry *I = &deps[i];
// Ignore non-local dependencies.
if (I->second.isNonLocal())
continue;
// We don't handle non-depedencies. If we already have a call, reject
// instruction dependencies.
if (I->second.isClobber() || cdep != 0) {
cdep = 0;
break;
}
CallInst *NonLocalDepCall = dyn_cast<CallInst>(I->second.getInst());
// FIXME: All duplicated with non-local case.
if (NonLocalDepCall && DT->properlyDominates(I->first, C->getParent())){
cdep = NonLocalDepCall;
continue;
cdep = 0;
break;
if (!cdep) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
if (cdep->getNumOperands() != C->getNumOperands()) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
for (unsigned i = 1; i < C->getNumOperands(); ++i) {
uint32_t c_vn = lookup_or_add(C->getOperand(i));
uint32_t cd_vn = lookup_or_add(cdep->getOperand(i));
if (c_vn != cd_vn) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
uint32_t v = lookup_or_add(cdep);
valueNumbering.insert(std::make_pair(V, v));
return v;
} else {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
} else if (BinaryOperator* BO = dyn_cast<BinaryOperator>(V)) {
Owen Anderson
committed
Expression e = create_expression(BO);
Owen Anderson
committed
DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
if (EI != expressionNumbering.end()) {
valueNumbering.insert(std::make_pair(V, EI->second));
return EI->second;
} else {
expressionNumbering.insert(std::make_pair(e, nextValueNumber));
valueNumbering.insert(std::make_pair(V, nextValueNumber));
Owen Anderson
committed
return nextValueNumber++;
}
} else if (CmpInst* C = dyn_cast<CmpInst>(V)) {
Expression e = create_expression(C);
Owen Anderson
committed
DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
if (EI != expressionNumbering.end()) {
valueNumbering.insert(std::make_pair(V, EI->second));
return EI->second;
} else {
expressionNumbering.insert(std::make_pair(e, nextValueNumber));
valueNumbering.insert(std::make_pair(V, nextValueNumber));
Owen Anderson
committed
return nextValueNumber++;
}
} else if (ShuffleVectorInst* U = dyn_cast<ShuffleVectorInst>(V)) {
Expression e = create_expression(U);
Owen Anderson
committed
DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
if (EI != expressionNumbering.end()) {
valueNumbering.insert(std::make_pair(V, EI->second));
return EI->second;
} else {
expressionNumbering.insert(std::make_pair(e, nextValueNumber));
valueNumbering.insert(std::make_pair(V, nextValueNumber));
Owen Anderson
committed
return nextValueNumber++;
}
} else if (ExtractElementInst* U = dyn_cast<ExtractElementInst>(V)) {
Expression e = create_expression(U);
Owen Anderson
committed
DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
if (EI != expressionNumbering.end()) {
valueNumbering.insert(std::make_pair(V, EI->second));
return EI->second;
} else {
expressionNumbering.insert(std::make_pair(e, nextValueNumber));
valueNumbering.insert(std::make_pair(V, nextValueNumber));
Owen Anderson
committed
return nextValueNumber++;
}
} else if (InsertElementInst* U = dyn_cast<InsertElementInst>(V)) {
Expression e = create_expression(U);
Owen Anderson
committed
DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
if (EI != expressionNumbering.end()) {
valueNumbering.insert(std::make_pair(V, EI->second));
return EI->second;
} else {
expressionNumbering.insert(std::make_pair(e, nextValueNumber));
valueNumbering.insert(std::make_pair(V, nextValueNumber));
Owen Anderson
committed
return nextValueNumber++;
}
} else if (SelectInst* U = dyn_cast<SelectInst>(V)) {
Expression e = create_expression(U);
Owen Anderson
committed
DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
if (EI != expressionNumbering.end()) {
valueNumbering.insert(std::make_pair(V, EI->second));
return EI->second;
} else {
expressionNumbering.insert(std::make_pair(e, nextValueNumber));
valueNumbering.insert(std::make_pair(V, nextValueNumber));
Owen Anderson
committed
return nextValueNumber++;
}
} else if (CastInst* U = dyn_cast<CastInst>(V)) {
Expression e = create_expression(U);
Owen Anderson
committed
DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
if (EI != expressionNumbering.end()) {
valueNumbering.insert(std::make_pair(V, EI->second));
return EI->second;
} else {
expressionNumbering.insert(std::make_pair(e, nextValueNumber));
valueNumbering.insert(std::make_pair(V, nextValueNumber));
Owen Anderson
committed
return nextValueNumber++;
}
} else if (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(V)) {
Expression e = create_expression(U);
Owen Anderson
committed
DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
if (EI != expressionNumbering.end()) {
valueNumbering.insert(std::make_pair(V, EI->second));
return EI->second;
} else {
expressionNumbering.insert(std::make_pair(e, nextValueNumber));
valueNumbering.insert(std::make_pair(V, nextValueNumber));
Owen Anderson
committed
return nextValueNumber++;
}
} else {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
}
/// lookup - Returns the value number of the specified value. Fails if
/// the value has not yet been numbered.
uint32_t ValueTable::lookup(Value *V) const {
Owen Anderson
committed
DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V);
assert(VI != valueNumbering.end() && "Value not numbered?");
return VI->second;
Owen Anderson
committed
}
/// clear - Remove all entries from the ValueTable
void ValueTable::clear() {
valueNumbering.clear();
expressionNumbering.clear();
nextValueNumber = 1;
}
/// erase - Remove a value from the value numbering
void ValueTable::erase(Value *V) {
valueNumbering.erase(V);
}
Bill Wendling
committed
/// verifyRemoved - Verify that the value is removed from all internal data
/// structures.
void ValueTable::verifyRemoved(const Value *V) const {
for (DenseMap<Value*, uint32_t>::iterator
I = valueNumbering.begin(), E = valueNumbering.end(); I != E; ++I) {
assert(I->first != V && "Inst still occurs in value numbering map!");
}
}
Owen Anderson
committed
//===----------------------------------------------------------------------===//
Owen Anderson
committed
//===----------------------------------------------------------------------===//
Owen Anderson
committed
namespace {
struct ValueNumberScope {
Owen Anderson
committed
ValueNumberScope* parent;
DenseMap<uint32_t, Value*> table;
Owen Anderson
committed
ValueNumberScope(ValueNumberScope* p) : parent(p) { }
};
}
Owen Anderson
committed
namespace {
class GVN : public FunctionPass {
Owen Anderson
committed
bool runOnFunction(Function &F);
public:
static char ID; // Pass identification, replacement for typeid
GVN() : FunctionPass(&ID) { }
Owen Anderson
committed
private:
MemoryDependenceAnalysis *MD;
DominatorTree *DT;
Owen Anderson
committed
ValueTable VN;
Owen Anderson
committed
DenseMap<BasicBlock*, ValueNumberScope*> localAvail;
typedef DenseMap<Value*, SmallPtrSet<Instruction*, 4> > PhiMapType;
PhiMapType phiMap;
Owen Anderson
committed
// This transformation requires dominator postdominator info
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<DominatorTree>();
AU.addRequired<MemoryDependenceAnalysis>();
AU.addRequired<AliasAnalysis>();
Owen Anderson
committed
AU.addPreserved<DominatorTree>();
AU.addPreserved<AliasAnalysis>();
Owen Anderson
committed
}
Owen Anderson
committed
// Helper fuctions
// FIXME: eliminate or document these better
bool processLoad(LoadInst* L,
Chris Lattner
committed
SmallVectorImpl<Instruction*> &toErase);
bool processInstruction(Instruction *I,
Chris Lattner
committed
SmallVectorImpl<Instruction*> &toErase);
Chris Lattner
committed
SmallVectorImpl<Instruction*> &toErase);
bool processBlock(BasicBlock *BB);
Value *GetValueForBlock(BasicBlock *BB, Instruction *orig,
DenseMap<BasicBlock*, Value*> &Phis,
bool top_level = false);
Owen Anderson
committed
void dump(DenseMap<uint32_t, Value*>& d);
Value *CollapsePhi(PHINode* p);
Owen Anderson
committed
bool performPRE(Function& F);
Value *lookupNumber(BasicBlock *BB, uint32_t num);
Value *AttemptRedundancyElimination(Instruction *orig, unsigned valno);
void cleanupGlobalSets();
Bill Wendling
committed
void verifyRemoved(const Instruction *I) const;
Owen Anderson
committed
};
Owen Anderson
committed
char GVN::ID = 0;
}
// createGVNPass - The public interface to this file...
FunctionPass *llvm::createGVNPass() { return new GVN(); }
static RegisterPass<GVN> X("gvn",
"Global Value Numbering");
Owen Anderson
committed
void GVN::dump(DenseMap<uint32_t, Value*>& d) {
Owen Anderson
committed
for (DenseMap<uint32_t, Value*>::iterator I = d.begin(),
E = d.end(); I != E; ++I) {
Owen Anderson
committed
printf("%d\n", I->first);
I->second->dump();
}
printf("}\n");
}
static bool isSafeReplacement(PHINode* p, Instruction *inst) {
if (!isa<PHINode>(inst))
return true;
for (Instruction::use_iterator UI = p->use_begin(), E = p->use_end();
UI != E; ++UI)
if (PHINode* use_phi = dyn_cast<PHINode>(UI))
if (use_phi->getParent() == inst->getParent())
return false;
Value *GVN::CollapsePhi(PHINode *PN) {
Value *ConstVal = PN->hasConstantValue(DT);
if (!ConstVal) return 0;
Instruction *Inst = dyn_cast<Instruction>(ConstVal);
if (!Inst)
return ConstVal;
if (DT->dominates(Inst, PN))
if (isSafeReplacement(PN, Inst))
return Inst;
/// GetValueForBlock - Get the value to use within the specified basic block.
/// available values are in Phis.
Value *GVN::GetValueForBlock(BasicBlock *BB, Instruction *Orig,
DenseMap<BasicBlock*, Value*> &Phis,
// If we have already computed this value, return the previously computed val.
Owen Anderson
committed
DenseMap<BasicBlock*, Value*>::iterator V = Phis.find(BB);
if (V != Phis.end() && !TopLevel) return V->second;
// If the block is unreachable, just return undef, since this path
// can't actually occur at runtime.
if (!DT->isReachableFromEntry(BB))
return Phis[BB] = UndefValue::get(Orig->getType());
if (BasicBlock *Pred = BB->getSinglePredecessor()) {
Value *ret = GetValueForBlock(Pred, Orig, Phis);
Owen Anderson
committed
Phis[BB] = ret;
return ret;
// Get the number of predecessors of this block so we can reserve space later.
// If there is already a PHI in it, use the #preds from it, otherwise count.
// Getting it from the PHI is constant time.
unsigned NumPreds;
if (PHINode *ExistingPN = dyn_cast<PHINode>(BB->begin()))
NumPreds = ExistingPN->getNumIncomingValues();
else
NumPreds = std::distance(pred_begin(BB), pred_end(BB));
// Otherwise, the idom is the loop, so we need to insert a PHI node. Do so
// now, then get values to fill in the incoming values for the PHI.
PHINode *PN = PHINode::Create(Orig->getType(), Orig->getName()+".rle",
PN->reserveOperandSpace(NumPreds);
Phis.insert(std::make_pair(BB, PN));
// Fill in the incoming values for the block.
for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
Value *val = GetValueForBlock(*PI, Orig, Phis);
VN.getAliasAnalysis()->copyValue(Orig, PN);
// Attempt to collapse PHI nodes that are trivially redundant
Value *v = CollapsePhi(PN);
if (!v) {
// Cache our phi construction results
if (LoadInst* L = dyn_cast<LoadInst>(Orig))
Owen Anderson
committed
phiMap[L->getPointerOperand()].insert(PN);
else
if (isa<PointerType>(v->getType()))
MD->invalidateCachedPointerInfo(v);
Owen Anderson
committed
for (DenseMap<BasicBlock*, Value*>::iterator I = Phis.begin(),
E = Phis.end(); I != E; ++I)
if (I->second == PN)
I->second = v;
Owen Anderson
committed
DEBUG(errs() << "GVN removed: " << *PN << '\n');
MD->removeInstruction(PN);
Bill Wendling
committed
DEBUG(verifyRemoved(PN));
/// IsValueFullyAvailableInBlock - Return true if we can prove that the value
/// we're analyzing is fully available in the specified block. As we go, keep
/// track of which blocks we know are fully alive in FullyAvailableBlocks. This
/// map is actually a tri-state map with the following values:
/// 0) we know the block *is not* fully available.
/// 1) we know the block *is* fully available.
/// 2) we do not know whether the block is fully available or not, but we are
/// currently speculating that it will be.
/// 3) we are speculating for this block and have used that to speculate for
/// other blocks.
static bool IsValueFullyAvailableInBlock(BasicBlock *BB,
DenseMap<BasicBlock*, char> &FullyAvailableBlocks) {
// Optimistically assume that the block is fully available and check to see
// if we already know about this block in one lookup.
std::pair<DenseMap<BasicBlock*, char>::iterator, char> IV =
FullyAvailableBlocks.insert(std::make_pair(BB, 2));
// If the entry already existed for this block, return the precomputed value.
if (!IV.second) {
// If this is a speculative "available" value, mark it as being used for
// speculation of other blocks.
if (IV.first->second == 2)
IV.first->second = 3;
return IV.first->second != 0;
}
// Otherwise, see if it is fully available in all predecessors.
pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
// If this block has no predecessors, it isn't live-in here.
if (PI == PE)
for (; PI != PE; ++PI)
// If the value isn't fully available in one of our predecessors, then it
// isn't fully available in this block either. Undo our previous
// optimistic assumption and bail out.
if (!IsValueFullyAvailableInBlock(*PI, FullyAvailableBlocks))
return true;
// SpeculationFailure - If we get here, we found out that this is not, after
// all, a fully-available block. We have a problem if we speculated on this and
// used the speculation to mark other blocks as available.
SpeculationFailure:
char &BBVal = FullyAvailableBlocks[BB];
// If we didn't speculate on this, just return with it set to false.
if (BBVal == 2) {
BBVal = 0;
return false;
}
// If we did speculate on this value, we could have blocks set to 1 that are
// incorrect. Walk the (transitive) successors of this block and mark them as
// 0 if set to one.
SmallVector<BasicBlock*, 32> BBWorklist;
BBWorklist.push_back(BB);
while (!BBWorklist.empty()) {
BasicBlock *Entry = BBWorklist.pop_back_val();
// Note that this sets blocks to 0 (unavailable) if they happen to not
// already be in FullyAvailableBlocks. This is safe.
char &EntryVal = FullyAvailableBlocks[Entry];
if (EntryVal == 0) continue; // Already unavailable.
// Mark as unavailable.
EntryVal = 0;
for (succ_iterator I = succ_begin(Entry), E = succ_end(Entry); I != E; ++I)
BBWorklist.push_back(*I);
}
/// CanCoerceMustAliasedValueToLoad - Return true if
/// CoerceAvailableValueToLoadType will succeed.
static bool CanCoerceMustAliasedValueToLoad(Value *StoredVal,
const Type *LoadTy,
const TargetData &TD) {
// If the loaded or stored value is an first class array or struct, don't try
// to transform them. We need to be able to bitcast to integer.
if (isa<StructType>(LoadTy) || isa<ArrayType>(LoadTy) ||
isa<StructType>(StoredVal->getType()) ||
isa<ArrayType>(StoredVal->getType()))
return false;
// The store has to be at least as big as the load.
if (TD.getTypeSizeInBits(StoredVal->getType()) <
TD.getTypeSizeInBits(LoadTy))
return false;
return true;
}
/// CoerceAvailableValueToLoadType - If we saw a store of a value to memory, and
/// then a load from a must-aliased pointer of a different type, try to coerce
/// the stored value. LoadedTy is the type of the load we want to replace and
/// InsertPt is the place to insert new instructions.
///
/// If we can't do it, return null.
static Value *CoerceAvailableValueToLoadType(Value *StoredVal,
const Type *LoadedTy,
Instruction *InsertPt,
const TargetData &TD) {
if (!CanCoerceMustAliasedValueToLoad(StoredVal, LoadedTy, TD))
return 0;
const Type *StoredValTy = StoredVal->getType();
uint64_t StoreSize = TD.getTypeSizeInBits(StoredValTy);
uint64_t LoadSize = TD.getTypeSizeInBits(LoadedTy);
// If the store and reload are the same size, we can always reuse it.
if (StoreSize == LoadSize) {
if (isa<PointerType>(StoredValTy) && isa<PointerType>(LoadedTy)) {
// Pointer to Pointer -> use bitcast.
return new BitCastInst(StoredVal, LoadedTy, "", InsertPt);
}
// Convert source pointers to integers, which can be bitcast.
if (isa<PointerType>(StoredValTy)) {
StoredValTy = TD.getIntPtrType(StoredValTy->getContext());
StoredVal = new PtrToIntInst(StoredVal, StoredValTy, "", InsertPt);
}
const Type *TypeToCastTo = LoadedTy;
if (isa<PointerType>(TypeToCastTo))
TypeToCastTo = TD.getIntPtrType(StoredValTy->getContext());
if (StoredValTy != TypeToCastTo)
StoredVal = new BitCastInst(StoredVal, TypeToCastTo, "", InsertPt);