mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
Add a new getPredicateOnEdge method which returns more rich information for
constant constraints. Improve the LVI lattice to include inequality constraints. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86950 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7707a0df5b
commit
b52675b643
@ -31,19 +31,21 @@ public:
|
||||
static char ID;
|
||||
LazyValueInfo() : FunctionPass(&ID), PImpl(0) {}
|
||||
|
||||
/// Tristate - This is used to return yes/no/dunno results.
|
||||
/// Tristate - This is used to return true/false/dunno results.
|
||||
enum Tristate {
|
||||
Unknown = -1, No = 0, Yes = 1
|
||||
Unknown = -1, False = 0, True = 1
|
||||
};
|
||||
|
||||
|
||||
// Public query interface.
|
||||
|
||||
/// 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.
|
||||
Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
|
||||
BasicBlock *FromBB, BasicBlock *ToBB);
|
||||
|
||||
|
||||
/// isEqual - Determine whether the specified value is known to be equal or
|
||||
/// not-equal to the specified constant at the end of the specified block.
|
||||
Tristate isEqual(Value *V, Constant *C, BasicBlock *BB);
|
||||
|
||||
/// getConstant - Determine whether the specified value is known to be a
|
||||
/// constant at the end of the specified block. Return null if not.
|
||||
Constant *getConstant(Value *V, BasicBlock *BB);
|
||||
|
@ -51,13 +51,17 @@ class LVILatticeVal {
|
||||
undefined,
|
||||
/// constant - This LLVM Value has a specific constant value.
|
||||
constant,
|
||||
|
||||
/// notconstant - This LLVM value is known to not have the specified value.
|
||||
notconstant,
|
||||
|
||||
/// overdefined - This instruction is not known to be constant, and we know
|
||||
/// it has a value.
|
||||
overdefined
|
||||
};
|
||||
|
||||
/// Val: This stores the current lattice value along with the Constant* for
|
||||
/// the constant if this is a 'constant' value.
|
||||
/// the constant if this is a 'constant' or 'notconstant' value.
|
||||
PointerIntPair<Constant *, 2, LatticeValueTy> Val;
|
||||
|
||||
public:
|
||||
@ -68,9 +72,15 @@ public:
|
||||
Res.markConstant(C);
|
||||
return Res;
|
||||
}
|
||||
static LVILatticeVal getNot(Constant *C) {
|
||||
LVILatticeVal Res;
|
||||
Res.markNotConstant(C);
|
||||
return Res;
|
||||
}
|
||||
|
||||
bool isUndefined() const { return Val.getInt() == undefined; }
|
||||
bool isConstant() const { return Val.getInt() == constant; }
|
||||
bool isNotConstant() const { return Val.getInt() == notconstant; }
|
||||
bool isOverdefined() const { return Val.getInt() == overdefined; }
|
||||
|
||||
Constant *getConstant() const {
|
||||
@ -78,12 +88,9 @@ public:
|
||||
return Val.getPointer();
|
||||
}
|
||||
|
||||
/// getConstantInt - If this is a constant with a ConstantInt value, return it
|
||||
/// otherwise return null.
|
||||
ConstantInt *getConstantInt() const {
|
||||
if (isConstant())
|
||||
return dyn_cast<ConstantInt>(getConstant());
|
||||
return 0;
|
||||
Constant *getNotConstant() const {
|
||||
assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
|
||||
return Val.getPointer();
|
||||
}
|
||||
|
||||
/// markOverdefined - Return true if this is a change in status.
|
||||
@ -108,12 +115,41 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// markNotConstant - Return true if this is a change in status.
|
||||
bool markNotConstant(Constant *V) {
|
||||
if (isNotConstant()) {
|
||||
assert(getNotConstant() == V && "Marking !constant with different value");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isConstant())
|
||||
assert(getConstant() != V && "Marking not constant with different value");
|
||||
else
|
||||
assert(isUndefined());
|
||||
|
||||
Val.setInt(notconstant);
|
||||
assert(V && "Marking constant with NULL");
|
||||
Val.setPointer(V);
|
||||
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 (RHS.isNotConstant()) {
|
||||
if (isNotConstant()) {
|
||||
if (getNotConstant() != RHS.getNotConstant())
|
||||
return markOverdefined();
|
||||
return false;
|
||||
}
|
||||
if (isConstant() && getConstant() != RHS.getNotConstant())
|
||||
return markOverdefined();
|
||||
return markNotConstant(RHS.getNotConstant());
|
||||
}
|
||||
|
||||
// RHS must be a constant, we must be undef or constant.
|
||||
if (isConstant() && getConstant() != RHS.getConstant())
|
||||
return markOverdefined();
|
||||
@ -130,6 +166,9 @@ raw_ostream &operator<<(raw_ostream &OS, const LVILatticeVal &Val) {
|
||||
return OS << "undefined";
|
||||
if (Val.isOverdefined())
|
||||
return OS << "overdefined";
|
||||
|
||||
if (Val.isNotConstant())
|
||||
return OS << "notconstant<" << *Val.getNotConstant() << '>';
|
||||
return OS << "constant<" << *Val.getConstant() << '>';
|
||||
}
|
||||
}
|
||||
@ -181,6 +220,7 @@ static LVILatticeVal GetValueOnEdge(Value *V, BasicBlock *BBFrom,
|
||||
// false SETNE.
|
||||
if (isTrueDest == (ICI->getPredicate() == ICmpInst::ICMP_EQ))
|
||||
return LVILatticeVal::get(cast<Constant>(ICI->getOperand(1)));
|
||||
return LVILatticeVal::getNot(cast<Constant>(ICI->getOperand(1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -291,22 +331,50 @@ Constant *LazyValueInfo::getConstantOnEdge(Value *V, BasicBlock *FromBB,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// isEqual - Determine whether the specified value is known to be equal or
|
||||
/// not-equal to the specified constant at the end of the specified block.
|
||||
/// 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::isEqual(Value *V, Constant *C, BasicBlock *BB) {
|
||||
LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
|
||||
BasicBlock *FromBB, BasicBlock *ToBB) {
|
||||
LVILatticeVal Result;
|
||||
|
||||
// If already a constant, we can use constant folding.
|
||||
if (Constant *VC = dyn_cast<Constant>(V)) {
|
||||
// Ignore FP for now. TODO, consider what form of equality we want.
|
||||
if (C->getType()->isFPOrFPVector())
|
||||
return Unknown;
|
||||
Result = LVILatticeVal::get(VC);
|
||||
} else {
|
||||
DenseMap<BasicBlock*, LVILatticeVal> BlockValues;
|
||||
|
||||
Constant *Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_EQ, VC,C,TD);
|
||||
if (ConstantInt *ResCI = dyn_cast<ConstantInt>(Res))
|
||||
return ResCI->isZero() ? No : Yes;
|
||||
DEBUG(errs() << "Getting value " << *V << " on edge from '"
|
||||
<< FromBB->getName() << "' to '" << ToBB->getName() << "'\n");
|
||||
Result = GetValueOnEdge(V, FromBB, ToBB, BlockValues);
|
||||
DEBUG(errs() << " Result = " << Result << "\n");
|
||||
}
|
||||
|
||||
// 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_or_null<ConstantInt>(Res))
|
||||
return ResCI->isZero() ? False : True;
|
||||
} else 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_EQ,
|
||||
Result.getNotConstant(), C, TD);
|
||||
if (Res->isNullValue())
|
||||
return True;
|
||||
}
|
||||
}
|
||||
|
||||
// Not a very good implementation.
|
||||
return Unknown;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user