Add the beginnings of infrastructure for range tracking.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110388 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson
2010-08-05 22:59:19 +00:00
parent 6387176c31
commit 5be2e78fa1

View File

@ -19,6 +19,7 @@
#include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetData.h"
#include "llvm/Support/CFG.h" #include "llvm/Support/CFG.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ValueHandle.h" #include "llvm/Support/ValueHandle.h"
@ -51,12 +52,15 @@ class LVILatticeVal {
enum LatticeValueTy { enum LatticeValueTy {
/// undefined - This LLVM Value has no known value yet. /// undefined - This LLVM Value has no known value yet.
undefined, undefined,
/// constant - This LLVM Value has a specific constant value. /// constant - This LLVM Value has a specific constant value.
constant, constant,
/// notconstant - This LLVM value is known to not have the specified value. /// notconstant - This LLVM value is known to not have the specified value.
notconstant, notconstant,
/// constantrange
constantrange,
/// overdefined - This instruction is not known to be constant, and we know /// overdefined - This instruction is not known to be constant, and we know
/// it has a value. /// it has a value.
overdefined overdefined
@ -66,9 +70,10 @@ class LVILatticeVal {
/// the constant if this is a 'constant' or 'notconstant' value. /// the constant if this is a 'constant' or 'notconstant' value.
LatticeValueTy Tag; LatticeValueTy Tag;
Constant *Val; Constant *Val;
ConstantRange Range;
public: public:
LVILatticeVal() : Tag(undefined), Val(0) {} LVILatticeVal() : Tag(undefined), Val(0), Range(1, true) {}
static LVILatticeVal get(Constant *C) { static LVILatticeVal get(Constant *C) {
LVILatticeVal Res; LVILatticeVal Res;
@ -81,10 +86,11 @@ public:
return Res; return Res;
} }
bool isUndefined() const { return Tag == undefined; } bool isUndefined() const { return Tag == undefined; }
bool isConstant() const { return Tag == constant; } bool isConstant() const { return Tag == constant; }
bool isNotConstant() const { return Tag == notconstant; } bool isNotConstant() const { return Tag == notconstant; }
bool isOverdefined() const { return Tag == overdefined; } bool isConstantRange() const { return Tag == constantrange; }
bool isOverdefined() const { return Tag == overdefined; }
Constant *getConstant() const { Constant *getConstant() const {
assert(isConstant() && "Cannot get the constant of a non-constant!"); assert(isConstant() && "Cannot get the constant of a non-constant!");
@ -96,6 +102,12 @@ public:
return Val; 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. /// markOverdefined - Return true if this is a change in status.
bool markOverdefined() { bool markOverdefined() {
if (isOverdefined()) if (isOverdefined())
@ -136,6 +148,32 @@ public:
return true; return true;
} }
/// markConstantRange - Return true if this is a change in status.
bool markConstantRange(const ConstantRange NewR) {
if (isConstantRange()) {
if (NewR.isEmptySet())
return markOverdefined();
assert(Range.contains(NewR) &&
"Marking constant range with non-subset range!");
bool changed = Range == NewR;
Range = NewR;
return changed;
}
assert(isUndefined());
if (NewR.isEmptySet())
return markOverdefined();
else if (NewR.isFullSet()) {
Tag = undefined;
return true;
}
Tag = constantrange;
Range = NewR;
return true;
}
/// mergeIn - Merge the specified lattice value into this one, updating this /// mergeIn - Merge the specified lattice value into this one, updating this
/// one and returning true if anything changed. /// one and returning true if anything changed.
bool mergeIn(const LVILatticeVal &RHS) { bool mergeIn(const LVILatticeVal &RHS) {
@ -162,7 +200,23 @@ public:
return markNotConstant(RHS.getNotConstant()); return markNotConstant(RHS.getNotConstant());
} }
if (RHS.isConstantRange()) {
if (isConstantRange()) {
ConstantRange NewR = Range.intersectWith(RHS.getConstantRange());
if (NewR.isEmptySet())
return markOverdefined();
else
return markConstantRange(NewR);
}
assert(isUndefined() && "Unexpected lattice");
return markConstantRange(RHS.getConstantRange());
}
// RHS must be a constant, we must be undef, constant, or notconstant. // RHS must be a constant, we must be undef, constant, or notconstant.
assert(!isConstantRange() &&
"Constant and ConstantRange cannot be merged.");
if (isUndefined()) if (isUndefined())
return markConstant(RHS.getConstant()); return markConstant(RHS.getConstant());