//===- LazyValueInfo.cpp - Value constraint analysis ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface for lazy computation of value constraint
// information.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "lazy-value-info"
#include "llvm/Analysis/LazyValueInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include <map>
#include <set>
#include <stack>
using namespace llvm;

char LazyValueInfo::ID = 0;
INITIALIZE_PASS(LazyValueInfo, "lazy-value-info",
                "Lazy Value Information Analysis", false, true)

namespace llvm {
  FunctionPass *createLazyValueInfoPass() { return new LazyValueInfo(); }
}


//===----------------------------------------------------------------------===//
//                               LVILatticeVal
//===----------------------------------------------------------------------===//

/// LVILatticeVal - This is the information tracked by LazyValueInfo for each
/// value.
///
/// FIXME: This is basically just for bringup, this can be made a lot more rich
/// in the future.
///
namespace {
class LVILatticeVal {
  enum LatticeValueTy {
    /// undefined - This Value has no known value yet.
    undefined,
    
    /// constant - This Value has a specific constant value.
    constant,
    /// notconstant - This Value is known to not have the specified value.
    notconstant,
    
    /// constantrange - The Value falls within this range.
    constantrange,
    
    /// overdefined - This value is not known to be constant, and we know that
    /// it has a value.
    overdefined
  };
  
  /// Val: This stores the current lattice value along with the Constant* for
  /// the constant if this is a 'constant' or 'notconstant' value.
  LatticeValueTy Tag;
  Constant *Val;
  ConstantRange Range;
  
public:
  LVILatticeVal() : Tag(undefined), Val(0), Range(1, true) {}

  static LVILatticeVal get(Constant *C) {
    LVILatticeVal Res;
    if (!isa<UndefValue>(C))
      Res.markConstant(C);
    return Res;
  }
  static LVILatticeVal getNot(Constant *C) {
    LVILatticeVal Res;
    if (!isa<UndefValue>(C))
      Res.markNotConstant(C);
    return Res;
  }
  static LVILatticeVal getRange(ConstantRange CR) {
    LVILatticeVal Res;
    Res.markConstantRange(CR);
    return Res;
  }
  
  bool isUndefined() const     { return Tag == undefined; }
  bool isConstant() const      { return Tag == constant; }
  bool isNotConstant() const   { return Tag == notconstant; }
  bool isConstantRange() const { return Tag == constantrange; }
  bool isOverdefined() const   { return Tag == overdefined; }
  
  Constant *getConstant() const {
    assert(isConstant() && "Cannot get the constant of a non-constant!");
    return Val;
  }
  
  Constant *getNotConstant() const {
    assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
    return Val;
  }
  
  ConstantRange getConstantRange() const {
    assert(isConstantRange() &&
           "Cannot get the constant-range of a non-constant-range!");
    return Range;
  }
  
  /// markOverdefined - Return true if this is a change in status.
  bool markOverdefined() {
    if (isOverdefined())
      return false;
    Tag = overdefined;
    return true;
  }

  /// markConstant - Return true if this is a change in status.
  bool markConstant(Constant *V) {
    assert(V && "Marking constant with NULL");
    if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
      return markConstantRange(ConstantRange(CI->getValue()));
    if (isa<UndefValue>(V))
      return false;

    assert((!isConstant() || getConstant() == V) &&
           "Marking constant with different value");
    assert(isUndefined());
    Tag = constant;
    Val = V;
    return true;
  }
  
  /// markNotConstant - Return true if this is a change in status.
  bool markNotConstant(Constant *V) {
    assert(V && "Marking constant with NULL");
    if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
      return markConstantRange(ConstantRange(CI->getValue()+1, CI->getValue()));
    if (isa<UndefValue>(V))
      return false;

    assert((!isConstant() || getConstant() != V) &&
           "Marking constant !constant with same value");
    assert((!isNotConstant() || getNotConstant() == V) &&
           "Marking !constant with different value");
    assert(isUndefined() || isConstant());
    Tag = notconstant;
    Val = V;
    return true;
  }
  
  /// markConstantRange - Return true if this is a change in status.
  bool markConstantRange(const ConstantRange NewR) {
    if (isConstantRange()) {
      if (NewR.isEmptySet())
        return markOverdefined();
      
      bool changed = Range == NewR;
      Range = NewR;
      return changed;
    }
    
    assert(isUndefined());
    if (NewR.isEmptySet())
      return markOverdefined();
    
    Tag = constantrange;
    Range = NewR;
    return true;
  }
  
