bool RelativeMinMax::mulMinMax(Expr PrevMin, Expr PrevMax, Expr OtherMin, Expr OtherMax, Expr &Min, Expr &Max) { if (OtherMin == OtherMax && OtherMin.isConstant()) { if (OtherMin.isPositive()) { Min = PrevMin * OtherMin; Max = PrevMax * OtherMax; } else { Min = PrevMax * OtherMax; Max = PrevMin * OtherMin; } } else if (PrevMin == PrevMax && PrevMin.isConstant()) { if (PrevMin.isPositive()) { Min = PrevMin * OtherMin; Max = PrevMax * OtherMax; } else { Min = PrevMax * OtherMax; Max = PrevMin * OtherMin; } } else { Min = (PrevMin * OtherMin).min(PrevMin * OtherMax) .min(OtherMin * PrevMax); Max = (PrevMax * OtherMin).max(PrevMax * OtherMax) .max(OtherMax * PrevMin); } }
// greater or equal bool ge(const Expr &a, const Expr &b) { if(!a.isConstant() and b.isConstant()) return true; else if(a.isConstant() and !b.isConstant()) return true; else return (a >= b).isEQ(Expr::getTrue(*SI)); }
///Expr comparison functions // less than bool lt(const Expr &a, const Expr &b) { /*if(!a.isEQ(Expr::getPlusInf(*SI)) and b.isEQ(Expr::getPlusInf(*SI))) return true; else if(a.isEQ(Expr::getMinusInf(*SI)) and !b.isEQ(Expr::getMinusInf(*SI))) return true;*/ if(!a.isConstant() and b.isConstant()) return true; else if(a.isConstant() and !b.isConstant()) return true; else return (a < b).isEQ(Expr::getTrue(*SI)); }
void testConstant(){ TestModel m; Var a = m.addVar("a"); Var b = m.addVar("b"); Expr c = 4; TS_ASSERT(c.isConstant()); c += a; TS_ASSERT(!c.isConstant()); Expr d = a + 4; TS_ASSERT(!d.isConstant()); Expr e = 4 + a; TS_ASSERT(!e.isConstant()); }
void Tes(Expr c, string test, OPType type, bool isconstant=false){ TS_ASSERT_EQUALS(c.toString(), test); TS_ASSERT_EQUALS(c.getType(), type); TS_ASSERT_EQUALS(c.isConstant(), isconstant); }
// Applies the narrowing operations void RangeBasedPointerAnalysis::applyNarrowing() { for(auto i : RangedPointers) { for(auto j = i.second->addr_begin(), je = i.second->addr_end(); j != je; j++) { Address* a = *j; if(!(*j)->Narrowing_Ops.empty()) { Range narrowed = Range(a->getOffset()->getLower(), a->getOffset()->getUpper()); std::pair<bool,bool> growth; if(narrowed.getUpper().isEQ(Expr::getPlusInf(*SI))) growth.second = true; if(narrowed.getLower().isEQ(Expr::getMinusInf(*SI))) growth.first = true; for(auto z : a->Narrowing_Ops) { if(z.second->cmp_op == CmpInst::ICMP_EQ) { //errs() << "=\n"; RangedPointer* rp = RangedPointers[z.second->cmp_v]; for(auto w = rp->addr_begin(), we = rp->addr_end(); w != we; w++) { Expr dw = (*w)->getOffset()->getLower() + z.second->context->getUpper(); if(!narrowed.getUpper().isConstant() and !dw.isConstant()) narrowed.setUpper(narrowed.getUpper().min(dw)); else if(gt(narrowed.getUpper(), dw)) narrowed.setUpper(dw); //narrowed.setUpper(narrowed.getUpper().min(dw)); Expr up = (*w)->getOffset()->getUpper() + z.second->context->getLower(); if(!narrowed.getLower().isConstant() and !up.isConstant()) narrowed.setLower(narrowed.getLower().max(up)); else if(lt(narrowed.getLower(), up)) narrowed.setLower(up); //narrowed.setLower(narrowed.getLower().max(up)); } } else if(z.second->cmp_op == CmpInst::ICMP_NE) { //errs() << "!=\n"; RangedPointer* rp = RangedPointers[z.second->cmp_v]; for(auto w = rp->addr_begin(), we = rp->addr_end(); w != we; w++) { if(a->widened) { if(growth.second) { Expr dw = (*w)->getOffset()->getLower() + z.second->context->getUpper(); if(!narrowed.getUpper().isConstant() and !dw.isConstant()) narrowed.setUpper(narrowed.getUpper().min(dw - 1)); else if(ge(narrowed.getUpper(), dw)) narrowed.setUpper(dw - 1); //narrowed.setUpper(narrowed.getUpper().min(dw - 1)); } else if(growth.first) { Expr up = (*w)->getOffset()->getUpper() + z.second->context->getLower(); if(!narrowed.getLower().isConstant() and !up.isConstant()) narrowed.setLower(narrowed.getLower().max(up + 1)); else if(le(narrowed.getLower(), up)) narrowed.setLower(up + 1); //narrowed.setLower(narrowed.getLower().max(up + 1)); } } } } else if(z.second->cmp_op == CmpInst::ICMP_SLT) { //errs() << "<\n"; RangedPointer* rp = RangedPointers[z.second->cmp_v]; for(auto w = rp->addr_begin(), we = rp->addr_end(); w != we; w++) { Expr dw = (*w)->getOffset()->getLower() + z.second->context->getUpper(); if(!narrowed.getUpper().isConstant() and !dw.isConstant()) narrowed.setUpper(narrowed.getUpper().min(dw - 1)); else if(ge(narrowed.getUpper(), dw)) narrowed.setUpper(dw - 1); //narrowed.setUpper(narrowed.getUpper().min(dw - 1)); } } else if(z.second->cmp_op == CmpInst::ICMP_SLE) { //errs() << "<=\n"; RangedPointer* rp = RangedPointers[z.second->cmp_v]; for(auto w = rp->addr_begin(), we = rp->addr_end(); w != we; w++) { Expr dw = (*w)->getOffset()->getLower() + z.second->context->getUpper(); if(!narrowed.getUpper().isConstant() and !dw.isConstant()) narrowed.setUpper(narrowed.getUpper().min(dw)); else if(gt(narrowed.getUpper(), dw)) narrowed.setUpper(dw); //narrowed.setUpper(narrowed.getUpper().min(dw)); } } else if(z.second->cmp_op == CmpInst::ICMP_SGT) { //errs() << ">\n"; RangedPointer* rp = RangedPointers[z.second->cmp_v]; for(auto w = rp->addr_begin(), we = rp->addr_end(); w != we; w++) { Expr up = (*w)->getOffset()->getUpper() + z.second->context->getLower(); if(!narrowed.getLower().isConstant() and !up.isConstant()) narrowed.setLower(narrowed.getLower().max(up + 1)); else if(le(narrowed.getLower(), up)) narrowed.setLower(up + 1); //narrowed.setLower(narrowed.getLower().max(up + 1)); } } else if(z.second->cmp_op == CmpInst::ICMP_SGE) { //errs() << ">=\n"; RangedPointer* rp = RangedPointers[z.second->cmp_v]; for(auto w = rp->addr_begin(), we = rp->addr_end(); w != we; w++) { Expr up = (*w)->getOffset()->getUpper() + z.second->context->getLower(); if(!narrowed.getLower().isConstant() and !up.isConstant()) narrowed.setLower(narrowed.getLower().max(up)); else if(lt(narrowed.getLower(), up)) narrowed.setLower(up); //narrowed.setLower(narrowed.getLower().max(up)); } } } a->Narrowing_Ops.clear(); a->setOffset(narrowed.getLower(), narrowed.getUpper()); } } } }
bool RelativeMinMax::getMinMax(Expr Ex, Expr &Min, Expr &Max) { if (Ex.isConstant()) { Min = Ex; Max = Ex; } else if (Ex.isSymbol()) { // Bounds of induction variables have special treatment. if (PHINode *Phi = dyn_cast<PHINode>(Ex.getSymbolValue())) { if (Loop *L = LIE_->getLoopForInductionVariable(Phi)) { Expr IndvarStart, IndvarEnd, IndvarStep; LIE_->getLoopInfo(L, Phi, IndvarStart, IndvarEnd, IndvarStep); BranchInst *BI = cast<BranchInst>(L->getExitingBlock()->getTerminator()); ICmpInst *ICI = cast<ICmpInst>(BI->getCondition()); Expr MinStart, MaxStart, MinEnd, MaxEnd; if (!getMinMax(IndvarStart, MinStart, MaxStart) || !getMinMax(IndvarEnd, MinEnd, MaxEnd)) { RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for " << IndvarStart << " and/or" << IndvarEnd << "\n"); return false; } // FIXME: we should wrap the loop in a conditional so that the following // min/max assumptions always hold. switch (ICI->getPredicate()) { case CmpInst::ICMP_SLT: case CmpInst::ICMP_ULT: case CmpInst::ICMP_SLE: case CmpInst::ICMP_ULE: Min = MinStart; Max = MaxEnd; break; case CmpInst::ICMP_SGT: case CmpInst::ICMP_UGT: case CmpInst::ICMP_UGE: case CmpInst::ICMP_SGE: Min = MaxStart; Max = MinEnd; break; default: llvm_unreachable("Invalid comparison predicate"); } RMM_DEBUG(dbgs() << "RelativeMinMax: min/max for induction variable " << *Phi << ": " << Min << ", " << Max << "\n"); return true; } } Min = Ex; Max = Ex; } else if (Ex.isAdd()) { for (auto SubEx : Ex) { Expr TmpMin, TmpMax; if (!getMinMax(SubEx, TmpMin, TmpMax)) { RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for " << SubEx << "\n"); return false; } addMinMax(TmpMin, TmpMax, Min, Max, Min, Max); } } else if (Ex.isMul()) { Min = Expr::InvalidExpr(); for (auto SubEx : Ex) { Expr TmpMin, TmpMax; if (!getMinMax(SubEx, TmpMin, TmpMax)) { RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for " << SubEx << "\n"); return false; } if (!Min.isValid()) { Min = TmpMin; Max = TmpMax; } else { mulMinMax(TmpMin, TmpMax, Min, Max, Min, Max); } } } else if (Ex.isPow()) { if (!Ex.getPowExp().isConstant()) { RMM_DEBUG(dbgs() << "RelativeMinMax: non-constant exponent\n"); return false; } Expr BaseMin, BaseMax; if (!getMinMax(Ex.getPowBase(), BaseMin, BaseMax)) { RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for " << Ex.getPowBase() << "\n"); return false; } if (Ex.getPowExp().isPositive()) { Min = BaseMin ^ Ex.getPowExp(); Max = BaseMax ^ Ex.getPowExp(); } else { Min = BaseMax ^ Ex.getPowExp(); Max = BaseMin ^ Ex.getPowExp(); } } else if (Ex.isMin()) { Expr MinFirst, MinSecond, Bogus; getMinMax(Ex.at(0), MinFirst, Bogus); getMinMax(Ex.at(1), MinSecond, Bogus); Min = Max = MinFirst.min(MinSecond); } else if (Ex.isMax()) { Expr MaxFirst, MaxSecond, Bogus; getMinMax(Ex.at(0), MaxFirst, Bogus); getMinMax(Ex.at(1), MaxSecond, Bogus); Min = Max = MaxFirst.max(MaxSecond); } else { RMM_DEBUG(dbgs() << "RelativeMinMax: unhandled expression: " << Ex << "\n"); return false; } return true; }