mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91666 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			718 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			718 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===- 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.back();
 | |
|         stack.pop_back();
 | |
|         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;
 | |
| }
 |