Static Value-Flow Analysis
Loading...
Searching...
No Matches
SVF::MHP Class Reference

#include <MHP.h>

Classes

struct  NodeThreadSummary

Public Types

enum class  StateRepresentation { MaterializedContexts , QuerySummaries }
typedef Set< const FunObjVar * > FunSet
typedef FIFOWorkList< CxtThreadStmt > CxtThreadStmtWorkList
typedef Set< CxtThreadStmt > CxtThreadStmtSet
typedef Map< CxtThreadStmt, NodeBS > ThreadStmtToThreadInterleav
typedef Map< const ICFGNode *, CxtThreadStmtSet > InstToThreadStmtSetMap
typedef Map< const ICFGNode *, NodeThreadSummary > InstToThreadSummaryMap
typedef SVFLoopAndDomInfo::LoopBBs LoopBBs
typedef Set< CxtStmt > LockSpan
typedef std::pair< const FunObjVar *, const FunObjVar * > FuncPair
typedef Map< FuncPair, bool > FuncPairToBool

Public Member Functions

virtual ~MHP ()
 Destructor.
template<class ICFGGraph, class CGGraph>
void analyze (ICFGGraph icfg, CGGraph cg)
template<class ICFGGraph, class CGGraph>
void analyzeInterleaving (ICFGGraph icfg, CGGraph cg)
 Analyze thread interleaving.
ThreadCallGraph * getThreadCallGraph () const
 Get ThreadCallGraph.
TCT * getTCT () const
 Get Thread Creation Tree.
bool isConnectedfromMain (const FunObjVar *fun)
 Whether the function is connected from main function in thread call graph.
virtual bool mayHappenInParallel (const ICFGNode *i1, const ICFGNode *i2)
 Interface to query whether two instructions may happen-in-parallel.
virtual bool mayHappenInParallelCache (const ICFGNode *i1, const ICFGNode *i2)
virtual bool mayHappenInParallelInst (const ICFGNode *i1, const ICFGNode *i2)
virtual bool executedByTheSameThread (const ICFGNode *i1, const ICFGNode *i2)
const NodeThreadSummary * getThreadSummary (const ICFGNode *inst) const
const NodeBS & getInterleavingThreads (const CxtThreadStmt &cts)
 Get interleaving thread for statement inst.
bool hasInterleavingThreads (const CxtThreadStmt &cts) const
const CxtThreadStmtSet & getThreadStmtSet (const ICFGNode *inst) const
 Get/has ThreadStmt.
bool hasThreadStmtSet (const ICFGNode *inst) const
void printInterleaving ()
 Print interleaving results.

Static Public Member Functions

template<class ICFGGraph, class CGGraph>
static std::unique_ptr< MHP > create (TCT *t, ICFGGraph icfg, CGGraph cg, StateRepresentation representation=StateRepresentation::MaterializedContexts)
 Construct MHP and initialize its graph-dependent ForkJoinAnalysis.

Public Attributes

u32_t numOfTotalQueries
 Total number of queries.
u32_t numOfMHPQueries
 Number of queries are answered as may-happen-in-parallel.
double interleavingTime
double interleavingQueriesTime

Protected Types

typedef Map< const SVFBasicBlock *, std::vector< CxtStmt > > BBToSymJoinsMap
typedef Map< CxtStmt, Set< const SVFBasicBlock * > > SymJoinToLoopMap

Protected Member Functions

 MHP (TCT *t, StateRepresentation representation=StateRepresentation::MaterializedContexts)
