Example #1
0
Range Range::widen(const Range& Other) const {
  RANGE_DEBUG(dbgs() << "widen() :: " << *this << " :: " << Other << "\n");
  if (Other.getLower() == Expr::GetBottomValue() ||
      Other.getUpper() == Expr::GetBottomValue()) {
    if (Other.getLower() != Other.getUpper())
      dbgs() << "widen() :: " << *this << " :: " << Other << "\n";
    assert(Other.getLower() == Other.getUpper() && "Inconsistent state");
    RANGE_DEBUG(dbgs() << "widen() = " << *this << "\n");
    return *this;
  }

  if (getLower() == Expr::GetBottomValue() ||
      getUpper() == Expr::GetBottomValue()) {
    assert(getLower() == getUpper() && "Inconsistent state");
    RANGE_DEBUG(dbgs() << "widen() = " << Other << "\n");
    return Other;
  }

  Expr Lower = Other.getLower() == getLower() ? getLower()
                                              : Expr::GetMinusInfValue();
  Expr Upper = Other.getUpper() == getUpper() ? getUpper()
                                              : Expr::GetPlusInfValue();
  RANGE_DEBUG(dbgs() << "widen() = " << Range(Lower, Upper) << "\n");
  return Range(Lower, Upper);
}
Example #2
0
Range Range::operator/(const Range& Other) const {
  if (Other.getLower().isStrictlyPositive() || getLower().isStrictlyPositive())
    return Range(getUpper() / Other.getUpper(),
                 getLower() / Other.getUpper());
  if (Other.getLower().isNegative() || getLower().isNegative())
    return Range(getLower() / Other.getLower(),
                 getUpper() / Other.getUpper());
  return GetInfRange();
}
Example #3
0
Range Range::operator*(const Range& Other) const {
  //errs() << "MUL: " << *this << " * " << Other << "\n";
  if (Other.getLower().isNegative() || getLower().isNegative()) {
    //errs() << "NEG\n";
    return Range(getUpper() * Other.getUpper(),
                 getLower() * Other.getUpper());
  } if (Other.getLower().isNonNegative() || getLower().isNonNegative()) {
    //errs() << "POS\n";
    return Range(getLower() * Other.getLower(),
                 getUpper() * Other.getUpper());
  }
  return GetInfRange();
}
/*
 * function join
 *
 * Here we perform the join operation in the interval lattice,
 * using Cousot's widening operator. We join the current abstract state
 * with the new_abstract_state and update the current abstract state of
 * the node.
 *
 * This function returns true if the current abstract state has changed.
 */
bool llvm::RangeAnalysis::join(GraphNode* Node, Range new_abstract_state){

	//Do not widen the range of a value that has an initial value
	if (!getInitialState(Node).isMaxRange()) {
		return false;
	}


	Range oldInterval = out_state[Node];
	Range newInterval = new_abstract_state;

	APInt oldLower = oldInterval.getLower();
	APInt oldUpper = oldInterval.getUpper();
	APInt newLower = newInterval.getLower();
	APInt newUpper = newInterval.getUpper();



	if (oldInterval.isUnknown())
		out_state[Node] = newInterval;
	else {

		if (widening_count[Node] < MaxIterationCount) {
			out_state[Node] = oldInterval.unionWith(newInterval);
			widening_count[Node]++;
		} else {
			//Widening
			APInt oldLower = oldInterval.getLower();
			APInt oldUpper = oldInterval.getUpper();
			APInt newLower = newInterval.getLower();
			APInt newUpper = newInterval.getUpper();
			if (newLower.slt(oldLower))
				if (newUpper.sgt(oldUpper))
					out_state[Node] = Range(Min, Max);
				else
					out_state[Node] = Range(Min, oldUpper);
			else if (newUpper.sgt(oldUpper))
				out_state[Node] = Range(oldLower, Max);
		}
	}

	bool hasChanged = oldInterval != out_state[Node];

	return hasChanged;
}
/*
 * function meet
 *
 * Here we perform the meet operation in the interval lattice,
 * using Cousot's narrowing operator. We meet the current abstract state
 * with the new_abstract_state and update the current abstract state of
 * the node.
 *
 * This function returns true if the current abstract state has changed.
 */