  /// mergeIn - Merge the specified lattice value into this one, updating this
  /// one and returning true if anything changed.
  bool mergeIn(const LVILatticeVal &RHS) {
    if (RHS.isUndefined() || isOverdefined()) return false;
    if (RHS.isOverdefined()) return markOverdefined();

    if (isUndefined()) {
      Tag = RHS.Tag;
      Val = RHS.Val;
      Range = RHS.Range;
      return true;
    }

    if (isConstant()) {
      if (RHS.isConstant()) {
        if (Val == RHS.Val)
          return false;
        return markOverdefined();
      }

      if (RHS.isNotConstant()) {
        if (Val == RHS.Val)
          return markOverdefined();

        // Unless we can prove that the two Constants are different, we must
        // move to overdefined.
        // FIXME: use TargetData for smarter constant folding.
        if (ConstantInt *Res = dyn_cast<ConstantInt>(
                ConstantFoldCompareInstOperands(CmpInst::ICMP_NE,
                                                getConstant(),
                                                RHS.getNotConstant())))
          if (Res->isOne())
            return markNotConstant(RHS.getNotConstant());

        return markOverdefined();
      }

      // RHS is a ConstantRange, LHS is a non-integer Constant.

      // FIXME: consider the case where RHS is a range [1, 0) and LHS is
      // a function. The correct result is to pick up RHS.

      return markOverdefined();
    }

    if (isNotConstant()) {
      if (RHS.isConstant()) {
        if (Val == RHS.Val)
          return markOverdefined();

        // Unless we can prove that the two Constants are different, we must
        // move to overdefined.
        // FIXME: use TargetData for smarter constant folding.
        if (ConstantInt *Res = dyn_cast<ConstantInt>(
                ConstantFoldCompareInstOperands(CmpInst::ICMP_NE,
                                                getNotConstant(),
                                                RHS.getConstant())))
          if (Res->isOne())
            return false;

        return markOverdefined();
      }

      if (RHS.isNotConstant()) {
        if (Val == RHS.Val)
          return false;
        return markOverdefined();
      }

      return markOverdefined();
    }

    assert(isConstantRange() && "New LVILattice type?");
    if (!RHS.isConstantRange())
      return markOverdefined();

    ConstantRange NewR = Range.unionWith(RHS.getConstantRange());
    if (NewR.isFullSet())
      return markOverdefined();
    return markConstantRange(NewR);
  }
};
  
} // end anonymous namespace.

namespace llvm {
raw_ostream &operator<<(raw_ostream &OS, const LVILatticeVal &Val)
    LLVM_ATTRIBUTE_USED;
raw_ostream &operator<<(raw_ostream &OS, const LVILatticeVal &Val) {
  if (Val.isUndefined())
    return OS << "undefined";
  if (Val.isOverdefined())
    return OS << "overdefined";

  if (Val.isNotConstant())
    return OS << "notconstant<" << *Val.getNotConstant() << '>';
  else if (Val.isConstantRange())
    return OS << "constantrange<" << Val.getConstantRange().getLower() << ", "
              << Val.getConstantRange().getUpper() << '>';
  return OS << "constant<" << *Val.getConstant() << '>';
}
}

//===----------------------------------------------------------------------===//
//                          LazyValueInfoCache Decl
//===----------------------------------------------------------------------===//

namespace {
  /// LVIValueHandle - A callback value handle update the cache when
  /// values are erased.
  class LazyValueInfoCache;
  struct LVIValueHandle : public CallbackVH {
    LazyValueInfoCache *Parent;
      
    LVIValueHandle(Value *V, LazyValueInfoCache *P)
      : CallbackVH(V), Parent(P) { }
      
    void deleted();
    void allUsesReplacedWith(Value *V) {
      deleted();
    }
  };
}

namespace llvm {
  template<>
  struct DenseMapInfo<LVIValueHandle> {
    typedef DenseMapInfo<Value*> PointerInfo;
    static inline LVIValueHandle getEmptyKey() {
      return LVIValueHandle(PointerInfo::getEmptyKey(),
                            static_cast<LazyValueInfoCache*>(0));
    }
    static inline LVIValueHandle getTombstoneKey() {
      return LVIValueHandle(PointerInfo::getTombstoneKey(),
                            static_cast<LazyValueInfoCache*>(0));
    }
    static unsigned getHashValue(const LVIValueHandle &Val) {
      return PointerInfo::getHashValue(Val);
    }
    static bool isEqual(const LVIValueHandle &LHS, const LVIValueHandle &RHS) {
      return LHS == RHS;
    }
  };
  
  template<>
  struct DenseMapInfo<std::pair<AssertingVH<BasicBlock>, Value*> > {
    typedef std::pair<AssertingVH<BasicBlock>, Value*> PairTy;
    typedef DenseMapInfo<AssertingVH<BasicBlock> > APointerInfo;
    typedef DenseMapInfo<Value*> BPointerInfo;
    static inline PairTy getEmptyKey() {
      return std::make_pair(APointerInfo::getEmptyKey(),
                            BPointerInfo::getEmptyKey());
    }
    static inline PairTy getTombstoneKey() {
      return std::make_pair(APointerInfo::getTombstoneKey(), 
                            BPointerInfo::getTombstoneKey());
    }
    static unsigned getHashValue( const PairTy &Val) {
      return APointerInfo::getHashValue(Val.first) ^ 
             BPointerInfo::getHashValue(Val.second);
    }
    static bool isEqual(const PairTy &LHS, const PairTy &RHS) {
      return APointerInfo::isEqual(LHS.first, RHS.first) &&
             BPointerInfo::isEqual(LHS.second, RHS.second);
    }
  };
}