template<class ICFGGraph, class CGGraph>
void updateNonCandidateFunInterleaving (ICFGGraph icfg, CGGraph cg)
template<class ICFGGraph, class CGGraph>
void buildQuerySummaries (ICFGGraph icfg, CGGraph cg)
template<class ICFGGraph, class CGGraph>
void handleNonCandidateFun (ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
 Handle non-candidate function.
template<class ICFGGraph, class CGGraph>
void handleFork (ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
 Handle fork.
template<class ICFGGraph, class CGGraph>
void handleJoin (ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
 Handle join.
template<class ICFGGraph, class CGGraph>
void handleCall (ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
 Handle call.
template<class ICFGGraph, class CGGraph>
void handleRet (ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
 Handle return.
template<class ICFGGraph, class CGGraph>
void handleIntra (ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
 Handle intra.
void buildSymJoinKillTables ()
NodeBS edgeFlow (const CxtThreadStmt &cts, const ICFGNode *dst)
void addInterleavingThread (const CxtThreadStmt &tgr, NodeID tid)
 Add/Remove interleaving thread for statement inst.
void addInterleavingThread (const CxtThreadStmt &tgr, const CxtThreadStmt &src)
void addInterleavingBits (const CxtThreadStmt &tgr, const NodeBS &bits)
void rmInterleavingThread (const CxtThreadStmt &tgr, const NodeBS &tids, const ICFGNode *joinsite)
template<class ICFGGraph, class CGGraph>
void updateAncestorThreads (ICFGGraph icfg, CGGraph cg, NodeID tid)
 Update Ancestor and sibling threads.
template<class ICFGGraph, class CGGraph>
void updateSiblingThreads (ICFGGraph icfg, CGGraph cg, NodeID tid)
bool isRecurFullJoin (NodeID parentTid, NodeID curTid)
 Thread curTid can be fully joined by parentTid recursively.
bool isMustJoin (const NodeID curTid, const ICFGNode *joinsite)
 Whether a join site must join a thread t.
bool isMultiForkedThread (NodeID curTid)
 A thread is a multiForked thread if it is in a loop or recursion.
void pushCxt (CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
 Context helper functions.
bool matchAndPopCxt (CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
 Match context.
bool isContextSuffix (const CallStrCxt &lhs, const CallStrCxt call)
 If lhs is a suffix of rhs, including equal.
bool pushToCTSWorkList (const CxtThreadStmt &cs)
 WorkList helper functions.
CxtThreadStmt popFromCTSWorkList ()
bool isTDFork (const ICFGNode *call)
 Whether it is a fork site.
bool isTDJoin (const ICFGNode *call)
 Whether it is a join site.
NodeBS getDirAndIndJoinedTid (const CallStrCxt &cxt, const ICFGNode *call)
 Return thread id(s) which are directly or indirectly joined at this join site.
bool hasJoinInSymmetricLoop (const CallStrCxt &cxt, const ICFGNode *call) const
 Whether a context-sensitive join satisfies symmetric loop pattern.
const LoopBBs & getJoinInSymmetricLoop (const CallStrCxt &cxt, const ICFGNode *call) const
 Whether a context-sensitive join satisfies symmetric loop pattern.
bool isHBPair (NodeID tid1, NodeID tid2)
 Whether thread t1 happens before t2 based on ForkJoin Analysis.

Protected Attributes

ThreadCallGraph * tcg
 TCG.
TCT * tct
 TCT.
ForkJoinAnalysis * fja
 ForJoin Analysis.
CxtThreadStmtWorkList cxtStmtList
 CxtThreadStmt worklist.
ThreadStmtToThreadInterleav threadStmtToThreadInterLeav
BBToSymJoinsMap bbToSymJoins
 Map a statement to its thread interleavings.
SymJoinToLoopMap symJoinLoop
 symmetric in-loop join -> its loop's blocks
InstToThreadStmtSetMap instToTSMap
 Map an instruction to its ThreadStmtSet.
InstToThreadSummaryMap instToThreadSummary
 Exact per-node/per-tid query compression.
Map< const ICFGNode *, const ICFGNode * > querySummaryOwner
 Non-candidate node -> entry summary.
StateRepresentation stateRepresentation
FuncPairToBool nonCandidateFuncMHPRelMap

Detailed Description

This class serves as a base may-happen in parallel analysis for multithreaded program Given a statement under an abstract thread, it tells which abstract threads may be alive at the same time (May-happen-in-parallel).

Definition at line 51 of file MHP.h.

Member Typedef Documentation

◆ BBToSymJoinsMap

typedef Map<const SVFBasicBlock*, std::vector<CxtStmt> > SVF::MHP::BBToSymJoinsMap
protected

Symmetric-join loop-exit kills, applied to EDGE flows (node states stay pure unions, so paths bypassing the join keep their interleavings).

Definition at line 195 of file MHP.h.

◆ CxtThreadStmtSet

Definition at line 57 of file MHP.h.

◆ CxtThreadStmtWorkList

Definition at line 56 of file MHP.h.

◆ FuncPair

typedef std::pair<const FunObjVar*,const FunObjVar*> SVF::MHP::FuncPair

Definition at line 75 of file MHP.h.

◆ FuncPairToBool

Definition at line 76 of file MHP.h.

◆ FunSet

typedef Set<const FunObjVar*> SVF::MHP::FunSet

Definition at line 55 of file MHP.h.

◆ InstToThreadStmtSetMap

Definition at line 59 of file MHP.h.

◆ InstToThreadSummaryMap

Definition at line 70 of file MHP.h.

◆ LockSpan

Definition at line 73 of file MHP.h.

◆ LoopBBs

Definition at line 71 of file MHP.h.

◆ SymJoinToLoopMap

typedef Map<CxtStmt, Set<const SVFBasicBlock*> > SVF::MHP::SymJoinToLoopMap
protected

Definition at line 196 of file MHP.h.

◆ ThreadStmtToThreadInterleav

Definition at line 58 of file MHP.h.

Member Enumeration Documentation

◆ StateRepresentation

enum class SVF::MHP::StateRepresentation
strong
Enumerator
MaterializedContexts 
QuerySummaries 

Definition at line 78 of file MHP.h.

79 {
80 MaterializedContexts,
81 QuerySummaries
82 };

Constructor & Destructor Documentation

◆ ~MHP()

MHP::~MHP ( )
virtual

Destructor.

Destructor

Definition at line 105 of file MHP.cpp.

106{
107 delete fja;
108}
ForkJoinAnalysis * fja
ForJoin Analysis.
Definition MHP.h:323

◆ MHP()

MHP::MHP ( TCT * t,
StateRepresentation representation = StateRepresentation::MaterializedContexts )
explicitprotected

Construction is paired with ForkJoinAnalysis initialization by create().

Parameters
representationKeep per-context copies for clients that enumerate raw states (the pre-analysis detector and slicer). Main-phase clients issue only MHP queries and can use the exact projected query summary instead.

Constructor

Definition at line 48 of file MHP.cpp.

49 : tcg(t->getThreadCallGraph()), tct(t),
50 stateRepresentation(representation),
53{
54 fja = new ForkJoinAnalysis(tct);
55}
TCT * tct
TCT.
Definition MHP.h:322
u32_t numOfTotalQueries
Total number of queries.
Definition MHP.h:335
ThreadCallGraph * tcg
TCG.
Definition MHP.h:321
StateRepresentation stateRepresentation
Definition MHP.h:331
double interleavingQueriesTime
Definition MHP.h:338
u32_t numOfMHPQueries
Number of queries are answered as may-happen-in-parallel.
Definition MHP.h:336
double interleavingTime
Definition MHP.h:337
ThreadCallGraph * getThreadCallGraph() const
Get TCG.
Definition TCT.h:199

Member Function Documentation

◆ addInterleavingBits()

void SVF::MHP::addInterleavingBits ( const CxtThreadStmt & tgr,
const NodeBS & bits )
inlineprotected

Definition at line 220 of file MHP.h.

221 {
222 bool changed = threadStmtToThreadInterLeav[tgr] |= bits;
223 if(changed)
224 {
225 instToTSMap[tgr.getStmt()].insert(tgr);
227 }
228 }
InstToThreadStmtSetMap instToTSMap
Map an instruction to its ThreadStmtSet.
Definition MHP.h:328
ThreadStmtToThreadInterleav threadStmtToThreadInterLeav
Definition MHP.h:325
bool pushToCTSWorkList(const CxtThreadStmt &cs)
WorkList helper functions.
Definition MHP.h:286

◆ addInterleavingThread() [1/2]

void SVF::MHP::addInterleavingThread ( const CxtThreadStmt & tgr,
const CxtThreadStmt & src )
inlineprotected

Definition at line 211 of file MHP.h.

212 {
214 if(changed)
215 {
216 instToTSMap[tgr.getStmt()].insert(tgr);
218 }
219 }

◆ addInterleavingThread() [2/2]

void SVF::MHP::addInterleavingThread ( const CxtThreadStmt & tgr,
NodeID tid )
inlineprotected

Add/Remove interleaving thread for statement inst.

Definition at line 203 of file MHP.h.

204 {
205 if(threadStmtToThreadInterLeav[tgr].test_and_set(tid))
206 {
207 instToTSMap[tgr.getStmt()].insert(tgr);
209 }
210 }

◆ analyze()

template<class ICFGGraph, class CGGraph>
template void MHP::analyze< const SlicedICFGView *, const SlicedThreadCallGraphView * > ( ICFGGraph icfg,
CGGraph cg )

Start analysis here. One implementation for the whole program and a slice: the compute is templated on the two graphs it traverses – the ICFG (ICFG* whole / const SlicedICFGView* sliced) and the CallGraph (CallGraph* whole / const SlicedThreadCallGraphView* sliced) – and calls their GenericGraphTraits specialisations directly (no wrapper layer).

Start analysis here

Definition at line 115 of file MHP.cpp.

116{
117 DBOUT(DGENERAL, outs() << pasMsg("MHP interleaving analysis\n"));
118 DBOUT(DMTA, outs() << pasMsg("MHP interleaving analysis\n"));
119 DOTIMESTAT(double interleavingStart = PTAStat::getClk(true));
120 analyzeInterleaving(icfg, cg);
121 DOTIMESTAT(double interleavingEnd = PTAStat::getClk(true));
122 DOTIMESTAT(interleavingTime += (interleavingEnd - interleavingStart) / TIMEINTERVAL);
123}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:576
#define TIMEINTERVAL
Definition SVFType.h:604
#define DMTA
Definition SVFType.h:597
#define DGENERAL
Definition SVFType.h:582
#define DOTIMESTAT(X)
Definition SVFType.h:578
void analyzeInterleaving(ICFGGraph icfg, CGGraph cg)
Analyze thread interleaving.
Definition MHP.cpp:129
static double getClk(bool mark=false)
Definition SVFStat.cpp:52
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:121
std::ostream & outs()
Overwrite llvm::outs().
Definition SVFUtil.h:58

◆ analyzeInterleaving()

template<class ICFGGraph, class CGGraph>
void MHP::analyzeInterleaving ( ICFGGraph icfg,
CGGraph cg )

Analyze thread interleaving.

Analyze thread interleaving

handle non-candidate function

handle candidate function

update non-candidate functions' interleaving

Definition at line 129 of file MHP.cpp.

130{
131 for (const std::pair<const NodeID, TCTNode*>& tpair : *tct)
132 {
133 const CxtThread& ct = tpair.second->getCxtThread();
134 NodeID rootTid = tpair.first;
135 const FunObjVar* routine = tct->getStartRoutineOfCxtThread(ct);
136 const ICFGNode* svfInst = GenericGraphTraits<ICFGGraph>::getFunEntry(icfg, routine);
137 CxtThreadStmt rootcts(rootTid, ct.getContext(), svfInst);
138
139 addInterleavingThread(rootcts, rootTid);
140 updateAncestorThreads(icfg, cg, rootTid);
141 updateSiblingThreads(icfg, cg, rootTid);
142
143 while (!cxtStmtList.empty())
144 {
145 CxtThreadStmt cts = popFromCTSWorkList();
146 const ICFGNode* curInst = cts.getStmt();
147
148 DBOUT(DMTA, outs() << "-----\nMHP analysis root thread: " << rootTid << " ");
149 DBOUT(DMTA, cts.dump());
150 DBOUT(DMTA, outs() << "current thread interleaving: < ");
152 DBOUT(DMTA, outs() << " >\n-----\n");
153
155 if (!tct->isCandidateFun(curInst->getFun()))
156 {
157 handleNonCandidateFun(icfg, cg, cts);
158 }
160 else
161 {
162 if (isTDFork(curInst))
163 {
164 handleFork(icfg, cg, cts, rootTid);
165 }
166 else if (isTDJoin(curInst))
167 {
168 handleJoin(icfg, cg, cts, rootTid);
169 }
170 else if (tct->isCallSite(curInst) && !tct->isExtCall(curInst))
171 {
172 handleCall(icfg, cg, cts, rootTid);
173 }
174 else if (SVFUtil::dyn_cast<FunExitICFGNode>(curInst))
175 {
176 handleRet(icfg, cg, cts);
177 }
178 else
179 {
180 handleIntra(icfg, cg, cts);
181 }
182 }
183 }
184 }
185
189 buildQuerySummaries(icfg, cg);
190
193}
const ICFGNode * getStmt() const
Return current statement.
Definition CxtStmt.h:61
void dump() const
Dump CxtThreadStmt.
Definition CxtStmt.h:174
const CallStrCxt & getContext() const
Return context of the thread.
Definition CxtStmt.h:204
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:75
CxtThreadStmtWorkList cxtStmtList
CxtThreadStmt worklist.
Definition MHP.h:324
void handleRet(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
Handle return.
Definition MHP.cpp:507
void printInterleaving()
Print interleaving results.
Definition MHP.cpp:887
void updateSiblingThreads(ICFGGraph icfg, CGGraph cg, NodeID tid)
Definition MHP.cpp:654
void handleFork(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
Handle fork.
Definition MHP.cpp:341
void updateAncestorThreads(ICFGGraph icfg, CGGraph cg, NodeID tid)
Update Ancestor and sibling threads.
Definition MHP.cpp:610
void handleCall(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
Handle call.
Definition MHP.cpp:438
void addInterleavingThread(const CxtThreadStmt &tgr, NodeID tid)
Add/Remove interleaving thread for statement inst.
Definition MHP.h:203
const NodeBS & getInterleavingThreads(const CxtThreadStmt &cts)
Get interleaving thread for statement inst.
Definition MHP.h:130
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition MHP.h:297
void handleJoin(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
Handle join.
Definition MHP.cpp:374
void buildQuerySummaries(ICFGGraph icfg, CGGraph cg)
Definition MHP.cpp:201
void updateNonCandidateFunInterleaving(ICFGGraph icfg, CGGraph cg)
Definition MHP.cpp:275
void handleIntra(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
Handle intra.
Definition MHP.cpp:585
CxtThreadStmt popFromCTSWorkList()
Definition MHP.h:290
void handleNonCandidateFun(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
Handle non-candidate function.
Definition MHP.cpp:316
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition MHP.h:303
static const Option< bool > PrintInterLev
Definition Options.h:157
void dumpSet(NodeBS To, OutStream &O=SVFUtil::outs())
Dump sparse bitvector set.
Definition SVFUtil.cpp:169
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition Casting.h:405
u32_t NodeID
Definition GeneralType.h:76

◆ buildQuerySummaries()

template<class ICFGGraph, class CGGraph>
void MHP::buildQuerySummaries ( ICFGGraph icfg,
CGGraph cg )
protected

Build the exact, context-compressed representation used by repeated MHP queries after the context-sensitive fixed point has converged.

Compress the converged context-sensitive states for repeated MHP queries. Contexts are retained in the propagation maps; this is a query-only index and therefore cannot change the fixed point.

Definition at line 201 of file MHP.cpp.

202{
203 instToThreadSummary.clear();
204 querySummaryOwner.clear();
205 for (const auto& instAndStates : instToTSMap)
206 {
207 NodeThreadSummary& summary = instToThreadSummary[instAndStates.first];
208 for (const CxtThreadStmt& state : instAndStates.second)
209 {
210 const NodeID tid = state.getTid();
211 summary.tids.set(tid);
212 ThreadStmtToThreadInterleav::const_iterator it =
213 threadStmtToThreadInterLeav.find(state);
214 assert(it != threadStmtToThreadInterLeav.end() &&
215 "MHP query summary requires a converged context state");
216 summary.interleavingByTid[tid] |= it->second;
217 }
218 }
219
221 return;
222
223 // The materialized representation copies a non-candidate function entry's state
224 // unchanged to each of that function's nodes. Main-phase clients need only
225 // query answers, so project the already-compressed entry summary instead of
226 // creating one CxtThreadStmt and one NodeBS per context at every node.
227 using CGTraits = GenericGraphTraits<CGGraph>;
228 for (auto nodeIt = CGTraits::nodes_begin(cg),
229 nodeEnd = CGTraits::nodes_end(cg); nodeIt != nodeEnd; ++nodeIt)
230 {
231 const CallGraphNode* callGraphNode = CGTraits::getRawNode(*nodeIt);
232 const FunObjVar* fun = callGraphNode->getFunction();
233 if (tct->isCandidateFun(fun) || isExtCall(fun))
234 continue;
235
236 const ICFGNode* entryNode =
237 GenericGraphTraits<ICFGGraph>::getFunEntry(icfg, fun);
238 InstToThreadSummaryMap::const_iterator entryIt =
239 instToThreadSummary.find(entryNode);
240 if (entryIt == instToThreadSummary.end())
241 continue;
242
243 std::vector<const ICFGNode*> funICFGNodes;
244 GenericGraphTraits<ICFGGraph>::getFunICFGNodes(icfg, fun, funICFGNodes);
245 for (const ICFGNode* node : funICFGNodes)
246 {
247 if (node == entryNode)
248 continue;
249 const bool inserted = querySummaryOwner.emplace(node, entryNode).second;
250 assert(inserted && instToThreadSummary.find(node) == instToThreadSummary.end() &&
251 "non-candidate internal node unexpectedly had a raw MHP state");
252 (void)inserted;
253 }
254 }
255}
const FunObjVar * getFunction() const
Get function of this call node.
Definition CallGraph.h:191
NodeID getTid() const
Return current context.
Definition CxtStmt.h:138
InstToThreadSummaryMap instToThreadSummary
Exact per-node/per-tid query compression.
Definition MHP.h:329
Map< const ICFGNode *, const ICFGNode * > querySummaryOwner
Non-candidate node -> entry summary.
Definition MHP.h:330
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:526

◆ buildSymJoinKillTables()

void MHP::buildSymJoinKillTables ( )
protected

Index the SCEV-symmetric in-loop joins by their loop blocks.

Definition at line 60 of file MHP.cpp.

61{
62 for (const auto& joinAndLoop : fja->getSymmetricLoopJoins())
63 {
64 Set<const SVFBasicBlock*>& loopBlocks = symJoinLoop[joinAndLoop.first];
65 for (const SVFBasicBlock* bb : joinAndLoop.second)
66 {
67 loopBlocks.insert(bb);
68 bbToSymJoins[bb].push_back(joinAndLoop.first);
69 }
70 }
71}
BBToSymJoinsMap bbToSymJoins
Map a statement to its thread interleavings.
Definition MHP.h:326
SymJoinToLoopMap symJoinLoop
symmetric in-loop join -> its loop's blocks
Definition MHP.h:327
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition GeneralType.h:51

◆ create()

template<class ICFGGraph, class CGGraph>
std::unique_ptr< MHP > SVF::MHP::create ( TCT * t,
ICFGGraph icfg,
CGGraph cg,
StateRepresentation representation = StateRepresentation::MaterializedContexts )
static

Construct MHP and initialize its graph-dependent ForkJoinAnalysis.

Definition at line 646 of file MHP.h.

648{
649 std::unique_ptr<MHP> mhp(new MHP(t, representation));
650 mhp->fja->analyzeForkJoinPair(icfg, cg);
651 mhp->buildSymJoinKillTables();
652 return mhp;
653}
MHP(TCT *t, StateRepresentation representation=StateRepresentation::MaterializedContexts)
Definition MHP.cpp:48

◆ edgeFlow()

NodeBS MHP::edgeFlow ( const CxtThreadStmt & cts,
const ICFGNode * dst )
protected

Flow along edge cts.stmt -> dst: an edge leaving a symmetric join loop drops the joined tids (edge kill; the destination's state is never subtracted from).

Definition at line 77 of file MHP.cpp.

78{
80 const SVFBasicBlock* srcBB = cts.getStmt()->getBB();
81 const SVFBasicBlock* dstBB = dst->getBB();
82 if (srcBB == nullptr || dstBB == nullptr || srcBB == dstBB)
83 return flow;
84 BBToSymJoinsMap::const_iterator it = bbToSymJoins.find(srcBB);
85 if (it == bbToSymJoins.end())
86 return flow;
87 for (const CxtStmt& join : it->second)
88 {
89 if (join.getContext() != cts.getContext())
90 continue;
91 const Set<const SVFBasicBlock*>& loopBlocks = symJoinLoop[join];
92 if (loopBlocks.find(dstBB) != loopBlocks.end())
93 continue; // edge stays inside the loop
94 if (!isMustJoin(cts.getTid(), join.getStmt()))
95 continue;
98 }
99 return flow;
100}
const CallStrCxt & getContext() const
Return current context.
Definition CxtStmt.h:56
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
Definition ICFGNode.h:81
bool isMustJoin(const NodeID curTid, const ICFGNode *joinsite)
Whether a join site must join a thread t.
Definition MHP.cpp:719
NodeBS getDirAndIndJoinedTid(const CallStrCxt &cxt, const ICFGNode *call)
Return thread id(s) which are directly or indirectly joined at this join site.
Definition MHP.cpp:729
bool intersectWithComplement(const SparseBitVector &RHS)
SparseBitVector NodeBS
Definition GeneralType.h:82

◆ executedByTheSameThread()

bool MHP::executedByTheSameThread ( const ICFGNode * i1,
const ICFGNode * i2 )
virtual

Definition at line 866 of file MHP.cpp.

867{
868 const NodeThreadSummary* summary1 = getThreadSummary(i1);
869 const NodeThreadSummary* summary2 = getThreadSummary(i2);
870 if (summary1 == nullptr || summary2 == nullptr)
871 return true;
872
873 for (NodeID tid1 : summary1->tids)
874 {
875 for (NodeID tid2 : summary2->tids)
876 {
877 if (tid1 != tid2 || isMultiForkedThread(tid1))
878 return false;
879 }
880 }
881 return true;
882}
bool isMultiForkedThread(NodeID curTid)
A thread is a multiForked thread if it is in a loop or recursion.
Definition MHP.h:257
const NodeThreadSummary * getThreadSummary(const ICFGNode *inst) const
Definition MHP.cpp:257

◆ getDirAndIndJoinedTid()

NodeBS MHP::getDirAndIndJoinedTid ( const CallStrCxt & cxt,
const ICFGNode * call )
protected

Return thread id(s) which are directly or indirectly joined at this join site.

Return thread id(s) which are directly or indirectly joined at this join site

Definition at line 729 of file MHP.cpp.

730{
731 CxtStmt cs(cxt, call);
732 return fja->getDirAndIndJoinedTid(cs);
733}

◆ getInterleavingThreads()

const NodeBS & SVF::MHP::getInterleavingThreads ( const CxtThreadStmt & cts)
inline

Get interleaving thread for statement inst.

Definition at line 130 of file MHP.h.

131 {
132 return threadStmtToThreadInterLeav[cts];
133 }

◆ getJoinInSymmetricLoop()

const MHP::LoopBBs & MHP::getJoinInSymmetricLoop ( const CallStrCxt & cxt,
const ICFGNode * call ) const
protected

Whether a context-sensitive join satisfies symmetric loop pattern.

Definition at line 745 of file MHP.cpp.

746{
747 CxtStmt cs(cxt, call);
748 return fja->getJoinInSymmetricLoop(cs);
749}

◆ getTCT()

TCT * SVF::MHP::getTCT ( ) const
inline

Get Thread Creation Tree.

Definition at line 110 of file MHP.h.

111 {
112 return tct;
113 }

◆ getThreadCallGraph()

ThreadCallGraph * SVF::MHP::getThreadCallGraph ( ) const
inline

Get ThreadCallGraph.

Definition at line 104 of file MHP.h.

105 {
106 return tcg;
107 }

◆ getThreadStmtSet()

const CxtThreadStmtSet & SVF::MHP::getThreadStmtSet ( const ICFGNode * inst) const
inline

Get/has ThreadStmt.

Definition at line 142 of file MHP.h.

143 {
144 InstToThreadStmtSetMap::const_iterator it = instToTSMap.find(inst);
145 assert(it!=instToTSMap.end() && "no thread access the instruction?");
146 return it->second;
147 }

◆ getThreadSummary()

const MHP::NodeThreadSummary * MHP::getThreadSummary ( const ICFGNode * inst) const

Representation-independent per-thread summary used by MHP clients. Available after analyze() in both materialized and summary-only modes.

Definition at line 257 of file MHP.cpp.

258{
259 InstToThreadSummaryMap::const_iterator it = instToThreadSummary.find(inst);
260 if (it != instToThreadSummary.end())
261 return &it->second;
262 const auto ownerIt = querySummaryOwner.find(inst);
263 if (ownerIt == querySummaryOwner.end())
264 return nullptr;
265 it = instToThreadSummary.find(ownerIt->second);
266 assert(it != instToThreadSummary.end() &&
267 "non-candidate query-summary owner has no entry summary");
268 return &it->second;
269}

◆ handleCall()

template<class ICFGGraph, class CGGraph>
void MHP::handleCall ( ICFGGraph icfg,
CGGraph cg,
const CxtThreadStmt & cts,
NodeID rootTid )
protected

Handle call.

Handle call instruction in the current thread scope (excluding any fork site)

Propagate to the return site of the call instruction, only if the callee is a non-candidate function, while for candidate function, return site should be handled after the callee is handled.

Definition at line 438 of file MHP.cpp.

439{
440
441 const ICFGNode* call = cts.getStmt();
442 const CallStrCxt& curCxt = cts.getContext();
443 const CallICFGNode* cbn = cast<CallICFGNode>(call);
444 CallGraphNode* callerNode = tcg->getCallGraphNode(cbn->getFun());
445 std::vector<const CallGraphEdge*> outEdges;
446 GenericGraphTraits<CGGraph>::getOutEdges(cg, callerNode, outEdges);
447 for (const CallGraphEdge* edge : outEdges)
448 {
449 if (edge->getEdgeKind() != CallGraphEdge::CallRetEdge ||
450 !GenericGraphTraits<CGGraph>::containsCallSite(cg, edge, cbn))
451 continue;
452 const FunObjVar* svfcallee = edge->getDstNode()->getFunction();
453 if (isExtCall(svfcallee))
454 continue;
455
456 CallStrCxt newCxt = curCxt;
457 pushCxt(newCxt, cbn, svfcallee);
458 const ICFGNode* svfEntryInst =
459 GenericGraphTraits<ICFGGraph>::getFunEntry(icfg, svfcallee);
460 if (svfEntryInst == nullptr)
461 continue;
462 CxtThreadStmt newCts(cts.getTid(), newCxt, svfEntryInst);
463 addInterleavingThread(newCts, cts);
464
465 // Return-flow rendezvous: if the callee's exit already has state
466 // under newCxt, forward it now (handleRet cannot see late callsites).
467 if (tct->isCandidateFun(svfcallee) && svfcallee->hasBasicBlock())
468 {
469 const ICFGNode* exitInst =
470 GenericGraphTraits<ICFGGraph>::getFunExit(icfg, svfcallee);
471 if (exitInst == nullptr)
472 continue;
473 CxtThreadStmt exitCts(cts.getTid(), newCxt, exitInst);
474 if (threadStmtToThreadInterLeav.find(exitCts) !=
476 {
477 CxtThreadStmt retCts(cts.getTid(), curCxt,
478 cbn->getRetICFGNode());
479 addInterleavingThread(retCts, exitCts);
480 }
481 }
482 }
483
487 if (const CallICFGNode *callSite = SVFUtil::cast<CallICFGNode>(call))
488 {
490 GenericGraphTraits<CGGraph>::getCallees(cg, callSite, callees);
491 if (!tct->isCandidateFun(callees))
492 {
493 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), callSite->getRetICFGNode());
494 addInterleavingThread(newCts, cts);
495 }
496 }
497 else
498 {
499 assert(false && "cts.getStmt() is not a CallICFGNode!");
500 }
501}
Set< const FunObjVar * > FunctionSet
Definition CallGraph.h:247
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:440
bool hasBasicBlock() const
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
Definition MHP.h:265
std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
Definition Casting.h:360
std::vector< u32_t > CallStrCxt
Definition GeneralType.h:96

◆ handleFork()

template<class ICFGGraph, class CGGraph>
void MHP::handleFork ( ICFGGraph icfg,
CGGraph cg,
const CxtThreadStmt & cts,
NodeID rootTid )
protected

Handle fork.

Handle fork

Definition at line 341 of file MHP.cpp.

342{
343
344 const ICFGNode* call = cts.getStmt();
345 const CallStrCxt& curCxt = cts.getContext();
346
347 assert(isTDFork(call));
348 const CallICFGNode* cbn = cast<CallICFGNode>(call);
349 CallGraphNode* callerNode = tcg->getCallGraphNode(cbn->getFun());
350 std::vector<const CallGraphEdge*> outEdges;
351 GenericGraphTraits<CGGraph>::getOutEdges(cg, callerNode, outEdges);
352 for (const CallGraphEdge* edge : outEdges)
353 {
354 if (edge->getEdgeKind() != CallGraphEdge::TDForkEdge ||
355 !GenericGraphTraits<CGGraph>::containsCallSite(cg, edge, cbn))
356 continue;
357 const FunObjVar* svfroutine = edge->getDstNode()->getFunction();
358 CallStrCxt newCxt = curCxt;
359 pushCxt(newCxt, cbn, svfroutine);
360 const ICFGNode* stmt = GenericGraphTraits<ICFGGraph>::getFunEntry(icfg, svfroutine);
361 CxtThread ct(newCxt, call);
362 if (!tct->hasTCTNode(ct))
363 continue;
364 CxtThreadStmt newcts(tct->getTCTNode(ct)->getId(), ct.getContext(), stmt);
365 addInterleavingThread(newcts, cts);
366 }
367 handleIntra(icfg, cg, cts);
368}

◆ handleIntra()

template<class ICFGGraph, class CGGraph>
void MHP::handleIntra ( ICFGGraph icfg,
CGGraph cg,
const CxtThreadStmt & cts )
protected

Handle intra.

Handling intraprocedural statements (successive statements on the CFG )

Definition at line 585 of file MHP.cpp.

586{
587 const SVFBasicBlock* srcBB = cts.getStmt()->getBB();
588 const bool mayExitSymJoinLoop =
589 srcBB != nullptr && bbToSymJoins.find(srcBB) != bbToSymJoins.end();
590
591 std::vector<const ICFGNode*> succ;
592 GenericGraphTraits<ICFGGraph>::getSuccNodes(icfg, cts.getStmt(), succ);
593 for (const ICFGNode* dst : succ)
594 {
595 if(dst->getFun() == cts.getStmt()->getFun())
596 {
597 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), dst);
598 if (mayExitSymJoinLoop)
599 addInterleavingBits(newCts, edgeFlow(cts, dst));
600 else
601 addInterleavingThread(newCts, cts);
602 }
603 }
604}
NodeBS edgeFlow(const CxtThreadStmt &cts, const ICFGNode *dst)
Definition MHP.cpp:77
void addInterleavingBits(const CxtThreadStmt &tgr, const NodeBS &bits)
Definition MHP.h:220

◆ handleJoin()

template<class ICFGGraph, class CGGraph>
void MHP::handleJoin ( ICFGGraph icfg,
CGGraph cg,
const CxtThreadStmt & cts,
NodeID rootTid )
protected

Handle join.

Handle join

for the join site in a loop loop which does not join the current thread we process the loop exit

Definition at line 374 of file MHP.cpp.

375{
376
377 const CallStrCxt& curCxt = cts.getContext();
378
379 assert(isTDJoin(cts.getStmt()));
380
381 const CallICFGNode* call = SVFUtil::cast<CallICFGNode>(cts.getStmt());
382
383 NodeBS joinedTids = getDirAndIndJoinedTid(curCxt, call);
384 if (!joinedTids.empty())
385 {
386 if (fja->hasJoinLoop(call))
387 {
388 // Seed the loop exits with the flow along the exiting edge (see
389 // edgeFlow): the kill applies to the flow, not the exit's state.
390 NodeBS flow = getInterleavingThreads(cts);
391 if (hasJoinInSymmetricLoop(curCxt, call) && isMustJoin(cts.getTid(), call))
392 flow.intersectWithComplement(joinedTids);
393
394 std::vector<const SVFBasicBlock*> exitbbs;
395 call->getFun()->getExitBlocksOfLoop(call->getBB(), exitbbs);
396 while (!exitbbs.empty())
397 {
398 const SVFBasicBlock* eb = exitbbs.back();
399 exitbbs.pop_back();
400 // Seed the post-join interleaving at the loop-exit entry. The slicer
401 // retains these entries as anchors, so the seed always lands on a kept
402 // node (no runtime projection needed).
403 CxtThreadStmt newCts(cts.getTid(), curCxt, eb->front());
404 addInterleavingBits(newCts, flow);
405 }
406 }
407 else
408 {
409 rmInterleavingThread(cts, joinedTids, call);
410 DBOUT(DMTA, outs() << "\n\t match join site " << call->toString() << " for thread " << rootTid << "\n");
411 }
412 }
415 else
416 {
417 if (fja->hasJoinLoop(call))
418 {
419 std::vector<const SVFBasicBlock*> exitbbs;
420 call->getFun()->getExitBlocksOfLoop(call->getBB(), exitbbs);
421 while (!exitbbs.empty())
422 {
423 const SVFBasicBlock* eb = exitbbs.back();
424 exitbbs.pop_back();
425 // Seed at the loop-exit entry (a retained anchor; see above).
426 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), eb->front());
427 addInterleavingThread(newCts, cts);
428 }
429 }
430 }
431 handleIntra(icfg, cg, cts);
432}
const std::string toString() const override
Definition ICFG.cpp:129
void getExitBlocksOfLoop(const SVFBasicBlock *bb, BBList &exitbbs) const
void rmInterleavingThread(const CxtThreadStmt &tgr, const NodeBS &tids, const ICFGNode *joinsite)
Definition MHP.h:229
bool hasJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.cpp:738
const ICFGNode * front() const
const ICFGNode * back() const

◆ handleNonCandidateFun()

template<class ICFGGraph, class CGGraph>
void MHP::handleNonCandidateFun ( ICFGGraph icfg,
CGGraph cg,
const CxtThreadStmt & cts )
protected

Handle non-candidate function.

Handle call instruction in the current thread scope (excluding any fork site)

Definition at line 316 of file MHP.cpp.

317{
318 const ICFGNode* curInst = cts.getStmt();
319 const FunObjVar* curfun = curInst->getFun();
320 assert((curInst == GenericGraphTraits<ICFGGraph>::getFunEntry(icfg, curfun)) && "curInst is not the entry of non candidate function.");
321 const CallStrCxt& curCxt = cts.getContext();
322 CallGraphNode* node = tcg->getCallGraphNode(curfun);
323 std::vector<const CallGraphEdge*> outEdges;
324 GenericGraphTraits<CGGraph>::getOutEdges(cg, node, outEdges);
325 for (const CallGraphEdge* edge : outEdges)
326 {
327 const FunObjVar* callee = edge->getDstNode()->getFunction();
328 if (!isExtCall(callee))
329 {
330 const ICFGNode* calleeInst = GenericGraphTraits<ICFGGraph>::getFunEntry(icfg, callee);
331 CxtThreadStmt newCts(cts.getTid(), curCxt, calleeInst);
332 addInterleavingThread(newCts, cts);
333 }
334 }
335}

◆ handleRet()

template<class ICFGGraph, class CGGraph>
void MHP::handleRet ( ICFGGraph icfg,
CGGraph cg,
const CxtThreadStmt & cts )
protected

Handle return.

Handle return instruction in the current thread scope (excluding any join site)

Definition at line 507 of file MHP.cpp.

508{
509 CallGraphNode* curFunNode = tcg->getCallGraphNode(cts.getStmt()->getFun());
510 std::vector<const CallGraphEdge*> inEdges;
511 GenericGraphTraits<CGGraph>::getInEdges(cg, curFunNode, inEdges);
512 for (const CallGraphEdge* edgeConst : inEdges)
513 {
515 continue;
516 std::vector<const CallICFGNode*> directCalls;
517 GenericGraphTraits<CGGraph>::getDirectCalls(cg, edgeConst, directCalls);
518 for (const CallICFGNode* callSite : directCalls)
519 {
520 CallStrCxt newCxt = cts.getContext();
521 if (matchAndPopCxt(newCxt, callSite, curFunNode->getFunction()))
522 {
523 std::vector<const ICFGNode*> succ;
524 GenericGraphTraits<ICFGGraph>::getSuccNodes(icfg, cts.getStmt(), succ);
525 for (const ICFGNode* dst : succ)
526 {
527 if(dst->getFun() == callSite->getFun())
528 {
529 // Iterate over callSite's call string context and use as the successor's context
530 if (!hasThreadStmtSet(callSite))
531 continue;
532 for (const CxtThreadStmt& cxtThreadStmt:
533 getThreadStmtSet(callSite))
534 {
535 CallStrCxt callSiteCxt = cxtThreadStmt.getContext();
536 // If new context is a suffix of the call site context
537 if (isContextSuffix(newCxt, callSiteCxt))
538 {
539 CxtThreadStmt newCts(cts.getTid(), callSiteCxt, dst);
540 addInterleavingThread(newCts, cts);
541 }
542 }
543 }
544 }
545 }
546 }
547 std::vector<const CallICFGNode*> indirectCalls;
548 GenericGraphTraits<CGGraph>::getIndirectCalls(cg, edgeConst, indirectCalls);
549 for (const CallICFGNode* callSite : indirectCalls)
550 {
551 CallStrCxt newCxt = cts.getContext();
552 if (matchAndPopCxt(newCxt, callSite, curFunNode->getFunction()))
553 {
554 std::vector<const ICFGNode*> succ;
555 GenericGraphTraits<ICFGGraph>::getSuccNodes(icfg, cts.getStmt(), succ);
556 for (const ICFGNode* dst : succ)
557 {
558 if(dst->getFun() == callSite->getFun())
559 {
560 // Iterate over callSite's call string context and use as the successor's context
561 if (!hasThreadStmtSet(callSite))
562 continue;
563 for (const CxtThreadStmt& cxtThreadStmt:
564 getThreadStmtSet(callSite))
565 {
566 CallStrCxt callSiteCxt = cxtThreadStmt.getContext();
567 // If new context is a suffix of the call site context
568 if (isContextSuffix(newCxt, callSiteCxt))
569 {
570 CxtThreadStmt newCts(cts.getTid(), callSiteCxt, dst);
571 addInterleavingThread(newCts, cts);
572 }
573 }
574 }
575 }
576 }
577 }
578 }
579}
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
Definition MHP.h:273
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt call)
If lhs is a suffix of rhs, including equal.
Definition MHP.h:278
const CxtThreadStmtSet & getThreadStmtSet(const ICFGNode *inst) const
Get/has ThreadStmt.
Definition MHP.h:142
bool hasThreadStmtSet(const ICFGNode *inst) const
Definition MHP.h:148
LLVM_NODISCARD bool isa(const Y &Val)
Definition Casting.h:241

◆ hasInterleavingThreads()

bool SVF::MHP::hasInterleavingThreads ( const CxtThreadStmt & cts) const
inline

Definition at line 134 of file MHP.h.

135 {
137 }

◆ hasJoinInSymmetricLoop()

bool MHP::hasJoinInSymmetricLoop ( const CallStrCxt & cxt,
const ICFGNode * call ) const
protected

Whether a context-sensitive join satisfies symmetric loop pattern.

Whether a context-sensitive join satisfies symmetric loop pattern

Definition at line 738 of file MHP.cpp.

739{
740 CxtStmt cs(cxt, call);
741 return fja->hasJoinInSymmetricLoop(cs);
742}

◆ hasThreadStmtSet()

bool SVF::MHP::hasThreadStmtSet ( const ICFGNode * inst) const
inline

Definition at line 148 of file MHP.h.

149 {
150 return instToTSMap.find(inst)!=instToTSMap.end();
151 }

◆ isConnectedfromMain()

bool MHP::isConnectedfromMain ( const FunObjVar * fun)

Whether the function is connected from main function in thread call graph.

Definition at line 759 of file MHP.cpp.

760{
761 CallGraphNode* cgnode = tcg->getCallGraphNode(fun);
762 FIFOWorkList<const CallGraphNode*> worklist;
763 TCT::PTACGNodeSet visited;
764 worklist.push(cgnode);
765 visited.insert(cgnode);
766 while (!worklist.empty())
767 {
768 const CallGraphNode* node = worklist.pop();
770 return true;
771 for (CallGraphNode::const_iterator nit = node->InEdgeBegin(), neit = node->InEdgeEnd(); nit != neit; nit++)
772 {
773 const CallGraphNode* srcNode = (*nit)->getSrcNode();
774 if (visited.find(srcNode) == visited.end())
775 {
776 visited.insert(srcNode);
777 worklist.push(srcNode);
778 }
779 }
780 }
781 return false;
782}
bool push(const Data &data)
Definition WorkList.h:180
bool empty() const
Definition WorkList.h:161
iterator InEdgeBegin()
iterator InEdgeEnd()
Set< const CallGraphNode * > PTACGNodeSet
Definition TCT.h:176
bool isProgEntryFunction(const FunObjVar *)
Program entry function e.g. main.
Definition SVFUtil.cpp:531

◆ isContextSuffix()

bool SVF::MHP::isContextSuffix ( const CallStrCxt & lhs,
const CallStrCxt call )
inlineprotected

If lhs is a suffix of rhs, including equal.

Definition at line 278 of file MHP.h.

279 {
280 return tct->isContextSuffix(lhs,call);
281 }

◆ isHBPair()

bool MHP::isHBPair ( NodeID tid1,
NodeID tid2 )
protected

Whether thread t1 happens before t2 based on ForkJoin Analysis.

Whether two thread t1 happens-fore t2

Definition at line 754 of file MHP.cpp.

755{
756 return fja->isHBPair(tid1, tid2);
757}

◆ isMultiForkedThread()

bool SVF::MHP::isMultiForkedThread ( NodeID curTid)
inlineprotected

A thread is a multiForked thread if it is in a loop or recursion.

Definition at line 257 of file MHP.h.

258 {
259 return tct->getTCTNode(curTid)->isMultiforked();
260 }

◆ isMustJoin()

bool MHP::isMustJoin ( const NodeID curTid,
const ICFGNode * joinsite )
protected

Whether a join site must join a thread t.

A join site must join t if (1) t is not a multiforked thread (2) the join site of t is not in recursion

Definition at line 719 of file MHP.cpp.

720{
721 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(joinsite);
722 assert(call && isTDJoin(call) && "not a join site!");
723 return !isMultiForkedThread(curTid) && !tct->isJoinSiteInRecursion(call);
724}

◆ isRecurFullJoin()

bool MHP::isRecurFullJoin ( NodeID parentTid,
NodeID curTid )
protected

Thread curTid can be fully joined by parentTid recursively.

Whether curTid can be fully joined by parentTid recursively

Definition at line 684 of file MHP.cpp.

685{
686 if (parentTid == curTid)
687 return true;
688
689 const TCTNode* curNode = tct->getTCTNode(curTid);
690 FIFOWorkList<const TCTNode*> worklist;
691 worklist.push(curNode);
692 while (!worklist.empty())
693 {
694 const TCTNode* node = worklist.pop();
695 for (TCTEdge* edge : node->getInEdges())
696 {
697 NodeID srcID = edge->getSrcID();
698 if (fja->isFullJoin(srcID, node->getId()))
699 {
700 if (srcID == parentTid)
701 return true;
702 else
703 worklist.push(edge->getSrcNode());
704 }
705 else
706 {
707 return false;
708 }
709 }
710 }
711 return false;
712}
const GEdgeSetTy & getInEdges() const
NodeID getId() const
Get ID.
Definition SVFValue.h:158

◆ isTDFork()

bool SVF::MHP::isTDFork ( const ICFGNode * call)
inlineprotected

Whether it is a fork site.

Definition at line 297 of file MHP.h.

298 {
299 const CallICFGNode* fork = SVFUtil::dyn_cast<CallICFGNode>(call);
300 return fork && tcg->getThreadAPI()->isTDFork(fork);
301 }

◆ isTDJoin()

bool SVF::MHP::isTDJoin ( const ICFGNode * call)
inlineprotected

Whether it is a join site.

Definition at line 303 of file MHP.h.

304 {
305 const CallICFGNode* join = SVFUtil::dyn_cast<CallICFGNode>(call);
306 return join && tcg->getThreadAPI()->isTDJoin(join);
307 }

◆ matchAndPopCxt()

bool SVF::MHP::matchAndPopCxt ( CallStrCxt & cxt,
const CallICFGNode * call,
const FunObjVar * callee )
inlineprotected

Match context.

Definition at line 273 of file MHP.h.

274 {
275 return tct->matchAndPopCxt(cxt,call,callee);
276 }

◆ mayHappenInParallel()

bool MHP::mayHappenInParallel ( const ICFGNode * i1,
const ICFGNode * i2 )
virtual

Interface to query whether two instructions may happen-in-parallel.

Definition at line 854 of file MHP.cpp.

855{
857
858 DOTIMESTAT(double queryStart = PTAStat::getClk(true));
859 bool mhp = mayHappenInParallelCache(i1, i2);
860 DOTIMESTAT(double queryEnd = PTAStat::getClk(true));
861 DOTIMESTAT(interleavingQueriesTime += (queryEnd - queryStart) / TIMEINTERVAL);
862
863 return mhp;
864}
virtual bool mayHappenInParallelCache(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:832

◆ mayHappenInParallelCache()

bool MHP::mayHappenInParallelCache ( const ICFGNode * i1,
const ICFGNode * i2 )
virtual

Definition at line 832 of file MHP.cpp.

833{
834 if (!tct->isCandidateFun(i1->getFun()) && !tct->isCandidateFun(i2->getFun()))
835 {
836 FuncPair funpair = std::make_pair(i1->getFun(), i2->getFun());
837 FuncPairToBool::const_iterator it = nonCandidateFuncMHPRelMap.find(funpair);
838 if (it == nonCandidateFuncMHPRelMap.end())
839 {
840 bool mhp = mayHappenInParallelInst(i1, i2);
841 nonCandidateFuncMHPRelMap[funpair] = mhp;
842 return mhp;
843 }
844 else
845 {
846 if (it->second)
848 return it->second;
849 }
850 }
851 return mayHappenInParallelInst(i1, i2);
852}
FuncPairToBool nonCandidateFuncMHPRelMap
Definition MHP.h:332
std::pair< const FunObjVar *, const FunObjVar * > FuncPair
Definition MHP.h:75
virtual bool mayHappenInParallelInst(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:794

◆ mayHappenInParallelInst()

bool MHP::mayHappenInParallelInst ( const ICFGNode * i1,
const ICFGNode * i2 )
virtual

Answer MHP queries For a pair of ThreadStmts (t1,s1) = <l1> (t2,s2) = <l2> They may happen in parallel if (1) t1 == t2 and t1 inloop/incycle (2) t1!=t2 and t1 \in l2 and t2 \in l1

TODO: Any instruction in dead function is assumed no MHP with others.

Definition at line 794 of file MHP.cpp.

795{
797 const NodeThreadSummary* summary1 = getThreadSummary(i1);
798 const NodeThreadSummary* summary2 = getThreadSummary(i2);
799 if (summary1 == nullptr || summary2 == nullptr)
800 return false;
801
802 // Original rule for distinct tids:
803 // exists c1,c2. L(i1,tid1,c1)[tid2] && L(i2,tid2,c2)[tid1].
804 // The two context choices are independent, so this is exactly equivalent
805 // to testing the two per-tid context unions. No context correlation is lost.
806 for (NodeID tid1 : summary1->tids)
807 {
808 if (summary2->tids.test(tid1) && isMultiForkedThread(tid1))
809 {
811 return true;
812 }
813
814 const auto firstFlowIt = summary1->interleavingByTid.find(tid1);
815 assert(firstFlowIt != summary1->interleavingByTid.end());
816 for (NodeID tid2 : firstFlowIt->second)
817 {
818 if (tid1 == tid2 || !summary2->tids.test(tid2))
819 continue;
820 const auto secondFlowIt = summary2->interleavingByTid.find(tid2);
821 assert(secondFlowIt != summary2->interleavingByTid.end());
822 if (secondFlowIt->second.test(tid1))
823 {
825 return true;
826 }
827 }
828 }
829 return false;
830}

◆ popFromCTSWorkList()

CxtThreadStmt SVF::MHP::popFromCTSWorkList ( )
inlineprotected

Definition at line 290 of file MHP.h.

291 {
292 CxtThreadStmt ctp = cxtStmtList.pop();
293 return ctp;
294 }

◆ printInterleaving()

void MHP::printInterleaving ( )

Print interleaving results.

Print interleaving results

Definition at line 887 of file MHP.cpp.

888{
889 for (const auto& pair : threadStmtToThreadInterLeav)
890 {
891 outs() << "( t" << pair.first.getTid()
892 << pair.first.getStmt()->toString() << " ) ==> [";
893 for (unsigned i : pair.second)
894 {
895 outs() << " " << i << " ";
896 }
897 outs() << "]\n";
898 }
899}

◆ pushCxt()

void SVF::MHP::pushCxt ( CallStrCxt & cxt,
const CallICFGNode * call,
const FunObjVar * callee )
inlineprotected

Context helper functions.

Push calling context

handle calling context for candidate functions only

Definition at line 265 of file MHP.h.

266 {
268 if(tct->isCandidateFun(call->getFun()) == false)
269 return;
270 tct->pushCxt(cxt,call,callee);
271 }

◆ pushToCTSWorkList()

bool SVF::MHP::pushToCTSWorkList ( const CxtThreadStmt & cs)
inlineprotected

WorkList helper functions.

Definition at line 286 of file MHP.h.

287 {
288 return cxtStmtList.push(cs);
289 }

◆ rmInterleavingThread()

void SVF::MHP::rmInterleavingThread ( const CxtThreadStmt & tgr,
const NodeBS & tids,
const ICFGNode * joinsite )
inlineprotected

Definition at line 229 of file MHP.h.

230 {
231 NodeBS joinedTids;
232 for(NodeBS::iterator it = tids.begin(), eit = tids.end(); it!=eit; ++it)
233 {
234 if(isMustJoin(tgr.getTid(),joinsite))
235 joinedTids.set(*it);
236 }
237 if(threadStmtToThreadInterLeav[tgr].intersectWithComplement(joinedTids))
238 {
240 }
241 }
SparseBitVectorIterator iterator

◆ updateAncestorThreads()

template<class ICFGGraph, class CGGraph>
void MHP::updateAncestorThreads ( ICFGGraph icfg,
CGGraph cg,
NodeID curTid )
protected

Update Ancestor and sibling threads.

Update interleavings of ancestor threads according to TCT

Definition at line 610 of file MHP.cpp.

611{
612 NodeBS ancestorAndSelfTids = tct->getAncestorThreads(curTid);
613 DBOUT(DMTA, outs() << "##Ancestor thread of " << curTid << " is : ");
614 DBOUT(DMTA, dumpSet(ancestorAndSelfTids));
615 DBOUT(DMTA, outs() << "\n");
616 ancestorAndSelfTids.set(curTid);
617
618 for (const unsigned tid : ancestorAndSelfTids)
619 {
620 const CxtThread& ct = tct->getTCTNode(tid)->getCxtThread();
621 if (const ICFGNode* forkInst = ct.getThread())
622 {
623 // Mark the fork site's successors under the graph, so a sliced run
624 // marks kept successors (a marker on a removed node would strand).
625 std::vector<const ICFGNode*> succ;
626 GenericGraphTraits<ICFGGraph>::getSuccNodes(icfg, forkInst, succ);
627 for(const ICFGNode* dst : succ)
628 {
629 // Ensure dst node is in the same function as forkInst
630 if(dst->getFun() == forkInst->getFun())
631 {
632 for (const auto& forkSiteCxt : tct->getCxtOfCxtThread(ct))
633 {
634 CxtThreadStmt cts(forkSiteCxt.first, forkSiteCxt.second, dst);
635 addInterleavingThread(cts, curTid);
636 }
637 }
638 }
639 }
640 }
641}
const ICFGNode * getThread() const
Return forksite.
Definition CxtStmt.h:209
void set(unsigned Idx)

◆ updateNonCandidateFunInterleaving()

template<class ICFGGraph, class CGGraph>
void MHP::updateNonCandidateFunInterleaving ( ICFGGraph icfg,
CGGraph cg )
protected

Update non-candidate functions' interleaving. Copy interleaving threads of the entry inst to other insts.

Update non-candidate functions' interleaving

Definition at line 275 of file MHP.cpp.

276{
277 // Copy each non-candidate function entry's interleaving to the function's
278 // other nodes under the graph. Runs after the worklist has drained, so
279 // addInterleavingThread's push is inert.
280 using CGTraits = GenericGraphTraits<CGGraph>;
281 for (auto nodeIt = CGTraits::nodes_begin(cg),
282 nodeEnd = CGTraits::nodes_end(cg); nodeIt != nodeEnd; ++nodeIt)
283 {
284 const CallGraphNode* callGraphNode = CGTraits::getRawNode(*nodeIt);
285 const FunObjVar* fun = callGraphNode->getFunction();
286 if (tct->isCandidateFun(fun) || isExtCall(fun))
287 continue;
288
289 const ICFGNode* entryNode = GenericGraphTraits<ICFGGraph>::getFunEntry(icfg, fun);
290 if (!hasThreadStmtSet(entryNode))
291 continue;
292
293 const CxtThreadStmtSet& tsSet = getThreadStmtSet(entryNode);
294
295 std::vector<const ICFGNode*> funICFGNodes;
296 GenericGraphTraits<ICFGGraph>::getFunICFGNodes(icfg, fun, funICFGNodes);
297
298 for (const CxtThreadStmt& cts : tsSet)
299 {
300 const CallStrCxt& curCxt = cts.getContext();
301 for (const ICFGNode* curNode : funICFGNodes)
302 {
303 if (curNode == entryNode)
304 continue;
305 CxtThreadStmt newCts(cts.getTid(), curCxt, curNode);
306 addInterleavingThread(newCts, cts);
307 }
308 }
309 }
310}
Set< CxtThreadStmt > CxtThreadStmtSet
Definition MHP.h:57

◆ updateSiblingThreads()

template<class ICFGGraph, class CGGraph>
void MHP::updateSiblingThreads ( ICFGGraph icfg,
CGGraph cg,
NodeID curTid )
protected

Update interleavings of sibling threads according to TCT

Exclude sibling thread that never happen in parallel based on ForkJoinAnalysis

The interleaving of a thread t is not unnecessary to be updated if (1) t HB Sibling and t fully joins curTid recursively or (2) Sibling HB t

Definition at line 654 of file MHP.cpp.

655{
656 NodeBS ancestorAndSelfTids = tct->getAncestorThreads(curTid);
657 ancestorAndSelfTids.set(curTid);
658 for (const unsigned tid : ancestorAndSelfTids)
659 {
660 NodeBS siblingTds = tct->getSiblingThread(tid);
661 for (const unsigned stid : siblingTds)
662 {
663 if ((isHBPair(tid, stid) && isRecurFullJoin(tid, curTid)) || isHBPair(stid, tid))
664 continue;
665
666 const CxtThread& ct = tct->getTCTNode(stid)->getCxtThread();
667 const FunObjVar* routine = tct->getStartRoutineOfCxtThread(ct);
668 // The entry node under the graph: the same node the sibling thread's
669 // own propagation starts from (see analyzeInterleaving's root cts).
670 const ICFGNode* stmt = GenericGraphTraits<ICFGGraph>::getFunEntry(icfg, routine);
671 CxtThreadStmt cts(stid, ct.getContext(), stmt);
672 addInterleavingThread(cts, curTid);
673 }
674
675 DBOUT(DMTA, outs() << "##Sibling thread of " << curTid << " is : ");
676 DBOUT(DMTA, dumpSet(siblingTds));
677 DBOUT(DMTA, outs() << "\n");
678 }
679}
bool isRecurFullJoin(NodeID parentTid, NodeID curTid)
Thread curTid can be fully joined by parentTid recursively.
Definition MHP.cpp:684
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens before t2 based on ForkJoin Analysis.
Definition MHP.cpp:754

Member Data Documentation

◆ bbToSymJoins

BBToSymJoinsMap SVF::MHP::bbToSymJoins
protected

Map a statement to its thread interleavings.

loop block -> symmetric in-loop joins of that loop

Definition at line 326 of file MHP.h.

◆ cxtStmtList

CxtThreadStmtWorkList SVF::MHP::cxtStmtList
protected

CxtThreadStmt worklist.

Definition at line 324 of file MHP.h.

◆ fja

ForkJoinAnalysis* SVF::MHP::fja
protected

ForJoin Analysis.

Definition at line 323 of file MHP.h.

◆ instToThreadSummary

InstToThreadSummaryMap SVF::MHP::instToThreadSummary
protected

Exact per-node/per-tid query compression.

Definition at line 329 of file MHP.h.

◆ instToTSMap

InstToThreadStmtSetMap SVF::MHP::instToTSMap
protected

Map an instruction to its ThreadStmtSet.

Definition at line 328 of file MHP.h.

◆ interleavingQueriesTime

double SVF::MHP::interleavingQueriesTime

Definition at line 338 of file MHP.h.

◆ interleavingTime

double SVF::MHP::interleavingTime

Definition at line 337 of file MHP.h.

◆ nonCandidateFuncMHPRelMap

FuncPairToBool SVF::MHP::nonCandidateFuncMHPRelMap
protected

Definition at line 332 of file MHP.h.

◆ numOfMHPQueries

u32_t SVF::MHP::numOfMHPQueries

Number of queries are answered as may-happen-in-parallel.

Definition at line 336 of file MHP.h.

◆ numOfTotalQueries

u32_t SVF::MHP::numOfTotalQueries

Total number of queries.

Definition at line 335 of file MHP.h.

◆ querySummaryOwner

Map<const ICFGNode*, const ICFGNode*> SVF::MHP::querySummaryOwner
protected

Non-candidate node -> entry summary.

Definition at line 330 of file MHP.h.

◆ stateRepresentation

StateRepresentation SVF::MHP::stateRepresentation
protected

Definition at line 331 of file MHP.h.

◆ symJoinLoop

SymJoinToLoopMap SVF::MHP::symJoinLoop
protected

symmetric in-loop join -> its loop's blocks

Definition at line 327 of file MHP.h.

◆ tcg

ThreadCallGraph* SVF::MHP::tcg
protected

TCG.

Definition at line 321 of file MHP.h.

◆ tct

TCT* SVF::MHP::tct
protected

TCT.

Definition at line 322 of file MHP.h.

◆ threadStmtToThreadInterLeav

ThreadStmtToThreadInterleav SVF::MHP::threadStmtToThreadInterLeav
protected

Definition at line 325 of file MHP.h.


The documentation for this class was generated from the following files: