62 for (
const auto& joinAndLoop :
fja->getSymmetricLoopJoins())
67 loopBlocks.insert(bb);
82 if (srcBB ==
nullptr || dstBB ==
nullptr || srcBB == dstBB)
84 BBToSymJoinsMap::const_iterator it =
bbToSymJoins.find(srcBB);
87 for (
const CxtStmt& join : it->second)
92 if (loopBlocks.find(dstBB) != loopBlocks.end())
114template<
class ICFGGraph,
class CGGraph>
128template<
class ICFGGraph,
class CGGraph>
131 for (
const std::pair<const NodeID, TCTNode*>& tpair : *
tct)
133 const CxtThread& ct = tpair.second->getCxtThread();
134 NodeID rootTid = tpair.first;
135 const FunObjVar* routine =
tct->getStartRoutineOfCxtThread(ct);
148 DBOUT(
DMTA,
outs() <<
"-----\nMHP analysis root thread: " << rootTid <<
" ");
155 if (!
tct->isCandidateFun(curInst->
getFun()))
170 else if (
tct->isCallSite(curInst) && !
tct->isExtCall(curInst))
200template<
class ICFGGraph,
class CGGraph>
212 ThreadStmtToThreadInterleav::const_iterator it =
215 "MHP query summary requires a converged context state");
228 for (
auto nodeIt = CGTraits::nodes_begin(cg),
229 nodeEnd = CGTraits::nodes_end(cg); nodeIt != nodeEnd; ++nodeIt)
231 const CallGraphNode* callGraphNode = CGTraits::getRawNode(*nodeIt);
238 InstToThreadSummaryMap::const_iterator entryIt =
243 std::vector<const ICFGNode*> funICFGNodes;
245 for (
const ICFGNode* node : funICFGNodes)
247 if (node == entryNode)
251 "non-candidate internal node unexpectedly had a raw MHP state");
267 "non-candidate query-summary owner has no entry summary");
274template<
class ICFGGraph,
class CGGraph>
281 for (
auto nodeIt = CGTraits::nodes_begin(cg),
282 nodeEnd = CGTraits::nodes_end(cg); nodeIt != nodeEnd; ++nodeIt)
284 const CallGraphNode* callGraphNode = CGTraits::getRawNode(*nodeIt);
295 std::vector<const ICFGNode*> funICFGNodes;
301 for (
const ICFGNode* curNode : funICFGNodes)
303 if (curNode == entryNode)
315template<
class ICFGGraph,
class CGGraph>
323 std::vector<const CallGraphEdge*> outEdges;
340template<
class ICFGGraph,
class CGGraph>
350 std::vector<const CallGraphEdge*> outEdges;
359 pushCxt(newCxt, cbn, svfroutine);
362 if (!
tct->hasTCTNode(ct))
373template<
class ICFGGraph,
class CGGraph>
384 if (!joinedTids.
empty())
386 if (
fja->hasJoinLoop(call))
394 std::vector<const SVFBasicBlock*> exitbbs;
396 while (!exitbbs.empty())
410 DBOUT(
DMTA,
outs() <<
"\n\t match join site " << call->
toString() <<
" for thread " << rootTid <<
"\n");
417 if (
fja->hasJoinLoop(call))
419 std::vector<const SVFBasicBlock*> exitbbs;
421 while (!exitbbs.empty())
437template<
class ICFGGraph,
class CGGraph>
445 std::vector<const CallGraphEdge*> outEdges;
457 pushCxt(newCxt, cbn, svfcallee);
460 if (svfEntryInst ==
nullptr)
471 if (exitInst ==
nullptr)
491 if (!
tct->isCandidateFun(callees))
499 assert(
false &&
"cts.getStmt() is not a CallICFGNode!");
506template<
class ICFGGraph,
class CGGraph>
510 std::vector<const CallGraphEdge*> inEdges;
516 std::vector<const CallICFGNode*> directCalls;
523 std::vector<const ICFGNode*> succ;
527 if(dst->getFun() == callSite->getFun())
535 CallStrCxt callSiteCxt = cxtThreadStmt.getContext();
547 std::vector<const CallICFGNode*> indirectCalls;
554 std::vector<const ICFGNode*> succ;
558 if(dst->getFun() == callSite->getFun())
566 CallStrCxt callSiteCxt = cxtThreadStmt.getContext();
584template<
class ICFGGraph,
class CGGraph>
588 const bool mayExitSymJoinLoop =
591 std::vector<const ICFGNode*> succ;
598 if (mayExitSymJoinLoop)
609template<
class ICFGGraph,
class CGGraph>
612 NodeBS ancestorAndSelfTids =
tct->getAncestorThreads(curTid);
613 DBOUT(
DMTA,
outs() <<
"##Ancestor thread of " << curTid <<
" is : ");
616 ancestorAndSelfTids.
set(curTid);
618 for (
const unsigned tid : ancestorAndSelfTids)
620 const CxtThread& ct =
tct->getTCTNode(tid)->getCxtThread();
625 std::vector<const ICFGNode*> succ;
630 if(dst->getFun() == forkInst->getFun())
632 for (
const auto& forkSiteCxt :
tct->getCxtOfCxtThread(ct))
634 CxtThreadStmt cts(forkSiteCxt.first, forkSiteCxt.second, dst);
653template<
class ICFGGraph,
class CGGraph>
656 NodeBS ancestorAndSelfTids =
tct->getAncestorThreads(curTid);
657 ancestorAndSelfTids.
set(curTid);
658 for (
const unsigned tid : ancestorAndSelfTids)
660 NodeBS siblingTds =
tct->getSiblingThread(tid);
661 for (
const unsigned stid : siblingTds)
666 const CxtThread& ct =
tct->getTCTNode(stid)->getCxtThread();
667 const FunObjVar* routine =
tct->getStartRoutineOfCxtThread(ct);
675 DBOUT(
DMTA,
outs() <<
"##Sibling thread of " << curTid <<
" is : ");
686 if (parentTid == curTid)
689 const TCTNode* curNode =
tct->getTCTNode(curTid);
691 worklist.
push(curNode);
692 while (!worklist.
empty())
697 NodeID srcID = edge->getSrcID();
698 if (
fja->isFullJoin(srcID, node->
getId()))
700 if (srcID == parentTid)
703 worklist.
push(edge->getSrcNode());
722 assert(call &&
isTDJoin(call) &&
"not a join site!");
732 return fja->getDirAndIndJoinedTid(cs);
741 return fja->hasJoinInSymmetricLoop(cs);
748 return fja->getJoinInSymmetricLoop(cs);
756 return fja->isHBPair(tid1, tid2);
764 worklist.
push(cgnode);
765 visited.insert(cgnode);
766 while (!worklist.
empty())
774 if (visited.find(srcNode) == visited.end())
776 visited.insert(srcNode);
777 worklist.
push(srcNode);
799 if (summary1 ==
nullptr || summary2 ==
nullptr)
816 for (
NodeID tid2 : firstFlowIt->second)
818 if (tid1 == tid2 || !summary2->
tids.
test(tid2))
822 if (secondFlowIt->second.test(tid1))
870 if (summary1 ==
nullptr || summary2 ==
nullptr)
891 outs() <<
"( t" << pair.first.getTid()
892 << pair.first.getStmt()->toString() <<
" ) ==> [";
893 for (
unsigned i : pair.second)
895 outs() <<
" " << i <<
" ";
961template<
class ICFGGraph,
class CGGraph>
964 for (
const std::pair<const NodeID, TCTNode*>& tpair : *
tct)
966 const CxtThread& ct = tpair.second->getCxtThread();
967 const NodeID rootTid = tpair.first;
972 std::vector<const ICFGNode*> successors;
974 icfg, forkInst, successors);
975 for (
const ICFGNode* successor : successors)
977 if (successor->getFun() == forkInst->getFun())
979 for (
const auto& forkSiteCxt :
tct->getCxtOfCxtThread(ct))
981 CxtStmt newCts(forkSiteCxt.second, successor);
991 DBOUT(
DMTA,
outs() <<
"-----\nForkJoinAnalysis root thread: " << tpair.first <<
" ");
1002 else if (
tct->isCallSite(curInst) && !
tct->isExtCall(curInst))
1010 cg, callSite, callees);
1011 if (!
tct->isCandidateFun(callees))
1034 for (
NodeID parentTid :
tct->getParentThreads(rootTid))
1036 const CxtThread& parentCxtThread =
tct->getTCTNode(parentTid)->getCxtThread();
1037 const FunObjVar* parentRoutine =
tct->getStartRoutineOfCxtThread(parentCxtThread);
1039 icfg, parentRoutine))
1053template<
class ICFGGraph,
class CGGraph>
1063 std::vector<const CallGraphEdge*> outEdges;
1074 if (!
tct->hasTCTNode(ct))
1085template<
class ICFGGraph,
class CGGraph>
1095 std::vector<const CallGraphEdge*> outEdges;
1097 bool hasCallGraphEdge =
false;
1102 hasCallGraphEdge =
true;
1106 if (hasCallGraphEdge)
1108 const ICFGNode* forkSite =
tct->getTCTNode(rootTid)->getCxtThread().getThread();
1119 std::vector<const SVFBasicBlock *> exitbbs;
1121 while (!exitbbs.empty())
1126 CxtStmt newCts(curCxt, svfEntryInst);
1141 std::vector<const SVFBasicBlock*> exitbbs;
1143 while (!exitbbs.empty())
1148 CxtStmt newCts(curCxt, svfEntryInst);
1160 DBOUT(
DMTA,
outs() <<
"\n\t match join site " << call->
toString() <<
"for thread " << rootTid <<
"\n");
1168template<
class ICFGGraph,
class CGGraph>
1176 std::vector<const CallGraphEdge*> outEdges;
1187 pushCxt(newCxt, cbn, svfcallee);
1190 if (svfEntryInst ==
nullptr)
1192 CxtStmt newCts(newCxt, svfEntryInst);
1198template<
class ICFGGraph,
class CGGraph>
1206 std::vector<const CallGraphEdge*> inEdges;
1212 std::vector<const CallICFGNode*> directCalls;
1220 std::vector<const ICFGNode*> successors;
1222 icfg, callSite, successors);
1223 for (
const ICFGNode* successor : successors)
1225 if (successor->getFun() == callSite->getFun())
1233 CallStrCxt callSiteCxt = cxtStmt.getContext();
1237 CxtStmt newCts(callSiteCxt, successor);
1245 std::vector<const CallICFGNode*> indirectCalls;
1253 std::vector<const ICFGNode*> successors;
1255 icfg, callSite, successors);
1256 for (
const ICFGNode* successor : successors)
1258 if (successor->getFun() == callSite->getFun())
1266 CallStrCxt callSiteCxt = cxtStmt.getContext();
1270 CxtStmt newCts(callSiteCxt, successor);
1282template<
class ICFGGraph>
1289 std::vector<const ICFGNode*> successors;
1291 for (
const ICFGNode* successor : successors)
1293 if (successor->getFun() == curInst->
getFun())
1295 CxtStmt newCts(curCxt, successor);
1314 NodeBS allJoinTids = directJoinTids;
1317 for (
unsigned id : directJoinTids)
1322 while (!worklist.
empty())
1326 for (TCT::ThreadCreateEdgeSet::const_iterator it =
tct->getChildrenBegin(node), eit =
tct->getChildrenEnd(node); it != eit; ++it)
1328 NodeID childTid = (*it)->getDstID();
1331 allJoinTids.
set(childTid);
1332 worklist.
push(childTid);
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
const FunObjVar * getFunction() const
Get function of this call node.
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
Set< const FunObjVar * > FunctionSet
const std::string toString() const override
const RetICFGNode * getRetICFGNode() const
Return callsite.
void dump() const
Dump CxtStmt.
const CallStrCxt & getContext() const
Return current context.
const ICFGNode * getStmt() const
Return current statement.
NodeID getTid() const
Return current context.
void dump() const
Dump CxtThreadStmt.
const CallStrCxt & getContext() const
Return context of the thread.
const ICFGNode * getThread() const
Return forksite.
bool push(const Data &data)
void addToFullJoin(NodeID tid1, NodeID tid2)
full join and partial join
const SVFVar * getForkedThread(const CallICFGNode *call)
Get forked thread.
void handleIntra(ICFGGraph icfg, const CxtStmt &cts)
Handle intra.
bool isAliasedForkJoin(const CallICFGNode *forkSite, const CallICFGNode *joinSite)
Whether it is a matched fork join pair.
ValDomain getMarkedFlag(const CxtStmt &cs)
Mark thread flags for cxtStmt.
void addToHPPair(NodeID tid1, NodeID tid2)
SVFLoopAndDomInfo::LoopBBs LoopBBs
bool hasJoinLoop(const CallICFGNode *inst)
void addSymmetricLoopJoin(const CxtStmt &cs, LoopBBs &lp)
Add inloop join.
NodeBS getDirAndIndJoinedTid(const CxtStmt &cs)
Get directly and indirectly joined threadIDs based on a context-sensitive join site.
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
void analyzeForkJoinPair(ICFGGraph icfg, CGGraph cg)
CxtStmt popFromCTSWorkList()
bool hasCxtStmtsFromInst(const ICFGNode *inst) const
void addToHBPair(NodeID tid1, NodeID tid2)
ThreadCallGraph * getTCG() const
ThreadCallGraph.
void addToPartial(NodeID tid1, NodeID tid2)
void collectSCEVInfo()
functions
void clearFlagMap()
Clear flags.
void addDirectlyJoinTID(const CxtStmt &cs, NodeID tid)
maps a context-sensitive join site to a thread id
const SVFVar * getJoinedThread(const CallICFGNode *call)
Get joined thread.
LoopBBs & getJoinLoop(const CallICFGNode *inst)
Get loop for join site.
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
void handleRet(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts)
Handle return.
void handleFork(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts, NodeID rootTid)
Handle fork.
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt call)
If lhs is a suffix of rhs, including equal.
bool isFullJoin(NodeID tid1, NodeID tid2)
Whether t1 fully joins t2.
CxtStmtToTIDMap dirAndIndJoinMap
maps a context-sensitive join site to directly and indirectly joined thread ids
bool sameLoopTripCount(const ICFGNode *forkSite, const ICFGNode *joinSite)
Same loop trip count.
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
void markCxtStmtFlag(const CxtStmt &tgr, ValDomain flag)
Initialize TDAlive and TDDead flags.
CxtStmtWorkList cxtStmtList
context-sensitive statement worklist
ThreadAPI::ForkJoinAliasCache forkJoinAliasCache
NodeBS & getDirectlyJoinedTid(const CxtStmt &cs)
Get directly joined threadIDs based on a context-sensitive join site.
bool isSameSCEV(const ICFGNode *forkSite, const ICFGNode *joinSite)
Return true if the fork and join have the same SCEV.
void handleJoin(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts, NodeID rootTid)
Handle join.
void handleCall(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts)
Handle call.
const CxtStmtSet & getCxtStmtsFromInst(const ICFGNode *inst) const
Get CxtStmtSet for an instruction.
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
void getExitBlocksOfLoop(const SVFBasicBlock *bb, BBList &exitbbs) const
bool hasBasicBlock() const
const GEdgeSetTy & getInEdges() const
GEdgeSetTy::const_iterator const_iterator
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
virtual const std::string toString() const
CxtThreadStmtWorkList cxtStmtList
CxtThreadStmt worklist.
bool isRecurFullJoin(NodeID parentTid, NodeID curTid)
Thread curTid can be fully joined by parentTid recursively.
bool isMultiForkedThread(NodeID curTid)
A thread is a multiForked thread if it is in a loop or recursion.
void handleRet(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
Handle return.
void rmInterleavingThread(const CxtThreadStmt &tgr, const NodeBS &tids, const ICFGNode *joinsite)
virtual bool mayHappenInParallelCache(const ICFGNode *i1, const ICFGNode *i2)
void analyze(ICFGGraph icfg, CGGraph cg)
BBToSymJoinsMap bbToSymJoins
Map a statement to its thread interleavings.
FuncPairToBool nonCandidateFuncMHPRelMap
NodeBS edgeFlow(const CxtThreadStmt &cts, const ICFGNode *dst)
void printInterleaving()
Print interleaving results.
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
u32_t numOfTotalQueries
Total number of queries.
Set< CxtThreadStmt > CxtThreadStmtSet
void analyzeInterleaving(ICFGGraph icfg, CGGraph cg)
Analyze thread interleaving.
MHP(TCT *t, StateRepresentation representation=StateRepresentation::MaterializedContexts)
std::pair< const FunObjVar *, const FunObjVar * > FuncPair
SVFLoopAndDomInfo::LoopBBs LoopBBs
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt call)
If lhs is a suffix of rhs, including equal.
void updateSiblingThreads(ICFGGraph icfg, CGGraph cg, NodeID tid)
void handleFork(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
Handle fork.
void updateAncestorThreads(ICFGGraph icfg, CGGraph cg, NodeID tid)
Update Ancestor and sibling threads.
void handleCall(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
Handle call.
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
ThreadCallGraph * tcg
TCG.
void addInterleavingThread(const CxtThreadStmt &tgr, NodeID tid)
Add/Remove interleaving thread for statement inst.
const NodeBS & getInterleavingThreads(const CxtThreadStmt &cts)
Get interleaving thread for statement inst.
InstToThreadStmtSetMap instToTSMap
Map an instruction to its ThreadStmtSet.
virtual ~MHP()
Destructor.
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens before t2 based on ForkJoin Analysis.
ThreadCallGraph * getThreadCallGraph() const
Get ThreadCallGraph.
ThreadStmtToThreadInterleav threadStmtToThreadInterLeav
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
void addInterleavingBits(const CxtThreadStmt &tgr, const NodeBS &bits)
virtual bool executedByTheSameThread(const ICFGNode *i1, const ICFGNode *i2)
InstToThreadSummaryMap instToThreadSummary
Exact per-node/per-tid query compression.
virtual bool mayHappenInParallel(const ICFGNode *i1, const ICFGNode *i2)
Interface to query whether two instructions may happen-in-parallel.
void buildSymJoinKillTables()
const CxtThreadStmtSet & getThreadStmtSet(const ICFGNode *inst) const
Get/has ThreadStmt.
const LoopBBs & getJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
void handleJoin(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
Handle join.
ForkJoinAnalysis * fja
ForJoin Analysis.
const NodeThreadSummary * getThreadSummary(const ICFGNode *inst) const
bool hasJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
void buildQuerySummaries(ICFGGraph icfg, CGGraph cg)
bool hasThreadStmtSet(const ICFGNode *inst) const
SymJoinToLoopMap symJoinLoop
symmetric in-loop join -> its loop's blocks
StateRepresentation stateRepresentation
double interleavingQueriesTime
u32_t numOfMHPQueries
Number of queries are answered as may-happen-in-parallel.
void updateNonCandidateFunInterleaving(ICFGGraph icfg, CGGraph cg)
bool isMustJoin(const NodeID curTid, const ICFGNode *joinsite)
Whether a join site must join a thread t.
Map< const ICFGNode *, const ICFGNode * > querySummaryOwner
Non-candidate node -> entry summary.
bool isConnectedfromMain(const FunObjVar *fun)
Whether the function is connected from main function in thread call graph.
void handleIntra(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
Handle intra.
CxtThreadStmt popFromCTSWorkList()
void handleNonCandidateFun(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
Handle non-candidate function.
NodeBS getDirAndIndJoinedTid(const CallStrCxt &cxt, const ICFGNode *call)
Return thread id(s) which are directly or indirectly joined at this join site.
virtual bool mayHappenInParallelInst(const ICFGNode *i1, const ICFGNode *i2)
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
static const Option< bool > PrintInterLev
const ICFGNode * front() const
const ICFGNode * back() const
static double getClk(bool mark=false)
NodeID getId() const
Get ID.
bool test(unsigned Idx) const
bool intersectWithComplement(const SparseBitVector &RHS)
Set< const CallGraphNode * > PTACGNodeSet
bool isAliasedForkJoin(PointerAnalysis *pta, const SVFVar *forkArg, const SVFVar *joinArg) const
ThreadAPI * getThreadAPI() const
Thread API.
bool isProgEntryFunction(const FunObjVar *)
Program entry function e.g. main.
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
LLVM_NODISCARD bool isa(const Y &Val)
bool isExtCall(const FunObjVar *fun)
std::ostream & outs()
Overwrite llvm::outs().
void dumpSet(NodeBS To, OutStream &O=SVFUtil::outs())
Dump sparse bitvector set.
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
std::vector< u32_t > CallStrCxt
Map< NodeID, NodeBS > interleavingByTid