namespace { 
  /// LazyValueInfoCache - This is the cache kept by LazyValueInfo which
  /// maintains information about queries across the clients' queries.
  class LazyValueInfoCache {
    /// ValueCacheEntryTy - This is all of the cached block information for
    /// exactly one Value*.  The entries are sorted by the BasicBlock* of the
    /// entries, allowing us to do a lookup with a binary search.
    typedef std::map<AssertingVH<BasicBlock>, LVILatticeVal> ValueCacheEntryTy;

    /// ValueCache - This is all of the cached information for all values,
    /// mapped from Value* to key information.
    DenseMap<LVIValueHandle, ValueCacheEntryTy> ValueCache;
    
    /// OverDefinedCache - This tracks, on a per-block basis, the set of 
    /// values that are over-defined at the end of that block.  This is required
    /// for cache updating.
    typedef std::pair<AssertingVH<BasicBlock>, Value*> OverDefinedPairTy;
    DenseSet<OverDefinedPairTy> OverDefinedCache;
    
    /// BlockValueStack - This stack holds the state of the value solver
    /// during a query.  It basically emulates the callstack of the naive
    /// recursive value lookup process.
    std::stack<std::pair<BasicBlock*, Value*> > BlockValueStack;
    
    friend struct LVIValueHandle;
    
    /// OverDefinedCacheUpdater - A helper object that ensures that the
    /// OverDefinedCache is updated whenever solveBlockValue returns.
    struct OverDefinedCacheUpdater {
      LazyValueInfoCache *Parent;
      Value *Val;
      BasicBlock *BB;
      LVILatticeVal &BBLV;
      
      OverDefinedCacheUpdater(Value *V, BasicBlock *B, LVILatticeVal &LV,
                       LazyValueInfoCache *P)
        : Parent(P), Val(V), BB(B), BBLV(LV) { }
      
      bool markResult(bool changed) { 
        if (changed && BBLV.isOverdefined())
          Parent->OverDefinedCache.insert(std::make_pair(BB, Val));
        return changed;
      }
    };
    


    LVILatticeVal getBlockValue(Value *Val, BasicBlock *BB);
    bool getEdgeValue(Value *V, BasicBlock *F, BasicBlock *T,
                      LVILatticeVal &Result);
    bool hasBlockValue(Value *Val, BasicBlock *BB);

    // These methods process one work item and may add more. A false value
    // returned means that the work item was not completely processed and must
    // be revisited after going through the new items.
    bool solveBlockValue(Value *Val, BasicBlock *BB);
    bool solveBlockValueNonLocal(LVILatticeVal &BBLV,
                                 Value *Val, BasicBlock *BB);
    bool solveBlockValuePHINode(LVILatticeVal &BBLV,
                                PHINode *PN, BasicBlock *BB);
    bool solveBlockValueConstantRange(LVILatticeVal &BBLV,
                                      Instruction *BBI, BasicBlock *BB);

    void solve();
    
    ValueCacheEntryTy &lookup(Value *V) {
      return ValueCache[LVIValueHandle(V, this)];
    }

  public:
    /// getValueInBlock - This is the query interface to determine the lattice
    /// value for the specified Value* at the end of the specified block.
    LVILatticeVal getValueInBlock(Value *V, BasicBlock *BB);

    /// getValueOnEdge - This is the query interface to determine the lattice
    /// value for the specified Value* that is true on the specified edge.
    LVILatticeVal getValueOnEdge(Value *V, BasicBlock *FromBB,BasicBlock *ToBB);
    
    /// threadEdge - This is the update interface to inform the cache that an
    /// edge from PredBB to OldSucc has been threaded to be from PredBB to
    /// NewSucc.
    void threadEdge(BasicBlock *PredBB,BasicBlock *OldSucc,BasicBlock *NewSucc);
    
    /// eraseBlock - This is part of the update interface to inform the cache
    /// that a block has been deleted.
    void eraseBlock(BasicBlock *BB);
    
    /// clear - Empty the cache.
    void clear() {
      ValueCache.clear();
      OverDefinedCache.clear();
    }
  };
} // end anonymous namespace

void LVIValueHandle::deleted() {
  typedef std::pair<AssertingVH<BasicBlock>, Value*> OverDefinedPairTy;
  
  SmallVector<OverDefinedPairTy, 4> ToErase;
  for (DenseSet<OverDefinedPairTy>::iterator 
       I = Parent->OverDefinedCache.begin(),
       E = Parent->OverDefinedCache.end();
       I != E; ++I) {
    if (I->second == getValPtr())
      ToErase.push_back(*I);
  }
  
  for (SmallVector<OverDefinedPairTy, 4>::iterator I = ToErase.begin(),
       E = ToErase.end(); I != E; ++I)
    Parent->OverDefinedCache.erase(*I);
  
  // This erasure deallocates *this, so it MUST happen after we're done
  // using any and all members of *this.
  Parent->ValueCache.erase(*this);
}

