43using namespace SVFUtil;
49 : tcg(t->getThreadCallGraph()), tct(t),
51 numOfTotalQueries(0), numOfMHPQueries(0),
52 interleavingTime(0), interleavingQueriesTime(0)
89 if (
join.getContext() !=
cts.getContext())
96 flow.intersectWithComplement(
114template<
class ICFGGraph,
class CGGraph>
128template<
class ICFGGraph,
class CGGraph>
131 for (
const std::pair<const NodeID, TCTNode*>&
tpair : *
tct)
174 else if (SVFUtil::dyn_cast<FunExitICFGNode>(
curInst))
200template<
class ICFGGraph,
class CGGraph>
212 ThreadStmtToThreadInterleav::const_iterator it =
215 "MHP query summary requires a converged context state");
216 summary.interleavingByTid[tid] |= it->second;
228 for (
auto nodeIt = CGTraits::nodes_begin(
cg),
238 InstToThreadSummaryMap::const_iterator
entryIt =
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),
315template<
class ICFGGraph,
class CGGraph>
323 std::vector<const CallGraphEdge*>
outEdges;
340template<
class ICFGGraph,
class CGGraph>
350 std::vector<const CallGraphEdge*>
outEdges;
373template<
class ICFGGraph,
class CGGraph>
394 std::vector<const SVFBasicBlock*>
exitbbs;
419 std::vector<const SVFBasicBlock*>
exitbbs;
437template<
class ICFGGraph,
class CGGraph>
445 std::vector<const CallGraphEdge*>
outEdges;
478 cbn->getRetICFGNode());
499 assert(
false &&
"cts.getStmt() is not a CallICFGNode!");
506template<
class ICFGGraph,
class CGGraph>
510 std::vector<const CallGraphEdge*>
inEdges;
514 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(
edgeConst))
516 std::vector<const CallICFGNode*> directCalls;
523 std::vector<const ICFGNode*>
succ;
527 if(dst->getFun() ==
callSite->getFun())
547 std::vector<const CallICFGNode*> indirectCalls;
554 std::vector<const ICFGNode*>
succ;
558 if(dst->getFun() ==
callSite->getFun())
584template<
class ICFGGraph,
class CGGraph>
591 std::vector<const ICFGNode*>
succ;
595 if(dst->getFun() ==
cts.getStmt()->getFun())
609template<
class ICFGGraph,
class CGGraph>
625 std::vector<const ICFGNode*>
succ;
630 if(dst->getFun() ==
forkInst->getFun())
653template<
class ICFGGraph,
class CGGraph>
692 while (!worklist.
empty())
766 while (!worklist.
empty())
774 if (visited.find(
srcNode) == visited.end())
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)
972 std::vector<const ICFGNode*> successors;
1022 else if (SVFUtil::dyn_cast<FunExitICFGNode>(
curInst))
1053template<
class ICFGGraph,
class CGGraph>
1063 std::vector<const CallGraphEdge*>
outEdges;
1085template<
class ICFGGraph,
class CGGraph>
1095 std::vector<const CallGraphEdge*>
outEdges;
1097 bool hasCallGraphEdge =
false;
1102 hasCallGraphEdge =
true;
1106 if (hasCallGraphEdge)
1114 SVFUtil::cast<CallICFGNode>(
joinSite)) &&
1119 std::vector<const SVFBasicBlock *>
exitbbs;
1141 std::vector<const SVFBasicBlock*>
exitbbs;
1156 SVFUtil::cast<CallICFGNode>(
joinSite)))
1168template<
class ICFGGraph,
class CGGraph>
1176 std::vector<const CallGraphEdge*>
outEdges;
1198template<
class ICFGGraph,
class CGGraph>
1206 std::vector<const CallGraphEdge*>
inEdges;
1210 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(
edge))
1212 std::vector<const CallICFGNode*> directCalls;
1220 std::vector<const ICFGNode*> successors;
1245 std::vector<const CallICFGNode*> indirectCalls;
1253 std::vector<const ICFGNode*> successors;
1282template<
class ICFGGraph>
1289 std::vector<const ICFGNode*> successors;
1322 while (!worklist.
empty())
1438template void ForkJoinAnalysis::analyzeForkJoinPair<ICFG*, CallGraph*>(
1446template void MHP::analyze<ICFG*, CallGraph*>(
ICFG*,
CallGraph*);
#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 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.
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens-before thread t2.
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.
const CxtStmtToLoopMap & getSymmetricLoopJoins() const
All SCEV-symmetric in-loop joins and their loop blocks.
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 hasJoinInSymmetricLoop(const CxtStmt &cs) const
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
const LoopBBs & getJoinInSymmetricLoop(const CxtStmt &cs) const
Whether a context-sensitive join satisfies symmetric loop pattern.
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
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.
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_iterator end() const
const ICFGNode * back() const
static double getClk(bool mark=false)
NodeID getId() const
Get ID.
const CxtThread & getCxtThread() const
Get thread creation context, <fork site, call string context>
const NodeBS getAncestorThreads(NodeID tid) const
Get all ancestor threads.
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
bool isJoinSiteInRecursion(const CallICFGNode *join) const
Whether a join site is in recursion.
bool isCallSite(const ICFGNode *inst)
Whether it is a callsite.
NodeBS getParentThreads(NodeID tid) const
Get parent threads.
PointerAnalysis * getPTA() const
Get PTA.
Set< const CallGraphNode * > PTACGNodeSet
ThreadCreateEdgeSet::const_iterator getChildrenBegin(const TCTNode *node) const
Get children and parent nodes.
bool hasTCTNode(const CxtThread &ct) const
Find/Get TCT node.
const NodeBS getSiblingThread(NodeID tid) const
Get sibling threads.
bool isCandidateFun(const CallGraph::FunctionSet &callees) const
Whether it is a candidate function for indirect call.
bool isExtCall(const ICFGNode *inst)
Whether it is calling an external function.
ThreadCreateEdgeSet::const_iterator getChildrenEnd(const TCTNode *node) const
const FunObjVar * getStartRoutineOfCxtThread(const CxtThread &ct) const
get the start routine function of a thread
const CallStrCxtSet & getCxtOfCxtThread(const CxtThread &ct) const
get the contexts of a thread at its spawning sites (fork sites)
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.
bool isExtCall(const FunObjVar *fun)
std::ostream & outs()
Overwrite llvm::outs()
void dumpSet(NodeBS To, OutStream &O=SVFUtil::outs())
Dump sparse bitvector set.
llvm::IRBuilder IRBuilder
std::vector< u32_t > CallStrCxt