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));
}
Ejemplo n.º 4
0
        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());
        }
Ejemplo n.º 5
0
 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;
}