| //===- SCCVN.cpp - Eliminate redundant values -----------------------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This pass performs global value numbering to eliminate fully redundant |
| // instructions. This is based on the paper "SCC-based Value Numbering" |
| // by Cooper, et al. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #define DEBUG_TYPE "sccvn" |
| #include "llvm/Transforms/Scalar.h" |
| #include "llvm/BasicBlock.h" |
| #include "llvm/Constants.h" |
| #include "llvm/DerivedTypes.h" |
| #include "llvm/Function.h" |
| #include "llvm/Operator.h" |
| #include "llvm/Value.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/SparseBitVector.h" |
| #include "llvm/ADT/Statistic.h" |
| #include "llvm/Analysis/Dominators.h" |
| #include "llvm/Support/CFG.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Transforms/Utils/SSAUpdater.h" |
| using namespace llvm; |
| |
| STATISTIC(NumSCCVNInstr, "Number of instructions deleted by SCCVN"); |
| STATISTIC(NumSCCVNPhi, "Number of phis deleted by SCCVN"); |
| |
| //===----------------------------------------------------------------------===// |
| // ValueTable Class |
| //===----------------------------------------------------------------------===// |
| |
| /// This class holds the mapping between values and value numbers. It is used |
| /// as an efficient mechanism to determine the expression-wise equivalence of |
| /// two values. |
| namespace { |
| struct Expression { |
| enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL, |
| UDIV, SDIV, FDIV, UREM, SREM, |
| FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ, |
| ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE, |
| ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ, |
| FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE, |
| FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE, |
| FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT, |
| SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI, |
| FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT, |
| PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, CONSTANT, |
| INSERTVALUE, EXTRACTVALUE, EMPTY, TOMBSTONE }; |
| |
| ExpressionOpcode opcode; |
| const Type* type; |
| SmallVector<uint32_t, 4> varargs; |
| |
| 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 (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 { |
| return !(*this == other); |
| } |
| }; |
| |
| class ValueTable { |
| private: |
| DenseMap<Value*, uint32_t> valueNumbering; |
| DenseMap<Expression, uint32_t> expressionNumbering; |
| DenseMap<Value*, uint32_t> constantsNumbering; |
| |
| 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(ExtractValueInst* C); |
| Expression create_expression(InsertValueInst* C); |
| public: |
| ValueTable() : nextValueNumber(1) { } |
| uint32_t computeNumber(Value *V); |
| uint32_t lookup(Value *V); |
| void add(Value *V, uint32_t num); |
| void clear(); |
| void clearExpressions(); |
| void erase(Value *v); |
| unsigned size(); |
| void verifyRemoved(const Value *) const; |
| }; |
| } |
| |
| 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 = ((unsigned)((uintptr_t)e.type >> 4) ^ |
| (unsigned)((uintptr_t)e.type >> 9)); |
| |
| 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; |
| } |
| }; |
| template <> |
| struct isPodLike<Expression> { static const bool value = true; }; |
| |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // ValueTable Internal Functions |
| //===----------------------------------------------------------------------===// |
| Expression::ExpressionOpcode ValueTable::getOpcode(BinaryOperator* BO) { |
| switch(BO->getOpcode()) { |
| default: // THIS SHOULD NEVER HAPPEN |
| llvm_unreachable("Binary operator with unknown opcode?"); |
| case Instruction::Add: return Expression::ADD; |
| case Instruction::FAdd: return Expression::FADD; |
| case Instruction::Sub: return Expression::SUB; |
| case Instruction::FSub: return Expression::FSUB; |
| case Instruction::Mul: return Expression::MUL; |
| case Instruction::FMul: return Expression::FMUL; |
| case Instruction::UDiv: return Expression::UDIV; |
| case Instruction::SDiv: return Expression::SDIV; |
| case Instruction::FDiv: return Expression::FDIV; |
| case Instruction::URem: return Expression::UREM; |
| case Instruction::SRem: return Expression::SREM; |
| case Instruction::FRem: return Expression::FREM; |
| case Instruction::Shl: return Expression::SHL; |
| case Instruction::LShr: return Expression::LSHR; |
| case Instruction::AShr: return Expression::ASHR; |
| case Instruction::And: return Expression::AND; |
| case Instruction::Or: return Expression::OR; |
| case Instruction::Xor: return Expression::XOR; |
| } |
| } |
| |
| Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) { |
| if (isa<ICmpInst>(C)) { |
| switch (C->getPredicate()) { |
| default: // THIS SHOULD NEVER HAPPEN |
| llvm_unreachable("Comparison with unknown predicate?"); |
| case ICmpInst::ICMP_EQ: return Expression::ICMPEQ; |
| case ICmpInst::ICMP_NE: return Expression::ICMPNE; |
| case ICmpInst::ICMP_UGT: return Expression::ICMPUGT; |
| case ICmpInst::ICMP_UGE: return Expression::ICMPUGE; |
| case ICmpInst::ICMP_ULT: return Expression::ICMPULT; |
| case ICmpInst::ICMP_ULE: return Expression::ICMPULE; |
| case ICmpInst::ICMP_SGT: return Expression::ICMPSGT; |
| case ICmpInst::ICMP_SGE: return Expression::ICMPSGE; |
| case ICmpInst::ICMP_SLT: return Expression::ICMPSLT; |
| case ICmpInst::ICMP_SLE: return Expression::ICMPSLE; |
| } |
| } else { |
| switch (C->getPredicate()) { |
| default: // THIS SHOULD NEVER HAPPEN |
| llvm_unreachable("Comparison with unknown predicate?"); |
| case FCmpInst::FCMP_OEQ: return Expression::FCMPOEQ; |
| case FCmpInst::FCMP_OGT: return Expression::FCMPOGT; |
| case FCmpInst::FCMP_OGE: return Expression::FCMPOGE; |
| case FCmpInst::FCMP_OLT: return Expression::FCMPOLT; |
| case FCmpInst::FCMP_OLE: return Expression::FCMPOLE; |
| case FCmpInst::FCMP_ONE: return Expression::FCMPONE; |
| case FCmpInst::FCMP_ORD: return Expression::FCMPORD; |
| case FCmpInst::FCMP_UNO: return Expression::FCMPUNO; |
| case FCmpInst::FCMP_UEQ: return Expression::FCMPUEQ; |
| case FCmpInst::FCMP_UGT: return Expression::FCMPUGT; |
| case FCmpInst::FCMP_UGE: return Expression::FCMPUGE; |
| case FCmpInst::FCMP_ULT: return Expression::FCMPULT; |
| case FCmpInst::FCMP_ULE: return Expression::FCMPULE; |
| case FCmpInst::FCMP_UNE: return Expression::FCMPUNE; |
| } |
| } |
| } |
| |
| Expression::ExpressionOpcode ValueTable::getOpcode(CastInst* C) { |
| switch(C->getOpcode()) { |
| default: // THIS SHOULD NEVER HAPPEN |
| llvm_unreachable("Cast operator with unknown opcode?"); |
| case Instruction::Trunc: return Expression::TRUNC; |
| case Instruction::ZExt: return Expression::ZEXT; |
| case Instruction::SExt: return Expression::SEXT; |
| case Instruction::FPToUI: return Expression::FPTOUI; |
| case Instruction::FPToSI: return Expression::FPTOSI; |
| case Instruction::UIToFP: return Expression::UITOFP; |
| case Instruction::SIToFP: return Expression::SITOFP; |
| case Instruction::FPTrunc: return Expression::FPTRUNC; |
| case Instruction::FPExt: return Expression::FPEXT; |
| case Instruction::PtrToInt: return Expression::PTRTOINT; |
| case Instruction::IntToPtr: return Expression::INTTOPTR; |
| case Instruction::BitCast: return Expression::BITCAST; |
| } |
| } |
| |
| Expression ValueTable::create_expression(CallInst* C) { |
| Expression e; |
| |
| e.type = C->getType(); |
| e.opcode = Expression::CALL; |
| |
| e.varargs.push_back(lookup(C->getCalledFunction())); |
| for (CallInst::op_iterator I = C->op_begin()+1, E = C->op_end(); |
| I != E; ++I) |
| e.varargs.push_back(lookup(*I)); |
| |
| return e; |
| } |
| |
| Expression ValueTable::create_expression(BinaryOperator* BO) { |
| Expression e; |
| e.varargs.push_back(lookup(BO->getOperand(0))); |
| e.varargs.push_back(lookup(BO->getOperand(1))); |
| e.type = BO->getType(); |
| e.opcode = getOpcode(BO); |
| |
| return e; |
| } |
| |
| Expression ValueTable::create_expression(CmpInst* C) { |
| Expression e; |
| |
| e.varargs.push_back(lookup(C->getOperand(0))); |
| e.varargs.push_back(lookup(C->getOperand(1))); |
| e.type = C->getType(); |
| e.opcode = getOpcode(C); |
| |
| return e; |
| } |
| |
| Expression ValueTable::create_expression(CastInst* C) { |
| Expression e; |
| |
| e.varargs.push_back(lookup(C->getOperand(0))); |
| e.type = C->getType(); |
| e.opcode = getOpcode(C); |
| |
| return e; |
| } |
| |
| Expression ValueTable::create_expression(ShuffleVectorInst* S) { |
| Expression e; |
| |
| e.varargs.push_back(lookup(S->getOperand(0))); |
| e.varargs.push_back(lookup(S->getOperand(1))); |
| e.varargs.push_back(lookup(S->getOperand(2))); |
| e.type = S->getType(); |
| e.opcode = Expression::SHUFFLE; |
| |
| return e; |
| } |
| |
| Expression ValueTable::create_expression(ExtractElementInst* E) { |
| Expression e; |
| |
| e.varargs.push_back(lookup(E->getOperand(0))); |
| e.varargs.push_back(lookup(E->getOperand(1))); |
| e.type = E->getType(); |
| e.opcode = Expression::EXTRACT; |
| |
| return e; |
| } |
| |
| Expression ValueTable::create_expression(InsertElementInst* I) { |
| Expression e; |
| |
| e.varargs.push_back(lookup(I->getOperand(0))); |
| e.varargs.push_back(lookup(I->getOperand(1))); |
| e.varargs.push_back(lookup(I->getOperand(2))); |
| e.type = I->getType(); |
| e.opcode = Expression::INSERT; |
| |
| return e; |
| } |
| |
| Expression ValueTable::create_expression(SelectInst* I) { |
| Expression e; |
| |
| e.varargs.push_back(lookup(I->getCondition())); |
| e.varargs.push_back(lookup(I->getTrueValue())); |
| e.varargs.push_back(lookup(I->getFalseValue())); |
| e.type = I->getType(); |
| e.opcode = Expression::SELECT; |
| |
| return e; |
| } |
| |
| Expression ValueTable::create_expression(GetElementPtrInst* G) { |
| Expression e; |
| |
| e.varargs.push_back(lookup(G->getPointerOperand())); |
| 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(*I)); |
| |
| return e; |
| } |
| |
| Expression ValueTable::create_expression(ExtractValueInst* E) { |
| Expression e; |
| |
| e.varargs.push_back(lookup(E->getAggregateOperand())); |
| for (ExtractValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end(); |
| II != IE; ++II) |
| e.varargs.push_back(*II); |
| e.type = E->getType(); |
| e.opcode = Expression::EXTRACTVALUE; |
| |
| return e; |
| } |
| |
| Expression ValueTable::create_expression(InsertValueInst* E) { |
| Expression e; |
| |
| e.varargs.push_back(lookup(E->getAggregateOperand())); |
| e.varargs.push_back(lookup(E->getInsertedValueOperand())); |
| for (InsertValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end(); |
| II != IE; ++II) |
| e.varargs.push_back(*II); |
| e.type = E->getType(); |
| e.opcode = Expression::INSERTVALUE; |
| |
| return e; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // ValueTable External Functions |
| //===----------------------------------------------------------------------===// |
| |
| /// add - Insert a value into the table with a specified value number. |
| void ValueTable::add(Value *V, uint32_t num) { |
| valueNumbering[V] = num; |
| } |
| |
| /// computeNumber - Returns the value number for the specified value, assigning |
| /// it a new number if it did not have one before. |
| uint32_t ValueTable::computeNumber(Value *V) { |
| if (uint32_t v = valueNumbering[V]) |
| return v; |
| else if (uint32_t v= constantsNumbering[V]) |
| return v; |
| |
| if (!isa<Instruction>(V)) { |
| constantsNumbering[V] = nextValueNumber; |
| return nextValueNumber++; |
| } |
| |
| Instruction* I = cast<Instruction>(V); |
| Expression exp; |
| switch (I->getOpcode()) { |
| case Instruction::Add: |
| case Instruction::FAdd: |
| case Instruction::Sub: |
| case Instruction::FSub: |
| case Instruction::Mul: |
| case Instruction::FMul: |
| case Instruction::UDiv: |
| case Instruction::SDiv: |
| case Instruction::FDiv: |
| case Instruction::URem: |
| case Instruction::SRem: |
| case Instruction::FRem: |
| case Instruction::Shl: |
| case Instruction::LShr: |
| case Instruction::AShr: |
| case Instruction::And: |
| case Instruction::Or : |
| case Instruction::Xor: |
| exp = create_expression(cast<BinaryOperator>(I)); |
| break; |
| case Instruction::ICmp: |
| case Instruction::FCmp: |
| exp = create_expression(cast<CmpInst>(I)); |
| break; |
| case Instruction::Trunc: |
| case Instruction::ZExt: |
| case Instruction::SExt: |
| case Instruction::FPToUI: |
| case Instruction::FPToSI: |
| case Instruction::UIToFP: |
| case Instruction::SIToFP: |
| case Instruction::FPTrunc: |
| case Instruction::FPExt: |
| case Instruction::PtrToInt: |
| case Instruction::IntToPtr: |
| case Instruction::BitCast: |
| exp = create_expression(cast<CastInst>(I)); |
| break; |
| case Instruction::Select: |
| exp = create_expression(cast<SelectInst>(I)); |
| break; |
| case Instruction::ExtractElement: |
| exp = create_expression(cast<ExtractElementInst>(I)); |
| break; |
| case Instruction::InsertElement: |
| exp = create_expression(cast<InsertElementInst>(I)); |
| break; |
| case Instruction::ShuffleVector: |
| exp = create_expression(cast<ShuffleVectorInst>(I)); |
| break; |
| case Instruction::ExtractValue: |
| exp = create_expression(cast<ExtractValueInst>(I)); |
| break; |
| case Instruction::InsertValue: |
| exp = create_expression(cast<InsertValueInst>(I)); |
| break; |
| case Instruction::GetElementPtr: |
| exp = create_expression(cast<GetElementPtrInst>(I)); |
| break; |
| default: |
| valueNumbering[V] = nextValueNumber; |
| return nextValueNumber++; |
| } |
| |
| uint32_t& e = expressionNumbering[exp]; |
| if (!e) e = nextValueNumber++; |
| valueNumbering[V] = e; |
| |
| return e; |
| } |
| |
| /// lookup - Returns the value number of the specified value. Returns 0 if |
| /// the value has not yet been numbered. |
| uint32_t ValueTable::lookup(Value *V) { |
| if (!isa<Instruction>(V)) { |
| if (!constantsNumbering.count(V)) |
| constantsNumbering[V] = nextValueNumber++; |
| return constantsNumbering[V]; |
| } |
| |
| return valueNumbering[V]; |
| } |
| |
| /// clear - Remove all entries from the ValueTable |
| void ValueTable::clear() { |
| valueNumbering.clear(); |
| expressionNumbering.clear(); |
| constantsNumbering.clear(); |
| nextValueNumber = 1; |
| } |
| |
| void ValueTable::clearExpressions() { |
| expressionNumbering.clear(); |
| constantsNumbering.clear(); |
| nextValueNumber = 1; |
| } |
| |
| /// erase - Remove a value from the value numbering |
| void ValueTable::erase(Value *V) { |
| valueNumbering.erase(V); |
| } |
| |
| /// verifyRemoved - Verify that the value is removed from all internal data |
| /// structures. |
| void ValueTable::verifyRemoved(const Value *V) const { |
| for (DenseMap<Value*, uint32_t>::const_iterator |
| I = valueNumbering.begin(), E = valueNumbering.end(); I != E; ++I) { |
| assert(I->first != V && "Inst still occurs in value numbering map!"); |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // SCCVN Pass |
| //===----------------------------------------------------------------------===// |
| |
| namespace { |
| |
| struct ValueNumberScope { |
| ValueNumberScope* parent; |
| DenseMap<uint32_t, Value*> table; |
| SparseBitVector<128> availIn; |
| SparseBitVector<128> availOut; |
| |
| ValueNumberScope(ValueNumberScope* p) : parent(p) { } |
| }; |
| |
| class SCCVN : public FunctionPass { |
| bool runOnFunction(Function &F); |
| public: |
| static char ID; // Pass identification, replacement for typeid |
| SCCVN() : FunctionPass(&ID) { } |
| |
| private: |
| ValueTable VT; |
| DenseMap<BasicBlock*, ValueNumberScope*> BBMap; |
| |
| // This transformation requires dominator postdominator info |
| virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| AU.addRequired<DominatorTree>(); |
| |
| AU.addPreserved<DominatorTree>(); |
| AU.setPreservesCFG(); |
| } |
| }; |
| |
| char SCCVN::ID = 0; |
| } |
| |
| // createSCCVNPass - The public interface to this file... |
| FunctionPass *llvm::createSCCVNPass() { return new SCCVN(); } |
| |
| static RegisterPass<SCCVN> X("sccvn", |
| "SCC Value Numbering"); |
| |
| static Value *lookupNumber(ValueNumberScope *Locals, uint32_t num) { |
| while (Locals) { |
| DenseMap<uint32_t, Value*>::iterator I = Locals->table.find(num); |
| if (I != Locals->table.end()) |
| return I->second; |
| Locals = Locals->parent; |
| } |
| |
| return 0; |
| } |
| |
| bool SCCVN::runOnFunction(Function& F) { |
| // Implement the RPO version of the SCCVN algorithm. Conceptually, |
| // we optimisitically assume that all instructions with the same opcode have |
| // the same VN. Then we deepen our comparison by one level, to all |
| // instructions whose operands have the same opcodes get the same VN. We |
| // iterate this process until the partitioning stops changing, at which |
| // point we have computed a full numbering. |
| ReversePostOrderTraversal<Function*> RPOT(&F); |
| bool done = false; |
| while (!done) { |
| done = true; |
| VT.clearExpressions(); |
| for (ReversePostOrderTraversal<Function*>::rpo_iterator I = RPOT.begin(), |
| E = RPOT.end(); I != E; ++I) { |
| BasicBlock* BB = *I; |
| for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); |
| BI != BE; ++BI) { |
| uint32_t origVN = VT.lookup(BI); |
| uint32_t newVN = VT.computeNumber(BI); |
| if (origVN != newVN) |
| done = false; |
| } |
| } |
| } |
| |
| // Now, do a dominator walk, eliminating simple, dominated redundancies as we |
| // go. Also, build the ValueNumberScope structure that will be used for |
| // computing full availability. |
| DominatorTree& DT = getAnalysis<DominatorTree>(); |
| bool changed = false; |
| for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()), |
| DE = df_end(DT.getRootNode()); DI != DE; ++DI) { |
| BasicBlock* BB = DI->getBlock(); |
| if (DI->getIDom()) |
| BBMap[BB] = new ValueNumberScope(BBMap[DI->getIDom()->getBlock()]); |
| else |
| BBMap[BB] = new ValueNumberScope(0); |
| |
| for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { |
| uint32_t num = VT.lookup(I); |
| Value* repl = lookupNumber(BBMap[BB], num); |
| |
| if (repl) { |
| if (isa<PHINode>(I)) |
| ++NumSCCVNPhi; |
| else |
| ++NumSCCVNInstr; |
| I->replaceAllUsesWith(repl); |
| Instruction* OldInst = I; |
| ++I; |
| BBMap[BB]->table[num] = repl; |
| OldInst->eraseFromParent(); |
| changed = true; |
| } else { |
| BBMap[BB]->table[num] = I; |
| BBMap[BB]->availOut.set(num); |
| |
| ++I; |
| } |
| } |
| } |
| |
| // Perform a forward data-flow to compute availability at all points on |
| // the CFG. |
| do { |
| changed = false; |
| for (ReversePostOrderTraversal<Function*>::rpo_iterator I = RPOT.begin(), |
| E = RPOT.end(); I != E; ++I) { |
| BasicBlock* BB = *I; |
| ValueNumberScope *VNS = BBMap[BB]; |
| |
| SparseBitVector<128> preds; |
| bool first = true; |
| for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); |
| PI != PE; ++PI) { |
| if (first) { |
| preds = BBMap[*PI]->availOut; |
| first = false; |
| } else { |
| preds &= BBMap[*PI]->availOut; |
| } |
| } |
| |
| changed |= (VNS->availIn |= preds); |
| changed |= (VNS->availOut |= preds); |
| } |
| } while (changed); |
| |
| // Use full availability information to perform non-dominated replacements. |
| SSAUpdater SSU; |
| for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) { |
| if (!BBMap.count(FI)) continue; |
| for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); |
| BI != BE; ) { |
| uint32_t num = VT.lookup(BI); |
| if (!BBMap[FI]->availIn.test(num)) { |
| ++BI; |
| continue; |
| } |
| |
| SSU.Initialize(BI); |
| |
| SmallPtrSet<BasicBlock*, 8> visited; |
| SmallVector<BasicBlock*, 8> stack; |
| visited.insert(FI); |
| for (pred_iterator PI = pred_begin(FI), PE = pred_end(FI); |
| PI != PE; ++PI) |
| if (!visited.count(*PI)) |
| stack.push_back(*PI); |
| |
| while (!stack.empty()) { |
| BasicBlock* CurrBB = stack.pop_back_val(); |
| visited.insert(CurrBB); |
| |
| ValueNumberScope* S = BBMap[CurrBB]; |
| if (S->table.count(num)) { |
| SSU.AddAvailableValue(CurrBB, S->table[num]); |
| } else { |
| for (pred_iterator PI = pred_begin(CurrBB), PE = pred_end(CurrBB); |
| PI != PE; ++PI) |
| if (!visited.count(*PI)) |
| stack.push_back(*PI); |
| } |
| } |
| |
| Value* repl = SSU.GetValueInMiddleOfBlock(FI); |
| BI->replaceAllUsesWith(repl); |
| Instruction* CurInst = BI; |
| ++BI; |
| BBMap[FI]->table[num] = repl; |
| if (isa<PHINode>(CurInst)) |
| ++NumSCCVNPhi; |
| else |
| ++NumSCCVNInstr; |
| |
| CurInst->eraseFromParent(); |
| } |
| } |
| |
| VT.clear(); |
| for (DenseMap<BasicBlock*, ValueNumberScope*>::iterator |
| I = BBMap.begin(), E = BBMap.end(); I != E; ++I) |
| delete I->second; |
| BBMap.clear(); |
| |
| return changed; |
| } |