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 "Util/SVFUtil.h"
35#include "Util/PTAStat.h"
36
37using namespace SVF;
38using namespace SVFUtil;
39
40
44MHP::MHP(TCT* t) : tcg(t->getThreadCallGraph()), tct(t), numOfTotalQueries(0), numOfMHPQueries(0),
45 interleavingTime(0), interleavingQueriesTime(0)
46{
49}
50
55{
56 delete fja;
57}
58
63{
64 DBOUT(DGENERAL, outs() << pasMsg("MHP interleaving analysis\n"));
65 DBOUT(DMTA, outs() << pasMsg("MHP interleaving analysis\n"));
70}
71
76{
77 for (const std::pair<const NodeID, TCTNode*>& tpair : *tct)
78 {
79 const CxtThread& ct = tpair.second->getCxtThread();
80 NodeID rootTid = tpair.first;
82 const ICFGNode* svfInst = routine->getEntryBlock()->front();
83 CxtThreadStmt rootcts(rootTid, ct.getContext(), svfInst);
84
88
89 while (!cxtStmtList.empty())
90 {
92 const ICFGNode* curInst = cts.getStmt();
93 DBOUT(DMTA, outs() << "-----\nMHP analysis root thread: " << rootTid << " ");
94 DBOUT(DMTA, cts.dump());
95 DBOUT(DMTA, outs() << "current thread interleaving: < ");
97 DBOUT(DMTA, outs() << " >\n-----\n");
98
100 if (!tct->isCandidateFun(curInst->getFun()))
101 {
103 }
105 else
106 {
107 if (isTDFork(curInst))
108 {
110 }
111 else if (isTDJoin(curInst))
112 {
114 }
115 else if (tct->isCallSite(curInst) && !tct->isExtCall(curInst))
116 {
119 if (!tct->isCandidateFun(getCallee(SVFUtil::cast<CallICFGNode>(curInst), callees)))
121 }
122 else if (isRetInstNode(curInst))
123 {
124 handleRet(cts);
125 }
126 else
127 {
129 }
130 }
131 }
132 }
133
136
139}
140
145{
146 SVFModule* module = tct->getSVFModule();
147 for (const SVFFunction* fun : module->getFunctionSet())
148 {
149 if (!tct->isCandidateFun(fun) && !isExtCall(fun))
150 {
151 const ICFGNode* entryNode = fun->getEntryBlock()->front();
152
154 continue;
155
157
158 for (const CxtThreadStmt& cts : tsSet)
159 {
160 const CallStrCxt& curCxt = cts.getContext();
161
162 for (const SVFBasicBlock* svfbb : fun->getBasicBlockList())
163 {
164 for (const ICFGNode* curNode : svfbb->getICFGNodeList())
165 {
166 if (curNode == entryNode)
167 continue;
170 instToTSMap[curNode].insert(newCts);
171 }
172 }
173 }
174 }
175 }
176}
177
182{
183 const ICFGNode* curInst = cts.getStmt();
184 const SVFFunction* curfun = curInst->getFun();
185 assert((curInst == curfun->getEntryBlock()->front()) && "curInst is not the entry of non candidate function.");
186 const CallStrCxt& curCxt = cts.getContext();
189 {
190 const SVFFunction* callee = (*nit)->getDstNode()->getFunction();
191 if (!isExtCall(callee))
192 {
193 const ICFGNode* calleeInst = callee->getEntryBlock()->front();
196 }
197 }
198}
199
204{
205
206 const ICFGNode* call = cts.getStmt();
207 const CallStrCxt& curCxt = cts.getContext();
208
209 assert(isTDFork(call));
210 const CallICFGNode* cbn = cast<CallICFGNode>(call);
212 {
213
214 for (ThreadCallGraph::ForkEdgeSet::const_iterator cgIt = tcg->getForkEdgeBegin(cbn),
216 cgIt != ecgIt; ++cgIt)
217 {
218 const SVFFunction* svfroutine = (*cgIt)->getDstNode()->getFunction();
221 const ICFGNode* stmt = svfroutine->getEntryBlock()->front();
222 CxtThread ct(newCxt, call);
223 CxtThreadStmt newcts(tct->getTCTNode(ct)->getId(), ct.getContext(), stmt);
225 }
226 }
228}
229
234{
235
236 const CallStrCxt& curCxt = cts.getContext();
237
238 assert(isTDJoin(cts.getStmt()));
239
240 const CallICFGNode* call = SVFUtil::cast<CallICFGNode>(cts.getStmt());
241
243 if (!joinedTids.empty())
244 {
245 if (fja->hasJoinLoop(call))
246 {
247 std::vector<const SVFBasicBlock*> exitbbs;
248 call->getFun()->getExitBlocksOfLoop(call->getBB(), exitbbs);
249 while (!exitbbs.empty())
250 {
251 const SVFBasicBlock* eb = exitbbs.back();
252 exitbbs.pop_back();
253 const ICFGNode* svfEntryInst = eb->front();
258 }
259 }
260 else
261 {
263 DBOUT(DMTA, outs() << "\n\t match join site " << call->toString() << " for thread " << rootTid << "\n");
264 }
265 }
268 else
269 {
270 if (fja->hasJoinLoop(call))
271 {
272 std::vector<const SVFBasicBlock*> exitbbs;
273 call->getFun()->getExitBlocksOfLoop(call->getBB(), exitbbs);
274 while (!exitbbs.empty())
275 {
276 const SVFBasicBlock* eb = exitbbs.back();
277 exitbbs.pop_back();
278 const ICFGNode* svfEntryInst = eb->front();
279 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), svfEntryInst);
281 }
282 }
283 }
285}
286
291{
292
293 const ICFGNode* call = cts.getStmt();
294 const CallStrCxt& curCxt = cts.getContext();
295 const CallICFGNode* cbn = cast<CallICFGNode>(call);
297 {
298 for (PTACallGraph::CallGraphEdgeSet::const_iterator cgIt = tcg->getCallEdgeBegin(cbn),
300 cgIt != ecgIt; ++cgIt)
301 {
302
303 const SVFFunction* svfcallee = (*cgIt)->getDstNode()->getFunction();
304 if (isExtCall(svfcallee))
305 continue;
307 const CallICFGNode* callicfgnode = SVFUtil::cast<CallICFGNode>(call);
309 const ICFGNode* svfEntryInst = svfcallee->getEntryBlock()->front();
312 }
313 }
314}
315
320{
321 PTACallGraphNode* curFunNode = tcg->getCallGraphNode(cts.getStmt()->getFun());
322 for (PTACallGraphEdge* edge : curFunNode->getInEdges())
323 {
324 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edge))
325 continue;
326 for (PTACallGraphEdge::CallInstSet::const_iterator cit = (edge)->directCallsBegin(),
327 ecit = (edge)->directCallsEnd();
328 cit != ecit; ++cit)
329 {
330 CallStrCxt newCxt = cts.getContext();
331 if (matchCxt(newCxt, *cit, curFunNode->getFunction()))
332 {
333 for(const ICFGEdge* outEdge : cts.getStmt()->getOutEdges())
334 {
335 if(outEdge->getDstNode()->getFun() == cts.getStmt()->getFun())
336 {
337 CxtThreadStmt newCts(cts.getTid(), newCxt, outEdge->getDstNode());
339 }
340 }
341 }
342 }
343 for (PTACallGraphEdge::CallInstSet::const_iterator cit = (edge)->indirectCallsBegin(),
344 ecit = (edge)->indirectCallsEnd();
345 cit != ecit; ++cit)
346 {
347 CallStrCxt newCxt = cts.getContext();
348 if (matchCxt(newCxt, *cit, curFunNode->getFunction()))
349 {
350 for(const ICFGEdge* outEdge : cts.getStmt()->getOutEdges())
351 {
352 if(outEdge->getDstNode()->getFun() == cts.getStmt()->getFun())
353 {
354 CxtThreadStmt newCts(cts.getTid(), newCxt, outEdge->getDstNode());
356 }
357 }
358 }
359 }
360 }
361}
362
367{
368
369 for(const ICFGEdge* outEdge : cts.getStmt()->getOutEdges())
370 {
371 if(outEdge->getDstNode()->getFun() == cts.getStmt()->getFun())
372 {
373 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), outEdge->getDstNode());
375 }
376 }
377}
378
383{
385 DBOUT(DMTA, outs() << "##Ancestor thread of " << curTid << " is : ");
387 DBOUT(DMTA, outs() << "\n");
388 tds.set(curTid);
389
390 for (const unsigned i : tds)
391 {
392 const CxtThread& ct = tct->getTCTNode(i)->getCxtThread();
393 if (const ICFGNode* forkInst = ct.getThread())
394 {
396 for(const ICFGEdge* outEdge : forkInst->getOutEdges())
397 {
398 if(outEdge->getDstNode()->getFun() == forkInst->getFun())
399 {
402 }
403 }
404 }
405 }
406}
407
419{
421 tds.set(curTid);
422 for (const unsigned tid : tds)
423 {
425 for (const unsigned stid : siblingTds)
426 {
427 if ((isHBPair(tid, stid) && isRecurFullJoin(tid, curTid)) || isHBPair(stid, tid))
428 continue;
429
432 const ICFGNode* stmt = routine->getEntryBlock()->front();
433 CxtThreadStmt cts(stid, ct.getContext(), stmt);
435 }
436
437 DBOUT(DMTA, outs() << "##Sibling thread of " << curTid << " is : ");
439 DBOUT(DMTA, outs() << "\n");
440 }
441}
442
447{
448 if (parentTid == curTid)
449 return true;
450
453 worklist.push(curNode);
454 while (!worklist.empty())
455 {
456 const TCTNode* node = worklist.pop();
457 for (TCTEdge* edge : node->getInEdges())
458 {
459 NodeID srcID = edge->getSrcID();
460 if (fja->isFullJoin(srcID, node->getId()))
461 {
462 if (srcID == parentTid)
463 return true;
464 else
465 worklist.push(edge->getSrcNode());
466 }
467 else
468 {
469 return false;
470 }
471 }
472 }
473 return false;
474}
475
482{
483 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(joinsite);
484 assert(call && isTDJoin(call) && "not a join site!");
486}
487
492{
493 CxtStmt cs(cxt, call);
494 return fja->getDirAndIndJoinedTid(cs);
495}
496
500bool MHP::hasJoinInSymmetricLoop(const CallStrCxt& cxt, const ICFGNode* call) const
501{
502 CxtStmt cs(cxt, call);
503 return fja->hasJoinInSymmetricLoop(cs);
504}
505
507const MHP::LoopBBs& MHP::getJoinInSymmetricLoop(const CallStrCxt& cxt, const ICFGNode* call) const
508{
509 CxtStmt cs(cxt, call);
510 return fja->getJoinInSymmetricLoop(cs);
511}
512
517{
518 return fja->isHBPair(tid1, tid2);
519}
520
522{
525 TCT::PTACGNodeSet visited;
526 worklist.push(cgnode);
527 visited.insert(cgnode);
528 while (!worklist.empty())
529 {
530 const PTACallGraphNode* node = worklist.pop();
531 if ("main" == node->getFunction()->getName())
532 return true;
533 for (PTACallGraphNode::const_iterator nit = node->InEdgeBegin(), neit = node->InEdgeEnd(); nit != neit; nit++)
534 {
535 const PTACallGraphNode* srcNode = (*nit)->getSrcNode();
536 if (visited.find(srcNode) == visited.end())
537 {
538 visited.insert(srcNode);
539 worklist.push(srcNode);
540 }
541 }
542 }
543 return false;
544}
545
557{
558
561 return false;
562
565 for (const CxtThreadStmt& ts1 : tsSet1)
566 {
568 for (const CxtThreadStmt& ts2 : tsSet2)
569 {
571 if (ts1.getTid() != ts2.getTid())
572 {
573 if (l1.test(ts2.getTid()) && l2.test(ts1.getTid()))
574 {
576 return true;
577 }
578 }
579 else
580 {
581 if (isMultiForkedThread(ts1.getTid()))
582 {
584 return true;
585 }
586 }
587 }
588 }
589 return false;
590}
591
593{
594 if (!tct->isCandidateFun(i1->getFun()) && !tct->isCandidateFun(i2->getFun()))
595 {
596 FuncPair funpair = std::make_pair(i1->getFun(), i2->getFun());
597 FuncPairToBool::const_iterator it = nonCandidateFuncMHPRelMap.find(funpair);
598 if (it == nonCandidateFuncMHPRelMap.end())
599 {
600 bool mhp = mayHappenInParallelInst(i1, i2);
602 return mhp;
603 }
604 else
605 {
606 if (it->second)
608 return it->second;
609 }
610 }
612}
613
615{
617
618 DOTIMESTAT(double queryStart = PTAStat::getClk(true));
619 bool mhp = mayHappenInParallelCache(i1, i2);
620 DOTIMESTAT(double queryEnd = PTAStat::getClk(true));
622
623 return mhp;
624}
625
627{
629 return true;
630
633 for (const CxtThreadStmt&ts1 : tsSet1)
634 {
635 for (const CxtThreadStmt& ts2 : tsSet2)
636 {
637 if (ts1.getTid() != ts2.getTid() || isMultiForkedThread(ts1.getTid()))
638 return false;
639 }
640 }
641 return true;
642}
643
648{
649 for (const auto& pair : threadStmtToTheadInterLeav)
650 {
651 outs() << "( t" << pair.first.getTid()
652 << pair.first.getStmt()->toString() << " ) ==> [";
653 for (unsigned i : pair.second)
654 {
655 outs() << " " << i << " ";
656 }
657 outs() << "]\n";
658 }
659}
660
668{
669 // typedef Set<const ICFGNode*> CallInstSet;
670 // typedef Map<const SVFFunction*, CallInstSet> FunToFJSites;
671 // FunToFJSites funToFJSites;
672
673 // for (ThreadCallGraph::CallSiteSet::const_iterator it = tct->getThreadCallGraph()->forksitesBegin(),
674 // eit = tct->getThreadCallGraph()->forksitesEnd();
675 // it != eit; ++it)
676 // {
677 // const ICFGNode* fork = *it;
678 // funToFJSites[fork->getFun()].insert(fork);
679 // }
680
681 // for (ThreadCallGraph::CallSiteSet::const_iterator it = tct->getThreadCallGraph()->joinsitesBegin(),
682 // eit = tct->getThreadCallGraph()->joinsitesEnd();
683 // it != eit; ++it)
684 // {
685 // const ICFGNode* join = *it;
686 // funToFJSites[join->getFun()].insert(join);
687 // }
688
689 // for(FunToFJSites::const_iterator it = funToFJSites.begin(), eit = funToFJSites.end(); it!=eit; ++it)
690 // {
691 // // ScalarEvolution* SE = MTA::getSE(it->first);
692 // for(CallInstSet::const_iterator sit = it->second.begin(), esit = it->second.end(); sit!=esit; ++sit)
693 // {
694 // const SVFInstruction* callInst = *sit;
695 // if(tct->getThreadCallGraph()->isForksite(getCBN(callInst)))
696 // {
697 // // const SVFValue* forkSiteTidPtr = getForkedThread(callInst);
698 // // const SCEV *forkSiteTidPtrSCEV = SE->getSCEV(const_cast<Value*>(forkSiteTidPtr));
699 // // const SCEV *baseForkTidPtrSCEV = SE->getSCEV(const_cast<Value*>(getBasePtr(forkSiteTidPtr)));
700 // // forkSiteTidPtrSCEV = getSCEVMinusExpr(forkSiteTidPtrSCEV, baseForkTidPtrSCEV, SE);
701 // // PTASCEV scev(forkSiteTidPtr,nullptr,nullptr);
702 // // fkjnToPTASCEVMap.insert(std::make_pair(callInst,scev));
703 // }
704 // else
705 // {
706 // // const SVFValue* joinSiteTidPtr = getJoinedThread(callInst);
707 // //const SCEV *joinSiteTidPtrSCEV = SE->getSCEV(const_cast<Value*>(joinSiteTidPtr));
708 // //const SCEV *baseJoinTidPtrSCEV = SE->getSCEV(const_cast<Value*>(getBasePtr(joinSiteTidPtr)));
709 // //joinSiteTidPtrSCEV = getSCEVMinusExpr(joinSiteTidPtrSCEV, baseJoinTidPtrSCEV, SE);
710
711 // // PTASCEV scev(joinSiteTidPtr,nullptr,nullptr);
712 // // fkjnToPTASCEVMap.insert(std::make_pair(callInst,scev));
713 // }
714 // }
715 // }
716}
717
722{
723 for (const std::pair<const NodeID, TCTNode*>& tpair : *tct)
724 {
725 const CxtThread& ct = tpair.second->getCxtThread();
726 const NodeID rootTid = tpair.first;
727 clearFlagMap();
728 if (const ICFGNode* forkInst = ct.getThread())
729 {
732
733 for(const ICFGEdge* outEdge : forkInst->getOutEdges())
734 {
735 if(outEdge->getDstNode()->getFun() == forkInst->getFun())
736 {
737 CxtStmt newCts(forkSiteCxt, outEdge->getDstNode());
739 }
740 }
741
742 while (!cxtStmtList.empty())
743 {
745 const ICFGNode* curInst = cts.getStmt();
746 DBOUT(DMTA, outs() << "-----\nForkJoinAnalysis root thread: " << tpair.first << " ");
747 DBOUT(DMTA, cts.dump());
748 DBOUT(DMTA, outs() << "-----\n");
750 if (isTDFork(curInst))
751 {
753 }
754 else if (isTDJoin(curInst))
755 {
757 }
759 {
760
762 }
763 else if (isRetInstNode(curInst))
764 {
765 handleRet(cts);
766 }
767 else
768 {
770 }
771
772 if (curInst == exitInst)
773 {
774 if (getMarkedFlag(cts) != TDAlive)
776 else
778 }
779 }
780 }
781 }
782}
783
786{
787 const ICFGNode* call = cts.getStmt();
788 const CallStrCxt& curCxt = cts.getContext();
789
790 assert(isTDFork(call));
791 const CallICFGNode* cbn = cast<CallICFGNode>(call);
792 if (getTCG()->hasThreadForkEdge(cbn))
793 {
794 for (ThreadCallGraph::ForkEdgeSet::const_iterator cgIt = getTCG()->getForkEdgeBegin(cbn),
795 ecgIt = getTCG()->getForkEdgeEnd(cbn);
796 cgIt != ecgIt; ++cgIt)
797 {
798 const SVFFunction* callee = (*cgIt)->getDstNode()->getFunction();
801 CxtThread ct(newCxt, call);
802 if (getMarkedFlag(cts) != TDAlive)
804 else
806 }
807 }
809}
810
813{
814 const ICFGNode* call = cts.getStmt();
815 const CallStrCxt& curCxt = cts.getContext();
816
817 assert(isTDJoin(call));
818 const CallICFGNode* cbn = cast<CallICFGNode>(call);
819 if (getTCG()->hasCallGraphEdge(cbn))
820 {
822 const ICFGNode* joinSite = cts.getStmt();
823
824 if (isAliasedForkJoin(SVFUtil::cast<CallICFGNode>(forkSite), SVFUtil::cast<CallICFGNode>(joinSite)))
825 {
826 if (hasJoinLoop(SVFUtil::cast<CallICFGNode>(forkSite)))
827 {
828 LoopBBs& joinLoop = getJoinLoop(SVFUtil::cast<CallICFGNode>(forkSite));
829 std::vector<const SVFBasicBlock *> exitbbs;
830 joinSite->getFun()->getExitBlocksOfLoop(joinSite->getBB(), exitbbs);
831 while (!exitbbs.empty())
832 {
833 const SVFBasicBlock* eb = exitbbs.back();
834 exitbbs.pop_back();
835 const ICFGNode* svfEntryInst = eb->front();
839 {
842 }
843 else
845 }
846 }
847 else
848 {
851 DBOUT(DMTA, outs() << "\n\t match join site " << call->toString() << "for thread " << rootTid << "\n");
852 }
853 }
856 else
857 {
858 if (hasJoinLoop(SVFUtil::cast<CallICFGNode>(forkSite)))
859 {
860 std::vector<const SVFBasicBlock*> exitbbs;
861 joinSite->getFun()->getExitBlocksOfLoop(joinSite->getBB(), exitbbs);
862 while (!exitbbs.empty())
863 {
864 const SVFBasicBlock* eb = exitbbs.back();
865 exitbbs.pop_back();
866 const ICFGNode* svfEntryInst = eb->front();
869 }
870 }
871 }
872 }
874}
875
878{
879
880 const ICFGNode* call = cts.getStmt();
881 const CallStrCxt& curCxt = cts.getContext();
882 const CallICFGNode* cbn = SVFUtil::cast<CallICFGNode>(call);
883 if (getTCG()->hasCallGraphEdge(cbn))
884 {
885 for (PTACallGraph::CallGraphEdgeSet::const_iterator cgIt = getTCG()->getCallEdgeBegin(cbn),
886 ecgIt = getTCG()->getCallEdgeEnd(cbn);
887 cgIt != ecgIt; ++cgIt)
888 {
889 const SVFFunction* svfcallee = (*cgIt)->getDstNode()->getFunction();
890 if (isExtCall(svfcallee))
891 continue;
894 const ICFGNode* svfEntryInst = svfcallee->getEntryBlock()->front();
897 }
898 }
899}
900
903{
904 const ICFGNode* curInst = cts.getStmt();
905 const CallStrCxt& curCxt = cts.getContext();
906
908 for (PTACallGraphEdge* edge : curFunNode->getInEdges())
909 {
910 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edge))
911 continue;
912 for (PTACallGraphEdge::CallInstSet::const_iterator cit = edge->directCallsBegin(),
913 ecit = edge->directCallsEnd();
914 cit != ecit; ++cit)
915 {
917 const ICFGNode* curNode = (*cit);
918 if (matchCxt(newCxt, SVFUtil::cast<CallICFGNode>(curNode), curFunNode->getFunction()))
919 {
920 for(const ICFGEdge* outEdge : curNode->getOutEdges())
921 {
922 if(outEdge->getDstNode()->getFun() == curNode->getFun())
923 {
924 CxtStmt newCts(newCxt, outEdge->getDstNode());
926 }
927 }
928 }
929 }
930 for (PTACallGraphEdge::CallInstSet::const_iterator cit = edge->indirectCallsBegin(),
931 ecit = edge->indirectCallsEnd();
932 cit != ecit; ++cit)
933 {
935 const ICFGNode* curNode = (*cit);
936
937 if (matchCxt(newCxt, SVFUtil::cast<CallICFGNode>(curNode), curFunNode->getFunction()))
938 {
939 for(const ICFGEdge* outEdge : curNode->getOutEdges())
940 {
941 if(outEdge->getDstNode()->getFun() == curNode->getFun())
942 {
943 CxtStmt newCts(newCxt, outEdge->getDstNode());
945 }
946 }
947 }
948 }
949 }
950}
951
954{
955
956 const ICFGNode* curInst = cts.getStmt();
957 const CallStrCxt& curCxt = cts.getContext();
958
959 for(const ICFGEdge* outEdge : curInst->getOutEdges())
960 {
961 if(outEdge->getDstNode()->getFun() == curInst->getFun())
962 {
963 CxtStmt newCts(curCxt, outEdge->getDstNode());
965 }
966 }
967}
968
975{
976
977 CxtStmtToTIDMap::const_iterator it = dirAndIndJoinMap.find(cs);
978 if (it != dirAndIndJoinMap.end())
979 return it->second;
980
983
984 FIFOWorkList<NodeID> worklist;
985 for (unsigned id : directJoinTids)
986 {
987 worklist.push(id);
988 }
989
990 while (!worklist.empty())
991 {
992 NodeID tid = worklist.pop();
993 TCTNode* node = tct->getTCTNode(tid);
994 for (TCT::ThreadCreateEdgeSet::const_iterator it = tct->getChildrenBegin(node), eit = tct->getChildrenEnd(node); it != eit; ++it)
995 {
996 NodeID childTid = (*it)->getDstID();
997 if (isFullJoin(tid, childTid))
998 {
1000 worklist.push(childTid);
1001 }
1002 }
1003 }
1004
1006
1007 return allJoinTids;
1008}
1009
1010// static bool accessSameArrayIndex(const GetElementPtrInst* ptr1, const GetElementPtrInst* ptr2)
1011// {
1012
1013// std::vector<u32_t> ptr1vec;
1014// for (gep_type_iterator gi = gep_type_begin(*ptr1), ge = gep_type_end(*ptr1);
1015// gi != ge; ++gi)
1016// {
1017// if(SVFConstantInt* ci = SVFUtil::dyn_cast<SVFConstantInt>(LLVMModuleSet::getLLVMModuleSet()->getSVFValue(gi.getOperand())))
1018// {
1019// s32_t idx = ci->getSExtValue();
1020// ptr1vec.push_back(idx);
1021// }
1022// else
1023// return false;
1024// }
1025
1026// std::vector<u32_t> ptr2vec;
1027// for (gep_type_iterator gi = gep_type_begin(*ptr2), ge = gep_type_end(*ptr2);
1028// gi != ge; ++gi)
1029// {
1030// if(SVFConstantInt* ci = SVFUtil::dyn_cast<SVFConstantInt>(LLVMModuleSet::getLLVMModuleSet()->getSVFValue(gi.getOperand())))
1031// {
1032// s32_t idx = ci->getSExtValue();
1033// ptr2vec.push_back(idx);
1034// }
1035// else
1036// return false;
1037// }
1038
1039// return ptr1vec==ptr2vec;
1040// }
1041
1050{
1051
1052 // const PTASCEV& forkse = fkjnToPTASCEVMap[forkSite];
1053 // const PTASCEV& joinse = fkjnToPTASCEVMap[joinSite];
1054
1055 // //if(sameLoopTripCount(forkSite,joinSite) == false)
1056 // // return false;
1057
1058 // if(forkse.inloop && joinse.inloop)
1059 // return forkse.start==joinse.start && forkse.step == joinse.step && forkse.tripcount <= joinse.tripcount;
1060 // else if(SVFUtil::isa<GetElementPtrInst>(forkse.ptr) && SVFUtil::isa<GetElementPtrInst>(joinse.ptr))
1061 // return accessSameArrayIndex(SVFUtil::cast<GetElementPtrInst>(forkse.ptr),SVFUtil::cast<GetElementPtrInst>(joinse.ptr));
1062 // else if(SVFUtil::isa<GetElementPtrInst, GetElementPtrInst>(joinse.ptr))
1063 // return false;
1064 // else
1065 // return true;
1066
1067 return false;
1068}
1069
1074{
1075
1076 // ScalarEvolution* forkSE = getSE(forkSite);
1077 // ScalarEvolution* joinSE = getSE(joinSite);
1078
1079 // if(tct->hasLoop(forkSite) == false || tct->hasLoop(joinSite) == false)
1080 // return false;
1081
1082 // // Get loops
1083 // const LoopBBs& forkSiteLoop = tct->getLoop(forkSite);
1084 // const LoopBBs& joinSiteLoop = tct->getLoop(joinSite);
1085
1086 // const SCEV* forkLoopCountScev = forkSE->getBackedgeTakenCount(forkSiteLoop);
1087 // const SCEV* joinLoopCountScev = joinSE->getBackedgeTakenCount(joinSiteLoop);
1088
1089 // if(forkLoopCountScev!=forkSE->getCouldNotCompute())
1090 // {
1091 // if(forkLoopCountScev==joinLoopCountScev)
1092 // {
1093 // return true;
1094 // }
1095 // }
1096 return false;
1097}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:484
#define TIMEINTERVAL
Definition SVFType.h:512
#define DMTA
Definition SVFType.h:505
#define DGENERAL
Definition SVFType.h:490
#define DOTIMESTAT(X)
Definition SVFType.h:486
const std::string toString() const override
Definition ICFG.cpp:131
const ICFGNode * getThread() const
Return forksite.
Definition CxtStmt.h:211
bool push(const Data &data)
Definition WorkList.h:165
bool empty() const
Definition WorkList.h:146
void addToFullJoin(NodeID tid1, NodeID tid2)
full join and partial join
Definition MHP.h:517
const PTACallGraph::FunctionSet & getCallee(const ICFGNode *inst, PTACallGraph::FunctionSet &callees)
Definition MHP.h:485
ValDomain getMarkedFlag(const CxtStmt &cs)
Mark thread flags for cxtStmt.
Definition MHP.h:389
void addToHPPair(NodeID tid1, NodeID tid2)
Definition MHP.h:504
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition MHP.h:285
void analyzeForkJoinPair()
Definition MHP.cpp:721
bool hasJoinLoop(const CallICFGNode *inst)
Definition MHP.h:354
void addSymmetricLoopJoin(const CxtStmt &cs, LoopBBs &lp)
Add inloop join.
Definition MHP.h:528
void handleRet(const CxtStmt &cts)
Handle return.
Definition MHP.cpp:902
NodeBS getDirAndIndJoinedTid(const CxtStmt &cs)
Get directly and indirectly joined threadIDs based on a context-sensitive join site.
Definition MHP.cpp:974
bool matchCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Match context.
Definition MHP.h:458
CxtStmt popFromCTSWorkList()
Definition MHP.h:445
void addToHBPair(NodeID tid1, NodeID tid2)
Definition MHP.h:509
ThreadCallGraph * getTCG() const
ThreadCallGraph.
Definition MHP.h:491
void addToPartial(NodeID tid1, NodeID tid2)
Definition MHP.h:521
void collectSCEVInfo()
functions
Definition MHP.cpp:667
void clearFlagMap()
Clear flags.
Definition MHP.h:432
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Push calling context.
Definition MHP.h:453
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens-before thread t2.
Definition MHP.h:326
void addDirectlyJoinTID(const CxtStmt &cs, NodeID tid)
maps a context-sensitive join site to a thread id
Definition MHP.h:496
LoopBBs & getJoinLoop(const CallICFGNode *inst)
Get loop for join site.
Definition MHP.h:350
const ICFGNode * getExitInstOfParentRoutineFun(NodeID tid) const
Get exit instruction of the start routine function of tid's parent thread.
Definition MHP.h:341
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition MHP.h:464
bool isFullJoin(NodeID tid1, NodeID tid2)
Whether t1 fully joins t2.
Definition MHP.h:333
CxtStmtToTIDMap dirAndIndJoinMap
maps a context-sensitive join site to directly and indirectly joined thread ids
Definition MHP.h:536
void handleCall(const CxtStmt &cts, NodeID rootTid)
Handle call.
Definition MHP.cpp:877
bool hasJoinInSymmetricLoop(const CxtStmt &cs) const
Definition MHP.h:320
bool sameLoopTripCount(const ICFGNode *forkSite, const ICFGNode *joinSite)
Same loop trip count.
Definition MHP.cpp:1073
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition MHP.h:470
void markCxtStmtFlag(const CxtStmt &tgr, ValDomain flag)
Initialize TDAlive and TDDead flags.
Definition MHP.h:401
CxtStmtWorkList cxtStmtList
context-sensitive statement worklist
Definition MHP.h:534
const LoopBBs & getJoinInSymmetricLoop(const CxtStmt &cs) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.h:314
bool isAliasedForkJoin(const CallICFGNode *forkSite, const CallICFGNode *joinSite)
Whether it is a matched fork join pair.
Definition MHP.h:382
void handleIntra(const CxtStmt &cts)
Handle intra.
Definition MHP.cpp:953
void handleFork(const CxtStmt &cts, NodeID rootTid)
Handle fork.
Definition MHP.cpp:785
NodeBS & getDirectlyJoinedTid(const CxtStmt &cs)
Get directly joined threadIDs based on a context-sensitive join site.
Definition MHP.h:306
void handleJoin(const CxtStmt &cts, NodeID rootTid)
Handle join.
Definition MHP.cpp:812
bool isSameSCEV(const ICFGNode *forkSite, const ICFGNode *joinSite)
Return true if the fork and join have the same SCEV.
Definition MHP.cpp:1049
iterator OutEdgeEnd()
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
GEdgeSetTy::const_iterator const_iterator
iterator InEdgeBegin()
iterator InEdgeEnd()
virtual const SVFFunction * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:76
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
Definition ICFGNode.h:82
virtual const std::string toString() const
Definition ICFG.cpp:61
void analyze()
Start analysis here.
Definition MHP.cpp:62
CxtThreadStmtWorkList cxtStmtList
CxtThreadStmt worklist.
Definition MHP.h:255
bool isRecurFullJoin(NodeID parentTid, NodeID curTid)
Thread curTid can be fully joined by parentTid recursively.
Definition MHP.cpp:446
bool isMultiForkedThread(NodeID curTid)
A thread is a multiForked thread if it is in a loop or recursion.
Definition MHP.h:200
void rmInterleavingThread(const CxtThreadStmt &tgr, const NodeBS &tids, const ICFGNode *joinsite)
Definition MHP.h:172
virtual bool mayHappenInParallelCache(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:592
TCT * tct
TCT.
Definition MHP.h:253
FuncPairToBool nonCandidateFuncMHPRelMap
Definition MHP.h:258
void printInterleaving()
Print interleaving results.
Definition MHP.cpp:647
void updateSiblingThreads(NodeID tid)
Definition MHP.cpp:418
u32_t numOfTotalQueries
Total number of queries.
Definition MHP.h:262
Set< CxtThreadStmt > CxtThreadStmtSet
Definition MHP.h:51
void handleNonCandidateFun(const CxtThreadStmt &cts)
Handle non-candidate function.
Definition MHP.cpp:181
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition MHP.h:54
void handleJoin(const CxtThreadStmt &cts, NodeID rootTid)
Handle join.
Definition MHP.cpp:233
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Push calling context.
Definition MHP.h:205
ThreadCallGraph * tcg
TCG.
Definition MHP.h:252
void addInterleavingThread(const CxtThreadStmt &tgr, NodeID tid)
Add/Remove interleaving thread for statement inst.
Definition MHP.h:155
const NodeBS & getInterleavingThreads(const CxtThreadStmt &cts)
Get interleaving thread for statement inst.
Definition MHP.h:97
InstToThreadStmtSetMap instToTSMap
Map a statement to its thread interleavings.
Definition MHP.h:257
virtual ~MHP()
Destructor.
Definition MHP.cpp:54
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens before t2 based on ForkJoin Analysis.
Definition MHP.cpp:516
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition MHP.h:228
void handleRet(const CxtThreadStmt &cts)
Handle return.
Definition MHP.cpp:319
virtual bool executedByTheSameThread(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:626
bool matchCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Match context.
Definition MHP.h:210
virtual bool mayHappenInParallel(const ICFGNode *i1, const ICFGNode *i2)
Interface to query whether two instructions may happen-in-parallel.
Definition MHP.cpp:614
const CxtThreadStmtSet & getThreadStmtSet(const ICFGNode *inst) const
Get/has ThreadStmt.
Definition MHP.h:109
void handleFork(const CxtThreadStmt &cts, NodeID rootTid)
Handle fork.
Definition MHP.cpp:203
const LoopBBs & getJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.cpp:507
bool isConnectedfromMain(const SVFFunction *fun)
Whether the function is connected from main function in thread call graph.
Definition MHP.cpp:521
ForkJoinAnalysis * fja
ForJoin Analysis.
Definition MHP.h:254
bool hasJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.cpp:500
bool hasThreadStmtSet(const ICFGNode *inst) const
Definition MHP.h:115
double interleavingQueriesTime
Definition MHP.h:265
u32_t numOfMHPQueries
Number of queries are answered as may-happen-in-parallel.
Definition MHP.h:263
void updateNonCandidateFunInterleaving()
Definition MHP.cpp:144
MHP(TCT *t)
Constructor.
Definition MHP.cpp:44
bool isMustJoin(const NodeID curTid, const ICFGNode *joinsite)
Whether a join site must join a thread t.
Definition MHP.cpp:481
double interleavingTime
Definition MHP.h:264
std::pair< const SVFFunction *, const SVFFunction * > FuncPair
Definition MHP.h:58
CxtThreadStmt popFromCTSWorkList()
Definition MHP.h:221
const PTACallGraph::FunctionSet & getCallee(const CallICFGNode *inst, PTACallGraph::FunctionSet &callees)
Definition MHP.h:126
void analyzeInterleaving()
Analyze thread interleaving.
Definition MHP.cpp:75
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:491
void updateAncestorThreads(NodeID tid)
Update Ancestor and sibling threads.
Definition MHP.cpp:382
virtual bool mayHappenInParallelInst(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:556
void handleIntra(const CxtThreadStmt &cts)
Handle intra.
Definition MHP.cpp:366
void handleCall(const CxtThreadStmt &cts, NodeID rootTid)
Handle call.
Definition MHP.cpp:290
ThreadStmtToThreadInterleav threadStmtToTheadInterLeav
Definition MHP.h:256
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition MHP.h:234
static const Option< bool > PrintInterLev
Definition Options.h:159
const SVFFunction * getFunction() const
Get function of this call node.
CallGraphEdgeSet::const_iterator getCallEdgeEnd(const CallICFGNode *inst) const
CallGraphEdgeSet::const_iterator getCallEdgeBegin(const CallICFGNode *inst) const
Set< const SVFFunction * > FunctionSet
PTACallGraphNode * getCallGraphNode(NodeID id) const
Get call graph node.
bool hasCallGraphEdge(const CallICFGNode *inst) const
Get call graph edge via call instruction.
NodeID getId() const
Get ID.
const ICFGNode * back() const
Definition SVFValue.h:611
void getExitBlocksOfLoop(const SVFBasicBlock *bb, BBList &exitbbs) const
Definition SVFValue.h:476
static double getClk(bool mark=false)
Definition SVFStat.cpp:48
const std::string & getName() const
Definition SVFValue.h:243
void set(unsigned Idx)
const CxtThread & getCxtThread() const
Get CxtThread.
Definition TCT.h:101
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
Definition TCT.h:206
bool isJoinSiteInRecursion(const CallICFGNode *join) const
Whether a join site is in recursion.
Definition TCT.h:428
const SVFFunction * getStartRoutineOfCxtThread(const CxtThread &ct) const
get the start routine function of a thread
Definition TCT.h:377
bool isCallSite(const ICFGNode *inst)
Whether it is a callsite.
Definition TCT.h:271
ThreadCreateEdgeSet::const_iterator getChildrenBegin(const TCTNode *node) const
Get children and parent nodes.
Definition TCT.h:217
NodeID getParentThread(NodeID tid) const
Get parent thread.
Definition TCT.h:320
ThreadCallGraph * getThreadCallGraph() const
Get TCG.
Definition TCT.h:196
const NodeBS getSiblingThread(NodeID tid) const
Get sibling threads.
Definition TCT.h:350
const CallStrCxt & getCxtOfCxtThread(const CxtThread &ct) const
get the context of a thread at its spawning site (fork site)
Definition TCT.h:369
bool isCandidateFun(const PTACallGraph::FunctionSet &callees) const
Whether it is a candidate function for indirect call.
Definition TCT.h:291
const NodeBS getAncestorThread(NodeID tid) const
Get all ancestor threads.
Definition TCT.h:329
bool isExtCall(const ICFGNode *inst)
Whether it is calling an external function.
Definition TCT.h:264
ThreadCreateEdgeSet::const_iterator getChildrenEnd(const TCTNode *node) const
Definition TCT.h:221
Set< const PTACallGraphNode * > PTACGNodeSet
Definition TCT.h:163
ForkEdgeSet::const_iterator getForkEdgeEnd(const CallICFGNode *cs) const
ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode *cs) const
bool isExtCall(const SVFFunction *fun)
Definition SVFUtil.h:278
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:100
bool isRetInstNode(const ICFGNode *node)
Definition SVFUtil.cpp:389
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
void dumpSet(NodeBS To, OutStream &O=SVFUtil::outs())
Dump sparse bitvector set.
Definition SVFUtil.cpp:148
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:55
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
std::vector< u32_t > CallStrCxt