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);
}
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/// 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) {
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);
// Cast to pointer if the load needs a pointer type.
if (isa<PointerType>(LoadedTy))
StoredVal = new IntToPtrInst(StoredVal, LoadedTy, "", InsertPt);
return StoredVal;
}
// If the loaded value is smaller than the available value, then we can
// extract out a piece from it. If the available value is too small, then we
// can't do anything.
if (StoreSize < LoadSize)
return 0;
// Convert source pointers to integers, which can be manipulated.
if (isa<PointerType>(StoredValTy)) {
StoredValTy = TD.getIntPtrType(StoredValTy->getContext());
StoredVal = new PtrToIntInst(StoredVal, StoredValTy, "", InsertPt);
}
// Convert vectors and fp to integer, which can be manipulated.
if (!isa<IntegerType>(StoredValTy)) {
StoredValTy = IntegerType::get(StoredValTy->getContext(), StoreSize);
StoredVal = new BitCastInst(StoredVal, StoredValTy, "", InsertPt);