void LazyValueInfoCache::eraseBlock(BasicBlock *BB) {
  SmallVector<OverDefinedPairTy, 4> ToErase;
  for (DenseSet<OverDefinedPairTy>::iterator  I = OverDefinedCache.begin(),
       E = OverDefinedCache.end(); I != E; ++I) {
    if (I->first == BB)
      ToErase.push_back(*I);
  }
  
  for (SmallVector<OverDefinedPairTy, 4>::iterator I = ToErase.begin(),
       E = ToErase.end(); I != E; ++I)
    OverDefinedCache.erase(*I);

  for (DenseMap<LVIValueHandle, ValueCacheEntryTy>::iterator
       I = ValueCache.begin(), E = ValueCache.end(); I != E; ++I)
    I->second.erase(BB);
}

void LazyValueInfoCache::solve() {
  while (!BlockValueStack.empty()) {
    std::pair<BasicBlock*, Value*> &e = BlockValueStack.top();
    if (solveBlockValue(e.second, e.first))
      BlockValueStack.pop();
  }
}

bool LazyValueInfoCache::hasBlockValue(Value *Val, BasicBlock *BB) {
  // If already a constant, there is nothing to compute.
  if (isa<Constant>(Val))
    return true;

  LVIValueHandle ValHandle(Val, this);
  if (!ValueCache.count(ValHandle)) return false;
  return ValueCache[ValHandle].count(BB);
}

LVILatticeVal LazyValueInfoCache::getBlockValue(Value *Val, BasicBlock *BB) {
  // If already a constant, there is nothing to compute.
  if (Constant *VC = dyn_cast<Constant>(Val))
    return LVILatticeVal::get(VC);

  return lookup(Val)[BB];
}

bool LazyValueInfoCache::solveBlockValue(Value *Val, BasicBlock *BB) {
  if (isa<Constant>(Val))
    return true;

  ValueCacheEntryTy &Cache = lookup(Val);
  LVILatticeVal &BBLV = Cache[BB];
  
  // OverDefinedCacheUpdater is a helper object that will update
  // the OverDefinedCache for us when this method exits.  Make sure to
  // call markResult on it as we exist, passing a bool to indicate if the
  // cache needs updating, i.e. if we have solve a new value or not.
  OverDefinedCacheUpdater ODCacheUpdater(Val, BB, BBLV, this);

  // If we've already computed this block's value, return it.
  if (!BBLV.isUndefined()) {
    DEBUG(dbgs() << "  reuse BB '" << BB->getName() << "' val=" << BBLV <<'\n');
    
    // Since we're reusing a cached value here, we don't need to update the 
    // OverDefinedCahce.  The cache will have been properly updated 
    // whenever the cached value was inserted.
    ODCacheUpdater.markResult(false);
    return true;
  }

  // Otherwise, this is the first time we're seeing this block.  Reset the
  // lattice value to overdefined, so that cycles will terminate and be
  // conservatively correct.
  BBLV.markOverdefined();
  
  Instruction *BBI = dyn_cast<Instruction>(Val);
  if (BBI == 0 || BBI->getParent() != BB) {
    return ODCacheUpdater.markResult(solveBlockValueNonLocal(BBLV, Val, BB));
  }

  if (PHINode *PN = dyn_cast<PHINode>(BBI)) {
    return ODCacheUpdater.markResult(solveBlockValuePHINode(BBLV, PN, BB));
  }

  if (AllocaInst *AI = dyn_cast<AllocaInst>(BBI)) {
    BBLV = LVILatticeVal::getNot(ConstantPointerNull::get(AI->getType()));
    return ODCacheUpdater.markResult(true);
  }

  // We can only analyze the definitions of certain classes of instructions
  // (integral binops and casts at the moment), so bail if this isn't one.
  LVILatticeVal Result;
  if ((!isa<BinaryOperator>(BBI) && !isa<CastInst>(BBI)) ||
     !BBI->getType()->isIntegerTy()) {
    DEBUG(dbgs() << " compute BB '" << BB->getName()
                 << "' - overdefined because inst def found.\n");
    BBLV.markOverdefined();
    return ODCacheUpdater.markResult(true);
  }

  // FIXME: We're currently limited to binops with a constant RHS.  This should
  // be improved.
  BinaryOperator *BO = dyn_cast<BinaryOperator>(BBI);
  if (BO && !isa<ConstantInt>(BO->getOperand(1))) { 
    DEBUG(dbgs() << " compute BB '" << BB->getName()
                 << "' - overdefined because inst def found.\n");

    BBLV.markOverdefined();
    return ODCacheUpdater.markResult(true);
  }

  return ODCacheUpdater.markResult(solveBlockValueConstantRange(BBLV, BBI, BB));
}

