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/Compiler.h"
#include "llvm/Support/Debug.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
//===----------------------------------------------------------------------===//
// 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,
EXTRACTVALUE, INSERTVALUE, 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);
Expression create_expression(InsertValueInst* I);
Expression create_expression(ExtractValueInst* I);
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
};
}
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
}
}
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
Expression ValueTable::create_expression(InsertValueInst* I) {
Expression e;
e.type = I->getType();
e.firstVN = lookup_or_add(I->getOperand(0));
e.secondVN = lookup_or_add(I->getOperand(1));
e.thirdVN = 0;
e.function = 0;
e.opcode = Expression::INSERTVALUE;
for (InsertValueInst::op_iterator OI = I->op_begin()+2,
OE = I->op_end(); OI != OE; ++OI)
e.varargs.push_back(lookup_or_add(I));
return e;
}
Expression ValueTable::create_expression(ExtractValueInst* I) {
Expression e;
e.type = I->getType();
e.firstVN = lookup_or_add(I->getOperand(0));
e.secondVN = lookup_or_add(I->getOperand(1));
e.thirdVN = 0;
e.function = 0;
e.opcode = Expression::EXTRACTVALUE;
for (InsertValueInst::op_iterator OI = I->op_begin()+2,
OE = I->op_end(); OI != OE; ++OI)
e.varargs.push_back(lookup_or_add(I));
return e;
}
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++;
}
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
Instruction* local_dep = MD->getDependency(C);
if (local_dep == MemoryDependenceAnalysis::None) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
} else if (local_dep != MemoryDependenceAnalysis::NonLocal) {
if (!isa<CallInst>(local_dep)) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
CallInst* local_cdep = cast<CallInst>(local_dep);
if (local_cdep->getCalledFunction() != C->getCalledFunction() ||
local_cdep->getNumOperands() != C->getNumOperands()) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
} else if (!C->getCalledFunction()) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
} else {
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;
}
}
DenseMap<BasicBlock*, Value*> deps;
MD->getNonLocalDependency(C, deps);
CallInst* cdep = 0;
for (DenseMap<BasicBlock*, Value*>::iterator I = deps.begin(),
E = deps.end(); I != E; ++I) {
if (I->second == MemoryDependenceAnalysis::None) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
} else if (I->second != MemoryDependenceAnalysis::NonLocal) {
Owen Anderson
committed
if (DT->properlyDominates(I->first, C->getParent())) {
if (CallInst* CD = dyn_cast<CallInst>(I->second))
cdep = CD;
else {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
} else {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
}
}
}
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++;
} else if (!C->getCalledFunction()) {
valueNumbering.insert(std::make_pair(V, nextValueNumber));
return nextValueNumber++;
} else {
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));
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
return nextValueNumber++;
}
} else if (InsertValueInst* II = dyn_cast<InsertValueInst>(V)) {
Expression e = create_expression(II);
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 (ExtractValueInst* E = dyn_cast<ExtractValueInst>(V)) {
Expression e = create_expression(E);
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 (BinaryOperator* BO = dyn_cast<BinaryOperator>(V)) {
Owen Anderson
committed
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
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
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
//===----------------------------------------------------------------------===//
namespace llvm {
template<> struct DenseMapInfo<uint32_t> {
static inline uint32_t getEmptyKey() { return ~0; }
static inline uint32_t getTombstoneKey() { return ~0 - 1; }
Owen Anderson
committed
static unsigned getHashValue(const uint32_t& Val) { return Val * 37; }
static bool isPod() { return true; }
static bool isEqual(const uint32_t& LHS, const uint32_t& RHS) {
return LHS == RHS;
Owen Anderson
committed
}
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((intptr_t)&ID) { }
private:
ValueTable VN;
Owen Anderson
committed
DenseMap<BasicBlock*, DenseMap<uint32_t, Value*> > 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.setPreservesCFG();
AU.addRequired<DominatorTree>();
AU.addRequired<MemoryDependenceAnalysis>();
AU.addRequired<AliasAnalysis>();
AU.addPreserved<AliasAnalysis>();
Owen Anderson
committed
AU.addPreserved<MemoryDependenceAnalysis>();
}
// 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
};
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;
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
DenseMap<BasicBlock*, Value*> deps;
MD.getNonLocalDependency(L, deps);
DenseMap<BasicBlock*, Value*> repl;
// Filter out useless results (non-locals, etc)
for (DenseMap<BasicBlock*, Value*>::iterator I = deps.begin(), E = deps.end();
I != E; ++I) {
if (I->second == MemoryDependenceAnalysis::None)
if (I->second == MemoryDependenceAnalysis::NonLocal)
continue;
if (StoreInst* S = dyn_cast<StoreInst>(I->second)) {
if (S->getPointerOperand() != L->getPointerOperand())
} else if (LoadInst* LD = dyn_cast<LoadInst>(I->second)) {
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;
Instruction* dep = MD.getDependency(L);
if (dep == MemoryDependenceAnalysis::NonLocal &&
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
Owen Anderson
committed
while (dep != MemoryDependenceAnalysis::None &&
dep != MemoryDependenceAnalysis::NonLocal &&
(isa<LoadInst>(dep) || isa<StoreInst>(dep))) {