bool llvm::RangeAnalysis::meet(GraphNode* Node, Range new_abstract_state){

	Range oldInterval = out_state[Node];
	APInt oLower = out_state[Node].getLower();
	APInt oUpper = out_state[Node].getUpper();
	Range newInterval = new_abstract_state;

	APInt nLower = newInterval.getLower();
	APInt nUpper = newInterval.getUpper();

	if (narrowing_count[Node] < MaxIterationCount) {

		if (oLower.eq(Min) && nLower.ne(Min)) {
			out_state[Node] = Range(nLower, oUpper);
		} else {
			APInt smin = APIntOps::smin(oLower, nLower);
			if (oLower.ne(smin)) {
				out_state[Node] = Range(smin, oUpper);
			}
		}

		if (oUpper.eq(Max) && nUpper.ne(Max)) {
			out_state[Node] = Range(out_state[Node].getLower(), nUpper);
		} else {
			APInt smax = APIntOps::smax(oUpper, nUpper);
			if (oUpper.ne(smax)) {
				out_state[Node] = Range(out_state[Node].getLower(), smax);
			}
		}

	}

	if (SigmaOpNode* Sigma = dyn_cast<SigmaOpNode>(Node)){

		if (branchConstraints.count(Sigma) > 0) {
			out_state[Node] = out_state[Node].intersectWith(branchConstraints[Sigma]->getRange());
		}
	}

	bool hasChanged = oldInterval != out_state[Node];

	if (hasChanged) narrowing_count[Node]++;

	return hasChanged;
}
Example #6
0
Range Range::meet(const Range& Other) const {
  // errs() << "MEET: " << Other << ", " << *this << "\n";
  return Range(Other.getLower().min(getLower()),
               Other.getUpper().max(getUpper()));
}
Example #7
0
Range Range::operator-(const Range& Other) const {
  return Range(getLower() - Other.getUpper(),
               getUpper() - Other.getLower());
}
Example #8
0
bool Range::operator!=(const Range& other) const {
  return getLower().ne(other.getLower())
     || getUpper().ne(other.getUpper());
}
Example #9
0
bool Range::operator==(const Range& other) const {
  return getLower().eq(other.getLower())
     && getUpper().eq(other.getUpper());
}
// 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());
      }
    }
  }
}
Example #11
0
// addEdgesFor
// Creates a node for I and inserts edges from the created node to the
// appropriate node of other values.
void IneqGraph::addEdgesFor(Instruction *I) {
  if (I->getType()->isPointerTy())
    return;

  Range RI = RA->getRange(I);
  if (!RI.getLower().isMinSignedValue())
    addMayEdge(AlfaConst, I, -RI.getLower().getSExtValue());
  if (!RI.getUpper().isMaxSignedValue())
    addMayEdge(I, AlfaConst, RI.getUpper().getSExtValue());

  // TODO: Handle multiplication, remainder and division instructions.
  switch (I->getOpcode()) {
    case Instruction::SExt:
    case Instruction::ZExt:
    case Instruction::Trunc:
    case Instruction::BitCast:
      addMayEdge(I, I->getOperand(0), 0);
      addMayEdge(I->getOperand(0), I, 0);
      break;
    case Instruction::Add:
      // a = b + c
      // ==> a <= b + sup(c)
      // ==> a <= c + sup(b)
      // ==> b <= a - inf(c)
      // ==> c <= a - inf(b)
      {
        Value *A = I->getOperand(0);
        Value *B = I->getOperand(1);
        Range AR = RA->getRange(A);
        Range BR = RA->getRange(B);
        if (!isa<ConstantInt>(B) && !AR.getUpper().isMaxSignedValue())
          addMayEdge(I, B, AR.getUpper());
        if (!isa<ConstantInt>(A) && !BR.getUpper().isMaxSignedValue())
          addMayEdge(I, A, BR.getUpper());
        if (!isa<ConstantInt>(A) && !BR.getLower().isMinSignedValue())
          addMayEdge(A, I, -BR.getUpper());
        if (!isa<ConstantInt>(B) && !AR.getLower().isMinSignedValue())
          addMayEdge(B, I, -AR.getUpper());
        break;
      }
    case Instruction::Sub:
      // a = b - c
      // ==> a <= b - inf(c)
      {
        Value *A = I->getOperand(0);
        Value *B = I->getOperand(1);
        Range AR = RA->getRange(A);
        Range BR = RA->getRange(B);
        if (!isa<ConstantInt>(A) && !BR.getLower().isMinSignedValue())
          addMayEdge(I, A, -BR.getLower());
        break;
      }
    case Instruction::Br:
      // if (a > b) {
      //   a1 = sigma(a)
      //   b1 = sigma(b)
      {      
        BranchInst *BI = cast<BranchInst>(I);
        ICmpInst *Cmp = dyn_cast<ICmpInst>(I->getOperand(0));
        if (!Cmp)
          break;
        Value *L = Cmp->getOperand(0);
        DEBUG(dbgs() << "IneqGraph: L: " << *L << "\n");
        Value *R = Cmp->getOperand(1);
        DEBUG(dbgs() << "IneqGraph: R: " << *R << "\n");
        Value *LSigma = VS->findSigma(L, BI->getSuccessor(0), BI->getParent());
        DEBUG(dbgs() << "IneqGraph: LSigma: " << *LSigma << "\n");
        Value *RSigma = VS->findSigma(R, BI->getSuccessor(0), BI->getParent());
        DEBUG(dbgs() << "IneqGraph: RSigma: " << *RSigma << "\n");
        Value *LSExtSigma = VS->findSExtSigma(L, BI->getSuccessor(0), BI->getParent());
        DEBUG(dbgs() << "IneqGraph: LSExtSigma: " << *LSExtSigma << "\n");
        Value *RSExtSigma = VS->findSExtSigma(R, BI->getSuccessor(0), BI->getParent());
        DEBUG(dbgs() << "IneqGraph: RSExtSigma: " << *RSExtSigma << "\n");
        switch (Cmp->getPredicate()) {
          case ICmpInst::ICMP_SLT:
            DEBUG(dbgs() << "IneqGraph: SLT:\n");
            if (!isa<ConstantInt>(R) && LSigma) {
              if (RSigma)
                addMayEdge(LSigma, RSigma, -1);
              if (RSExtSigma)
                addMayEdge(LSigma, RSExtSigma, -1);
            }
            if (!isa<ConstantInt>(R) && LSExtSigma && LSExtSigma != LSigma) {
              if (RSigma)
                addMayEdge(LSExtSigma, RSigma, -1);
              if (RSExtSigma)
                addMayEdge(LSExtSigma, RSExtSigma, -1);
            }
            break;
          case ICmpInst::ICMP_SLE:
            DEBUG(dbgs() << "IneqGraph: SLE:\n");
            if (!isa<ConstantInt>(R) && LSigma && RSigma)
              addMayEdge(LSigma, RSigma, 0);
            if (!isa<ConstantInt>(R) && (LSExtSigma != LSigma || RSExtSigma != RSigma))
              addMayEdge(LSExtSigma, RSExtSigma, 0);
            break;
          default:
            break;
        }
        break;
      }
    case Instruction::PHI:
      {
        PHINode *Phi = cast<PHINode>(I);
        for (unsigned Idx = 0; Idx < Phi->getNumIncomingValues(); ++Idx) {
          addMustEdge(Phi, Phi->getIncomingValue(Idx), 0);
        }
        break;
      }
    case Instruction::Call:
      {
        CallInst *CI = cast<CallInst>(I);
        if (Function *F = CI->getCalledFunction()) {
          unsigned Idx = 0;
          for (Function::arg_iterator AI = F->arg_begin(), AE = F->arg_end();
               AI != AE; ++AI, ++Idx) {
            addMustEdge(&(*AI), CI->getArgOperand(Idx), 0);
          }
        }
        break;
      }
  }
}
/*
 * method computeStats
 *
 * computes the statistics that require the processing to be complete.
 */