static bool InstructionDereferencesPointer(Instruction *I, Value *Ptr) {
  if (LoadInst *L = dyn_cast<LoadInst>(I)) {
    return L->getPointerAddressSpace() == 0 &&
        GetUnderlyingObject(L->getPointerOperand()) ==
        GetUnderlyingObject(Ptr);
  }
  if (StoreInst *S = dyn_cast<StoreInst>(I)) {
    return S->getPointerAddressSpace() == 0 &&
        GetUnderlyingObject(S->getPointerOperand()) ==
        GetUnderlyingObject(Ptr);
  }
  if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) {
    if (MI->isVolatile()) return false;
    if (MI->getAddressSpace() != 0) return false;

    // FIXME: check whether it has a valuerange that excludes zero?
    ConstantInt *Len = dyn_cast<ConstantInt>(MI->getLength());
    if (!Len || Len->isZero()) return false;

    if (MI->getRawDest() == Ptr || MI->getDest() == Ptr)
      return true;
    if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI))
      return MTI->getRawSource() == Ptr || MTI->getSource() == Ptr;
  }
  return false;
}

bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV,
                                                 Value *Val, BasicBlock *BB) {
  LVILatticeVal Result;  // Start Undefined.

  // If this is a pointer, and there's a load from that pointer in this BB,
  // then we know that the pointer can't be NULL.
  bool NotNull = false;
  if (Val->getType()->isPointerTy()) {
    if (isa<AllocaInst>(Val)) {
      NotNull = true;
    } else {
      for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();BI != BE;++BI){
        if (InstructionDereferencesPointer(BI, Val)) {
          NotNull = true;
          break;
        }
      }
    }
  }

  // If this is the entry block, we must be asking about an argument.  The
  // value is overdefined.
  if (BB == &BB->getParent()->getEntryBlock()) {
    assert(isa<Argument>(Val) && "Unknown live-in to the entry block");
    if (NotNull) {
      const PointerType *PTy = cast<PointerType>(Val->getType());
      Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy));
    } else {
      Result.markOverdefined();
    }
    BBLV = Result;
    return true;
  }

  // Loop over all of our predecessors, merging what we know from them into
  // result.
  bool EdgesMissing = false;
  for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
    LVILatticeVal EdgeResult;
    EdgesMissing |= !getEdgeValue(Val, *PI, BB, EdgeResult);
    if (EdgesMissing)
      continue;

    Result.mergeIn(EdgeResult);

    // If we hit overdefined, exit early.  The BlockVals entry is already set
    // to overdefined.
    if (Result.isOverdefined()) {
      DEBUG(dbgs() << " compute BB '" << BB->getName()
            << "' - overdefined because of pred.\n");
      // If we previously determined that this is a pointer that can't be null
      // then return that rather than giving up entirely.
      if (NotNull) {
        const PointerType *PTy = cast<PointerType>(Val->getType());
        Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy));
      }
      
      BBLV = Result;
      return true;
    }
  }
  if (EdgesMissing)
    return false;

  // Return the merged value, which is more precise than 'overdefined'.
  assert(!Result.isOverdefined());
  BBLV = Result;
  return true;
}
  
bool LazyValueInfoCache::solveBlockValuePHINode(LVILatticeVal &BBLV,
                                                PHINode *PN, BasicBlock *BB) {
  LVILatticeVal Result;  // Start Undefined.

  // Loop over all of our predecessors, merging what we know from them into
  // result.
  bool EdgesMissing = false;
  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
    BasicBlock *PhiBB = PN->getIncomingBlock(i);
    Value *PhiVal = PN->getIncomingValue(i);
    LVILatticeVal EdgeResult;
    EdgesMissing |= !getEdgeValue(PhiVal, PhiBB, BB, EdgeResult);
    if (EdgesMissing)
      continue;

    Result.mergeIn(EdgeResult);

    // If we hit overdefined, exit early.  The BlockVals entry is already set
    // to overdefined.
    if (Result.isOverdefined()) {
      DEBUG(dbgs() << " compute BB '" << BB->getName()
            << "' - overdefined because of pred.\n");
      
      BBLV = Result;
      return true;
    }
  }
  if (EdgesMissing)
    return false;

  // Return the merged value, which is more precise than 'overdefined'.
  assert(!Result.isOverdefined() && "Possible PHI in entry block?");
  BBLV = Result;
  return true;
}

