Static Value-Flow Analysis
Loading...
Searching...
No Matches
MHP.cpp
Go to the documentation of this file.
1//===- MHP.cpp -- May-happen-in-parallel analysis-------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22
23/*
24 * MHP.cpp
25 *
26 * Created on: Jan 21, 2014
27 * Author: Yulei Sui, Peng Di
28 */
29
30#include "Util/Options.h"
31#include "MTA/MHP.h"
32#include "MTA/MTA.h"
33#include "MTA/LockAnalysis.h"
34#include "MTA/MTASlicer.h"
35#include "Util/SVFUtil.h"
36#include "Util/PTAStat.h"
38#include "Graphs/SlicedGraphs.h"
39#include "SVFIR/SVFIR.h"
40#include "WPA/Andersen.h"
41
42using namespace SVF;
43using namespace SVFUtil;
44
49 : tcg(t->getThreadCallGraph()), tct(t),
50 stateRepresentation(representation),
51 numOfTotalQueries(0), numOfMHPQueries(0),
52 interleavingTime(0), interleavingQueriesTime(0)
53{
55}
56
61{
62 for (const auto& joinAndLoop : fja->getSymmetricLoopJoins())
63 {
65 for (const SVFBasicBlock* bb : joinAndLoop.second)
66 {
67 loopBlocks.insert(bb);
68 bbToSymJoins[bb].push_back(joinAndLoop.first);
69 }
70 }
71}
72
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;
92 if (loopBlocks.find(dstBB) != loopBlocks.end())
93 continue; // edge stays inside the loop
94 if (!isMustJoin(cts.getTid(), join.getStmt()))
95 continue;
96 flow.intersectWithComplement(
97 getDirAndIndJoinedTid(join.getContext(), join.getStmt()));
98 }
99 return flow;
100}
101
106{
107 delete fja;
108}
109
110
114template<class ICFGGraph, class CGGraph>
116{
117 DBOUT(DGENERAL, outs() << pasMsg("MHP interleaving analysis\n"));
118 DBOUT(DMTA, outs() << pasMsg("MHP interleaving analysis\n"));
120 analyzeInterleaving(icfg, cg);
123}
124
128template<class ICFGGraph, class CGGraph>
130{
131 for (const std::pair<const NodeID, TCTNode*>& tpair : *tct)
132 {
133 const CxtThread& ct = tpair.second->getCxtThread();
134 NodeID rootTid = tpair.first;
137 CxtThreadStmt rootcts(rootTid, ct.getContext(), svfInst);
138
142
143 while (!cxtStmtList.empty())
144 {
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 {
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}
194
200template<class ICFGGraph, class CGGraph>
202{
203 instToThreadSummary.clear();
204 querySummaryOwner.clear();
205 for (const auto& instAndStates : instToTSMap)
206 {
208 for (const CxtThreadStmt& state : instAndStates.second)
209 {
210 const NodeID tid = state.getTid();
211 summary.tids.set(tid);
212 ThreadStmtToThreadInterleav::const_iterator it =
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.
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 =
238 InstToThreadSummaryMap::const_iterator entryIt =
240 if (entryIt == instToThreadSummary.end())
241 continue;
242
243 std::vector<const ICFGNode*> funICFGNodes;
245 for (const ICFGNode* node : funICFGNodes)
246 {
247 if (node == entryNode)
248 continue;
249 const bool inserted = querySummaryOwner.emplace(node, entryNode).second;
251 "non-candidate internal node unexpectedly had a raw MHP state");
252 (void)inserted;
253 }
254 }
255}
256
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}
270
274template<class ICFGGraph, class CGGraph>
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.
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
291 continue;
292
294
295 std::vector<const ICFGNode*> 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;
307 }
308 }
309 }
310}
311
315template<class ICFGGraph, class CGGraph>
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();
323 std::vector<const CallGraphEdge*> outEdges;
325 for (const CallGraphEdge* edge : outEdges)
326 {
327 const FunObjVar* callee = edge->getDstNode()->getFunction();
328 if (!isExtCall(callee))
329 {
333 }
334 }
335}
336
340template<class ICFGGraph, class CGGraph>
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);
350 std::vector<const CallGraphEdge*> outEdges;
352 for (const CallGraphEdge* edge : outEdges)
353 {
354 if (edge->getEdgeKind() != CallGraphEdge::TDForkEdge ||
356 continue;
357 const FunObjVar* svfroutine = edge->getDstNode()->getFunction();
361 CxtThread ct(newCxt, call);
362 if (!tct->hasTCTNode(ct))
363 continue;
364 CxtThreadStmt newcts(tct->getTCTNode(ct)->getId(), ct.getContext(), stmt);
366 }
367 handleIntra(icfg, cg, cts);
368}
369
373template<class ICFGGraph, class CGGraph>
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
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.
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());
405 }
406 }
407 else
408 {
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());
428 }
429 }
430 }
431 handleIntra(icfg, cg, cts);
432}
433
437template<class ICFGGraph, class CGGraph>
439{
440
441 const ICFGNode* call = cts.getStmt();
442 const CallStrCxt& curCxt = cts.getContext();
443 const CallICFGNode* cbn = cast<CallICFGNode>(call);
445 std::vector<const CallGraphEdge*> outEdges;
447 for (const CallGraphEdge* edge : outEdges)
448 {
449 if (edge->getEdgeKind() != CallGraphEdge::CallRetEdge ||
451 continue;
452 const FunObjVar* svfcallee = edge->getDstNode()->getFunction();
453 if (isExtCall(svfcallee))
454 continue;
455
458 const ICFGNode* svfEntryInst =
460 if (svfEntryInst == nullptr)
461 continue;
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 =
471 if (exitInst == nullptr)
472 continue;
476 {
477 CxtThreadStmt retCts(cts.getTid(), curCxt,
478 cbn->getRetICFGNode());
480 }
481 }
482 }
483
487 if (const CallICFGNode *callSite = SVFUtil::cast<CallICFGNode>(call))
488 {
492 {
493 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), callSite->getRetICFGNode());
495 }
496 }
497 else
498 {
499 assert(false && "cts.getStmt() is not a CallICFGNode!");
500 }
501}
502
506template<class ICFGGraph, class CGGraph>
508{
509 CallGraphNode* curFunNode = tcg->getCallGraphNode(cts.getStmt()->getFun());
510 std::vector<const CallGraphEdge*> inEdges;
512 for (const CallGraphEdge* edgeConst : inEdges)
513 {
514 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edgeConst))
515 continue;
516 std::vector<const CallICFGNode*> 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;
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
531 continue;
532 for (const CxtThreadStmt& cxtThreadStmt:
534 {
535 CallStrCxt callSiteCxt = cxtThreadStmt.getContext();
536 // If new context is a suffix of the call site context
538 {
539 CxtThreadStmt newCts(cts.getTid(), callSiteCxt, dst);
541 }
542 }
543 }
544 }
545 }
546 }
547 std::vector<const CallICFGNode*> 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;
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
562 continue;
563 for (const CxtThreadStmt& cxtThreadStmt:
565 {
566 CallStrCxt callSiteCxt = cxtThreadStmt.getContext();
567 // If new context is a suffix of the call site context
569 {
570 CxtThreadStmt newCts(cts.getTid(), callSiteCxt, dst);
572 }
573 }
574 }
575 }
576 }
577 }
578 }
579}
580
584template<class ICFGGraph, class CGGraph>
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;
593 for (const ICFGNode* dst : succ)
594 {
595 if(dst->getFun() == cts.getStmt()->getFun())
596 {
597 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), dst);
600 else
602 }
603 }
604}
605
609template<class ICFGGraph, class CGGraph>
611{
613 DBOUT(DMTA, outs() << "##Ancestor thread of " << curTid << " is : ");
615 DBOUT(DMTA, outs() << "\n");
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;
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);
636 }
637 }
638 }
639 }
640 }
641}
642
653template<class ICFGGraph, class CGGraph>
655{
658 for (const unsigned tid : ancestorAndSelfTids)
659 {
661 for (const unsigned stid : siblingTds)
662 {
663 if ((isHBPair(tid, stid) && isRecurFullJoin(tid, curTid)) || isHBPair(stid, tid))
664 continue;
665
668 // The entry node under the graph: the same node the sibling thread's
669 // own propagation starts from (see analyzeInterleaving's root cts).
671 CxtThreadStmt cts(stid, ct.getContext(), stmt);
673 }
674
675 DBOUT(DMTA, outs() << "##Sibling thread of " << curTid << " is : ");
677 DBOUT(DMTA, outs() << "\n");
678 }
679}
680
685{
686 if (parentTid == curTid)
687 return true;
688
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}
713
720{
721 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(joinsite);
722 assert(call && isTDJoin(call) && "not a join site!");
724}
725
730{
731 CxtStmt cs(cxt, call);
732 return fja->getDirAndIndJoinedTid(cs);
733}
734
738bool MHP::hasJoinInSymmetricLoop(const CallStrCxt& cxt, const ICFGNode* call) const
739{
740 CxtStmt cs(cxt, call);
741 return fja->hasJoinInSymmetricLoop(cs);
742}
743
745const MHP::LoopBBs& MHP::getJoinInSymmetricLoop(const CallStrCxt& cxt, const ICFGNode* call) const
746{
747 CxtStmt cs(cxt, call);
748 return fja->getJoinInSymmetricLoop(cs);
749}
750
755{
756 return fja->isHBPair(tid1, tid2);
757}
758
760{
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}
783
795{
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}
831
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);
842 return mhp;
843 }
844 else
845 {
846 if (it->second)
848 return it->second;
849 }
850 }
852}
853
855{
857
858 DOTIMESTAT(double queryStart = PTAStat::getClk(true));
859 bool mhp = mayHappenInParallelCache(i1, i2);
860 DOTIMESTAT(double queryEnd = PTAStat::getClk(true));
862
863 return mhp;
864}
865
867{
870 if (summary1 == nullptr || summary2 == nullptr)
871 return true;
872
873 for (NodeID tid1 : summary1->tids)
874 {
875 for (NodeID tid2 : summary2->tids)
876 {
878 return false;
879 }
880 }
881 return true;
882}
883
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}
900
908{
909 // typedef Set<const ICFGNode*> CallInstSet;
910 // typedef Map<const FunObjVar*, CallInstSet> FunToFJSites;
911 // FunToFJSites funToFJSites;
912
913 // for (ThreadCallGraph::CallSiteSet::const_iterator it = tct->getThreadCallGraph()->forksitesBegin(),
914 // eit = tct->getThreadCallGraph()->forksitesEnd();
915 // it != eit; ++it)
916 // {
917 // const ICFGNode* fork = *it;
918 // funToFJSites[fork->getFun()].insert(fork);
919 // }
920
921 // for (ThreadCallGraph::CallSiteSet::const_iterator it = tct->getThreadCallGraph()->joinsitesBegin(),
922 // eit = tct->getThreadCallGraph()->joinsitesEnd();
923 // it != eit; ++it)
924 // {
925 // const ICFGNode* join = *it;
926 // funToFJSites[join->getFun()].insert(join);
927 // }
928
929 // for(FunToFJSites::const_iterator it = funToFJSites.begin(), eit = funToFJSites.end(); it!=eit; ++it)
930 // {
931 // // ScalarEvolution* SE = MTA::getSE(it->first);
932 // for(CallInstSet::const_iterator sit = it->second.begin(), esit = it->second.end(); sit!=esit; ++sit)
933 // {
934 // const SVFInstruction* callInst = *sit;
935 // if(tct->getThreadCallGraph()->isForksite(getCBN(callInst)))
936 // {
937 // // const SVFValue* forkSiteTidPtr = getForkedThread(callInst);
938 // // const SCEV *forkSiteTidPtrSCEV = SE->getSCEV(const_cast<Value*>(forkSiteTidPtr));
939 // // const SCEV *baseForkTidPtrSCEV = SE->getSCEV(const_cast<Value*>(getBasePtr(forkSiteTidPtr)));
940 // // forkSiteTidPtrSCEV = getSCEVMinusExpr(forkSiteTidPtrSCEV, baseForkTidPtrSCEV, SE);
941 // // PTASCEV scev(forkSiteTidPtr,nullptr,nullptr);
942 // // fkjnToPTASCEVMap.insert(std::make_pair(callInst,scev));
943 // }
944 // else
945 // {
946 // // const SVFValue* joinSiteTidPtr = getJoinedThread(callInst);
947 // //const SCEV *joinSiteTidPtrSCEV = SE->getSCEV(const_cast<Value*>(joinSiteTidPtr));
948 // //const SCEV *baseJoinTidPtrSCEV = SE->getSCEV(const_cast<Value*>(getBasePtr(joinSiteTidPtr)));
949 // //joinSiteTidPtrSCEV = getSCEVMinusExpr(joinSiteTidPtrSCEV, baseJoinTidPtrSCEV, SE);
950
951 // // PTASCEV scev(joinSiteTidPtr,nullptr,nullptr);
952 // // fkjnToPTASCEVMap.insert(std::make_pair(callInst,scev));
953 // }
954 // }
955 // }
956}
957
961template<class ICFGGraph, class CGGraph>
963{
964 for (const std::pair<const NodeID, TCTNode*>& tpair : *tct)
965 {
966 const CxtThread& ct = tpair.second->getCxtThread();
967 const NodeID rootTid = tpair.first;
968 clearFlagMap();
969 if (const ICFGNode* forkInst = ct.getThread())
970 {
972 std::vector<const ICFGNode*> successors;
974 icfg, forkInst, successors);
975 for (const ICFGNode* successor : successors)
976 {
977 if (successor->getFun() == forkInst->getFun())
978 {
979 for (const auto& forkSiteCxt : tct->getCxtOfCxtThread(ct))
980 {
983 }
984 }
985 }
986
987 while (!cxtStmtList.empty())
988 {
990 const ICFGNode* curInst = cts.getStmt();
991 DBOUT(DMTA, outs() << "-----\nForkJoinAnalysis root thread: " << tpair.first << " ");
992 DBOUT(DMTA, cts.dump());
993 DBOUT(DMTA, outs() << "-----\n");
994 if (isTDFork(curInst))
995 {
996 handleFork(icfg, cg, cts, rootTid);
997 }
998 else if (isTDJoin(curInst))
999 {
1000 handleJoin(icfg, cg, cts, rootTid);
1001 }
1002 else if (tct->isCallSite(curInst) && !tct->isExtCall(curInst))
1003 {
1007 const CallICFGNode *callSite = SVFUtil::cast<CallICFGNode>(curInst);
1010 cg, callSite, callees);
1011 if (!tct->isCandidateFun(callees))
1012 {
1013 // Do not dive into non-candidate functions
1014 CxtStmt newCts(cts.getContext(), callSite->getRetICFGNode());
1016 }
1017 else
1018 {
1019 handleCall(icfg, cg, cts);
1020 }
1021 }
1022 else if (SVFUtil::dyn_cast<FunExitICFGNode>(curInst))
1023 {
1024 handleRet(icfg, cg, cts);
1025 }
1026 else
1027 {
1028 handleIntra(icfg, cts);
1029 }
1030
1035 {
1039 icfg, parentRoutine))
1040 {
1041 if (getMarkedFlag(cts) != TDAlive)
1043 else
1045 }
1046 }
1047 }
1048 }
1049 }
1050}
1051
1053template<class ICFGGraph, class CGGraph>
1055 const CxtStmt& cts, NodeID rootTid)
1056{
1057 const ICFGNode* call = cts.getStmt();
1058 const CallStrCxt& curCxt = cts.getContext();
1059
1060 assert(isTDFork(call));
1061 const CallICFGNode* cbn = cast<CallICFGNode>(call);
1063 std::vector<const CallGraphEdge*> outEdges;
1065 for (const CallGraphEdge* edge : outEdges)
1066 {
1067 if (edge->getEdgeKind() != CallGraphEdge::TDForkEdge ||
1069 continue;
1070 const FunObjVar* callee = edge->getDstNode()->getFunction();
1073 CxtThread ct(newCxt, call);
1074 if (!tct->hasTCTNode(ct))
1075 continue;
1076 if (getMarkedFlag(cts) != TDAlive)
1078 else
1080 }
1081 handleIntra(icfg, cts);
1082}
1083
1085template<class ICFGGraph, class CGGraph>
1087 const CxtStmt& cts, NodeID rootTid)
1088{
1089 const ICFGNode* call = cts.getStmt();
1090 const CallStrCxt& curCxt = cts.getContext();
1091
1092 assert(isTDJoin(call));
1093 const CallICFGNode* cbn = cast<CallICFGNode>(call);
1095 std::vector<const CallGraphEdge*> outEdges;
1097 bool hasCallGraphEdge = false;
1098 for (const CallGraphEdge* edge : outEdges)
1099 {
1101 {
1102 hasCallGraphEdge = true;
1103 break;
1104 }
1105 }
1106 if (hasCallGraphEdge)
1107 {
1109 const ICFGNode* joinSite = cts.getStmt();
1110
1111 if (hasJoinLoop(SVFUtil::cast<CallICFGNode>(joinSite)))
1112 {
1113 if (isAliasedForkJoin(SVFUtil::cast<CallICFGNode>(forkSite),
1114 SVFUtil::cast<CallICFGNode>(joinSite)) &&
1116 )
1117 {
1118 LoopBBs& joinLoop = getJoinLoop(SVFUtil::cast<CallICFGNode>(joinSite));
1119 std::vector<const SVFBasicBlock *> exitbbs;
1120 joinSite->getFun()->getExitBlocksOfLoop(joinSite->getBB(), exitbbs);
1121 while (!exitbbs.empty())
1122 {
1123 const SVFBasicBlock* eb = exitbbs.back();
1124 exitbbs.pop_back();
1125 const ICFGNode* svfEntryInst = eb->front();
1129 {
1132 }
1133 else
1135 }
1136 }
1139 else
1140 {
1141 std::vector<const SVFBasicBlock*> exitbbs;
1142 joinSite->getFun()->getExitBlocksOfLoop(joinSite->getBB(), exitbbs);
1143 while (!exitbbs.empty())
1144 {
1145 const SVFBasicBlock* eb = exitbbs.back();
1146 exitbbs.pop_back();
1147 const ICFGNode* svfEntryInst = eb->front();
1150 }
1151 }
1152 }
1153 else
1154 {
1155 if (isAliasedForkJoin(SVFUtil::cast<CallICFGNode>(forkSite),
1156 SVFUtil::cast<CallICFGNode>(joinSite)))
1157 {
1160 DBOUT(DMTA, outs() << "\n\t match join site " << call->toString() << "for thread " << rootTid << "\n");
1161 }
1162 }
1163 }
1164 handleIntra(icfg, cts);
1165}
1166
1168template<class ICFGGraph, class CGGraph>
1170 const CxtStmt& cts)
1171{
1172 const ICFGNode* call = cts.getStmt();
1173 const CallStrCxt& curCxt = cts.getContext();
1174 const CallICFGNode* cbn = SVFUtil::cast<CallICFGNode>(call);
1176 std::vector<const CallGraphEdge*> outEdges;
1178 for (const CallGraphEdge* edge : outEdges)
1179 {
1180 if (edge->getEdgeKind() != CallGraphEdge::CallRetEdge ||
1182 continue;
1183 const FunObjVar* svfcallee = edge->getDstNode()->getFunction();
1184 if (isExtCall(svfcallee))
1185 continue;
1188 const ICFGNode* svfEntryInst =
1190 if (svfEntryInst == nullptr)
1191 continue;
1194 }
1195}
1196
1198template<class ICFGGraph, class CGGraph>
1200 const CxtStmt& cts)
1201{
1202 const ICFGNode* curInst = cts.getStmt();
1203 const CallStrCxt& curCxt = cts.getContext();
1204
1206 std::vector<const CallGraphEdge*> inEdges;
1208 for (const CallGraphEdge* edge : inEdges)
1209 {
1210 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edge))
1211 continue;
1212 std::vector<const CallICFGNode*> directCalls;
1214 for (const CallICFGNode* callSite : directCalls)
1215 {
1218 curFunNode->getFunction()))
1219 {
1220 std::vector<const ICFGNode*> successors;
1222 icfg, callSite, successors);
1223 for (const ICFGNode* successor : successors)
1224 {
1225 if (successor->getFun() == callSite->getFun())
1226 {
1227 // Iterate over callSite's call string context and use as the successor's context
1229 continue;
1230 for (const CxtStmt& cxtStmt:
1232 {
1233 CallStrCxt callSiteCxt = cxtStmt.getContext();
1234 // If new context is a suffix of the call site context
1236 {
1239 }
1240 }
1241 }
1242 }
1243 }
1244 }
1245 std::vector<const CallICFGNode*> indirectCalls;
1247 for (const CallICFGNode* callSite : indirectCalls)
1248 {
1251 curFunNode->getFunction()))
1252 {
1253 std::vector<const ICFGNode*> successors;
1255 icfg, callSite, successors);
1256 for (const ICFGNode* successor : successors)
1257 {
1258 if (successor->getFun() == callSite->getFun())
1259 {
1260 // Iterate over callSite's call string context and use as the successor's context
1262 continue;
1263 for (const CxtStmt& cxtStmt:
1265 {
1266 CallStrCxt callSiteCxt = cxtStmt.getContext();
1267 // If new context is a suffix of the call site context
1269 {
1272 }
1273 }
1274 }
1275 }
1276 }
1277 }
1278 }
1279}
1280
1282template<class ICFGGraph>
1284 const CxtStmt& cts)
1285{
1286 const ICFGNode* curInst = cts.getStmt();
1287 const CallStrCxt& curCxt = cts.getContext();
1288
1289 std::vector<const ICFGNode*> successors;
1291 for (const ICFGNode* successor : successors)
1292 {
1293 if (successor->getFun() == curInst->getFun())
1294 {
1297 }
1298 }
1299}
1300
1307{
1308
1309 CxtStmtToTIDMap::const_iterator it = dirAndIndJoinMap.find(cs);
1310 if (it != dirAndIndJoinMap.end())
1311 return it->second;
1312
1315
1316 FIFOWorkList<NodeID> worklist;
1317 for (unsigned id : directJoinTids)
1318 {
1319 worklist.push(id);
1320 }
1321
1322 while (!worklist.empty())
1323 {
1324 NodeID tid = worklist.pop();
1325 TCTNode* node = tct->getTCTNode(tid);
1326 for (TCT::ThreadCreateEdgeSet::const_iterator it = tct->getChildrenBegin(node), eit = tct->getChildrenEnd(node); it != eit; ++it)
1327 {
1328 NodeID childTid = (*it)->getDstID();
1329 if (isFullJoin(tid, childTid))
1330 {
1331 allJoinTids.set(childTid);
1332 worklist.push(childTid);
1333 }
1334 }
1335 }
1336
1338
1339 return allJoinTids;
1340}
1341
1342// static bool accessSameArrayIndex(const GetElementPtrInst* ptr1, const GetElementPtrInst* ptr2)
1343// {
1344
1345// std::vector<u32_t> ptr1vec;
1346// for (gep_type_iterator gi = gep_type_begin(*ptr1), ge = gep_type_end(*ptr1);
1347// gi != ge; ++gi)
1348// {
1349// if(SVFConstantInt* ci = SVFUtil::dyn_cast<SVFConstantInt>(LLVMModuleSet::getLLVMModuleSet()->getSVFValue(gi.getOperand())))
1350// {
1351// s32_t idx = ci->getSExtValue();
1352// ptr1vec.push_back(idx);
1353// }
1354// else
1355// return false;
1356// }
1357
1358// std::vector<u32_t> ptr2vec;
1359// for (gep_type_iterator gi = gep_type_begin(*ptr2), ge = gep_type_end(*ptr2);
1360// gi != ge; ++gi)
1361// {
1362// if(SVFConstantInt* ci = SVFUtil::dyn_cast<SVFConstantInt>(LLVMModuleSet::getLLVMModuleSet()->getSVFValue(gi.getOperand())))
1363// {
1364// s32_t idx = ci->getSExtValue();
1365// ptr2vec.push_back(idx);
1366// }
1367// else
1368// return false;
1369// }
1370
1371// return ptr1vec==ptr2vec;
1372// }
1373
1382{
1383
1384 // const PTASCEV& forkse = fkjnToPTASCEVMap[forkSite];
1385 // const PTASCEV& joinse = fkjnToPTASCEVMap[joinSite];
1386
1387 // //if(sameLoopTripCount(forkSite,joinSite) == false)
1388 // // return false;
1389
1390 // if(forkse.inloop && joinse.inloop)
1391 // return forkse.start==joinse.start && forkse.step == joinse.step && forkse.tripcount <= joinse.tripcount;
1392 // else if(SVFUtil::isa<GetElementPtrInst>(forkse.ptr) && SVFUtil::isa<GetElementPtrInst>(joinse.ptr))
1393 // return accessSameArrayIndex(SVFUtil::cast<GetElementPtrInst>(forkse.ptr),SVFUtil::cast<GetElementPtrInst>(joinse.ptr));
1394 // else if(SVFUtil::isa<GetElementPtrInst, GetElementPtrInst>(joinse.ptr))
1395 // return false;
1396 // else
1397 // return true;
1398
1399 return false;
1400}
1401
1406{
1407
1408 // ScalarEvolution* forkSE = getSE(forkSite);
1409 // ScalarEvolution* joinSE = getSE(joinSite);
1410
1411 // if(tct->hasLoop(forkSite) == false || tct->hasLoop(joinSite) == false)
1412 // return false;
1413
1414 // // Get loops
1415 // const LoopBBs& forkSiteLoop = tct->getLoop(forkSite);
1416 // const LoopBBs& joinSiteLoop = tct->getLoop(joinSite);
1417
1418 // const SCEV* forkLoopCountScev = forkSE->getBackedgeTakenCount(forkSiteLoop);
1419 // const SCEV* joinLoopCountScev = joinSE->getBackedgeTakenCount(joinSiteLoop);
1420
1421 // if(forkLoopCountScev!=forkSE->getCouldNotCompute())
1422 // {
1423 // if(forkLoopCountScev==joinLoopCountScev)
1424 // {
1425 // return true;
1426 // }
1427 // }
1428 return false;
1429}
1430
1437
1438template void ForkJoinAnalysis::analyzeForkJoinPair<ICFG*, CallGraph*>(
1439 ICFG*, CallGraph*);
1443
1444// The two graphs the MHP analysis runs on; the algorithm above is written once
1445// and instantiated for both (all internal templates instantiate transitively).
1446template void MHP::analyze<ICFG*, CallGraph*>(ICFG*, CallGraph*);
1447template void MHP::analyze<const SlicedICFGView*, const SlicedThreadCallGraphView*>(const SlicedICFGView*, const SlicedThreadCallGraphView*);
#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
const FunObjVar * getFunction() const
Get function of this call node.
Definition CallGraph.h:191
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
Set< const FunObjVar * > FunctionSet
Definition CallGraph.h:247
const std::string toString() const override
Definition ICFG.cpp:129
const ICFGNode * getThread() const
Return forksite.
Definition CxtStmt.h:209
bool push(const Data &data)
Definition WorkList.h:180
bool empty() const
Definition WorkList.h:161
void addToFullJoin(NodeID tid1, NodeID tid2)
full join and partial join
Definition MHP.h:605
const SVFVar * getForkedThread(const CallICFGNode *call)
Get forked thread.
Definition MHP.h:569
void handleIntra(ICFGGraph icfg, const CxtStmt &cts)
Handle intra.
Definition MHP.cpp:1283
bool isAliasedForkJoin(const CallICFGNode *forkSite, const CallICFGNode *joinSite)
Whether it is a matched fork join pair.
Definition MHP.cpp:1431
ValDomain getMarkedFlag(const CxtStmt &cs)
Mark thread flags for cxtStmt.
Definition MHP.h:466
void addToHPPair(NodeID tid1, NodeID tid2)
Definition MHP.h:592
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition MHP.h:356
bool hasJoinLoop(const CallICFGNode *inst)
Definition MHP.h:420
void addSymmetricLoopJoin(const CxtStmt &cs, LoopBBs &lp)
Add inloop join.
Definition MHP.h:628
NodeBS getDirAndIndJoinedTid(const CxtStmt &cs)
Get directly and indirectly joined threadIDs based on a context-sensitive join site.
Definition MHP.cpp:1306
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
Definition MHP.h:545
void analyzeForkJoinPair(ICFGGraph icfg, CGGraph cg)
Definition MHP.cpp:962
CxtStmt popFromCTSWorkList()
Definition MHP.h:527
bool hasCxtStmtsFromInst(const ICFGNode *inst) const
Definition MHP.h:622
void addToHBPair(NodeID tid1, NodeID tid2)
Definition MHP.h:597
ThreadCallGraph * getTCG() const
ThreadCallGraph.
Definition MHP.h:579
void addToPartial(NodeID tid1, NodeID tid2)
Definition MHP.h:609
void collectSCEVInfo()
functions
Definition MHP.cpp:907
void clearFlagMap()
Clear flags.
Definition MHP.h:514
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens-before thread t2.
Definition MHP.h:401
void addDirectlyJoinTID(const CxtStmt &cs, NodeID tid)
maps a context-sensitive join site to a thread id
Definition MHP.h:584
const SVFVar * getJoinedThread(const CallICFGNode *call)
Get joined thread.
Definition MHP.h:574
LoopBBs & getJoinLoop(const CallICFGNode *inst)
Get loop for join site.
Definition MHP.h:416
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
Definition MHP.h:537
void handleRet(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts)
Handle return.
Definition MHP.cpp:1199
void handleFork(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts, NodeID rootTid)
Handle fork.
Definition MHP.cpp:1054
const CxtStmtToLoopMap & getSymmetricLoopJoins() const
All SCEV-symmetric in-loop joins and their loop blocks.
Definition MHP.h:425
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition MHP.h:557
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt call)
If lhs is a suffix of rhs, including equal.
Definition MHP.h:550
bool isFullJoin(NodeID tid1, NodeID tid2)
Whether t1 fully joins t2.
Definition MHP.h:408
CxtStmtToTIDMap dirAndIndJoinMap
maps a context-sensitive join site to directly and indirectly joined thread ids
Definition MHP.h:636
bool hasJoinInSymmetricLoop(const CxtStmt &cs) const
Definition MHP.h:395
bool sameLoopTripCount(const ICFGNode *forkSite, const ICFGNode *joinSite)
Same loop trip count.
Definition MHP.cpp:1405
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition MHP.h:563
void markCxtStmtFlag(const CxtStmt &tgr, ValDomain flag)
Initialize TDAlive and TDDead flags.
Definition MHP.h:478
CxtStmtWorkList cxtStmtList
context-sensitive statement worklist
Definition MHP.h:634
const LoopBBs & getJoinInSymmetricLoop(const CxtStmt &cs) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.h:389
ThreadAPI::ForkJoinAliasCache forkJoinAliasCache
Definition MHP.h:462
NodeBS & getDirectlyJoinedTid(const CxtStmt &cs)
Get directly joined threadIDs based on a context-sensitive join site.
Definition MHP.h:381
bool isSameSCEV(const ICFGNode *forkSite, const ICFGNode *joinSite)
Return true if the fork and join have the same SCEV.
Definition MHP.cpp:1381
void handleJoin(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts, NodeID rootTid)
Handle join.
Definition MHP.cpp:1086
void handleCall(ICFGGraph icfg, CGGraph cg, const CxtStmt &cts)
Handle call.
Definition MHP.cpp:1169
const CxtStmtSet & getCxtStmtsFromInst(const ICFGNode *inst) const
Get CxtStmtSet for an instruction.
Definition MHP.h:616
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
iterator InEdgeBegin()
iterator InEdgeEnd()
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:75
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
Definition ICFGNode.h:81
virtual const std::string toString() const
Definition ICFG.cpp:50
CxtThreadStmtWorkList cxtStmtList
CxtThreadStmt worklist.
Definition MHP.h:324
bool isRecurFullJoin(NodeID parentTid, NodeID curTid)
Thread curTid can be fully joined by parentTid recursively.
Definition MHP.cpp:684
bool isMultiForkedThread(NodeID curTid)
A thread is a multiForked thread if it is in a loop or recursion.
Definition MHP.h:257
void handleRet(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts)
Handle return.
Definition MHP.cpp:507
void rmInterleavingThread(const CxtThreadStmt &tgr, const NodeBS &tids, const ICFGNode *joinsite)
Definition MHP.h:229
virtual bool mayHappenInParallelCache(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:832
void analyze(ICFGGraph icfg, CGGraph cg)
Definition MHP.cpp:115
TCT * tct
TCT.
Definition MHP.h:322
BBToSymJoinsMap bbToSymJoins
Map a statement to its thread interleavings.
Definition MHP.h:326
FuncPairToBool nonCandidateFuncMHPRelMap
Definition MHP.h:332
NodeBS edgeFlow(const CxtThreadStmt &cts, const ICFGNode *dst)
Definition MHP.cpp:77
void printInterleaving()
Print interleaving results.
Definition MHP.cpp:887
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
Definition MHP.h:273
u32_t numOfTotalQueries
Total number of queries.
Definition MHP.h:335
Set< CxtThreadStmt > CxtThreadStmtSet
Definition MHP.h:57
void analyzeInterleaving(ICFGGraph icfg, CGGraph cg)
Analyze thread interleaving.
Definition MHP.cpp:129
MHP(TCT *t, StateRepresentation representation=StateRepresentation::MaterializedContexts)
Definition MHP.cpp:48
std::pair< const FunObjVar *, const FunObjVar * > FuncPair
Definition MHP.h:75
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition MHP.h:71
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt call)
If lhs is a suffix of rhs, including equal.
Definition MHP.h:278
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
StateRepresentation
Definition MHP.h:79
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
Definition MHP.h:265
ThreadCallGraph * tcg
TCG.
Definition MHP.h:321
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
InstToThreadStmtSetMap instToTSMap
Map an instruction to its ThreadStmtSet.
Definition MHP.h:328
virtual ~MHP()
Destructor.
Definition MHP.cpp:105
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens before t2 based on ForkJoin Analysis.
Definition MHP.cpp:754
ThreadStmtToThreadInterleav threadStmtToThreadInterLeav
Definition MHP.h:325
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition MHP.h:297
void addInterleavingBits(const CxtThreadStmt &tgr, const NodeBS &bits)
Definition MHP.h:220
virtual bool executedByTheSameThread(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:866
InstToThreadSummaryMap instToThreadSummary
Exact per-node/per-tid query compression.
Definition MHP.h:329
virtual bool mayHappenInParallel(const ICFGNode *i1, const ICFGNode *i2)
Interface to query whether two instructions may happen-in-parallel.
Definition MHP.cpp:854
void buildSymJoinKillTables()
Definition MHP.cpp:60
const CxtThreadStmtSet & getThreadStmtSet(const ICFGNode *inst) const
Get/has ThreadStmt.
Definition MHP.h:142
const LoopBBs & getJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.cpp:745
void handleJoin(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt &cts, NodeID rootTid)
Handle join.
Definition MHP.cpp:374
ForkJoinAnalysis * fja
ForJoin Analysis.
Definition MHP.h:323
const NodeThreadSummary * getThreadSummary(const ICFGNode *inst) const
Definition MHP.cpp:257
bool hasJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.cpp:738
void buildQuerySummaries(ICFGGraph icfg, CGGraph cg)
Definition MHP.cpp:201
bool hasThreadStmtSet(const ICFGNode *inst) const
Definition MHP.h:148
SymJoinToLoopMap symJoinLoop
symmetric in-loop join -> its loop's blocks
Definition MHP.h:327
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
void updateNonCandidateFunInterleaving(ICFGGraph icfg, CGGraph cg)
Definition MHP.cpp:275
bool isMustJoin(const NodeID curTid, const ICFGNode *joinsite)
Whether a join site must join a thread t.
Definition MHP.cpp:719
double interleavingTime
Definition MHP.h:337
Map< const ICFGNode *, const ICFGNode * > querySummaryOwner
Non-candidate node -> entry summary.
Definition MHP.h:330
bool isConnectedfromMain(const FunObjVar *fun)
Whether the function is connected from main function in thread call graph.
Definition MHP.cpp:759
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
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
virtual bool mayHappenInParallelInst(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:794
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition MHP.h:303
static const Option< bool > PrintInterLev
Definition Options.h:155
const_iterator end() const
const ICFGNode * back() const
static double getClk(bool mark=false)
Definition SVFStat.cpp:51
NodeID getId() const
Get ID.
Definition SVFValue.h:158
void set(unsigned Idx)
const CxtThread & getCxtThread() const
Get thread creation context, <fork site, call string context>
Definition TCT.h:103
const NodeBS getAncestorThreads(NodeID tid) const
Get all ancestor threads.
Definition TCT.h:336
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
Definition TCT.h:209
bool isJoinSiteInRecursion(const CallICFGNode *join) const
Whether a join site is in recursion.
Definition TCT.h:438
bool isCallSite(const ICFGNode *inst)
Whether it is a callsite.
Definition TCT.h:274
NodeBS getParentThreads(NodeID tid) const
Get parent threads.
Definition TCT.h:323
PointerAnalysis * getPTA() const
Get PTA.
Definition TCT.h:204
Set< const CallGraphNode * > PTACGNodeSet
Definition TCT.h:176
ThreadCreateEdgeSet::const_iterator getChildrenBegin(const TCTNode *node) const
Get children and parent nodes.
Definition TCT.h:220
bool hasTCTNode(const CxtThread &ct) const
Find/Get TCT node.
Definition TCT.h:281
const NodeBS getSiblingThread(NodeID tid) const
Get sibling threads.
Definition TCT.h:359
bool isCandidateFun(const CallGraph::FunctionSet &callees) const
Whether it is a candidate function for indirect call.
Definition TCT.h:294
bool isExtCall(const ICFGNode *inst)
Whether it is calling an external function.
Definition TCT.h:267
ThreadCreateEdgeSet::const_iterator getChildrenEnd(const TCTNode *node) const
Definition TCT.h:224
const FunObjVar * getStartRoutineOfCxtThread(const CxtThread &ct) const
get the start routine function of a thread
Definition TCT.h:388
const CallStrCxtSet & getCxtOfCxtThread(const CxtThread &ct) const
get the contexts of a thread at its spawning sites (fork sites)
Definition TCT.h:380
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.
Definition SVFUtil.cpp:446
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:105
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:441
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
void dumpSet(NodeBS To, OutStream &O=SVFUtil::outs())
Dump sparse bitvector set.
Definition SVFUtil.cpp:153
for isBitcode
Definition BasicTypes.h:70
u32_t NodeID
Definition GeneralType.h:76
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
std::vector< u32_t > CallStrCxt
Definition GeneralType.h:96