STATISTIC(NumBlocks , "Number of blocks marked unreachable");
STATISTIC(NumSnuggle , "Number of comparisons snuggled");
+static const ConstantRange empty(1, false);
+
namespace {
class DomTreeDFS {
public:
UGE = UGT | EQ_BIT
};
+#ifndef NDEBUG
/// validPredicate - determines whether a given value is actually a lattice
/// value. Only used in assertions or debugging.
static bool validPredicate(LatticeVal LV) {
return false;
}
}
+#endif
/// reversePredicate - reverse the direction of the inequality
static LatticeVal reversePredicate(LatticeVal LV) {
const_iterator end() const { return RangeList.end(); }
iterator find(DomTreeDFS::Node *Subtree) {
- static ConstantRange empty(1, false);
iterator E = end();
iterator I = std::lower_bound(begin(), E,
std::make_pair(Subtree, empty), swo);
}
const_iterator find(DomTreeDFS::Node *Subtree) const {
- static const ConstantRange empty(1, false);
const_iterator E = end();
const_iterator I = std::lower_bound(begin(), E,
std::make_pair(Subtree, empty), swo);
assert(!CR.isEmptySet() && "Empty ConstantRange.");
assert(!CR.isSingleElement() && "Refusing to store single element.");
- static ConstantRange empty(1, false);
iterator E = end();
iterator I =
std::lower_bound(begin(), E, std::make_pair(Subtree, empty), swo);
assert(!CR.isEmptySet() && "Can't deal with empty set.");
if (LV == NE)
- return makeConstantRange(ICmpInst::ICMP_NE, CR);
+ return ConstantRange::makeICmpRegion(ICmpInst::ICMP_NE, CR);
unsigned LV_s = LV & (SGT_BIT|SLT_BIT);
unsigned LV_u = LV & (UGT_BIT|ULT_BIT);
ConstantRange Range(CR.getBitWidth());
if (LV_s == SGT_BIT) {
- Range = Range.maximalIntersectWith(makeConstantRange(
+ Range = Range.maximalIntersectWith(ConstantRange::makeICmpRegion(
hasEQ ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_SGT, CR));
} else if (LV_s == SLT_BIT) {
- Range = Range.maximalIntersectWith(makeConstantRange(
+ Range = Range.maximalIntersectWith(ConstantRange::makeICmpRegion(
hasEQ ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_SLT, CR));
}
if (LV_u == UGT_BIT) {
- Range = Range.maximalIntersectWith(makeConstantRange(
+ Range = Range.maximalIntersectWith(ConstantRange::makeICmpRegion(
hasEQ ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_UGT, CR));
} else if (LV_u == ULT_BIT) {
- Range = Range.maximalIntersectWith(makeConstantRange(
+ Range = Range.maximalIntersectWith(ConstantRange::makeICmpRegion(
hasEQ ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_ULT, CR));
}
return Range;
}
- /// makeConstantRange - Creates a ConstantRange representing the set of all
- /// value that match the ICmpInst::Predicate with any of the values in CR.
- ConstantRange makeConstantRange(ICmpInst::Predicate ICmpOpcode,
- const ConstantRange &CR) {
- uint32_t W = CR.getBitWidth();
- switch (ICmpOpcode) {
- default: assert(!"Invalid ICmp opcode to makeConstantRange()");
- case ICmpInst::ICMP_EQ:
- return ConstantRange(CR.getLower(), CR.getUpper());
- case ICmpInst::ICMP_NE:
- if (CR.isSingleElement())
- return ConstantRange(CR.getUpper(), CR.getLower());
- return ConstantRange(W);
- case ICmpInst::ICMP_ULT:
- return ConstantRange(APInt::getMinValue(W), CR.getUnsignedMax());
- case ICmpInst::ICMP_SLT:
- return ConstantRange(APInt::getSignedMinValue(W), CR.getSignedMax());
- case ICmpInst::ICMP_ULE: {
- APInt UMax(CR.getUnsignedMax());
- if (UMax.isMaxValue())
- return ConstantRange(W);
- return ConstantRange(APInt::getMinValue(W), UMax + 1);
- }
- case ICmpInst::ICMP_SLE: {
- APInt SMax(CR.getSignedMax());
- if (SMax.isMaxSignedValue() || (SMax+1).isMaxSignedValue())
- return ConstantRange(W);
- return ConstantRange(APInt::getSignedMinValue(W), SMax + 1);
- }
- case ICmpInst::ICMP_UGT:
- return ConstantRange(CR.getUnsignedMin() + 1, APInt::getNullValue(W));
- case ICmpInst::ICMP_SGT:
- return ConstantRange(CR.getSignedMin() + 1,
- APInt::getSignedMinValue(W));
- case ICmpInst::ICMP_UGE: {
- APInt UMin(CR.getUnsignedMin());
- if (UMin.isMinValue())
- return ConstantRange(W);
- return ConstantRange(UMin, APInt::getNullValue(W));
- }
- case ICmpInst::ICMP_SGE: {
- APInt SMin(CR.getSignedMin());
- if (SMin.isMinSignedValue())
- return ConstantRange(W);
- return ConstantRange(SMin, APInt::getSignedMinValue(W));
- }
- }
- }
-
#ifndef NDEBUG
bool isCanonical(Value *V, DomTreeDFS::Node *Subtree) {
return V == VN.canonicalize(V, Subtree);
BasicBlock *TopBB;
Instruction *TopInst;
bool &modified;
+ LLVMContext *Context;
typedef InequalityGraph::Node Node;
Instruction *I2 = dyn_cast<Instruction>(R);
if (I2 && below(I2)) {
std::vector<Instruction *> ToNotify;
- for (Value::use_iterator UI = R->use_begin(), UE = R->use_end();
+ for (Value::use_iterator UI = I2->use_begin(), UE = I2->use_end();
UI != UE;) {
Use &TheUse = UI.getUse();
++UI;
- if (Instruction *I = dyn_cast<Instruction>(TheUse.getUser()))
- ToNotify.push_back(I);
+ Instruction *I = cast<Instruction>(TheUse.getUser());
+ ToNotify.push_back(I);
}
DOUT << "Simply removing " << *I2
++UI;
Value *V = TheUse.getUser();
if (!V->use_empty()) {
- if (Instruction *Inst = dyn_cast<Instruction>(V)) {
- if (aboveOrBelow(Inst))
- opsToDef(Inst);
- }
+ Instruction *Inst = cast<Instruction>(V);
+ if (aboveOrBelow(Inst))
+ opsToDef(Inst);
}
}
}
Top(DTDFS->getNodeForBlock(TopBB)),
TopBB(TopBB),
TopInst(NULL),
- modified(modified)
+ modified(modified),
+ Context(TopBB->getContext())
{
assert(Top && "VRPSolver created for unreachable basic block.");
}
switch (BO->getOpcode()) {
case Instruction::And: {
// "and i32 %a, %b" EQ -1 then %a EQ -1 and %b EQ -1
- ConstantInt *CI = ConstantInt::getAllOnesValue(Ty);
+ ConstantInt *CI = cast<ConstantInt>(Context->getAllOnesValue(Ty));
if (Canonical == CI) {
add(CI, Op0, ICmpInst::ICMP_EQ, NewContext);
add(CI, Op1, ICmpInst::ICMP_EQ, NewContext);
} break;
case Instruction::Or: {
// "or i32 %a, %b" EQ 0 then %a EQ 0 and %b EQ 0
- Constant *Zero = Constant::getNullValue(Ty);
+ Constant *Zero = Context->getNullValue(Ty);
if (Canonical == Zero) {
add(Zero, Op0, ICmpInst::ICMP_EQ, NewContext);
add(Zero, Op1, ICmpInst::ICMP_EQ, NewContext);
}
if (Canonical == LHS) {
if (isa<ConstantInt>(Canonical))
- add(RHS, Constant::getNullValue(Ty), ICmpInst::ICMP_EQ,
+ add(RHS, Context->getNullValue(Ty), ICmpInst::ICMP_EQ,
NewContext);
} else if (isRelatedBy(LHS, Canonical, ICmpInst::ICMP_NE)) {
- add(RHS, Constant::getNullValue(Ty), ICmpInst::ICMP_NE,
+ add(RHS, Context->getNullValue(Ty), ICmpInst::ICMP_NE,
NewContext);
}
} break;
}
// TODO: The GEPI indices are all zero. Copy from definition to operand,
// jumping the type plane as needed.
- if (isRelatedBy(GEPI, Constant::getNullValue(GEPI->getType()),
+ if (isRelatedBy(GEPI, Context->getNullValue(GEPI->getType()),
ICmpInst::ICMP_NE)) {
Value *Ptr = GEPI->getPointerOperand();
- add(Ptr, Constant::getNullValue(Ptr->getType()), ICmpInst::ICMP_NE,
+ add(Ptr, Context->getNullValue(Ptr->getType()), ICmpInst::ICMP_NE,
NewContext);
}
} else if (CastInst *CI = dyn_cast<CastInst>(I)) {
const Type *Ty = BO->getType();
assert(!Ty->isFPOrFPVector() && "Float in work queue!");
- Constant *Zero = Constant::getNullValue(Ty);
- ConstantInt *AllOnes = ConstantInt::getAllOnesValue(Ty);
+ Constant *Zero = Context->getNullValue(Ty);
+ Constant *One = Context->getConstantInt(Ty, 1);
+ ConstantInt *AllOnes = cast<ConstantInt>(Context->getAllOnesValue(Ty));
switch (Opcode) {
default: break;
case Instruction::LShr:
case Instruction::AShr:
case Instruction::Shl:
+ if (Op1 == Zero) {
+ add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
+ return;
+ }
+ break;
case Instruction::Sub:
if (Op1 == Zero) {
add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
return;
}
+ if (ConstantInt *CI0 = dyn_cast<ConstantInt>(Op0)) {
+ unsigned n_ci0 = VN.getOrInsertVN(Op1, Top);
+ ConstantRange CR = VR.range(n_ci0, Top);
+ if (!CR.isFullSet()) {
+ CR.subtract(CI0->getValue());
+ unsigned n_bo = VN.getOrInsertVN(BO, Top);
+ VR.applyRange(n_bo, CR, Top, this);
+ return;
+ }
+ }
+ if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Op1)) {
+ unsigned n_ci1 = VN.getOrInsertVN(Op0, Top);
+ ConstantRange CR = VR.range(n_ci1, Top);
+ if (!CR.isFullSet()) {
+ CR.subtract(CI1->getValue());
+ unsigned n_bo = VN.getOrInsertVN(BO, Top);
+ VR.applyRange(n_bo, CR, Top, this);
+ return;
+ }
+ }
break;
case Instruction::Or:
if (Op0 == AllOnes || Op1 == AllOnes) {
add(BO, AllOnes, ICmpInst::ICMP_EQ, NewContext);
return;
- } // fall-through
- case Instruction::Xor:
+ }
+ if (Op0 == Zero) {
+ add(BO, Op1, ICmpInst::ICMP_EQ, NewContext);
+ return;
+ } else if (Op1 == Zero) {
+ add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
+ return;
+ }
+ break;
case Instruction::Add:
+ if (ConstantInt *CI0 = dyn_cast<ConstantInt>(Op0)) {
+ unsigned n_ci0 = VN.getOrInsertVN(Op1, Top);
+ ConstantRange CR = VR.range(n_ci0, Top);
+ if (!CR.isFullSet()) {
+ CR.subtract(-CI0->getValue());
+ unsigned n_bo = VN.getOrInsertVN(BO, Top);
+ VR.applyRange(n_bo, CR, Top, this);
+ return;
+ }
+ }
+ if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Op1)) {
+ unsigned n_ci1 = VN.getOrInsertVN(Op0, Top);
+ ConstantRange CR = VR.range(n_ci1, Top);
+ if (!CR.isFullSet()) {
+ CR.subtract(-CI1->getValue());
+ unsigned n_bo = VN.getOrInsertVN(BO, Top);
+ VR.applyRange(n_bo, CR, Top, this);
+ return;
+ }
+ }
+ // fall-through
+ case Instruction::Xor:
if (Op0 == Zero) {
add(BO, Op1, ICmpInst::ICMP_EQ, NewContext);
return;
add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
return;
}
- // fall-through
+ if (Op0 == Zero || Op1 == Zero) {
+ add(BO, Zero, ICmpInst::ICMP_EQ, NewContext);
+ return;
+ }
+ break;
case Instruction::Mul:
if (Op0 == Zero || Op1 == Zero) {
add(BO, Zero, ICmpInst::ICMP_EQ, NewContext);
return;
}
+ if (Op0 == One) {
+ add(BO, Op1, ICmpInst::ICMP_EQ, NewContext);
+ return;
+ } else if (Op1 == One) {
+ add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
+ return;
+ }
break;
}
// "%x = add i32 %y, %z" and %x EQ %y then %z EQ 0
// "%x = add i32 %y, %z" and %x EQ %z then %y EQ 0
// "%x = shl i32 %y, %z" and %x EQ %y and %y NE 0 then %z EQ 0
- // "%x = udiv i32 %y, %z" and %x EQ %y then %z EQ 1
+ // "%x = udiv i32 %y, %z" and %x EQ %y and %y NE 0 then %z EQ 1
Value *Known = Op0, *Unknown = Op1,
*TheBO = VN.canonicalize(BO, Top);
case Instruction::UDiv:
case Instruction::SDiv:
if (Unknown == Op1) break;
- if (isRelatedBy(Known, Zero, ICmpInst::ICMP_NE)) {
- Constant *One = ConstantInt::get(Ty, 1);
+ if (isRelatedBy(Known, Zero, ICmpInst::ICMP_NE))
add(Unknown, One, ICmpInst::ICMP_EQ, NewContext);
- }
break;
}
}
// TODO: The GEPI indices are all zero. Copy from operand to definition,
// jumping the type plane as needed.
Value *Ptr = GEPI->getPointerOperand();
- if (isRelatedBy(Ptr, Constant::getNullValue(Ptr->getType()),
+ if (isRelatedBy(Ptr, Context->getNullValue(Ptr->getType()),
ICmpInst::ICMP_NE)) {
- add(GEPI, Constant::getNullValue(GEPI->getType()), ICmpInst::ICMP_NE,
+ add(GEPI, Context->getNullValue(GEPI->getType()), ICmpInst::ICMP_NE,
NewContext);
}
}
UE = O.LHS->use_end(); UI != UE;) {
Use &TheUse = UI.getUse();
++UI;
- if (Instruction *I = dyn_cast<Instruction>(TheUse.getUser())) {
- if (aboveOrBelow(I))
- opsToDef(I);
- }
+ Instruction *I = cast<Instruction>(TheUse.getUser());
+ if (aboveOrBelow(I))
+ opsToDef(I);
}
}
if (Instruction *I2 = dyn_cast<Instruction>(O.RHS)) {
UE = O.RHS->use_end(); UI != UE;) {
Use &TheUse = UI.getUse();
++UI;
- if (Instruction *I = dyn_cast<Instruction>(TheUse.getUser())) {
- if (aboveOrBelow(I))
- opsToDef(I);
- }
+ Instruction *I = cast<Instruction>(TheUse.getUser());
+ if (aboveOrBelow(I))
+ opsToDef(I);
}
}
}
delete DTDFS;
delete VR;
delete IG;
+ delete VN;
modified |= UB.kill();
void PredicateSimplifier::Forwards::visitAllocaInst(AllocaInst &AI) {
VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &AI);
- VRP.add(Constant::getNullValue(AI.getType()), &AI, ICmpInst::ICMP_NE);
+ VRP.add(AI.getParent()->getContext()->getNullValue(AI.getType()),
+ &AI, ICmpInst::ICMP_NE);
VRP.solve();
}
void PredicateSimplifier::Forwards::visitLoadInst(LoadInst &LI) {
Value *Ptr = LI.getPointerOperand();
- // avoid "load uint* null" -> null NE null.
+ // avoid "load i8* null" -> null NE null.
if (isa<Constant>(Ptr)) return;
VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &LI);
- VRP.add(Constant::getNullValue(Ptr->getType()), Ptr, ICmpInst::ICMP_NE);
+ VRP.add(LI.getParent()->getContext()->getNullValue(Ptr->getType()),
+ Ptr, ICmpInst::ICMP_NE);
VRP.solve();
}
if (isa<Constant>(Ptr)) return;
VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &SI);
- VRP.add(Constant::getNullValue(Ptr->getType()), Ptr, ICmpInst::ICMP_NE);
+ VRP.add(SI.getParent()->getContext()->getNullValue(Ptr->getType()),
+ Ptr, ICmpInst::ICMP_NE);
VRP.solve();
}
case Instruction::SDiv: {
Value *Divisor = BO.getOperand(1);
VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO);
- VRP.add(Constant::getNullValue(Divisor->getType()), Divisor,
- ICmpInst::ICMP_NE);
+ VRP.add(BO.getParent()->getContext()->getNullValue(Divisor->getType()),
+ Divisor, ICmpInst::ICMP_NE);
VRP.solve();
break;
}
if (!Op1->getValue().isAllOnesValue())
NextVal = ConstantInt::get(Op1->getValue()+1);
break;
-
}
+
if (NextVal) {
VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &IC);
if (VRP.isRelatedBy(IC.getOperand(0), NextVal,
ICmpInst::getInversePredicate(Pred))) {
- ICmpInst *NewIC = new ICmpInst(ICmpInst::ICMP_EQ, IC.getOperand(0),
- NextVal, "", &IC);
+ ICmpInst *NewIC = new ICmpInst(&IC, ICmpInst::ICMP_EQ,
+ IC.getOperand(0), NextVal, "");
NewIC->takeName(&IC);
IC.replaceAllUsesWith(NewIC);