bool LazyValueInfoCache::solveBlockValueConstantRange(LVILatticeVal &BBLV,
                                                      Instruction *BBI,
                                                      BasicBlock *BB) {
  // Figure out the range of the LHS.  If that fails, bail.
  if (!hasBlockValue(BBI->getOperand(0), BB)) {
    BlockValueStack.push(std::make_pair(BB, BBI->getOperand(0)));
    return false;
  }

  LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
  if (!LHSVal.isConstantRange()) {
    BBLV.markOverdefined();
    return true;
  }
  
  ConstantRange LHSRange = LHSVal.getConstantRange();
  ConstantRange RHSRange(1);
  const IntegerType *ResultTy = cast<IntegerType>(BBI->getType());
  if (isa<BinaryOperator>(BBI)) {
    if (ConstantInt *RHS = dyn_cast<ConstantInt>(BBI->getOperand(1))) {
      RHSRange = ConstantRange(RHS->getValue());
    } else {
      BBLV.markOverdefined();
      return true;
    }
  }

  // NOTE: We're currently limited by the set of operations that ConstantRange
  // can evaluate symbolically.  Enhancing that set will allows us to analyze
  // more definitions.
  LVILatticeVal Result;
  switch (BBI->getOpcode()) {
  case Instruction::Add:
    Result.markConstantRange(LHSRange.add(RHSRange));
    break;
  case Instruction::Sub:
    Result.markConstantRange(LHSRange.sub(RHSRange));
    break;
  case Instruction::Mul:
    Result.markConstantRange(LHSRange.multiply(RHSRange));
    break;
  case Instruction::UDiv:
    Result.markConstantRange(LHSRange.udiv(RHSRange));
    break;
  case Instruction::Shl:
    Result.markConstantRange(LHSRange.shl(RHSRange));
    break;
  case Instruction::LShr:
    Result.markConstantRange(LHSRange.lshr(RHSRange));
    break;
  case Instruction::Trunc:
    Result.markConstantRange(LHSRange.truncate(ResultTy->getBitWidth()));
    break;
  case Instruction::SExt:
    Result.markConstantRange(LHSRange.signExtend(ResultTy->getBitWidth()));
    break;
  case Instruction::ZExt:
    Result.markConstantRange(LHSRange.zeroExtend(ResultTy->getBitWidth()));
    break;
  case Instruction::BitCast:
    Result.markConstantRange(LHSRange);
    break;
  case Instruction::And:
    Result.markConstantRange(LHSRange.binaryAnd(RHSRange));
    break;
  case Instruction::Or:
    Result.markConstantRange(LHSRange.binaryOr(RHSRange));
    break;
  
  // Unhandled instructions are overdefined.
  default:
    DEBUG(dbgs() << " compute BB '" << BB->getName()
                 << "' - overdefined because inst def found.\n");
    Result.markOverdefined();
    break;
  }
  
  BBLV = Result;
  return true;
}

/// getEdgeValue - This method attempts to infer more complex 
bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom,
                                      BasicBlock *BBTo, LVILatticeVal &Result) {
  // If already a constant, there is nothing to compute.
  if (Constant *VC = dyn_cast<Constant>(Val)) {
    Result = LVILatticeVal::get(VC);
    return true;
  }
  
  // TODO: Handle more complex conditionals.  If (v == 0 || v2 < 1) is false, we
  // know that v != 0.
  if (BranchInst *BI = dyn_cast<BranchInst>(BBFrom->getTerminator())) {
    // If this is a conditional branch and only one successor goes to BBTo, then
    // we maybe able to infer something from the condition. 
    if (BI->isConditional() &&
        BI->getSuccessor(0) != BI->getSuccessor(1)) {
      bool isTrueDest = BI->getSuccessor(0) == BBTo;
      assert(BI->getSuccessor(!isTrueDest) == BBTo &&
             "BBTo isn't a successor of BBFrom");
      
      // If V is the condition of the branch itself, then we know exactly what
      // it is.
      if (BI->getCondition() == Val) {
        Result = LVILatticeVal::get(ConstantInt::get(
                              Type::getInt1Ty(Val->getContext()), isTrueDest));
        return true;
      }
      
      // If the condition of the branch is an equality comparison, we may be
      // able to infer the value.
      ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition());
      if (ICI && ICI->getOperand(0) == Val &&
          isa<Constant>(ICI->getOperand(1))) {
        if (ICI->isEquality()) {
          // We know that V has the RHS constant if this is a true SETEQ or
          // false SETNE. 
          if (isTrueDest == (ICI->getPredicate() == ICmpInst::ICMP_EQ))
            Result = LVILatticeVal::get(cast<Constant>(ICI->getOperand(1)));
          else
            Result = LVILatticeVal::getNot(cast<Constant>(ICI->getOperand(1)));
          return true;
        }

        if (ConstantInt *CI = dyn_cast<ConstantInt>(ICI->getOperand(1))) {
          // Calculate the range of values that would satisfy the comparison.
          ConstantRange CmpRange(CI->getValue(), CI->getValue()+1);
          ConstantRange TrueValues =
            ConstantRange::makeICmpRegion(ICI->getPredicate(), CmpRange);

          // If we're interested in the false dest, invert the condition.
          if (!isTrueDest) TrueValues = TrueValues.inverse();
          
          // Figure out the possible values of the query BEFORE this branch.  
          if (!hasBlockValue(Val, BBFrom)) {
            BlockValueStack.push(std::make_pair(BBFrom, Val));
            return false;
          }
          
          LVILatticeVal InBlock = getBlockValue(Val, BBFrom);
          if (!InBlock.isConstantRange()) {
            Result = LVILatticeVal::getRange(TrueValues);
            return true;
          }

          // Find all potential values that satisfy both the input and output
          // conditions.
          ConstantRange PossibleValues =
            TrueValues.intersectWith(InBlock.getConstantRange());

          Result = LVILatticeVal::getRange(PossibleValues);
          return true;
        }
      }
    }
  }

  // If the edge was formed by a switch on the value, then we may know exactly
  // what it is.
  if (SwitchInst *SI = dyn_cast<SwitchInst>(BBFrom->getTerminator())) {
    if (SI->getCondition() == Val) {
      // We don't know anything in the default case.
      if (SI->getDefaultDest() == BBTo) {
        Result.markOverdefined();
        return true;
      }
      
      // We only know something if there is exactly one value that goes from
      // BBFrom to BBTo.
      unsigned NumEdges = 0;
      ConstantInt *EdgeVal = 0;
      for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i) {
        if (SI->getSuccessor(i) != BBTo) continue;
        if (NumEdges++) break;
        EdgeVal = SI->getCaseValue(i);
      }
      assert(EdgeVal && "Missing successor?");
      if (NumEdges == 1) {
        Result = LVILatticeVal::get(EdgeVal);
        return true;
      }
    }
  }
  
  // Otherwise see if the value is known in the block.
  if (hasBlockValue(Val, BBFrom)) {
    Result = getBlockValue(Val, BBFrom);
    return true;
  }
  BlockValueStack.push(std::make_pair(BBFrom, Val));
  return false;
}