void llvm::RangeAnalysis::computeStats(){

	for(DepGraph::iterator It = depGraph->begin(), Iend = depGraph->end(); It != Iend; It++){

		GraphNode* Node = *It;

		bool isIntegerVariable = false;
		unsigned int currentBitWidth;

		//We only count precision statistics of VarNodes and MemNodes
		if (isa<OpNode>(Node)) {
			numOps++;
			continue;
		}

		if (isa<MemNode>(Node)) {
			numMems++;
		} else if (VarNode* VN = dyn_cast<VarNode>(Node)){
			Value* V = VN->getValue();

			if (isa<ConstantInt>(V)){
				numConstants++;
			} else {

				//Only Variables are considered for bitwidth reduction
				isIntegerVariable = V->getType()->isIntegerTy();
				numVars++;
				if(isIntegerVariable){
					currentBitWidth = V->getType()->getPrimitiveSizeInBits();
					usedBits += currentBitWidth;
				}
			}

		} else assert(false && "Unknown Node Type");

		assert(out_state.count(Node) && "Node not found in the list of computed ranges.");

		Range CR = out_state[Node];

		// If range is unknown, we have total needed bits
		if (CR.isUnknown()) {
			++numUnknown;
			if (isIntegerVariable) needBits += currentBitWidth;
			continue;
		}

		// If range is empty, we have 0 needed bits
		if (CR.isEmpty()) {
			++numEmpty;
			continue;
		}

		if (CR.getLower().eq(Min)) {
			if (CR.getUpper().eq(Max)) {
				++numMaxRange;
			}
			else {
				++numMinInfC;
			}
		}
		else if (CR.getUpper().eq(Max)) {
			++numCPlusInf;
		}
		else {
			++numCC;
		}

		//Compute needed bits >> only for variables
		if (isIntegerVariable) {
			unsigned ub, lb;

			if (CR.getLower().isNegative()) {
				APInt abs = CR.getLower().abs();
				lb = abs.getActiveBits() + 1;
			} else {
				lb = CR.getLower().getActiveBits() + 1;
			}

			if (CR.getUpper().isNegative()) {
				APInt abs = CR.getUpper().abs();
				ub = abs.getActiveBits() + 1;
			} else {
				ub = CR.getUpper().getActiveBits() + 1;
			}

			unsigned nBits = lb > ub ? lb : ub;

			// If both bounds are positive, decrement needed bits by 1
			if (!CR.getLower().isNegative() && !CR.getUpper().isNegative()) {
				--nBits;
			}

			if (nBits < currentBitWidth) {
				needBits += nBits;
			} else {
				needBits += currentBitWidth;
			}
		}


	}

	double totalB = usedBits;
	double needB = needBits;
	double reduction = (double) (totalB - needB) * 100 / totalB;
	percentReduction = (unsigned int) reduction;

}