//===- SCCP.cpp - Sparse Conditional Constant Propagation -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements sparse conditional constant propagation and merging:
//
// Specifically, this:
// * Assumes values are constant unless proven otherwise
// * Assumes BasicBlocks are dead unless proven otherwise
// * Proves values to be constant, and replaces them with constants
// * Proves conditional branches to be unconditional
//
// Notice that:
// * This pass has a habit of making definitions be dead. It is a good idea
// to to run a DCE pass sometime after running this pass.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sccp"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Type.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/hash_map"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
#include <set>
using namespace llvm;
// LatticeVal class - This class represents the different lattice values that an
// instruction may occupy. It is a simple class with value semantics.
//
namespace {
class LatticeVal {
enum {
undefined, // This instruction has no known value
constant, // This instruction has a constant value
overdefined // This instruction has an unknown value
} LatticeValue; // The current lattice position
Constant *ConstantVal; // If Constant value, the current value
public:
inline LatticeVal() : LatticeValue(undefined), ConstantVal(0) {}
// markOverdefined - Return true if this is a new status to be in...
inline bool markOverdefined() {
if (LatticeValue != overdefined) {
LatticeValue = overdefined;
return true;
}
return false;
}
// markConstant - Return true if this is a new status for us...
inline bool markConstant(Constant *V) {
if (LatticeValue != constant) {
LatticeValue = constant;
ConstantVal = V;
return true;
} else {
assert(ConstantVal == V && "Marking constant with different value");
}
return false;
}
inline bool isUndefined() const { return LatticeValue == undefined; }
inline bool isConstant() const { return LatticeValue == constant; }
inline bool isOverdefined() const { return LatticeValue == overdefined; }
inline Constant *getConstant() const {
assert(isConstant() && "Cannot get the constant of a non-constant!");
return ConstantVal;
}
};
} // end anonymous namespace
//===----------------------------------------------------------------------===//
//
/// SCCPSolver - This class is a general purpose solver for Sparse Conditional
/// Constant Propagation.
///
class SCCPSolver : public InstVisitor<SCCPSolver> {
std::set<BasicBlock*> BBExecutable;// The basic blocks that are executable
hash_map<Value*, LatticeVal> ValueState; // The state each value is in...
/// TrackedFunctionRetVals - If we are tracking arguments into and the return
/// value out of a function, it will have an entry in this map, indicating
/// what the known return value for the function is.
hash_map<Function*, LatticeVal> TrackedFunctionRetVals;
// The reason for two worklists is that overdefined is the lowest state
// on the lattice, and moving things to overdefined as fast as possible
// makes SCCP converge much faster.
// By having a separate worklist, we accomplish this because everything
// possibly overdefined will become overdefined at the soonest possible
// point.
std::vector<Value*> Over