LVILatticeVal LazyValueInfoCache::getValueInBlock(Value *V, BasicBlock *BB) {
  DEBUG(dbgs() << "LVI Getting block end value " << *V << " at '"
        << BB->getName() << "'\n");
  
  BlockValueStack.push(std::make_pair(BB, V));
  solve();
  LVILatticeVal Result = getBlockValue(V, BB);

  DEBUG(dbgs() << "  Result = " << Result << "\n");
  return Result;
}

LVILatticeVal LazyValueInfoCache::
getValueOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB) {
  DEBUG(dbgs() << "LVI Getting edge value " << *V << " from '"
        << FromBB->getName() << "' to '" << ToBB->getName() << "'\n");
  
  LVILatticeVal Result;
  if (!getEdgeValue(V, FromBB, ToBB, Result)) {
    solve();
    bool WasFastQuery = getEdgeValue(V, FromBB, ToBB, Result);
    (void)WasFastQuery;
    assert(WasFastQuery && "More work to do after problem solved?");
  }

  DEBUG(dbgs() << "  Result = " << Result << "\n");
  return Result;
}

void LazyValueInfoCache::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,
                                    BasicBlock *NewSucc) {
  // When an edge in the graph has been threaded, values that we could not 
  // determine a value for before (i.e. were marked overdefined) may be possible
  // to solve now.  We do NOT try to proactively update these values.  Instead,
  // we clear their entries from the cache, and allow lazy updating to recompute
  // them when needed.
  
  // The updating process is fairly simple: we need to dropped cached info
  // for all values that were marked overdefined in OldSucc, and for those same
  // values in any successor of OldSucc (except NewSucc) in which they were
  // also marked overdefined.
  std::vector<BasicBlock*> worklist;
  worklist.push_back(OldSucc);
  
  DenseSet<Value*> ClearSet;
  for (DenseSet<OverDefinedPairTy>::iterator I = OverDefinedCache.begin(),
       E = OverDefinedCache.end(); I != E; ++I) {
    if (I->first == OldSucc)
      ClearSet.insert(I->second);
  }
  
  // Use a worklist to perform a depth-first search of OldSucc's successors.
  // NOTE: We do not need a visited list since any blocks we have already
  // visited will have had their overdefined markers cleared already, and we
  // thus won't loop to their successors.
  while (!worklist.empty()) {
    BasicBlock *ToUpdate = worklist.back();
    worklist.pop_back();
    
    // Skip blocks only accessible through NewSucc.
    if (ToUpdate == NewSucc) continue;
    
    bool changed = false;
    for (DenseSet<Value*>::iterator I = ClearSet.begin(), E = ClearSet.end();
         I != E; ++I) {
      // If a value was marked overdefined in OldSucc, and is here too...
      DenseSet<OverDefinedPairTy>::iterator OI =
        OverDefinedCache.find(std::make_pair(ToUpdate, *I));
      if (OI == OverDefinedCache.end()) continue;

      // Remove it from the caches.
      ValueCacheEntryTy &Entry = ValueCache[LVIValueHandle(*I, this)];
      ValueCacheEntryTy::iterator CI = Entry.find(ToUpdate);

      assert(CI != Entry.end() && "Couldn't find entry to update?");
      Entry.erase(CI);
      OverDefinedCache.erase(OI);

      // If we removed anything, then we potentially need to update 
      // blocks successors too.
      changed = true;
    }

    if (!changed) continue;
    
    worklist.insert(worklist.end(), succ_begin(ToUpdate), succ_end(ToUpdate));
  }
}

