39using namespace SVFUtil;
48template <
class BaseMRG>
65 if (
const ThreadCallGraph* tcg = SVFUtil::dyn_cast<ThreadCallGraph>(this->getCallGraph()))
66 if (tcg->hasThreadForkEdge(cs))
68 ref = this->getRefSideEffectOfFunction(
callee);
85 ThreadCallGraph* tcg = SVFUtil::dyn_cast<ThreadCallGraph>(this->getCallGraph());
98 worklist.push(
this->getCallGraph()->getCallGraphNode(
111 return std::make_unique<ThreadMRG<DistinctMRG>>(pta, ptrOnlyMSSA);
113 return std::make_unique<ThreadMRG<IntraDisjointMRG>>(pta, ptrOnlyMSSA);
115 return std::make_unique<ThreadMRG<InterDisjointMRG>>(pta, ptrOnlyMSSA);
117 assert(
false &&
"unrecognised memory partition strategy");
144 assert(
svfg !=
nullptr &&
"base SVFG must be built before replacing its overlay");
146 "thread-aware overlay requires main ILA results");
188 SVFUtil::cast<RetIndSVFGEdge>(
edge)->addPointsTo(cpts);
207 SVFUtil::dyn_cast<ThreadCallGraph>(
svfg->getMSSA()->getPTA()->getCallGraph());
229 SVFUtil::cast<ActualOUTSVFGNode>(
247 const bool isLoad = SVFUtil::isa<LoadSVFGNode>(
svfgNode);
248 if (!isLoad && !SVFUtil::isa<StoreSVFGNode>(
svfgNode))
275 "thread-aware overlay edge escaped its construction scope");
294 assert(SVFUtil::isa<IndirectSVFGEdge>(
edge) &&
"should be an indirect value-flow edge!");
295 return (SVFUtil::cast<IndirectSVFGEdge>(
edge)->addPointsTo(
pts.toNodeBS()) ?
edge :
nullptr);
318 return found->second;
328 if (
edge->isIndirectVFGEdge() && !
edge->isThreadMHPIndirectVFGEdge() &&
330 worklist.insert(
edge->getSrcNode());
333 while (!worklist.empty())
335 const SVFGNode* node = *worklist.begin();
336 worklist.erase(worklist.begin());
337 visited.insert(node);
338 if (SVFUtil::isa<StoreSVFGNode>(node))
345 if (
edge->isIndirectVFGEdge() &&
346 !
edge->isThreadMHPIndirectVFGEdge() &&
348 visited.find(
edge->getSrcNode()) == visited.end())
349 worklist.insert(
edge->getSrcNode());
365 return found->second;
375 if (
edge->isIndirectVFGEdge() && !
edge->isThreadMHPIndirectVFGEdge() &&
377 worklist.insert(
edge->getDstNode());
380 while (!worklist.empty())
382 const SVFGNode* node = *worklist.begin();
383 worklist.erase(worklist.begin());
384 visited.insert(node);
385 if (SVFUtil::isa<StoreSVFGNode, LoadSVFGNode>(node))
392 if (
edge->isIndirectVFGEdge() &&
393 !
edge->isThreadMHPIndirectVFGEdge() &&
395 visited.find(
edge->getDstNode()) == visited.end())
396 worklist.insert(
edge->getDstNode());
411 return found->second;
433 assert(SVFUtil::isa<StoreSVFGNode>(node) &&
434 "tail test only for store nodes");
438 return found->second;
441 for (
NodeID id : successors)
444 if (SVFUtil::isa<LoadSVFGNode>(
successor))
447 SVFUtil::dyn_cast<StmtSVFGNode>(
successor);
482 if (!SVFUtil::isa<StoreSVFGNode>(
successor))
495 SVFUtil::dyn_cast<StmtSVFGNode>(
svfg->getSVFGNode(
id));
610 const StmtSVFGNode* src = SVFUtil::dyn_cast<StmtSVFGNode>(
613 const StmtSVFGNode* dst = SVFUtil::dyn_cast<StmtSVFGNode>(
616 assert(src !=
nullptr && dst !=
nullptr &&
617 "thread-aware candidates must reference statement nodes");
618 assert(SVFUtil::isa<StoreSVFGNode>(src) &&
619 "thread-aware candidate source must be a store");
621 "thread-aware candidate escaped its selected scope");
623 if (SVFUtil::isa<LoadSVFGNode>(dst))
625 else if (SVFUtil::isa<StoreSVFGNode>(dst))
669 SVFUtil::cast<StmtSVFGNode>(
svfg->getSVFGNode(
loadId));
680 SVFUtil::cast<StmtSVFGNode>(
svfg->getSVFGNode(
otherId));
const FunObjVar * getFunction() const
Get function of this call node.
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
IDToNodeMapTy::const_iterator const_iterator
iterator OutEdgeBegin()
iterators
bool isProtectedByCommonLock(const ICFGNode *i1, const ICFGNode *i2)
bool isInSameSpan(const ICFGNode *I1, const ICFGNode *I2)
virtual bool mayHappenInParallel(const ICFGNode *i1, const ICFGNode *i2)
Interface to query whether two instructions may happen-in-parallel.
bool recordThreadVFQueries
false = skip [THREAD-VF] recording
void connectMHPEdges(PointerAnalysis *pta)
Connect inter-thread (interference) value-flow edges for MHP pairs.
Map< const StmtSVFGNode *, SVFGNodeIDSet > predecessorCache
SVFGEdgeSet threadAwareEdges
std::unique_ptr< MRGenerator > createMRGenerator(BVDataPTAImpl *pta, bool ptrOnlyMSSA) override
void handleStoreStore(const StmtSVFGNode *firstStore, const StmtSVFGNode *secondStore, PointerAnalysis *pta)
void clearThreadAwareOverlay()
Remove all currently attached thread-aware interference edges.
SVFGEdge * addTDEdge(NodeID srcId, NodeID dstId, const PointsTo &pts)
Add a thread-MHP indirect value-flow edge srcId -> dstId carrying pts.
void connectThreadJoinEdges()
void collectLoadStoreSVFGNodes()
const ThreadVFCandidateList * overlayCandidates
Map< const StmtSVFGNode *, bool > spanTailCache
Map< const StmtSVFGNode *, SVFGNodeIDSet > successorCache
void replaceThreadAwareOverlay(MHP *mhp, LockAnalysis *lockAnalysis, const ThreadVFBuildConfig &config)
bool isInOverlayScope(const SVFGNode *node) const
void addJoinRetEdge(const FormalOUTSVFGNode *formalOut, const ActualOUTSVFGNode *actualOut, CallSiteID callSiteId)
void recordThreadVFSource(const StmtSVFGNode *source, const StmtSVFGNode *destination, bool commonLock)
LockAnalysis * lockAnalysis
bool isHeadOfSpan(const StmtSVFGNode *node)
bool labelInterferenceEdges
false = VFG_pre (sliced-only): omit edge points-to labels
ThreadVFQueryMap threadVFQueryMap
[THREAD-VF] per-edge query map (see getThreadVFQueryMap).
const SlicedSVFGView * overlayScope
Active overlay configuration; defaults suit VFG_pre.
bool isTailOfSpan(const StmtSVFGNode *node)
SVFGNodeIDSet getSuccessorNodes(const StmtSVFGNode *node)
void handleStoreLoad(const StmtSVFGNode *store, const StmtSVFGNode *load, PointerAnalysis *pta)
void buildSVFG() override
Rewrite the SVFG build hook: build the stock SVFG, then add MHP edges.
Map< const StmtSVFGNode *, bool > spanHeadCache
SVFGNodeIDSet getPredecessorNodes(const StmtSVFGNode *node)
Lock-span head/tail tests (non-interference lock-pair pruning).
bool hasCHI(const PAGEdge *inst) const
static const OptionMap< u32_t > MemPar
virtual const PointsTo & getPts(NodeID ptr)=0
Get points-to targets of a pointer. It needs to be implemented in child class.
std::unique_ptr< SVFG > svfg
NodeID getId() const
Get ID.
bool isKeptNode(const SVFGNode *n) const
Whether the node is retained (see the class comment for the rule).
bool intersects(const SparseBitVector< ElementSize > *RHS) const
NodeID getSrcNodeID() const
NodeID getDstNodeID() const
OrderedSet< const CallICFGNode *, CallSiteIdCmp > InstSet
void getJoinSites(const CallGraphNode *routine, InstSet &csSet)
virtual const ICFGNode * getICFGNode() const
Return corresponding ICFG node.
llvm::IRBuilder IRBuilder