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