//===----------------------------------------------------------------------===//
//                            LazyValueInfo Impl
//===----------------------------------------------------------------------===//

/// getCache - This lazily constructs the LazyValueInfoCache.
static LazyValueInfoCache &getCache(void *&PImpl) {
  if (!PImpl)
    PImpl = new LazyValueInfoCache();
  return *static_cast<LazyValueInfoCache*>(PImpl);
}

bool LazyValueInfo::runOnFunction(Function &F) {
  if (PImpl)
    getCache(PImpl).clear();
  
  TD = getAnalysisIfAvailable<TargetData>();
  // Fully lazy.
  return false;
}

void LazyValueInfo::releaseMemory() {
  // If the cache was allocated, free it.
  if (PImpl) {
    delete &getCache(PImpl);
    PImpl = 0;
  }
}

Constant *LazyValueInfo::getConstant(Value *V, BasicBlock *BB) {
  LVILatticeVal Result = getCache(PImpl).getValueInBlock(V, BB);
  
  if (Result.isConstant())
    return Result.getConstant();
  if (Result.isConstantRange()) {
    ConstantRange CR = Result.getConstantRange();
    if (const APInt *SingleVal = CR.getSingleElement())
      return ConstantInt::get(V->getContext(), *SingleVal);
  }
  return 0;
}

/// getConstantOnEdge - Determine whether the specified value is known to be a
/// constant on the specified edge.  Return null if not.
Constant *LazyValueInfo::getConstantOnEdge(Value *V, BasicBlock *FromBB,
                                           BasicBlock *ToBB) {
  LVILatticeVal Result = getCache(PImpl).getValueOnEdge(V, FromBB, ToBB);
  
  if (Result.isConstant())
    return Result.getConstant();
  if (Result.isConstantRange()) {
    ConstantRange CR = Result.getConstantRange();
    if (const APInt *SingleVal = CR.getSingleElement())
      return ConstantInt::get(V->getContext(), *SingleVal);
  }
  return 0;
}

/// getPredicateOnEdge - Determine whether the specified value comparison
/// with a constant is known to be true or false on the specified CFG edge.
/// Pred is a CmpInst predicate.
LazyValueInfo::Tristate
LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
                                  BasicBlock *FromBB, BasicBlock *ToBB) {
  LVILatticeVal Result = getCache(PImpl).getValueOnEdge(V, FromBB, ToBB);
  
  // If we know the value is a constant, evaluate the conditional.
  Constant *Res = 0;
  if (Result.isConstant()) {
    Res = ConstantFoldCompareInstOperands(Pred, Result.getConstant(), C, TD);
    if (ConstantInt *ResCI = dyn_cast<ConstantInt>(Res))
      return ResCI->isZero() ? False : True;
    return Unknown;
  }
  
  if (Result.isConstantRange()) {
    ConstantInt *CI = dyn_cast<ConstantInt>(C);
    if (!CI) return Unknown;
    
    ConstantRange CR = Result.getConstantRange();
    if (Pred == ICmpInst::ICMP_EQ) {
      if (!CR.contains(CI->getValue()))
        return False;
      
      if (CR.isSingleElement() && CR.contains(CI->getValue()))
        return True;
    } else if (Pred == ICmpInst::ICMP_NE) {
      if (!CR.contains(CI->getValue()))
        return True;
      
      if (CR.isSingleElement() && CR.contains(CI->getValue()))
        return False;
    }
    
    // Handle more complex predicates.
    ConstantRange TrueValues =
        ICmpInst::makeConstantRange((ICmpInst::Predicate)Pred, CI->getValue());
    if (TrueValues.contains(CR))
      return True;
    if (TrueValues.inverse().contains(CR))
      return False;
    return Unknown;
  }
  
  if (Result.isNotConstant()) {
    // If this is an equality comparison, we can try to fold it knowing that
    // "V != C1".
    if (Pred == ICmpInst::ICMP_EQ) {
      // !C1 == C -> false iff C1 == C.
      Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE,
                                            Result.getNotConstant(), C, TD);
      if (Res->isNullValue())
        return False;
    } else if (Pred == ICmpInst::ICMP_NE) {
      // !C1 != C -> true iff C1 == C.
      Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE,
                                            Result.getNotConstant(), C, TD);
      if (Res->isNullValue())
        return True;
    }
    return Unknown;
  }
  
  return Unknown;
}

void LazyValueInfo::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,
                               BasicBlock *NewSucc) {
  if (PImpl) getCache(PImpl).threadEdge(PredBB, OldSucc, NewSucc);
}

void LazyValueInfo::eraseBlock(BasicBlock *BB) {
  if (PImpl) getCache(PImpl).eraseBlock(BB);
}
