Ejemplo n.º 1
0
void ConstraintGraph::Change::undo(ConstraintGraph &cg) {
  /// Temporarily change the active scope to null, so we don't record
  /// any changes made while performing the undo operation.
  llvm::SaveAndRestore<ConstraintGraphScope *> prevActiveScope(cg.ActiveScope,
                                                               nullptr);

  switch (Kind) {
  case ChangeKind::AddedTypeVariable:
    cg.removeNode(TypeVar);
    break;

  case ChangeKind::AddedConstraint:
    cg.removeConstraint(TheConstraint);
    break;

  case ChangeKind::RemovedConstraint:
    cg.addConstraint(TheConstraint);
    break;

  case ChangeKind::ExtendedEquivalenceClass: {
    auto &node = cg[EquivClass.TypeVar];
    node.EquivalenceClass.erase(
      node.EquivalenceClass.begin() + EquivClass.PrevSize,
      node.EquivalenceClass.end());
    break;
   }

  case ChangeKind::BoundTypeVariable:
    cg.unbindTypeVariable(Binding.TypeVar, Binding.FixedType);
    break;
  }
}
Ejemplo n.º 2
0
/// Depth-first search for connected components
static void connectedComponentsDFS(ConstraintGraph &cg,
                                   ConstraintGraphNode &node,
                                   unsigned component,
                                   SmallVectorImpl<unsigned> &components) {
  // Local function that recurses on the given set of type variables.
  auto visitAdjacencies = [&](ArrayRef<TypeVariableType *> typeVars) {
    for (auto adj : typeVars) {
      auto nodeAndIndex = cg.lookupNode(adj);
      // If we've already seen this node in this component, we're done.
      unsigned &curComponent = components[nodeAndIndex.second];
      if (curComponent == component)
        continue;

      // Mark this node as part of this connected component, then recurse.
      assert(curComponent == components.size() && "Already in a component?");
      curComponent = component;
      connectedComponentsDFS(cg, nodeAndIndex.first, component, components);
    }
  };

  // Recurse to mark adjacent nodes as part of this connected component.
  visitAdjacencies(node.getAdjacencies());

  // Figure out the representative for this type variable.
  auto &cs = cg.getConstraintSystem();
  auto typeVarRep = cs.getRepresentative(node.getTypeVariable());
  if (typeVarRep == node.getTypeVariable()) {
    // This type variable is the representative of its set; visit all of the
    // other type variables in the same equivalence class.
    visitAdjacencies(node.getEquivalenceClass().slice(1));
  } else {
    // Otherwise, visit the representative of the set.
    visitAdjacencies(typeVarRep);
  }
}
tf::Pose relativePose (const ConstraintGraph& g, const unsigned n1,
                       const unsigned n2)
{
  const Graph& graph = g.graph();
  ShortestPath path = shortestPath(g, n1, n2);
  tf::Pose p;
  p.setIdentity();
  BOOST_FOREACH (const unsigned e, path.second)
    p *= util::toPose(graph[g.idEdge(e)].constraint.constraint.pose);
  return p;
}
Ejemplo n.º 4
0
void ConstraintGraph::Change::undo(ConstraintGraph &cg) {
  /// Temporarily change the active scope to null, so we don't record
  /// any changes made while performing the undo operation.
  llvm::SaveAndRestore<ConstraintGraphScope *> prevActiveScope(cg.ActiveScope,
                                                               nullptr);

  switch (Kind) {
  case ChangeKind::AddedTypeVariable:
    cg.removeNode(TypeVar);
    break;

  case ChangeKind::AddedConstraint:
    cg.removeConstraint(TheConstraint);
    break;

  case ChangeKind::RemovedConstraint:
    cg.addConstraint(TheConstraint);
    break;

  case ChangeKind::ExtendedEquivalenceClass: {
    auto &node = cg[EquivClass.TypeVar];
    node.EquivalenceClass.erase(
      node.EquivalenceClass.begin() + EquivClass.PrevSize,
      node.EquivalenceClass.end());
    break;
   }

  case ChangeKind::BoundTypeVariable:
    cg.unbindTypeVariable(Binding.TypeVar, Binding.FixedType);
    break;

  case ChangeKind::AddedMemberType: {
    auto &node = cg[MemberType.TypeVar];

    // Erase the member type entry from the 
    auto known = node.MemberTypeIndex.find(MemberType.Name);
    assert(known != node.MemberTypeIndex.end() && "Constraint graph corrupted");
    unsigned index = known->second;
    node.MemberTypeIndex.erase(known);

    // If this was not the last member type, swap it with the last
    // member type.
    if (index != node.MemberTypes.size()-1) {
      node.MemberTypes[index] = node.MemberTypes.back();
      node.MemberTypeIndex[node.MemberTypes[index].first] = index;
    }
     
    // Pop off the last member type.
    node.MemberTypes.pop_back();
    break;
  }
  }
}
ShortestPath shortestPath (const ConstraintGraph& g,
                           const unsigned src, const unsigned dest)
{
  typedef Graph::out_edge_iterator EdgeIter;
  const Graph& graph = g.graph();

  // Call Dijkstra's algorithm
  const GraphVertex v = g.idVertex(src);
  const GraphVertex w = g.idVertex(dest);
  const DijkstraResult res = dijkstra(graph, v);

  // Check path exists
  if (dest!=src && util::keyValue(res.second, w)==w)
    throw NoPathException(src, dest);

  // Extract node path
  list<unsigned> path;
  for (GraphVertex x=w; x!=util::keyValue(res.second, x);
       x=util::keyValue(res.second, x))
    path.push_front(graph[x].id);
  path.push_front(src);
  ShortestPath ret;
  copy(path.begin(), path.end(), back_inserter(ret.first));

  // Extract edge path
  // \todo Doesn't pick best edge when there are parallel edges
  for (unsigned i=0; i<ret.first.size()-1; i++)
  {
    const unsigned from = ret.first[i];
    const unsigned to = ret.first[i+1];
    pair<GraphEdge, bool> e = edge(g.idVertex(from), g.idVertex(to), graph);
    ROS_ASSERT(e.second);
    ret.second.push_back(graph[e.first].id);
  }
  
  return ret;
}
Ejemplo n.º 6
0
/// Require that the given condition evaluate true.
///
/// If the condition is not true, complain about the problem and abort.
///
/// \param condition The actual Boolean condition.
///
/// \param complaint A string that describes the problem.
///
/// \param cg The constraint graph that failed verification.
///
/// \param node If non-null, the graph node that failed verification.
///
/// \param extraContext If provided, a function that will be called to
/// provide extra, contextual information about the failure.
static void _require(bool condition, const Twine &complaint,
                     ConstraintGraph &cg,
                     ConstraintGraphNode *node,
                     const std::function<void()> &extraContext = nullptr) {
  if (condition)
    return;

  // Complain
  llvm::dbgs() << "Constraint graph verification failed: " << complaint << '\n';
  if (extraContext)
    extraContext();

  // Print the graph.
  // FIXME: Highlight the offending node/constraint/adjacency/etc.
  cg.print(llvm::dbgs());

  abort();
}
bool BlockFlow::identifyOutSet()
{
  bool MadeChange = false;
  std::vector<GlobalCheck*> outChecks;
  if (!isEntry && !killAll) {
    identifyInSet();
  #if DEBUG_GLOBAL
    errs() << "Generating Out-Set: " << blk->getName() << "\n";
  #endif
    // Identify checks from inSet that should be killed
    for (std::vector<GlobalCheck*>::iterator i = inSet.checks.begin(), e = inSet.checks.end();
            i != e; i++) {
      // For each global check, see if it survives past block, or if we can tell how variable changes 
      GlobalCheck *chk = *i;
      std::set<Value*>::iterator it = storeSet.find(chk->var);
      if (it == storeSet.end()) {
        outChecks.push_back(chk);
      } else {
        ConstraintGraph::CompareEnum change = cg->identifyMemoryChange(chk->var); 
        if (chk->isUpper) {
          // Upper-bound check
          switch (change) {
            case ConstraintGraph::EQUALS:
            case ConstraintGraph::LESS_THAN:
              outChecks.push_back(chk);
              break;
            default:
              break;
          }
        } else {
          // Lower-bound check
          switch (change) {
            case ConstraintGraph::EQUALS:
            case ConstraintGraph::GREATER_THAN:
              outChecks.push_back(chk);
              break;
            default:
              break;
          }
        }
      }
    }
  }
#if DEBUG_GLOBAL
  else {
    errs() << "Generating Out-Set: " << blk->getName() << "\n";
  }
#endif
  // Just identify checks that are live at the end of set
  for (std::vector<GlobalCheck*>::iterator i = globalChecks.begin(), e = globalChecks.end(); 
              i != e; i++) {
    GlobalCheck *chk = *i;
    bool add = true;
    for (unsigned int o = 0; o < outChecks.size(); o++) {
      GlobalCheck *oCheck = outChecks.at(o);
      ConstantInt *const1 = dyn_cast<ConstantInt>(chk->var);
      ConstantInt *const2 = dyn_cast<ConstantInt>(oCheck->var);
      if (chk->isUpper && oCheck->isUpper) {
        // Both upper bounds checks
        if (const1 != NULL && const2 != NULL) {
          // If both constants, replace with the more strict version
          if (const1->getSExtValue() > const2->getSExtValue()) {
            outChecks.at(o) = chk;
          }
          add = false;
          break;
        } else if (const1 == NULL && const2 == NULL) {
          if (chk->var == oCheck->var) {
            ConstantInt *bound1 = dyn_cast<ConstantInt>(chk->bound);
            ConstantInt *bound2 = dyn_cast<ConstantInt>(oCheck->bound);
            if (bound1 != NULL && bound2 != NULL) {
              if (bound1->getZExtValue() < bound2->getZExtValue()) {
                outChecks.at(o) = chk; 
              }
              add = false;
              break;
            } else if (bound1 == NULL && bound2 == NULL) {
              if (bound1 == bound2) {
                add = false;
                break;
              }
            }
          }
        }
      } else if (!chk->isUpper && !oCheck->isUpper) {
        // Both lower bounds checks
        if (const1 != NULL && const2 != NULL) {
          // If both constants, replace with the more strict version
          if (const1->getSExtValue() < const2->getSExtValue()) {
            outChecks.at(o) =  chk;
          }
          add = false;
          break;
        } else if (const1 == NULL && const2 == NULL) {
          if (chk->var == oCheck->var) {
            add = false;
            break;
          }
        }
      }
    }
    if (add) {
      outChecks.push_back(chk);
    }
  }  
  
  if (isEntry && outChecks.empty()) {
    outSet.allChecks = false;
    return true;
  }

  if (outChecks.empty()) {
    if (inSet.allChecks) {
      bool oldState = outSet.allChecks;
      outSet.checks.clear();
      outSet.allChecks = true;
      return oldState != true;
    } else {
      outSet.allChecks = false;
      if (outSet.checks.empty()) {
        return false;
      } else {
        outSet.checks.clear();
        return true;
      }
    }
  }

  for (std::vector<GlobalCheck*>::iterator i = outChecks.begin(), e = outChecks.end(); i != e; i++) {
  #if DEBUG_GLOBAL
    errs() << "Adding Check to Out Set:\n";
    (*i)->print();
  #endif
    MadeChange |= outSet.addAvailableCheck(*i);
  }
  return MadeChange;
}
Ejemplo n.º 8
0
/*!
 * Start here
 */
