diff options
Diffstat (limited to 'lib/Transforms/Scalar/GVNPRE.cpp')
-rw-r--r-- | lib/Transforms/Scalar/GVNPRE.cpp | 1892 |
1 files changed, 0 insertions, 1892 deletions
diff --git a/lib/Transforms/Scalar/GVNPRE.cpp b/lib/Transforms/Scalar/GVNPRE.cpp deleted file mode 100644 index 0f3153f..0000000 --- a/lib/Transforms/Scalar/GVNPRE.cpp +++ /dev/null @@ -1,1892 +0,0 @@ -//===- GVNPRE.cpp - Eliminate redundant values and expressions ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass performs a hybrid of global value numbering and partial redundancy -// elimination, known as GVN-PRE. It performs partial redundancy elimination on -// values, rather than lexical expressions, allowing a more comprehensive view -// the optimization. It replaces redundant values with uses of earlier -// occurences of the same value. While this is beneficial in that it eliminates -// unneeded computation, it also increases register pressure by creating large -// live ranges, and should be used with caution on platforms that are very -// sensitive to register pressure. -// -// Note that this pass does the value numbering itself, it does not use the -// ValueNumbering analysis passes. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "gvnpre" -#include "llvm/Value.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Instructions.h" -#include "llvm/Function.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Analysis/Dominators.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DepthFirstIterator.h" -#include "llvm/ADT/PostOrderIterator.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" -#include "llvm/Support/CFG.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include <algorithm> -#include <deque> -#include <map> -using namespace llvm; - -//===----------------------------------------------------------------------===// -// ValueTable Class -//===----------------------------------------------------------------------===// - -namespace { - -/// 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. - -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, - FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT, - SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI, - FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT, - PTRTOINT, INTTOPTR, BITCAST, GEP, EMPTY, - TOMBSTONE }; - - ExpressionOpcode opcode; - const Type* type; - uint32_t firstVN; - uint32_t secondVN; - uint32_t thirdVN; - SmallVector<uint32_t, 4> varargs; - - Expression() { } - explicit 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 (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 (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; - } - } -}; - -} - -namespace { - class VISIBILITY_HIDDEN ValueTable { - private: - DenseMap<Value*, uint32_t> valueNumbering; - DenseMap<Expression, uint32_t> expressionNumbering; - - 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); - public: - ValueTable() { nextValueNumber = 1; } - 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(); - }; -} - -namespace llvm { -template <> struct DenseMapInfo<Expression> { - static inline Expression getEmptyKey() { - return Expression(Expression::EMPTY); - } - - static inline Expression getTombstoneKey() { - return Expression(Expression::TOMBSTONE); - } - - 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; - - for (SmallVector<uint32_t, 4>::const_iterator I = e.varargs.begin(), - E = e.varargs.end(); I != E; ++I) - hash = *I + hash * 37; - - return hash; - } - static bool isEqual(const Expression &LHS, const Expression &RHS) { - return LHS == RHS; - } - static bool isPod() { return true; } -}; -} - -//===----------------------------------------------------------------------===// -// ValueTable Internal Functions -//===----------------------------------------------------------------------===// -Expression::ExpressionOpcode - ValueTable::getOpcode(BinaryOperator* BO) { - switch(BO->getOpcode()) { - 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; - - // THIS SHOULD NEVER HAPPEN - default: - assert(0 && "Binary operator with unknown opcode?"); - return Expression::ADD; - } -} - -Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) { - if (C->getOpcode() == Instruction::ICmp) { - switch (C->getPredicate()) { - 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; - - // THIS SHOULD NEVER HAPPEN - default: - assert(0 && "Comparison with unknown predicate?"); - return Expression::ICMPEQ; - } - } else { - switch (C->getPredicate()) { - 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; - - // THIS SHOULD NEVER HAPPEN - default: - assert(0 && "Comparison with unknown predicate?"); - return Expression::FCMPOEQ; - } - } -} - -Expression::ExpressionOpcode - ValueTable::getOpcode(CastInst* C) { - switch(C->getOpcode()) { - 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; - - // THIS SHOULD NEVER HAPPEN - default: - assert(0 && "Cast operator with unknown opcode?"); - return Expression::BITCAST; - } -} - -Expression ValueTable::create_expression(BinaryOperator* BO) { - Expression e; - - e.firstVN = lookup_or_add(BO->getOperand(0)); - e.secondVN = lookup_or_add(BO->getOperand(1)); - e.thirdVN = 0; - e.type = BO->getType(); - e.opcode = getOpcode(BO); - - return e; -} - -Expression ValueTable::create_expression(CmpInst* C) { - Expression e; - - e.firstVN = lookup_or_add(C->getOperand(0)); - e.secondVN = lookup_or_add(C->getOperand(1)); - e.thirdVN = 0; - e.type = C->getType(); - e.opcode = getOpcode(C); - - return e; -} - -Expression ValueTable::create_expression(CastInst* C) { - Expression e; - - e.firstVN = lookup_or_add(C->getOperand(0)); - e.secondVN = 0; - e.thirdVN = 0; - e.type = C->getType(); - e.opcode = getOpcode(C); - - return e; -} - -Expression ValueTable::create_expression(ShuffleVectorInst* S) { - Expression e; - - 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.type = S->getType(); - e.opcode = Expression::SHUFFLE; - - return e; -} - -Expression ValueTable::create_expression(ExtractElementInst* E) { - Expression e; - - e.firstVN = lookup_or_add(E->getOperand(0)); - e.secondVN = lookup_or_add(E->getOperand(1)); - e.thirdVN = 0; - e.type = E->getType(); - e.opcode = Expression::EXTRACT; - - return e; -} - -Expression ValueTable::create_expression(InsertElementInst* I) { - Expression e; - - 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.type = I->getType(); - e.opcode = Expression::INSERT; - - return e; -} - -Expression ValueTable::create_expression(SelectInst* I) { - Expression e; - - e.firstVN = lookup_or_add(I->getCondition()); - e.secondVN = lookup_or_add(I->getTrueValue()); - e.thirdVN = lookup_or_add(I->getFalseValue()); - e.type = I->getType(); - e.opcode = Expression::SELECT; - - return e; -} - -Expression ValueTable::create_expression(GetElementPtrInst* G) { - Expression e; - - e.firstVN = lookup_or_add(G->getPointerOperand()); - e.secondVN = 0; - e.thirdVN = 0; - e.type = G->getType(); - e.opcode = Expression::GEP; - - for (GetElementPtrInst::op_iterator I = G->idx_begin(), E = G->idx_end(); - I != E; ++I) - e.varargs.push_back(lookup_or_add(*I)); - - return e; -} - -//===----------------------------------------------------------------------===// -// ValueTable External Functions -//===----------------------------------------------------------------------===// - -/// 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 (BinaryOperator* BO = dyn_cast<BinaryOperator>(V)) { - 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); - if (VI != valueNumbering.end()) - return VI->second; - else - assert(0 && "Value not numbered?"); - - return 0; -} - -/// add - Add the specified value with the given value number, removing -/// its old number, if any -void ValueTable::add(Value* V, uint32_t num) { - DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V); - if (VI != valueNumbering.end()) - valueNumbering.erase(VI); - valueNumbering.insert(std::make_pair(V, num)); -} - -/// 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); -} - -/// size - Return the number of assigned value numbers -unsigned ValueTable::size() { - // NOTE: zero is never assigned - return nextValueNumber; -} - -namespace { - -//===----------------------------------------------------------------------===// -// ValueNumberedSet Class -//===----------------------------------------------------------------------===// - -class ValueNumberedSet { - private: - SmallPtrSet<Value*, 8> contents; - BitVector numbers; - public: - ValueNumberedSet() { numbers.resize(1); } - ValueNumberedSet(const ValueNumberedSet& other) { - numbers = other.numbers; - contents = other.contents; - } - - typedef SmallPtrSet<Value*, 8>::iterator iterator; - - iterator begin() { return contents.begin(); } - iterator end() { return contents.end(); } - - bool insert(Value* v) { return contents.insert(v); } - void insert(iterator I, iterator E) { contents.insert(I, E); } - void erase(Value* v) { contents.erase(v); } - unsigned count(Value* v) { return contents.count(v); } - size_t size() { return contents.size(); } - - void set(unsigned i) { - if (i >= numbers.size()) - numbers.resize(i+1); - - numbers.set(i); - } - - void operator=(const ValueNumberedSet& other) { - contents = other.contents; - numbers = other.numbers; - } - - void reset(unsigned i) { - if (i < numbers.size()) - numbers.reset(i); - } - - bool test(unsigned i) { - if (i >= numbers.size()) - return false; - - return numbers.test(i); - } - - void clear() { - contents.clear(); - numbers.clear(); - } -}; - -} - -//===----------------------------------------------------------------------===// -// GVNPRE Pass -//===----------------------------------------------------------------------===// - -namespace { - - class VISIBILITY_HIDDEN GVNPRE : public FunctionPass { - bool runOnFunction(Function &F); - public: - static char ID; // Pass identification, replacement for typeid - GVNPRE() : FunctionPass(&ID) {} - - private: - ValueTable VN; - SmallVector<Instruction*, 8> createdExpressions; - - DenseMap<BasicBlock*, ValueNumberedSet> availableOut; - DenseMap<BasicBlock*, ValueNumberedSet> anticipatedIn; - DenseMap<BasicBlock*, ValueNumberedSet> generatedPhis; - - // This transformation requires dominator postdominator info - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - AU.addRequiredID(BreakCriticalEdgesID); - AU.addRequired<UnifyFunctionExitNodes>(); - AU.addRequired<DominatorTree>(); - } - - // Helper fuctions - // FIXME: eliminate or document these better - void dump(ValueNumberedSet& s) const ; - void clean(ValueNumberedSet& set) ; - Value* find_leader(ValueNumberedSet& vals, uint32_t v) ; - Value* phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) ; - void phi_translate_set(ValueNumberedSet& anticIn, BasicBlock* pred, - BasicBlock* succ, ValueNumberedSet& out) ; - - void topo_sort(ValueNumberedSet& set, - SmallVector<Value*, 8>& vec) ; - - void cleanup() ; - bool elimination() ; - - void val_insert(ValueNumberedSet& s, Value* v) ; - void val_replace(ValueNumberedSet& s, Value* v) ; - bool dependsOnInvoke(Value* V) ; - void buildsets_availout(BasicBlock::iterator I, - ValueNumberedSet& currAvail, - ValueNumberedSet& currPhis, - ValueNumberedSet& currExps, - SmallPtrSet<Value*, 16>& currTemps); - bool buildsets_anticout(BasicBlock* BB, - ValueNumberedSet& anticOut, - SmallPtrSet<BasicBlock*, 8>& visited); - unsigned buildsets_anticin(BasicBlock* BB, - ValueNumberedSet& anticOut, - ValueNumberedSet& currExps, - SmallPtrSet<Value*, 16>& currTemps, - SmallPtrSet<BasicBlock*, 8>& visited); - void buildsets(Function& F) ; - - void insertion_pre(Value* e, BasicBlock* BB, - DenseMap<BasicBlock*, Value*>& avail, - std::map<BasicBlock*,ValueNumberedSet>& new_set); - unsigned insertion_mergepoint(SmallVector<Value*, 8>& workList, - df_iterator<DomTreeNode*>& D, - std::map<BasicBlock*, ValueNumberedSet>& new_set); - bool insertion(Function& F) ; - - }; - - char GVNPRE::ID = 0; - -} - -// createGVNPREPass - The public interface to this file... -FunctionPass *llvm::createGVNPREPass() { return new GVNPRE(); } - -static RegisterPass<GVNPRE> X("gvnpre", - "Global Value Numbering/Partial Redundancy Elimination"); - - -STATISTIC(NumInsertedVals, "Number of values inserted"); -STATISTIC(NumInsertedPhis, "Number of PHI nodes inserted"); -STATISTIC(NumEliminated, "Number of redundant instructions eliminated"); - -/// find_leader - Given a set and a value number, return the first -/// element of the set with that value number, or 0 if no such element -/// is present -Value* GVNPRE::find_leader(ValueNumberedSet& vals, uint32_t v) { - if (!vals.test(v)) - return 0; - - for (ValueNumberedSet::iterator I = vals.begin(), E = vals.end(); - I != E; ++I) - if (v == VN.lookup(*I)) - return *I; - - assert(0 && "No leader found, but present bit is set?"); - return 0; -} - -/// val_insert - Insert a value into a set only if there is not a value -/// with the same value number already in the set -void GVNPRE::val_insert(ValueNumberedSet& s, Value* v) { - uint32_t num = VN.lookup(v); - if (!s.test(num)) - s.insert(v); -} - -/// val_replace - Insert a value into a set, replacing any values already in -/// the set that have the same value number -void GVNPRE::val_replace(ValueNumberedSet& s, Value* v) { - if (s.count(v)) return; - - uint32_t num = VN.lookup(v); - Value* leader = find_leader(s, num); - if (leader != 0) - s.erase(leader); - s.insert(v); - s.set(num); -} - -/// phi_translate - Given a value, its parent block, and a predecessor of its -/// parent, translate the value into legal for the predecessor block. This -/// means translating its operands (and recursively, their operands) through -/// any phi nodes in the parent into values available in the predecessor -Value* GVNPRE::phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) { - if (V == 0) - return 0; - - // Unary Operations - if (CastInst* U = dyn_cast<CastInst>(V)) { - Value* newOp1 = 0; - if (isa<Instruction>(U->getOperand(0))) - newOp1 = phi_translate(U->getOperand(0), pred, succ); - else - newOp1 = U->getOperand(0); - - if (newOp1 == 0) - return 0; - - if (newOp1 != U->getOperand(0)) { - Instruction* newVal = 0; - if (CastInst* C = dyn_cast<CastInst>(U)) - newVal = CastInst::Create(C->getOpcode(), - newOp1, C->getType(), - C->getName()+".expr"); - - uint32_t v = VN.lookup_or_add(newVal); - - Value* leader = find_leader(availableOut[pred], v); - if (leader == 0) { - createdExpressions.push_back(newVal); - return newVal; - } else { - VN.erase(newVal); - delete newVal; - return leader; - } - } - - // Binary Operations - } if (isa<BinaryOperator>(V) || isa<CmpInst>(V) || - isa<ExtractElementInst>(V)) { - User* U = cast<User>(V); - - Value* newOp1 = 0; - if (isa<Instruction>(U->getOperand(0))) - newOp1 = phi_translate(U->getOperand(0), pred, succ); - else - newOp1 = U->getOperand(0); - - if (newOp1 == 0) - return 0; - - Value* newOp2 = 0; - if (isa<Instruction>(U->getOperand(1))) - newOp2 = phi_translate(U->getOperand(1), pred, succ); - else - newOp2 = U->getOperand(1); - - if (newOp2 == 0) - return 0; - - if (newOp1 != U->getOperand(0) || newOp2 != U->getOperand(1)) { - Instruction* newVal = 0; - if (BinaryOperator* BO = dyn_cast<BinaryOperator>(U)) - newVal = BinaryOperator::Create(BO->getOpcode(), - newOp1, newOp2, - BO->getName()+".expr"); - else if (CmpInst* C = dyn_cast<CmpInst>(U)) - newVal = CmpInst::Create(C->getOpcode(), - C->getPredicate(), - newOp1, newOp2, - C->getName()+".expr"); - else if (ExtractElementInst* E = dyn_cast<ExtractElementInst>(U)) - newVal = new ExtractElementInst(newOp1, newOp2, E->getName()+".expr"); - - uint32_t v = VN.lookup_or_add(newVal); - - Value* leader = find_leader(availableOut[pred], v); - if (leader == 0) { - createdExpressions.push_back(newVal); - return newVal; - } else { - VN.erase(newVal); - delete newVal; - return leader; - } - } - - // Ternary Operations - } else if (isa<ShuffleVectorInst>(V) || isa<InsertElementInst>(V) || - isa<SelectInst>(V)) { - User* U = cast<User>(V); - - Value* newOp1 = 0; - if (isa<Instruction>(U->getOperand(0))) - newOp1 = phi_translate(U->getOperand(0), pred, succ); - else - newOp1 = U->getOperand(0); - - if (newOp1 == 0) - return 0; - - Value* newOp2 = 0; - if (isa<Instruction>(U->getOperand(1))) - newOp2 = phi_translate(U->getOperand(1), pred, succ); - else - newOp2 = U->getOperand(1); - - if (newOp2 == 0) - return 0; - - Value* newOp3 = 0; - if (isa<Instruction>(U->getOperand(2))) - newOp3 = phi_translate(U->getOperand(2), pred, succ); - else - newOp3 = U->getOperand(2); - - if (newOp3 == 0) - return 0; - - if (newOp1 != U->getOperand(0) || - newOp2 != U->getOperand(1) || - newOp3 != U->getOperand(2)) { - Instruction* newVal = 0; - if (ShuffleVectorInst* S = dyn_cast<ShuffleVectorInst>(U)) - newVal = new ShuffleVectorInst(newOp1, newOp2, newOp3, - S->getName() + ".expr"); - else if (InsertElementInst* I = dyn_cast<InsertElementInst>(U)) - newVal = InsertElementInst::Create(newOp1, newOp2, newOp3, - I->getName() + ".expr"); - else if (SelectInst* I = dyn_cast<SelectInst>(U)) - newVal = SelectInst::Create(newOp1, newOp2, newOp3, - I->getName() + ".expr"); - - uint32_t v = VN.lookup_or_add(newVal); - - Value* leader = find_leader(availableOut[pred], v); - if (leader == 0) { - createdExpressions.push_back(newVal); - return newVal; - } else { - VN.erase(newVal); - delete newVal; - return leader; - } - } - - // Varargs operators - } else if (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(V)) { - Value* newOp1 = 0; - if (isa<Instruction>(U->getPointerOperand())) - newOp1 = phi_translate(U->getPointerOperand(), pred, succ); - else - newOp1 = U->getPointerOperand(); - - if (newOp1 == 0) - return 0; - - bool changed_idx = false; - SmallVector<Value*, 4> newIdx; - for (GetElementPtrInst::op_iterator I = U->idx_begin(), E = U->idx_end(); - I != E; ++I) - if (isa<Instruction>(*I)) { - Value* newVal = phi_translate(*I, pred, succ); - newIdx.push_back(newVal); - if (newVal != *I) - changed_idx = true; - } else { - newIdx.push_back(*I); - } - - if (newOp1 != U->getPointerOperand() || changed_idx) { - Instruction* newVal = - GetElementPtrInst::Create(newOp1, - newIdx.begin(), newIdx.end(), - U->getName()+".expr"); - - uint32_t v = VN.lookup_or_add(newVal); - - Value* leader = find_leader(availableOut[pred], v); - if (leader == 0) { - createdExpressions.push_back(newVal); - return newVal; - } else { - VN.erase(newVal); - delete newVal; - return leader; - } - } - - // PHI Nodes - } else if (PHINode* P = dyn_cast<PHINode>(V)) { - if (P->getParent() == succ) - return P->getIncomingValueForBlock(pred); - } - - return V; -} - -/// phi_translate_set - Perform phi translation on every element of a set -void GVNPRE::phi_translate_set(ValueNumberedSet& anticIn, - BasicBlock* pred, BasicBlock* succ, - ValueNumberedSet& out) { - for (ValueNumberedSet::iterator I = anticIn.begin(), - E = anticIn.end(); I != E; ++I) { - Value* V = phi_translate(*I, pred, succ); - if (V != 0 && !out.test(VN.lookup_or_add(V))) { - out.insert(V); - out.set(VN.lookup(V)); - } - } -} - -/// dependsOnInvoke - Test if a value has an phi node as an operand, any of -/// whose inputs is an invoke instruction. If this is true, we cannot safely -/// PRE the instruction or anything that depends on it. -bool GVNPRE::dependsOnInvoke(Value* V) { - if (PHINode* p = dyn_cast<PHINode>(V)) { - for (PHINode::op_iterator I = p->op_begin(), E = p->op_end(); I != E; ++I) - if (isa<InvokeInst>(*I)) - return true; - return false; - } else { - return false; - } -} - -/// clean - Remove all non-opaque values from the set whose operands are not -/// themselves in the set, as well as all values that depend on invokes (see -/// above) -void GVNPRE::clean(ValueNumberedSet& set) { - SmallVector<Value*, 8> worklist; - worklist.reserve(set.size()); - topo_sort(set, worklist); - - for (unsigned i = 0; i < worklist.size(); ++i) { - Value* v = worklist[i]; - - // Handle unary ops - if (CastInst* U = dyn_cast<CastInst>(v)) { - bool lhsValid = !isa<Instruction>(U->getOperand(0)); - lhsValid |= set.test(VN.lookup(U->getOperand(0))); - if (lhsValid) - lhsValid = !dependsOnInvoke(U->getOperand(0)); - - if (!lhsValid) { - set.erase(U); - set.reset(VN.lookup(U)); - } - - // Handle binary ops - } else if (isa<BinaryOperator>(v) || isa<CmpInst>(v) || - isa<ExtractElementInst>(v)) { - User* U = cast<User>(v); - - bool lhsValid = !isa<Instruction>(U->getOperand(0)); - lhsValid |= set.test(VN.lookup(U->getOperand(0))); - if (lhsValid) - lhsValid = !dependsOnInvoke(U->getOperand(0)); - - bool rhsValid = !isa<Instruction>(U->getOperand(1)); - rhsValid |= set.test(VN.lookup(U->getOperand(1))); - if (rhsValid) - rhsValid = !dependsOnInvoke(U->getOperand(1)); - - if (!lhsValid || !rhsValid) { - set.erase(U); - set.reset(VN.lookup(U)); - } - - // Handle ternary ops - } else if (isa<ShuffleVectorInst>(v) || isa<InsertElementInst>(v) || - isa<SelectInst>(v)) { - User* U = cast<User>(v); - - bool lhsValid = !isa<Instruction>(U->getOperand(0)); - lhsValid |= set.test(VN.lookup(U->getOperand(0))); - if (lhsValid) - lhsValid = !dependsOnInvoke(U->getOperand(0)); - - bool rhsValid = !isa<Instruction>(U->getOperand(1)); - rhsValid |= set.test(VN.lookup(U->getOperand(1))); - if (rhsValid) - rhsValid = !dependsOnInvoke(U->getOperand(1)); - - bool thirdValid = !isa<Instruction>(U->getOperand(2)); - thirdValid |= set.test(VN.lookup(U->getOperand(2))); - if (thirdValid) - thirdValid = !dependsOnInvoke(U->getOperand(2)); - - if (!lhsValid || !rhsValid || !thirdValid) { - set.erase(U); - set.reset(VN.lookup(U)); - } - - // Handle varargs ops - } else if (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(v)) { - bool ptrValid = !isa<Instruction>(U->getPointerOperand()); - ptrValid |= set.test(VN.lookup(U->getPointerOperand())); - if (ptrValid) - ptrValid = !dependsOnInvoke(U->getPointerOperand()); - - bool varValid = true; - for (GetElementPtrInst::op_iterator I = U->idx_begin(), E = U->idx_end(); - I != E; ++I) - if (varValid) { - varValid &= !isa<Instruction>(*I) || set.test(VN.lookup(*I)); - varValid &= !dependsOnInvoke(*I); - } - - if (!ptrValid || !varValid) { - set.erase(U); - set.reset(VN.lookup(U)); - } - } - } -} - -/// topo_sort - Given a set of values, sort them by topological -/// order into the provided vector. -void GVNPRE::topo_sort(ValueNumberedSet& set, SmallVector<Value*, 8>& vec) { - SmallPtrSet<Value*, 16> visited; - SmallVector<Value*, 8> stack; - for (ValueNumberedSet::iterator I = set.begin(), E = set.end(); - I != E; ++I) { - if (visited.count(*I) == 0) - stack.push_back(*I); - - while (!stack.empty()) { - Value* e = stack.back(); - - // Handle unary ops - if (CastInst* U = dyn_cast<CastInst>(e)) { - Value* l = find_leader(set, VN.lookup(U->getOperand(0))); - - if (l != 0 && isa<Instruction>(l) && - visited.count(l) == 0) - stack.push_back(l); - else { - vec.push_back(e); - visited.insert(e); - stack.pop_back(); - } - - // Handle binary ops - } else if (isa<BinaryOperator>(e) || isa<CmpInst>(e) || - isa<ExtractElementInst>(e)) { - User* U = cast<User>(e); - Value* l = find_leader(set, VN.lookup(U->getOperand(0))); - Value* r = find_leader(set, VN.lookup(U->getOperand(1))); - - if (l != 0 && isa<Instruction>(l) && - visited.count(l) == 0) - stack.push_back(l); - else if (r != 0 && isa<Instruction>(r) && - visited.count(r) == 0) - stack.push_back(r); - else { - vec.push_back(e); - visited.insert(e); - stack.pop_back(); - } - - // Handle ternary ops - } else if (isa<InsertElementInst>(e) || isa<ShuffleVectorInst>(e) || - isa<SelectInst>(e)) { - User* U = cast<User>(e); - Value* l = find_leader(set, VN.lookup(U->getOperand(0))); - Value* r = find_leader(set, VN.lookup(U->getOperand(1))); - Value* m = find_leader(set, VN.lookup(U->getOperand(2))); - - if (l != 0 && isa<Instruction>(l) && - visited.count(l) == 0) - stack.push_back(l); - else if (r != 0 && isa<Instruction>(r) && - visited.count(r) == 0) - stack.push_back(r); - else if (m != 0 && isa<Instruction>(m) && - visited.count(m) == 0) - stack.push_back(m); - else { - vec.push_back(e); - visited.insert(e); - stack.pop_back(); - } - - // Handle vararg ops - } else if (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(e)) { - Value* p = find_leader(set, VN.lookup(U->getPointerOperand())); - - if (p != 0 && isa<Instruction>(p) && - visited.count(p) == 0) - stack.push_back(p); - else { - bool push_va = false; - for (GetElementPtrInst::op_iterator I = U->idx_begin(), - E = U->idx_end(); I != E; ++I) { - Value * v = find_leader(set, VN.lookup(*I)); - if (v != 0 && isa<Instruction>(v) && visited.count(v) == 0) { - stack.push_back(v); - push_va = true; - } - } - - if (!push_va) { - vec.push_back(e); - visited.insert(e); - stack.pop_back(); - } - } - - // Handle opaque ops - } else { - visited.insert(e); - vec.push_back(e); - stack.pop_back(); - } - } - - stack.clear(); - } -} - -/// dump - Dump a set of values to standard error -void GVNPRE::dump(ValueNumberedSet& s) const { - DOUT << "{ "; - for (ValueNumberedSet::iterator I = s.begin(), E = s.end(); - I != E; ++I) { - DOUT << "" << VN.lookup(*I) << ": "; - DEBUG((*I)->dump()); - } - DOUT << "}\n\n"; -} - -/// elimination - Phase 3 of the main algorithm. Perform full redundancy -/// elimination by walking the dominator tree and removing any instruction that -/// is dominated by another instruction with the same value number. -bool GVNPRE::elimination() { - bool changed_function = false; - - SmallVector<std::pair<Instruction*, Value*>, 8> replace; - SmallVector<Instruction*, 8> erase; - - DominatorTree& DT = getAnalysis<DominatorTree>(); - - for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()), - E = df_end(DT.getRootNode()); DI != E; ++DI) { - BasicBlock* BB = DI->getBlock(); - - for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); - BI != BE; ++BI) { - - if (isa<BinaryOperator>(BI) || isa<CmpInst>(BI) || - isa<ShuffleVectorInst>(BI) || isa<InsertElementInst>(BI) || - isa<ExtractElementInst>(BI) || isa<SelectInst>(BI) || - isa<CastInst>(BI) || isa<GetElementPtrInst>(BI)) { - - if (availableOut[BB].test(VN.lookup(BI)) && - !availableOut[BB].count(BI)) { - Value *leader = find_leader(availableOut[BB], VN.lookup(BI)); - if (Instruction* Instr = dyn_cast<Instruction>(leader)) - if (Instr->getParent() != 0 && Instr != BI) { - replace.push_back(std::make_pair(BI, leader)); - erase.push_back(BI); - ++NumEliminated; - } - } - } - } - } - - while (!replace.empty()) { - std::pair<Instruction*, Value*> rep = replace.back(); - replace.pop_back(); - rep.first->replaceAllUsesWith(rep.second); - changed_function = true; - } - - for (SmallVector<Instruction*, 8>::iterator I = erase.begin(), - E = erase.end(); I != E; ++I) - (*I)->eraseFromParent(); - - return changed_function; -} - -/// cleanup - Delete any extraneous values that were created to represent -/// expressions without leaders. -void GVNPRE::cleanup() { - while (!createdExpressions.empty()) { - Instruction* I = createdExpressions.back(); - createdExpressions.pop_back(); - - delete I; - } -} - -/// buildsets_availout - When calculating availability, handle an instruction -/// by inserting it into the appropriate sets -void GVNPRE::buildsets_availout(BasicBlock::iterator I, - ValueNumberedSet& currAvail, - ValueNumberedSet& currPhis, - ValueNumberedSet& currExps, - SmallPtrSet<Value*, 16>& currTemps) { - // Handle PHI nodes - if (PHINode* p = dyn_cast<PHINode>(I)) { - unsigned num = VN.lookup_or_add(p); - - currPhis.insert(p); - currPhis.set(num); - - // Handle unary ops - } else if (CastInst* U = dyn_cast<CastInst>(I)) { - Value* leftValue = U->getOperand(0); - - unsigned num = VN.lookup_or_add(U); - - if (isa<Instruction>(leftValue)) - if (!currExps.test(VN.lookup(leftValue))) { - currExps.insert(leftValue); - currExps.set(VN.lookup(leftValue)); - } - - if (!currExps.test(num)) { - currExps.insert(U); - currExps.set(num); - } - - // Handle binary ops - } else if (isa<BinaryOperator>(I) || isa<CmpInst>(I) || - isa<ExtractElementInst>(I)) { - User* U = cast<User>(I); - Value* leftValue = U->getOperand(0); - Value* rightValue = U->getOperand(1); - - unsigned num = VN.lookup_or_add(U); - - if (isa<Instruction>(leftValue)) - if (!currExps.test(VN.lookup(leftValue))) { - currExps.insert(leftValue); - currExps.set(VN.lookup(leftValue)); - } - - if (isa<Instruction>(rightValue)) - if (!currExps.test(VN.lookup(rightValue))) { - currExps.insert(rightValue); - currExps.set(VN.lookup(rightValue)); - } - - if (!currExps.test(num)) { - currExps.insert(U); - currExps.set(num); - } - - // Handle ternary ops - } else if (isa<InsertElementInst>(I) || isa<ShuffleVectorInst>(I) || - isa<SelectInst>(I)) { - User* U = cast<User>(I); - Value* leftValue = U->getOperand(0); - Value* rightValue = U->getOperand(1); - Value* thirdValue = U->getOperand(2); - - VN.lookup_or_add(U); - - unsigned num = VN.lookup_or_add(U); - - if (isa<Instruction>(leftValue)) - if (!currExps.test(VN.lookup(leftValue))) { - currExps.insert(leftValue); - currExps.set(VN.lookup(leftValue)); - } - if (isa<Instruction>(rightValue)) - if (!currExps.test(VN.lookup(rightValue))) { - currExps.insert(rightValue); - currExps.set(VN.lookup(rightValue)); - } - if (isa<Instruction>(thirdValue)) - if (!currExps.test(VN.lookup(thirdValue))) { - currExps.insert(thirdValue); - currExps.set(VN.lookup(thirdValue)); - } - - if (!currExps.test(num)) { - currExps.insert(U); - currExps.set(num); - } - - // Handle vararg ops - } else if (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(I)) { - Value* ptrValue = U->getPointerOperand(); - - VN.lookup_or_add(U); - - unsigned num = VN.lookup_or_add(U); - - if (isa<Instruction>(ptrValue)) - if (!currExps.test(VN.lookup(ptrValue))) { - currExps.insert(ptrValue); - currExps.set(VN.lookup(ptrValue)); - } - - for (GetElementPtrInst::op_iterator OI = U->idx_begin(), OE = U->idx_end(); - OI != OE; ++OI) - if (isa<Instruction>(*OI) && !currExps.test(VN.lookup(*OI))) { - currExps.insert(*OI); - currExps.set(VN.lookup(*OI)); - } - - if (!currExps.test(VN.lookup(U))) { - currExps.insert(U); - currExps.set(num); - } - - // Handle opaque ops - } else if (!I->isTerminator()){ - VN.lookup_or_add(I); - - currTemps.insert(I); - } - - if (!I->isTerminator()) - if (!currAvail.test(VN.lookup(I))) { - currAvail.insert(I); - currAvail.set(VN.lookup(I)); - } -} - -/// buildsets_anticout - When walking the postdom tree, calculate the ANTIC_OUT -/// set as a function of the ANTIC_IN set of the block's predecessors -bool GVNPRE::buildsets_anticout(BasicBlock* BB, - ValueNumberedSet& anticOut, - SmallPtrSet<BasicBlock*, 8>& visited) { - if (BB->getTerminator()->getNumSuccessors() == 1) { - if (BB->getTerminator()->getSuccessor(0) != BB && - visited.count(BB->getTerminator()->getSuccessor(0)) == 0) { - return true; - } - else { - phi_translate_set(anticipatedIn[BB->getTerminator()->getSuccessor(0)], - BB, BB->getTerminator()->getSuccessor(0), anticOut); - } - } else if (BB->getTerminator()->getNumSuccessors() > 1) { - BasicBlock* first = BB->getTerminator()->getSuccessor(0); - for (ValueNumberedSet::iterator I = anticipatedIn[first].begin(), - E = anticipatedIn[first].end(); I != E; ++I) { - anticOut.insert(*I); - anticOut.set(VN.lookup(*I)); - } - - for (unsigned i = 1; i < BB->getTerminator()->getNumSuccessors(); ++i) { - BasicBlock* currSucc = BB->getTerminator()->getSuccessor(i); - ValueNumberedSet& succAnticIn = anticipatedIn[currSucc]; - - SmallVector<Value*, 16> temp; - - for (ValueNumberedSet::iterator I = anticOut.begin(), - E = anticOut.end(); I != E; ++I) - if (!succAnticIn.test(VN.lookup(*I))) - temp.push_back(*I); - - for (SmallVector<Value*, 16>::iterator I = temp.begin(), E = temp.end(); - I != E; ++I) { - anticOut.erase(*I); - anticOut.reset(VN.lookup(*I)); - } - } - } - - return false; -} - -/// buildsets_anticin - Walk the postdom tree, calculating ANTIC_OUT for -/// each block. ANTIC_IN is then a function of ANTIC_OUT and the GEN -/// sets populated in buildsets_availout -unsigned GVNPRE::buildsets_anticin(BasicBlock* BB, - ValueNumberedSet& anticOut, - ValueNumberedSet& currExps, - SmallPtrSet<Value*, 16>& currTemps, - SmallPtrSet<BasicBlock*, 8>& visited) { - ValueNumberedSet& anticIn = anticipatedIn[BB]; - unsigned old = anticIn.size(); - - bool defer = buildsets_anticout(BB, anticOut, visited); - if (defer) - return 0; - - anticIn.clear(); - - for (ValueNumberedSet::iterator I = anticOut.begin(), - E = anticOut.end(); I != E; ++I) { - anticIn.insert(*I); - anticIn.set(VN.lookup(*I)); - } - for (ValueNumberedSet::iterator I = currExps.begin(), - E = currExps.end(); I != E; ++I) { - if (!anticIn.test(VN.lookup(*I))) { - anticIn.insert(*I); - anticIn.set(VN.lookup(*I)); - } - } - - for (SmallPtrSet<Value*, 16>::iterator I = currTemps.begin(), - E = currTemps.end(); I != E; ++I) { - anticIn.erase(*I); - anticIn.reset(VN.lookup(*I)); - } - - clean(anticIn); - anticOut.clear(); - - if (old != anticIn.size()) - return 2; - else - return 1; -} - -/// buildsets - Phase 1 of the main algorithm. Construct the AVAIL_OUT -/// and the ANTIC_IN sets. -void GVNPRE::buildsets(Function& F) { - DenseMap<BasicBlock*, ValueNumberedSet> generatedExpressions; - DenseMap<BasicBlock*, SmallPtrSet<Value*, 16> > generatedTemporaries; - - DominatorTree &DT = getAnalysis<DominatorTree>(); - - // Phase 1, Part 1: calculate AVAIL_OUT - - // Top-down walk of the dominator tree - for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()), - E = df_end(DT.getRootNode()); DI != E; ++DI) { - - // Get the sets to update for this block - ValueNumberedSet& currExps = generatedExpressions[DI->getBlock()]; - ValueNumberedSet& currPhis = generatedPhis[DI->getBlock()]; - SmallPtrSet<Value*, 16>& currTemps = generatedTemporaries[DI->getBlock()]; - ValueNumberedSet& currAvail = availableOut[DI->getBlock()]; - - BasicBlock* BB = DI->getBlock(); - - // A block inherits AVAIL_OUT from its dominator - if (DI->getIDom() != 0) - currAvail = availableOut[DI->getIDom()->getBlock()]; - - for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); - BI != BE; ++BI) - buildsets_availout(BI, currAvail, currPhis, currExps, - currTemps); - - } - - // Phase 1, Part 2: calculate ANTIC_IN - - SmallPtrSet<BasicBlock*, 8> visited; - SmallPtrSet<BasicBlock*, 4> block_changed; - for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) - block_changed.insert(FI); - - bool changed = true; - unsigned iterations = 0; - - while (changed) { - changed = false; - ValueNumberedSet anticOut; - - // Postorder walk of the CFG - for (po_iterator<BasicBlock*> BBI = po_begin(&F.getEntryBlock()), - BBE = po_end(&F.getEntryBlock()); BBI != BBE; ++BBI) { - BasicBlock* BB = *BBI; - - if (block_changed.count(BB) != 0) { - unsigned ret = buildsets_anticin(BB, anticOut,generatedExpressions[BB], - generatedTemporaries[BB], visited); - - if (ret == 0) { - changed = true; - continue; - } else { - visited.insert(BB); - - if (ret == 2) - for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); - PI != PE; ++PI) { - block_changed.insert(*PI); - } - else - block_changed.erase(BB); - - changed |= (ret == 2); - } - } - } - - iterations++; - } -} - -/// insertion_pre - When a partial redundancy has been identified, eliminate it -/// by inserting appropriate values into the predecessors and a phi node in -/// the main block -void GVNPRE::insertion_pre(Value* e, BasicBlock* BB, - DenseMap<BasicBlock*, Value*>& avail, - std::map<BasicBlock*, ValueNumberedSet>& new_sets) { - for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) { - Value* e2 = avail[*PI]; - if (!availableOut[*PI].test(VN.lookup(e2))) { - User* U = cast<User>(e2); - - Value* s1 = 0; - if (isa<BinaryOperator>(U->getOperand(0)) || - isa<CmpInst>(U->getOperand(0)) || - isa<ShuffleVectorInst>(U->getOperand(0)) || - isa<ExtractElementInst>(U->getOperand(0)) || - isa<InsertElementInst>(U->getOperand(0)) || - isa<SelectInst>(U->getOperand(0)) || - isa<CastInst>(U->getOperand(0)) || - isa<GetElementPtrInst>(U->getOperand(0))) - s1 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(0))); - else - s1 = U->getOperand(0); - - Value* s2 = 0; - - if (isa<BinaryOperator>(U) || - isa<CmpInst>(U) || - isa<ShuffleVectorInst>(U) || - isa<ExtractElementInst>(U) || - isa<InsertElementInst>(U) || - isa<SelectInst>(U)) { - if (isa<BinaryOperator>(U->getOperand(1)) || - isa<CmpInst>(U->getOperand(1)) || - isa<ShuffleVectorInst>(U->getOperand(1)) || - isa<ExtractElementInst>(U->getOperand(1)) || - isa<InsertElementInst>(U->getOperand(1)) || - isa<SelectInst>(U->getOperand(1)) || - isa<CastInst>(U->getOperand(1)) || - isa<GetElementPtrInst>(U->getOperand(1))) { - s2 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(1))); - } else { - s2 = U->getOperand(1); - } - } - - // Ternary Operators - Value* s3 = 0; - if (isa<ShuffleVectorInst>(U) || - isa<InsertElementInst>(U) || - isa<SelectInst>(U)) { - if (isa<BinaryOperator>(U->getOperand(2)) || - isa<CmpInst>(U->getOperand(2)) || - isa<ShuffleVectorInst>(U->getOperand(2)) || - isa<ExtractElementInst>(U->getOperand(2)) || - isa<InsertElementInst>(U->getOperand(2)) || - isa<SelectInst>(U->getOperand(2)) || - isa<CastInst>(U->getOperand(2)) || - isa<GetElementPtrInst>(U->getOperand(2))) { - s3 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(2))); - } else { - s3 = U->getOperand(2); - } - } - - // Vararg operators - SmallVector<Value*, 4> sVarargs; - if (GetElementPtrInst* G = dyn_cast<GetElementPtrInst>(U)) { - for (GetElementPtrInst::op_iterator OI = G->idx_begin(), - OE = G->idx_end(); OI != OE; ++OI) { - if (isa<BinaryOperator>(*OI) || - isa<CmpInst>(*OI) || - isa<ShuffleVectorInst>(*OI) || - isa<ExtractElementInst>(*OI) || - isa<InsertElementInst>(*OI) || - isa<SelectInst>(*OI) || - isa<CastInst>(*OI) || - isa<GetElementPtrInst>(*OI)) { - sVarargs.push_back(find_leader(availableOut[*PI], - VN.lookup(*OI))); - } else { - sVarargs.push_back(*OI); - } - } - } - - Value* newVal = 0; - if (BinaryOperator* BO = dyn_cast<BinaryOperator>(U)) - newVal = BinaryOperator::Create(BO->getOpcode(), s1, s2, - BO->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (CmpInst* C = dyn_cast<CmpInst>(U)) - newVal = CmpInst::Create(C->getOpcode(), C->getPredicate(), s1, s2, - C->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (ShuffleVectorInst* S = dyn_cast<ShuffleVectorInst>(U)) - newVal = new ShuffleVectorInst(s1, s2, s3, S->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (InsertElementInst* S = dyn_cast<InsertElementInst>(U)) - newVal = InsertElementInst::Create(s1, s2, s3, S->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (ExtractElementInst* S = dyn_cast<ExtractElementInst>(U)) - newVal = new ExtractElementInst(s1, s2, S->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (SelectInst* S = dyn_cast<SelectInst>(U)) - newVal = SelectInst::Create(s1, s2, s3, S->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (CastInst* C = dyn_cast<CastInst>(U)) - newVal = CastInst::Create(C->getOpcode(), s1, C->getType(), - C->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (GetElementPtrInst* G = dyn_cast<GetElementPtrInst>(U)) - newVal = GetElementPtrInst::Create(s1, sVarargs.begin(), sVarargs.end(), - G->getName()+".gvnpre", - (*PI)->getTerminator()); - - VN.add(newVal, VN.lookup(U)); - - ValueNumberedSet& predAvail = availableOut[*PI]; - val_replace(predAvail, newVal); - val_replace(new_sets[*PI], newVal); - predAvail.set(VN.lookup(newVal)); - - DenseMap<BasicBlock*, Value*>::iterator av = avail.find(*PI); - if (av != avail.end()) - avail.erase(av); - avail.insert(std::make_pair(*PI, newVal)); - - ++NumInsertedVals; - } - } - - PHINode* p = 0; - - for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) { - if (p == 0) - p = PHINode::Create(avail[*PI]->getType(), "gvnpre-join", BB->begin()); - - p->addIncoming(avail[*PI], *PI); - } - - VN.add(p, VN.lookup(e)); - val_replace(availableOut[BB], p); - availableOut[BB].set(VN.lookup(e)); - generatedPhis[BB].insert(p); - generatedPhis[BB].set(VN.lookup(e)); - new_sets[BB].insert(p); - new_sets[BB].set(VN.lookup(e)); - - ++NumInsertedPhis; -} - -/// insertion_mergepoint - When walking the dom tree, check at each merge -/// block for the possibility of a partial redundancy. If present, eliminate it -unsigned GVNPRE::insertion_mergepoint(SmallVector<Value*, 8>& workList, - df_iterator<DomTreeNode*>& D, - std::map<BasicBlock*, ValueNumberedSet >& new_sets) { - bool changed_function = false; - bool new_stuff = false; - - BasicBlock* BB = D->getBlock(); - for (unsigned i = 0; i < workList.size(); ++i) { - Value* e = workList[i]; - - if (isa<BinaryOperator>(e) || isa<CmpInst>(e) || - isa<ExtractElementInst>(e) || isa<InsertElementInst>(e) || - isa<ShuffleVectorInst>(e) || isa<SelectInst>(e) || isa<CastInst>(e) || - isa<GetElementPtrInst>(e)) { - if (availableOut[D->getIDom()->getBlock()].test(VN.lookup(e))) - continue; - - DenseMap<BasicBlock*, Value*> avail; - bool by_some = false; - bool all_same = true; - Value * first_s = 0; - - for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; - ++PI) { - Value *e2 = phi_translate(e, *PI, BB); - Value *e3 = find_leader(availableOut[*PI], VN.lookup(e2)); - - if (e3 == 0) { - DenseMap<BasicBlock*, Value*>::iterator av = avail.find(*PI); - if (av != avail.end()) - avail.erase(av); - avail.insert(std::make_pair(*PI, e2)); - all_same = false; - } else { - DenseMap<BasicBlock*, Value*>::iterator av = avail.find(*PI); - if (av != avail.end()) - avail.erase(av); - avail.insert(std::make_pair(*PI, e3)); - - by_some = true; - if (first_s == 0) - first_s = e3; - else if (first_s != e3) - all_same = false; - } - } - - if (by_some && !all_same && - !generatedPhis[BB].test(VN.lookup(e))) { - insertion_pre(e, BB, avail, new_sets); - - changed_function = true; - new_stuff = true; - } - } - } - - unsigned retval = 0; - if (changed_function) - retval += 1; - if (new_stuff) - retval += 2; - - return retval; -} - -/// insert - Phase 2 of the main algorithm. Walk the dominator tree looking for -/// merge points. When one is found, check for a partial redundancy. If one is -/// present, eliminate it. Repeat this walk until no changes are made. -bool GVNPRE::insertion(Function& F) { - bool changed_function = false; - - DominatorTree &DT = getAnalysis<DominatorTree>(); - - std::map<BasicBlock*, ValueNumberedSet> new_sets; - bool new_stuff = true; - while (new_stuff) { - new_stuff = false; - for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()), - E = df_end(DT.getRootNode()); DI != E; ++DI) { - BasicBlock* BB = DI->getBlock(); - - if (BB == 0) - continue; - - ValueNumberedSet& availOut = availableOut[BB]; - ValueNumberedSet& anticIn = anticipatedIn[BB]; - - // Replace leaders with leaders inherited from dominator - if (DI->getIDom() != 0) { - ValueNumberedSet& dom_set = new_sets[DI->getIDom()->getBlock()]; - for (ValueNumberedSet::iterator I = dom_set.begin(), - E = dom_set.end(); I != E; ++I) { - val_replace(new_sets[BB], *I); - val_replace(availOut, *I); - } - } - - // If there is more than one predecessor... - if (pred_begin(BB) != pred_end(BB) && ++pred_begin(BB) != pred_end(BB)) { - SmallVector<Value*, 8> workList; - workList.reserve(anticIn.size()); - topo_sort(anticIn, workList); - - unsigned result = insertion_mergepoint(workList, DI, new_sets); - if (result & 1) - changed_function = true; - if (result & 2) - new_stuff = true; - } - } - } - - return changed_function; -} - -// GVNPRE::runOnFunction - This is the main transformation entry point for a -// function. -// -bool GVNPRE::runOnFunction(Function &F) { - // Clean out global sets from any previous functions - VN.clear(); - createdExpressions.clear(); - availableOut.clear(); - anticipatedIn.clear(); - generatedPhis.clear(); - - bool changed_function = false; - - // Phase 1: BuildSets - // This phase calculates the AVAIL_OUT and ANTIC_IN sets - buildsets(F); - - // Phase 2: Insert - // This phase inserts values to make partially redundant values - // fully redundant - changed_function |= insertion(F); - - // Phase 3: Eliminate - // This phase performs trivial full redundancy elimination - changed_function |= elimination(); - - // Phase 4: Cleanup - // This phase cleans up values that were created solely - // as leaders for expressions - cleanup(); - - return changed_function; -} |