/* * 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; }