void AndersenStat::performStat() {

    assert(isa<Andersen>(pta) && "not an andersen pta pass!! what else??");
    endClk();

    PAG* pag = pta->getPAG();
    ConstraintGraph* consCG = pta->getConstraintGraph();

    // collect constraint graph cycles
    collectCycleInfo(consCG);

    // stat null ptr number
    statNullPtr();

    u32_t numOfCopys = 0;
    u32_t numOfGeps = 0;
    // collect copy and gep edges
    for(ConstraintEdge::ConstraintEdgeSetTy::iterator it = consCG->getDirectCGEdges().begin(),
            eit = consCG->getDirectCGEdges().end(); it!=eit; ++it) {
        if(isa<CopyCGEdge>(*it))
            numOfCopys++;
        else if(isa<GepCGEdge>(*it))
            numOfGeps++;
        else
            assert(false && "what else!!");
    }

    u32_t cgNodeNumber = 0;
    for (ConstraintGraph::ConstraintNodeIDToNodeMapTy::iterator nodeIt = consCG->begin(), nodeEit = consCG->end();
            nodeIt != nodeEit; nodeIt++) {
        cgNodeNumber++;
    }

    u32_t totalPointers = 0;
    u32_t totalTopLevPointers = 0;
    u32_t totalPtsSize = 0;
    u32_t totalTopLevPtsSize = 0;
    for (PAG::iterator iter = pta->getPAG()->begin(), eiter = pta->getPAG()->end();
            iter != eiter; ++iter) {
        NodeID node = iter->first;
        PointsTo& pts = pta->getPts(node);
        u32_t size = pts.count();
        totalPointers++;
        totalPtsSize+=size;

        if(pta->getPAG()->isValidTopLevelPtr(pta->getPAG()->getPAGNode(node))) {
            totalTopLevPointers++;
            totalTopLevPtsSize+=size;
        }

        if(size > _MaxPtsSize )
            _MaxPtsSize = size;
    }


    PTAStat::performStat();

    timeStatMap[TotalAnalysisTime] = (endTime - startTime)/TIMEINTERVAL;
    timeStatMap[SCCDetectionTime] = Andersen::timeOfSCCDetection;
    timeStatMap[SCCMergeTime] =  Andersen::timeOfSCCMerges;
    timeStatMap[CollapseTime] =  Andersen::timeOfCollapse;

    timeStatMap[ProcessLoadStoreTime] =  Andersen::timeOfProcessLoadStore;
    timeStatMap[ProcessCopyGepTime] =  Andersen::timeOfProcessCopyGep;
    timeStatMap[UpdateCallGraphTime] =  Andersen::timeOfUpdateCallGraph;

    PTNumStatMap[TotalNumOfPointers] = pag->getValueNodeNum() + pag->getFieldValNodeNum();
    PTNumStatMap[TotalNumOfObjects] = pag->getObjectNodeNum() + pag->getFieldObjNodeNum();
    PTNumStatMap[TotalNumOfEdges] = consCG->getLoadCGEdges().size() + consCG->getStoreCGEdges().size()
                                    + numOfCopys + numOfGeps;

    PTNumStatMap[NumOfAddrs] =  consCG->getAddrCGEdges().size();
    PTNumStatMap[NumOfCopys] = numOfCopys;
    PTNumStatMap[NumOfGeps] =  numOfGeps;
    PTNumStatMap[NumOfLoads] = consCG->getLoadCGEdges().size();
    PTNumStatMap[NumOfStores] = consCG->getStoreCGEdges().size();

    PTNumStatMap[NumOfProcessedAddrs] = Andersen::numOfProcessedAddr;
    PTNumStatMap[NumOfProcessedCopys] = Andersen::numOfProcessedCopy;
    PTNumStatMap[NumOfProcessedGeps] = Andersen::numOfProcessedGep;
    PTNumStatMap[NumOfProcessedLoads] = Andersen::numOfProcessedLoad;
    PTNumStatMap[NumOfProcessedStores] = Andersen::numOfProcessedStore;

    PTNumStatMap[NumOfPointers] = pag->getValueNodeNum();
    PTNumStatMap[NumOfMemObjects] = pag->getObjectNodeNum();
    PTNumStatMap[NumOfGepFieldPointers] = pag->getFieldValNodeNum();
    PTNumStatMap[NumOfGepFieldObjects] = pag->getFieldObjNodeNum();

    PTNumStatMap[NumberOfCGNode] = cgNodeNumber;

    timeStatMap[AveragePointsToSetSize] = (double)totalPtsSize/totalPointers;;
    timeStatMap[AverageTopLevPointsToSetSize] = (double)totalTopLevPtsSize/totalTopLevPointers;;

    PTNumStatMap[MaxPointsToSetSize] = _MaxPtsSize;

    PTNumStatMap[NumOfIterations] = pta->numOfIteration;

    PTNumStatMap[NumOfIndirectCallSites] = consCG->getIndirectCallsites().size();
    PTNumStatMap[NumOfIndirectEdgeSolved] = pta->getNumOfResolvedIndCallEdge();

    PTNumStatMap[NumOfSCCDetection] = Andersen::numOfSCCDetection;
    PTNumStatMap[NumOfCycles] = _NumOfCycles;
    PTNumStatMap[NumOfPWCCycles] = _NumOfPWCCycles;
    PTNumStatMap[NumOfNodesInCycles] = _NumOfNodesInCycles;
    PTNumStatMap[MaxNumOfNodesInSCC] = _MaxNumOfNodesInSCC;
    PTNumStatMap[NumOfNullPointer] = _NumOfNullPtr;
    PTNumStatMap["PointsToConstPtr"] = _NumOfConstantPtr;
    PTNumStatMap["PointsToBlkPtr"] = _NumOfBlackholePtr;

    printStat();

}