Skip to content
GVN.cpp 77.4 KiB
Newer Older
//===- GVN.cpp - Eliminate redundant values and loads ---------------------===//
// 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.  It also performs simple dead load elimination.
//
// Note that this pass does the value numbering itself; it does not use the
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "gvn"
#include "llvm/Transforms/Scalar.h"
Devang Patel's avatar
Devang Patel committed
#include "llvm/IntrinsicInst.h"
#include "llvm/Operator.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Analysis/PHITransAddr.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/SSAUpdater.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/IRBuilder.h"
STATISTIC(NumGVNInstr,  "Number of instructions deleted");
STATISTIC(NumGVNLoad,   "Number of loads deleted");
STATISTIC(NumGVNPRE,    "Number of instructions PRE'd");
STATISTIC(NumGVNBlocks, "Number of blocks merged");
STATISTIC(NumPRELoad,   "Number of loads PRE'd");
static cl::opt<bool> EnablePRE("enable-pre",
                               cl::init(true), cl::Hidden);
static cl::opt<bool> EnableLoadPRE("enable-load-pre", cl::init(true));
//===----------------------------------------------------------------------===//
//                         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 {
    enum ExpressionOpcode { 
      ADD = Instruction::Add,
      FADD = Instruction::FAdd,
      SUB = Instruction::Sub,
      FSUB = Instruction::FSub,
      MUL = Instruction::Mul,
      FMUL = Instruction::FMul,
      UDIV = Instruction::UDiv,
      SDIV = Instruction::SDiv,
      FDIV = Instruction::FDiv,
      UREM = Instruction::URem,
      SREM = Instruction::SRem,
      FREM = Instruction::FRem,
      SHL = Instruction::Shl,
      LSHR = Instruction::LShr,
      ASHR = Instruction::AShr,
      AND = Instruction::And,
      OR = Instruction::Or,
      XOR = Instruction::Xor,
      TRUNC = Instruction::Trunc,
      ZEXT = Instruction::ZExt,
      SEXT = Instruction::SExt,
      FPTOUI = Instruction::FPToUI,
      FPTOSI = Instruction::FPToSI,
      UITOFP = Instruction::UIToFP,
      SITOFP = Instruction::SIToFP,
      FPTRUNC = Instruction::FPTrunc,
      FPEXT = Instruction::FPExt,
      PTRTOINT = Instruction::PtrToInt,
      INTTOPTR = Instruction::IntToPtr,
      BITCAST = Instruction::BitCast,
      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, 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 (function != other.function)
        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;
Chris Lattner's avatar
Chris Lattner committed
    /*bool operator!=(const Expression &other) const {
Chris Lattner's avatar
Chris Lattner committed
    }*/
    private:
      DenseMap<Value*, uint32_t> valueNumbering;
      DenseMap<Expression, uint32_t> expressionNumbering;
      AliasAnalysis* AA;
      MemoryDependenceAnalysis* MD;
      DominatorTree* DT;
      Expression::ExpressionOpcode getOpcode(CmpInst* 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(ExtractValueInst* C);
      Expression create_expression(InsertValueInst* C);
      
      uint32_t lookup_or_add_call(CallInst* C);
      ValueTable() : nextValueNumber(1) { }
      uint32_t lookup_or_add(Value *V);
      uint32_t lookup(Value *V) const;
      void add(Value *V, uint32_t num);
      void erase(Value *v);
      void setAliasAnalysis(AliasAnalysis* A) { AA = A; }
      AliasAnalysis *getAliasAnalysis() const { return AA; }
      void setMemDep(MemoryDependenceAnalysis* M) { MD = M; }
      void setDomTree(DominatorTree* D) { DT = D; }
      uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
      void verifyRemoved(const Value *) const;
template <> struct DenseMapInfo<Expression> {
Owen Anderson's avatar
Owen Anderson committed
  static inline Expression getEmptyKey() {
    return Expression(Expression::EMPTY);
  }
Owen Anderson's avatar
Owen Anderson committed
  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) ^
Loading
Loading full blame...