Newer
Older
Owen Anderson
committed
//===- GVN.cpp - Eliminate redundant values and loads ------------===//
//
// 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.
//
Matthijs Kooijman
committed
// Note that this pass does the value numbering itself, it does not use the
// 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/Instructions.h"
#include "llvm/Value.h"
Owen Anderson
committed
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#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"
Owen Anderson
committed
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
Owen Anderson
committed
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
Owen Anderson
committed
using namespace llvm;
STATISTIC(NumGVNInstr, "Number of instructions deleted");
STATISTIC(NumGVNLoad, "Number of loads deleted");
Owen Anderson
committed
STATISTIC(NumGVNPRE, "Number of instructions PRE'd");
Owen Anderson
committed
STATISTIC(NumGVNBlocks, "Number of blocks merged");
static cl::opt<bool> EnablePRE("enable-pre",
cl::init(true), cl::Hidden);
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 VISIBILITY_HIDDEN Expression {
enum ExpressionOpcode { ADD, SUB, MUL, 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,
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;
Value* function;
Owen Anderson
committed
Expression() { }
Expression(ExpressionOpcode o) : opcode(o) { }
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;
for (size_t i = 0; i < varargs.size(); ++i)
if (varargs[i] != other.varargs[i])
return false;
return true;
}
}
bool operator!=(const Expression &other) const {
if (opcode != other.opcode)
return true;
else if (opcode == EMPTY || opcode == TOMBSTONE)
return false;
else if (type != other.type)
return true;
else if (function != other.function)
return true;
Owen Anderson
committed
else if (firstVN != other.firstVN)
return true;
else if (secondVN != other.secondVN)
return true;
else if (thirdVN != other.thirdVN)
return true;
else {
if (varargs.size() != other.varargs.size())
return true;
for (size_t i = 0; i < varargs.size(); ++i)
if (varargs[i] != other.varargs[i])
return true;
return false;
}
}
};
class VISIBILITY_HIDDEN ValueTable {
private:
DenseMap<Value*, uint32_t> valueNumbering;
DenseMap<Expression, uint32_t> expressionNumbering;
AliasAnalysis* AA;
MemoryDependenceAnalysis* MD;
DominatorTree* DT;
Owen Anderson
committed
uint32_t nextValueNumber;
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) { }
Owen Anderson
committed
uint32_t lookup_or_add(Value* V);
uint32_t lookup(Value* V) const;
void add(Value* V, uint32_t num);
void clear();
void erase(Value* v);
unsigned size();
void setAliasAnalysis(AliasAnalysis* A) { AA = A; }
void setMemDep(MemoryDependenceAnalysis* M) { MD = M; }
void setDomTree(DominatorTree* D) { DT = D; }
Owen Anderson
committed
uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
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;
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;
Owen Anderson
committed
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
assert(0 && "Binary operator with unknown opcode?");
case Instruction::Add: return Expression::ADD;
case Instruction::Sub: return Expression::SUB;
case Instruction::Mul: return Expression::MUL;
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) || isa<VICmpInst>(C)) {
Owen Anderson
committed
switch (C->getPredicate()) {
default: // THIS SHOULD NEVER HAPPEN
assert(0 && "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
}
}
assert((isa<FCmpInst>(C) || isa<VFCmpInst>(C)) && "Unknown compare");
switch (C->getPredicate()) {
default: // THIS SHOULD NEVER HAPPEN
assert(0 && "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
assert(0 && "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);
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);
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);
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;
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;
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;
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;
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;
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) {
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) {
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.isNone()) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
if (Instruction *LocalDepInst = local_dep.getInst()) {
if (!isa<CallInst>(LocalDepInst)) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
CallInst* local_cdep = cast<CallInst>(LocalDepInst);
if (local_cdep->getCalledFunction() != C->getCalledFunction() ||
local_cdep->getNumOperands() != C->getNumOperands()) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
if (!C->getCalledFunction()) {
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;
}
SmallVector<std::pair<BasicBlock*, MemDepResult>, 32> deps;
MD->getNonLocalDependency(C, deps);
CallInst* cdep = 0;
// Check to see if we have a single dominating call instruction that is
// identical to C.
for (SmallVector<std::pair<BasicBlock*, MemDepResult>, 32>
::iterator I = deps.begin(), E = deps.end(); I != E; ++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.isNone() || 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->getCalledFunction() != C->getCalledFunction() ||
cdep->getNumOperands() != C->getNumOperands()) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
if (!C->getCalledFunction()) {
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
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
Expression e = create_expression(BO);
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 (CmpInst* C = dyn_cast<CmpInst>(V)) {
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 (ShuffleVectorInst* U = dyn_cast<ShuffleVectorInst>(V)) {
Expression e = create_expression(U);
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 (ExtractElementInst* U = dyn_cast<ExtractElementInst>(V)) {
Expression e = create_expression(U);
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 (InsertElementInst* U = dyn_cast<InsertElementInst>(V)) {
Expression e = create_expression(U);
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 (SelectInst* U = dyn_cast<SelectInst>(V)) {
Expression e = create_expression(U);
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 (CastInst* U = dyn_cast<CastInst>(V)) {
Expression e = create_expression(U);
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 (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(V)) {
Expression e = create_expression(U);
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 {
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 {
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);
}
Owen Anderson
committed
//===----------------------------------------------------------------------===//
Owen Anderson
committed
//===----------------------------------------------------------------------===//
Owen Anderson
committed
namespace {
struct VISIBILITY_HIDDEN ValueNumberScope {
ValueNumberScope* parent;
DenseMap<uint32_t, Value*> table;
ValueNumberScope(ValueNumberScope* p) : parent(p) { }
};
}
Owen Anderson
committed
namespace {
class VISIBILITY_HIDDEN GVN : public FunctionPass {
bool runOnFunction(Function &F);
public:
static char ID; // Pass identification, replacement for typeid
GVN() : FunctionPass(&ID) { }
Owen Anderson
committed
private:
ValueTable VN;
Owen Anderson
committed
DenseMap<BasicBlock*, ValueNumberScope*> localAvail;
Owen Anderson
committed
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
}
// Helper fuctions
// FIXME: eliminate or document these better
bool processLoad(LoadInst* L,
Chris Lattner
committed
DenseMap<Value*, LoadInst*> &lastLoad,
SmallVectorImpl<Instruction*> &toErase);
Owen Anderson
committed
bool processInstruction(Instruction* I,
DenseMap<Value*, LoadInst*>& lastSeenLoad,
Chris Lattner
committed
SmallVectorImpl<Instruction*> &toErase);
Chris Lattner
committed
SmallVectorImpl<Instruction*> &toErase);
Value *GetValueForBlock(BasicBlock *BB, LoadInst* orig,
DenseMap<BasicBlock*, Value*> &Phis,
bool top_level = false);
Owen Anderson
committed
void dump(DenseMap<uint32_t, Value*>& d);
Value* CollapsePhi(PHINode* p);
bool isSafeReplacement(PHINode* p, Instruction* inst);
Owen Anderson
committed
bool performPRE(Function& F);
Owen Anderson
committed
Value* lookupNumber(BasicBlock* BB, uint32_t num);
Owen Anderson
committed
bool mergeBlockIntoPredecessor(BasicBlock* BB);
void cleanupGlobalSets();
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");
}
Value* GVN::CollapsePhi(PHINode* p) {
DominatorTree &DT = getAnalysis<DominatorTree>();
Value* constVal = p->hasConstantValue();
Instruction* inst = dyn_cast<Instruction>(constVal);
if (!inst)
return constVal;
if (DT.dominates(inst, p))
if (isSafeReplacement(p, inst))
return inst;
bool GVN::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;
return true;
}
/// GetValueForBlock - Get the value to use within the specified basic block.
/// available values are in Phis.
Value *GVN::GetValueForBlock(BasicBlock *BB, LoadInst* orig,
DenseMap<BasicBlock*, Value*> &Phis,
bool top_level) {
// 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() && !top_level) return V->second;
// If the block is unreachable, just return undef, since this path
// can't actually occur at runtime.
if (!getAnalysis<DominatorTree>().isReachableFromEntry(BB))
return Phis[BB] = UndefValue::get(orig->getType());
Owen Anderson
committed
Owen Anderson
committed
BasicBlock* singlePred = BB->getSinglePredecessor();
if (singlePred) {
Owen Anderson
committed
Value *ret = GetValueForBlock(singlePred, orig, Phis);
Phis[BB] = ret;
return ret;
// 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",
BB->begin());
PN->reserveOperandSpace(std::distance(pred_begin(BB), pred_end(BB)));
Owen Anderson
committed
if (Phis.count(BB) == 0)
Phis.insert(std::make_pair(BB, PN));
Owen Anderson
committed
// 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);
PN->addIncoming(val, *PI);
}
AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
AA.copyValue(orig, PN);
// Attempt to collapse PHI nodes that are trivially redundant
Value* v = CollapsePhi(PN);
if (!v) {
// Cache our phi construction results
phiMap[orig->getPointerOperand()].insert(PN);
return PN;
}
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
Owen Anderson
committed
MD.removeInstruction(PN);
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
/// processNonLocalLoad - Attempt to eliminate a load whose dependencies are
/// non-local by performing PHI construction.
Chris Lattner
committed
SmallVectorImpl<Instruction*> &toErase) {
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
// Find the non-local dependencies of the load
SmallVector<std::pair<BasicBlock*, MemDepResult>, 32> deps;
MD.getNonLocalDependency(L, deps);
// If we had to process more than one hundred blocks to find the
// dependencies, this load isn't worth worrying about. Optimizing
// it will be too expensive.
if (deps.size() > 100)
return false;
BasicBlock *EntryBlock = &L->getParent()->getParent()->getEntryBlock();
DenseMap<BasicBlock*, Value*> repl;
// Filter out useless results (non-locals, etc)
for (SmallVector<std::pair<BasicBlock*, MemDepResult>, 32>::iterator
I = deps.begin(), E = deps.end(); I != E; ++I) {
if (I->second.isNone()) {
repl[I->first] = UndefValue::get(L->getType());
continue;
}
if (I->second.isNonLocal()) {
// If this is a non-local dependency in the entry block, then we depend on
// the value live-in at the start of the function. We could insert a load
// in the entry block to get this, but for now we'll just bail out.
// FIXME: Consider emitting a load in the entry block to catch this case!
if (I->first == EntryBlock)
return false;
continue;
if (StoreInst* S = dyn_cast<StoreInst>(I->second.getInst())) {
if (S->getPointerOperand() != L->getPointerOperand())
} else if (LoadInst* LD = dyn_cast<LoadInst>(I->second.getInst())) {
if (LD->getPointerOperand() != L->getPointerOperand())
} else {
return false;
}
// Use cached PHI construction information from previous runs
SmallPtrSet<Instruction*, 4>& p = phiMap[L->getPointerOperand()];
for (SmallPtrSet<Instruction*, 4>::iterator I = p.begin(), E = p.end();
I != E; ++I) {
if ((*I)->getParent() == L->getParent()) {
MD.removeInstruction(L);
L->replaceAllUsesWith(*I);
toErase.push_back(L);
NumGVNLoad++;
return true;
}
repl.insert(std::make_pair((*I)->getParent(), *I));
Value* v = GetValueForBlock(L->getParent(), L, repl, true);
MD.removeInstruction(L);
L->replaceAllUsesWith(v);
toErase.push_back(L);
return true;
}
/// processLoad - Attempt to eliminate a load, first by eliminating it
/// locally, and then attempting non-local elimination if that fails.
Chris Lattner
committed
bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
SmallVectorImpl<Instruction*> &toErase) {
Owen Anderson
committed
if (L->isVolatile()) {
lastLoad[L->getPointerOperand()] = L;
return false;
}
Value* pointer = L->getPointerOperand();
LoadInst*& last = lastLoad[pointer];
// ... to a pointer that has been loaded from before...
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
Owen Anderson
committed
bool removedNonLocal = false;
MemDepResult dep = MD.getDependency(L);
if (dep.isNonLocal() &&
Owen Anderson
committed
L->getParent() != &L->getParent()->getParent()->getEntryBlock()) {
removedNonLocal = processNonLocalLoad(L, toErase);
if (!removedNonLocal)
last = L;
return removedNonLocal;
}
Owen Anderson
committed
bool deletedLoad = false;
// Walk up the dependency chain until we either find
// a dependency we can use, or we can't walk any further
while (Instruction *DepInst = dep.getInst()) {
Owen Anderson
committed
// ... that depends on a store ...
if (StoreInst* S = dyn_cast<StoreInst>(DepInst)) {
Owen Anderson
committed
if (S->getPointerOperand() == pointer) {
// Remove it!
MD.removeInstruction(L);
Owen Anderson
committed
L->replaceAllUsesWith(S->getOperand(0));
toErase.push_back(L);
deletedLoad = true;
NumGVNLoad++;
}
// Whether we removed it or not, we can't
// go any further
break;
} else if (!isa<LoadInst>(DepInst)) {
// Only want to handle loads below.
break;
Owen Anderson
committed
} else if (!last) {
// If we don't depend on a store, and we haven't
// been loaded before, bail.
break;
} else if (DepInst == last) {
Owen Anderson
committed
// Remove it!
MD.removeInstruction(L);