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 {
118 }
119 else if (SVFUtil::dyn_cast<FunExitICFGNode>(curInst))
120 {
121 handleRet(cts);
122 }
123 else
124 {
126 }
127 }
128 }
129 }
130
133
136}
137
142{
143 for (const auto& item : *PAG::getPAG()->getCallGraph())
144 {
145 const FunObjVar* fun = item.second->getFunction();
146 if (!tct->isCandidateFun(fun) && !isExtCall(fun))
147 {
148 const ICFGNode* entryNode = fun->getEntryBlock()->front();
149
151 continue;
152
154
155 for (const CxtThreadStmt& cts : tsSet)
156 {
157 const CallStrCxt& curCxt = cts.getContext();
158
159 for (auto it : *fun)
160 {
161 const SVFBasicBlock* svfbb = it.second;
162 for (const ICFGNode* curNode : svfbb->getICFGNodeList())
163 {
164 if (curNode == entryNode)
165 continue;
168 instToTSMap[curNode].insert(newCts);
169 }
170 }
171 }
172 }
173 }
174}
175
180{
181 const ICFGNode* curInst = cts.getStmt();
182 const FunObjVar* curfun = curInst->getFun();
183 assert((curInst == curfun->getEntryBlock()->front()) && "curInst is not the entry of non candidate function.");
184 const CallStrCxt& curCxt = cts.getContext();
186 for (CallGraphNode::const_iterator nit = node->OutEdgeBegin(), neit = node->OutEdgeEnd(); nit != neit; nit++)
187 {
188 const FunObjVar* callee = (*nit)->getDstNode()->getFunction();
189 if (!isExtCall(callee))
190 {
191 const ICFGNode* calleeInst = callee->getEntryBlock()->front();
194 }
195 }
196}
197
202{
203
204 const ICFGNode* call = cts.getStmt();
205 const CallStrCxt& curCxt = cts.getContext();
206
207 assert(isTDFork(call));
208 const CallICFGNode* cbn = cast<CallICFGNode>(call);
210 {
211
212 for (ThreadCallGraph::ForkEdgeSet::const_iterator cgIt = tcg->getForkEdgeBegin(cbn),
214 cgIt != ecgIt; ++cgIt)
215 {
216 const FunObjVar* svfroutine = (*cgIt)->getDstNode()->getFunction();
219 const ICFGNode* stmt = svfroutine->getEntryBlock()->front();
220 CxtThread ct(newCxt, call);
221 CxtThreadStmt newcts(tct->getTCTNode(ct)->getId(), ct.getContext(), stmt);
223 }
224 }
226}
227
232{
233
234 const CallStrCxt& curCxt = cts.getContext();
235
236 assert(isTDJoin(cts.getStmt()));
237
238 const CallICFGNode* call = SVFUtil::cast<CallICFGNode>(cts.getStmt());
239
241 if (!joinedTids.empty())
242 {
243 if (fja->hasJoinLoop(call))
244 {
245 std::vector<const SVFBasicBlock*> exitbbs;
246 call->getFun()->getExitBlocksOfLoop(call->getBB(), exitbbs);
247 while (!exitbbs.empty())
248 {
249 const SVFBasicBlock* eb = exitbbs.back();
250 exitbbs.pop_back();
251 const ICFGNode* svfEntryInst = eb->front();
256 }
257 }
258 else
259 {
261 DBOUT(DMTA, outs() << "\n\t match join site " << call->toString() << " for thread " << rootTid << "\n");
262 }
263 }
266 else
267 {
268 if (fja->hasJoinLoop(call))
269 {
270 std::vector<const SVFBasicBlock*> exitbbs;
271 call->getFun()->getExitBlocksOfLoop(call->getBB(), exitbbs);
272 while (!exitbbs.empty())
273 {
274 const SVFBasicBlock* eb = exitbbs.back();
275 exitbbs.pop_back();
276 const ICFGNode* svfEntryInst = eb->front();
277 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), svfEntryInst);
279 }
280 }
281 }
283}
284
289{
290
291 const ICFGNode* call = cts.getStmt();
292 const CallStrCxt& curCxt = cts.getContext();
293 const CallICFGNode* cbn = cast<CallICFGNode>(call);
295 {
296 for (CallGraph::CallGraphEdgeSet::const_iterator cgIt = tcg->getCallEdgeBegin(cbn),
298 cgIt != ecgIt; ++cgIt)
299 {
300
301 const FunObjVar* svfcallee = (*cgIt)->getDstNode()->getFunction();
302 if (isExtCall(svfcallee))
303 continue;
305 const CallICFGNode* callicfgnode = SVFUtil::cast<CallICFGNode>(call);
307 const ICFGNode* svfEntryInst = svfcallee->getEntryBlock()->front();
310 }
311 }
312
316 if (const CallICFGNode *callSite = SVFUtil::cast<CallICFGNode>(call))
317 {
320 {
321 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), callSite->getRetICFGNode());
323 }
324 }
325 else
326 {
327 assert(false && "cts.getStmt() is not a CallICFGNode!");
328 }
329}
330
335{
336 CallGraphNode* curFunNode = tcg->getCallGraphNode(cts.getStmt()->getFun());
337 for (CallGraphEdge* edge : curFunNode->getInEdges())
338 {
339 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edge))
340 continue;
341 for (CallGraphEdge::CallInstSet::const_iterator cit = (edge)->directCallsBegin(),
342 ecit = (edge)->directCallsEnd();
343 cit != ecit; ++cit)
344 {
345 CallStrCxt newCxt = cts.getContext();
346 if (matchAndPopCxt(newCxt, *cit, curFunNode->getFunction()))
347 {
348 for(const ICFGEdge* outEdge : cts.getStmt()->getOutEdges())
349 {
350 if(outEdge->getDstNode()->getFun() == (*cit)->getFun())
351 {
352 // Iterate over callSite's call string context and use as the successor's context
353 if (!hasThreadStmtSet(*cit))
354 continue;
356 {
357 CallStrCxt callSiteCxt = cxtThreadStmt.getContext();
358 // If new context is a suffix of the call site context
360 {
361 CxtThreadStmt newCts(cts.getTid(), callSiteCxt, outEdge->getDstNode());
363 }
364 }
365 }
366 }
367 }
368 }
369 for (CallGraphEdge::CallInstSet::const_iterator cit = (edge)->indirectCallsBegin(),
370 ecit = (edge)->indirectCallsEnd();
371 cit != ecit; ++cit)
372 {
373 CallStrCxt newCxt = cts.getContext();
374 if (matchAndPopCxt(newCxt, *cit, curFunNode->getFunction()))
375 {
376 for(const ICFGEdge* outEdge : cts.getStmt()->getOutEdges())
377 {
378 if(outEdge->getDstNode()->getFun() == (*cit)->getFun())
379 {
380 // Iterate over callSite's call string context and use as the successor's context
381 if (!hasThreadStmtSet(*cit))
382 continue;
384 {
385 CallStrCxt callSiteCxt = cxtThreadStmt.getContext();
386 // If new context is a suffix of the call site context
388 {
389 CxtThreadStmt newCts(cts.getTid(), callSiteCxt, outEdge->getDstNode());
391 }
392 }
393 }
394 }
395 }
396 }
397 }
398}
399
404{
405 for(const ICFGEdge* outEdge : cts.getStmt()->getOutEdges())
406 {
407 if(outEdge->getDstNode()->getFun() == cts.getStmt()->getFun())
408 {
409 CxtThreadStmt newCts(cts.getTid(), cts.getContext(), outEdge->getDstNode());
411 }
412 }
413}
414
419{
421 DBOUT(DMTA, outs() << "##Ancestor thread of " << curTid << " is : ");
423 DBOUT(DMTA, outs() << "\n");
425
426 for (const unsigned tid : ancestorAndSelfTids)
427 {
428 const CxtThread& ct = tct->getTCTNode(tid)->getCxtThread();
429 if (const ICFGNode* forkInst = ct.getThread())
430 {
431 for(const ICFGEdge* outEdge : forkInst->getOutEdges())
432 {
433 // Ensure dst node is in the same function as forkInst
434 if(outEdge->getDstNode()->getFun() == forkInst->getFun())
435 {
436 for (const auto& forkSiteCxt : tct->getCxtOfCxtThread(ct))
437 {
438 CxtThreadStmt cts(forkSiteCxt.first, forkSiteCxt.second, outEdge->getDstNode());
440 }
441 }
442 }
443 }
444 }
445}
446
458{
461 for (const unsigned tid : ancestorAndSelfTids)
462 {
464 for (const unsigned stid : siblingTds)
465 {
466 if ((isHBPair(tid, stid) && isRecurFullJoin(tid, curTid)) || isHBPair(stid, tid))
467 continue;
468
471 const ICFGNode* stmt = routine->getEntryBlock()->front();
472 CxtThreadStmt cts(stid, ct.getContext(), stmt);
474 }
475
476 DBOUT(DMTA, outs() << "##Sibling thread of " << curTid << " is : ");
478 DBOUT(DMTA, outs() << "\n");
479 }
480}
481
486{
487 if (parentTid == curTid)
488 return true;
489
492 worklist.push(curNode);
493 while (!worklist.empty())
494 {
495 const TCTNode* node = worklist.pop();
496 for (TCTEdge* edge : node->getInEdges())
497 {
498 NodeID srcID = edge->getSrcID();
499 if (fja->isFullJoin(srcID, node->getId()))
500 {
501 if (srcID == parentTid)
502 return true;
503 else
504 worklist.push(edge->getSrcNode());
505 }
506 else
507 {
508 return false;
509 }
510 }
511 }
512 return false;
513}
514
521{
522 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(joinsite);
523 assert(call && isTDJoin(call) && "not a join site!");
525}
526
531{
532 CxtStmt cs(cxt, call);
533 return fja->getDirAndIndJoinedTid(cs);
534}
535
539bool MHP::hasJoinInSymmetricLoop(const CallStrCxt& cxt, const ICFGNode* call) const
540{
541 CxtStmt cs(cxt, call);
542 return fja->hasJoinInSymmetricLoop(cs);
543}
544
546const MHP::LoopBBs& MHP::getJoinInSymmetricLoop(const CallStrCxt& cxt, const ICFGNode* call) const
547{
548 CxtStmt cs(cxt, call);
549 return fja->getJoinInSymmetricLoop(cs);
550}
551
556{
557 return fja->isHBPair(tid1, tid2);
558}
559
561{
564 TCT::PTACGNodeSet visited;
565 worklist.push(cgnode);
566 visited.insert(cgnode);
567 while (!worklist.empty())
568 {
569 const CallGraphNode* node = worklist.pop();
570 if ("main" == node->getFunction()->getName())
571 return true;
572 for (CallGraphNode::const_iterator nit = node->InEdgeBegin(), neit = node->InEdgeEnd(); nit != neit; nit++)
573 {
574 const CallGraphNode* srcNode = (*nit)->getSrcNode();
575 if (visited.find(srcNode) == visited.end())
576 {
577 visited.insert(srcNode);
578 worklist.push(srcNode);
579 }
580 }
581 }
582 return false;
583}
584
596{
597
600 return false;
601
604 for (const CxtThreadStmt& ts1 : tsSet1)
605 {
607 for (const CxtThreadStmt& ts2 : tsSet2)
608 {
610 if (ts1.getTid() != ts2.getTid())
611 {
612 if (l1.test(ts2.getTid()) && l2.test(ts1.getTid()))
613 {
615 return true;
616 }
617 }
618 else
619 {
620 if (isMultiForkedThread(ts1.getTid()))
621 {
623 return true;
624 }
625 }
626 }
627 }
628 return false;
629}
630
632{
633 if (!tct->isCandidateFun(i1->getFun()) && !tct->isCandidateFun(i2->getFun()))
634 {
635 FuncPair funpair = std::make_pair(i1->getFun(), i2->getFun());
636 FuncPairToBool::const_iterator it = nonCandidateFuncMHPRelMap.find(funpair);
637 if (it == nonCandidateFuncMHPRelMap.end())
638 {
639 bool mhp = mayHappenInParallelInst(i1, i2);
641 return mhp;
642 }
643 else
644 {
645 if (it->second)
647 return it->second;
648 }
649 }
651}
652
654{
656
657 DOTIMESTAT(double queryStart = PTAStat::getClk(true));
658 bool mhp = mayHappenInParallelCache(i1, i2);
659 DOTIMESTAT(double queryEnd = PTAStat::getClk(true));
661
662 return mhp;
663}
664
666{
668 return true;
669
672 for (const CxtThreadStmt&ts1 : tsSet1)
673 {
674 for (const CxtThreadStmt& ts2 : tsSet2)
675 {
676 if (ts1.getTid() != ts2.getTid() || isMultiForkedThread(ts1.getTid()))
677 return false;
678 }
679 }
680 return true;
681}
682
687{
688 for (const auto& pair : threadStmtToThreadInterLeav)
689 {
690 outs() << "( t" << pair.first.getTid()
691 << pair.first.getStmt()->toString() << " ) ==> [";
692 for (unsigned i : pair.second)
693 {
694 outs() << " " << i << " ";
695 }
696 outs() << "]\n";
697 }
698}
699
707{
708 // typedef Set<const ICFGNode*> CallInstSet;
709 // typedef Map<const FunObjVar*, CallInstSet> FunToFJSites;
710 // FunToFJSites funToFJSites;
711
712 // for (ThreadCallGraph::CallSiteSet::const_iterator it = tct->getThreadCallGraph()->forksitesBegin(),
713 // eit = tct->getThreadCallGraph()->forksitesEnd();
714 // it != eit; ++it)
715 // {
716 // const ICFGNode* fork = *it;
717 // funToFJSites[fork->getFun()].insert(fork);
718 // }
719
720 // for (ThreadCallGraph::CallSiteSet::const_iterator it = tct->getThreadCallGraph()->joinsitesBegin(),
721 // eit = tct->getThreadCallGraph()->joinsitesEnd();
722 // it != eit; ++it)
723 // {
724 // const ICFGNode* join = *it;
725 // funToFJSites[join->getFun()].insert(join);
726 // }
727
728 // for(FunToFJSites::const_iterator it = funToFJSites.begin(), eit = funToFJSites.end(); it!=eit; ++it)
729 // {
730 // // ScalarEvolution* SE = MTA::getSE(it->first);
731 // for(CallInstSet::const_iterator sit = it->second.begin(), esit = it->second.end(); sit!=esit; ++sit)
732 // {
733 // const SVFInstruction* callInst = *sit;
734 // if(tct->getThreadCallGraph()->isForksite(getCBN(callInst)))
735 // {
736 // // const SVFValue* forkSiteTidPtr = getForkedThread(callInst);
737 // // const SCEV *forkSiteTidPtrSCEV = SE->getSCEV(const_cast<Value*>(forkSiteTidPtr));
738 // // const SCEV *baseForkTidPtrSCEV = SE->getSCEV(const_cast<Value*>(getBasePtr(forkSiteTidPtr)));
739 // // forkSiteTidPtrSCEV = getSCEVMinusExpr(forkSiteTidPtrSCEV, baseForkTidPtrSCEV, SE);
740 // // PTASCEV scev(forkSiteTidPtr,nullptr,nullptr);
741 // // fkjnToPTASCEVMap.insert(std::make_pair(callInst,scev));
742 // }
743 // else
744 // {
745 // // const SVFValue* joinSiteTidPtr = getJoinedThread(callInst);
746 // //const SCEV *joinSiteTidPtrSCEV = SE->getSCEV(const_cast<Value*>(joinSiteTidPtr));
747 // //const SCEV *baseJoinTidPtrSCEV = SE->getSCEV(const_cast<Value*>(getBasePtr(joinSiteTidPtr)));
748 // //joinSiteTidPtrSCEV = getSCEVMinusExpr(joinSiteTidPtrSCEV, baseJoinTidPtrSCEV, SE);
749
750 // // PTASCEV scev(joinSiteTidPtr,nullptr,nullptr);
751 // // fkjnToPTASCEVMap.insert(std::make_pair(callInst,scev));
752 // }
753 // }
754 // }
755}
756
761{
762 for (const std::pair<const NodeID, TCTNode*>& tpair : *tct)
763 {
764 const CxtThread& ct = tpair.second->getCxtThread();
765 const NodeID rootTid = tpair.first;
766 clearFlagMap();
767 if (const ICFGNode* forkInst = ct.getThread())
768 {
770 for(const ICFGEdge* outEdge : forkInst->getOutEdges())
771 {
772 if(outEdge->getDstNode()->getFun() == forkInst->getFun())
773 {
774 for (const auto& forkSiteCxt : tct->getCxtOfCxtThread(ct))
775 {
776 CxtStmt newCts(forkSiteCxt.second, outEdge->getDstNode());
778 }
779 }
780 }
781
782 while (!cxtStmtList.empty())
783 {
785 const ICFGNode* curInst = cts.getStmt();
786 DBOUT(DMTA, outs() << "-----\nForkJoinAnalysis root thread: " << tpair.first << " ");
787 DBOUT(DMTA, cts.dump());
788 DBOUT(DMTA, outs() << "-----\n");
790 if (isTDFork(curInst))
791 {
793 }
794 else if (isTDJoin(curInst))
795 {
797 }
798 else if (tct->isCallSite(curInst) && !tct->isExtCall(curInst))
799 {
803 const CallICFGNode *callSite = SVFUtil::cast<CallICFGNode>(curInst);
806 {
807 // Do not dive into non-candidate functions
808 CxtStmt newCts(cts.getContext(), callSite->getRetICFGNode());
810 }
811 else
812 {
814 }
815 }
816 else if (SVFUtil::dyn_cast<FunExitICFGNode>(curInst))
817 {
818 handleRet(cts);
819 }
820 else
821 {
823 }
824
829 {
832 if (curInst == parentRoutine->getExitBB()->back())
833 {
834 if (getMarkedFlag(cts) != TDAlive)
836 else
838 }
839 }
840 }
841 }
842 }
843}
844
847{
848 const ICFGNode* call = cts.getStmt();
849 const CallStrCxt& curCxt = cts.getContext();
850
851 assert(isTDFork(call));
852 const CallICFGNode* cbn = cast<CallICFGNode>(call);
853 if (getTCG()->hasThreadForkEdge(cbn))
854 {
855 for (ThreadCallGraph::ForkEdgeSet::const_iterator cgIt = getTCG()->getForkEdgeBegin(cbn),
856 ecgIt = getTCG()->getForkEdgeEnd(cbn);
857 cgIt != ecgIt; ++cgIt)
858 {
859 const FunObjVar* callee = (*cgIt)->getDstNode()->getFunction();
862 CxtThread ct(newCxt, call);
863 if (getMarkedFlag(cts) != TDAlive)
865 else
867 }
868 }
870}
871
874{
875 const ICFGNode* call = cts.getStmt();
876 const CallStrCxt& curCxt = cts.getContext();
877
878 assert(isTDJoin(call));
879 const CallICFGNode* cbn = cast<CallICFGNode>(call);
880 if (getTCG()->hasCallGraphEdge(cbn))
881 {
883 const ICFGNode* joinSite = cts.getStmt();
884
885 if (hasJoinLoop(SVFUtil::cast<CallICFGNode>(joinSite)))
886 {
887 if (isAliasedForkJoin(SVFUtil::cast<CallICFGNode>(forkSite),
888 SVFUtil::cast<CallICFGNode>(joinSite)) &&
890 )
891 {
892 LoopBBs& joinLoop = getJoinLoop(SVFUtil::cast<CallICFGNode>(joinSite));
893 std::vector<const SVFBasicBlock *> exitbbs;
894 joinSite->getFun()->getExitBlocksOfLoop(joinSite->getBB(), exitbbs);
895 while (!exitbbs.empty())
896 {
897 const SVFBasicBlock* eb = exitbbs.back();
898 exitbbs.pop_back();
899 const ICFGNode* svfEntryInst = eb->front();
903 {
906 }
907 else
909 }
910 }
913 else
914 {
915 std::vector<const SVFBasicBlock*> exitbbs;
916 joinSite->getFun()->getExitBlocksOfLoop(joinSite->getBB(), exitbbs);
917 while (!exitbbs.empty())
918 {
919 const SVFBasicBlock* eb = exitbbs.back();
920 exitbbs.pop_back();
921 const ICFGNode* svfEntryInst = eb->front();
924 }
925 }
926 }
927 else
928 {
929 if (isAliasedForkJoin(SVFUtil::cast<CallICFGNode>(forkSite),
930 SVFUtil::cast<CallICFGNode>(joinSite)))
931 {
934 DBOUT(DMTA, outs() << "\n\t match join site " << call->toString() << "for thread " << rootTid << "\n");
935 }
936 }
937 }
939}
940
943{
944
945 const ICFGNode* call = cts.getStmt();
946 const CallStrCxt& curCxt = cts.getContext();
947 const CallICFGNode* cbn = SVFUtil::cast<CallICFGNode>(call);
948 if (getTCG()->hasCallGraphEdge(cbn))
949 {
950 for (CallGraph::CallGraphEdgeSet::const_iterator cgIt = getTCG()->getCallEdgeBegin(cbn),
951 ecgIt = getTCG()->getCallEdgeEnd(cbn);
952 cgIt != ecgIt; ++cgIt)
953 {
954 const FunObjVar* svfcallee = (*cgIt)->getDstNode()->getFunction();
955 if (isExtCall(svfcallee))
956 continue;
959 const ICFGNode* svfEntryInst = svfcallee->getEntryBlock()->front();
962 }
963 }
964}
965
968{
969 const ICFGNode* curInst = cts.getStmt();
970 const CallStrCxt& curCxt = cts.getContext();
971
973 for (CallGraphEdge* edge : curFunNode->getInEdges())
974 {
975 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edge))
976 continue;
977 for (CallGraphEdge::CallInstSet::const_iterator cit = edge->directCallsBegin(),
978 ecit = edge->directCallsEnd();
979 cit != ecit; ++cit)
980 {
982 const ICFGNode* curNode = (*cit);
983 if (matchAndPopCxt(newCxt, SVFUtil::cast<CallICFGNode>(curNode), curFunNode->getFunction()))
984 {
985 for(const ICFGEdge* outEdge : curNode->getOutEdges())
986 {
987 if(outEdge->getDstNode()->getFun() == curNode->getFun())
988 {
989 // Iterate over callSite's call string context and use as the successor's context
991 continue;
992 for (const CxtStmt& cxtStmt: getCxtStmtsFromInst(*cit))
993 {
994 CallStrCxt callSiteCxt = cxtStmt.getContext();
995 // If new context is a suffix of the call site context
997 {
998 CxtStmt newCts(callSiteCxt, outEdge->getDstNode());
1000 }
1001 }
1002 }
1003 }
1004 }
1005 }
1006 for (CallGraphEdge::CallInstSet::const_iterator cit = edge->indirectCallsBegin(),
1007 ecit = edge->indirectCallsEnd();
1008 cit != ecit; ++cit)
1009 {
1011 const ICFGNode* curNode = (*cit);
1012
1013 if (matchAndPopCxt(newCxt, SVFUtil::cast<CallICFGNode>(curNode), curFunNode->getFunction()))
1014 {
1015 for(const ICFGEdge* outEdge : curNode->getOutEdges())
1016 {
1017 if(outEdge->getDstNode()->getFun() == curNode->getFun())
1018 {
1019 // Iterate over callSite's call string context and use as the successor's context
1020 if (!hasCxtStmtsFromInst(*cit))
1021 continue;
1022 for (const CxtStmt& cxtStmt: getCxtStmtsFromInst(*cit))
1023 {
1024 CallStrCxt callSiteCxt = cxtStmt.getContext();
1025 // If new context is a suffix of the call site context
1027 {
1028 CxtStmt newCts(callSiteCxt, outEdge->getDstNode());
1030 }
1031 }
1032 }
1033 }
1034 }
1035 }
1036 }
1037}
1038
1041{
1042
1043 const ICFGNode* curInst = cts.getStmt();
1044 const CallStrCxt& curCxt = cts.getContext();
1045
1046 for(const ICFGEdge* outEdge : curInst->getOutEdges())
1047 {
1048 if(outEdge->getDstNode()->getFun() == curInst->getFun())
1049 {
1050 CxtStmt newCts(curCxt, outEdge->getDstNode());
1052 }
1053 }
1054}
1055
1062{
1063
1064 CxtStmtToTIDMap::const_iterator it = dirAndIndJoinMap.find(cs);
1065 if (it != dirAndIndJoinMap.end())
1066 return it->second;
1067
1070
1071 FIFOWorkList<NodeID> worklist;
1072 for (unsigned id : directJoinTids)
1073 {
1074 worklist.push(id);
1075 }
1076
1077 while (!worklist.empty())
1078 {
1079 NodeID tid = worklist.pop();
1080 TCTNode* node = tct->getTCTNode(tid);
1081 for (TCT::ThreadCreateEdgeSet::const_iterator it = tct->getChildrenBegin(node), eit = tct->getChildrenEnd(node); it != eit; ++it)
1082 {
1083 NodeID childTid = (*it)->getDstID();
1084 if (isFullJoin(tid, childTid))
1085 {
1086 allJoinTids.set(childTid);
1087 worklist.push(childTid);
1088 }
1089 }
1090 }
1091
1093
1094 return allJoinTids;
1095}
1096
1097// static bool accessSameArrayIndex(const GetElementPtrInst* ptr1, const GetElementPtrInst* ptr2)
1098// {
1099
1100// std::vector<u32_t> ptr1vec;
1101// for (gep_type_iterator gi = gep_type_begin(*ptr1), ge = gep_type_end(*ptr1);
1102// gi != ge; ++gi)
1103// {
1104// if(SVFConstantInt* ci = SVFUtil::dyn_cast<SVFConstantInt>(LLVMModuleSet::getLLVMModuleSet()->getSVFValue(gi.getOperand())))
1105// {
1106// s32_t idx = ci->getSExtValue();
1107// ptr1vec.push_back(idx);
1108// }
1109// else
1110// return false;
1111// }
1112
1113// std::vector<u32_t> ptr2vec;
1114// for (gep_type_iterator gi = gep_type_begin(*ptr2), ge = gep_type_end(*ptr2);
1115// gi != ge; ++gi)
1116// {
1117// if(SVFConstantInt* ci = SVFUtil::dyn_cast<SVFConstantInt>(LLVMModuleSet::getLLVMModuleSet()->getSVFValue(gi.getOperand())))
1118// {
1119// s32_t idx = ci->getSExtValue();
1120// ptr2vec.push_back(idx);
1121// }
1122// else
1123// return false;
1124// }
1125
1126// return ptr1vec==ptr2vec;
1127// }
1128
1137{
1138
1139 // const PTASCEV& forkse = fkjnToPTASCEVMap[forkSite];
1140 // const PTASCEV& joinse = fkjnToPTASCEVMap[joinSite];
1141
1142 // //if(sameLoopTripCount(forkSite,joinSite) == false)
1143 // // return false;
1144
1145 // if(forkse.inloop && joinse.inloop)
1146 // return forkse.start==joinse.start && forkse.step == joinse.step && forkse.tripcount <= joinse.tripcount;
1147 // else if(SVFUtil::isa<GetElementPtrInst>(forkse.ptr) && SVFUtil::isa<GetElementPtrInst>(joinse.ptr))
1148 // return accessSameArrayIndex(SVFUtil::cast<GetElementPtrInst>(forkse.ptr),SVFUtil::cast<GetElementPtrInst>(joinse.ptr));
1149 // else if(SVFUtil::isa<GetElementPtrInst, GetElementPtrInst>(joinse.ptr))
1150 // return false;
1151 // else
1152 // return true;
1153
1154 return false;
1155}
1156
1161{
1162
1163 // ScalarEvolution* forkSE = getSE(forkSite);
1164 // ScalarEvolution* joinSE = getSE(joinSite);
1165
1166 // if(tct->hasLoop(forkSite) == false || tct->hasLoop(joinSite) == false)
1167 // return false;
1168
1169 // // Get loops
1170 // const LoopBBs& forkSiteLoop = tct->getLoop(forkSite);
1171 // const LoopBBs& joinSiteLoop = tct->getLoop(joinSite);
1172
1173 // const SCEV* forkLoopCountScev = forkSE->getBackedgeTakenCount(forkSiteLoop);
1174 // const SCEV* joinLoopCountScev = joinSE->getBackedgeTakenCount(joinSiteLoop);
1175
1176 // if(forkLoopCountScev!=forkSE->getCouldNotCompute())
1177 // {
1178 // if(forkLoopCountScev==joinLoopCountScev)
1179 // {
1180 // return true;
1181 // }
1182 // }
1183 return false;
1184}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:497
#define TIMEINTERVAL
Definition SVFType.h:525
#define DMTA
Definition SVFType.h:518
#define DGENERAL
Definition SVFType.h:503
#define DOTIMESTAT(X)
Definition SVFType.h:499
cJSON * item
Definition cJSON.h:222
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.
CallGraphEdgeSet::const_iterator getCallEdgeBegin(const CallICFGNode *inst) const
Definition CallGraph.h:433
bool hasCallGraphEdge(const CallICFGNode *inst) const
Get call graph edge via call instruction.
Definition CallGraph.h:429
Set< const FunObjVar * > FunctionSet
Definition CallGraph.h:244
CallGraphEdgeSet::const_iterator getCallEdgeEnd(const CallICFGNode *inst) const
Definition CallGraph.h:440
const std::string toString() const override
Definition ICFG.cpp:139
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:540
ValDomain getMarkedFlag(const CxtStmt &cs)
Mark thread flags for cxtStmt.
Definition MHP.h:396
void addToHPPair(NodeID tid1, NodeID tid2)
Definition MHP.h:527
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition MHP.h:297
void analyzeForkJoinPair()
Definition MHP.cpp:760
bool hasJoinLoop(const CallICFGNode *inst)
Definition MHP.h:361
const CallGraph::FunctionSet & getCallee(const ICFGNode *inst, CallGraph::FunctionSet &callees)
Definition MHP.h:508
void addSymmetricLoopJoin(const CxtStmt &cs, LoopBBs &lp)
Add inloop join.
Definition MHP.h:563
void handleRet(const CxtStmt &cts)
Handle return.
Definition MHP.cpp:967
NodeBS getDirAndIndJoinedTid(const CxtStmt &cs)
Get directly and indirectly joined threadIDs based on a context-sensitive join site.
Definition MHP.cpp:1061
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
Definition MHP.h:475
CxtStmt popFromCTSWorkList()
Definition MHP.h:457
bool hasCxtStmtsFromInst(const ICFGNode *inst) const
Definition MHP.h:557
void addToHBPair(NodeID tid1, NodeID tid2)
Definition MHP.h:532
ThreadCallGraph * getTCG() const
ThreadCallGraph.
Definition MHP.h:514
void addToPartial(NodeID tid1, NodeID tid2)
Definition MHP.h:544
void collectSCEVInfo()
functions
Definition MHP.cpp:706
void clearFlagMap()
Clear flags.
Definition MHP.h:444
bool isHBPair(NodeID tid1, NodeID tid2)
Whether thread t1 happens-before thread t2.
Definition MHP.h:342
void addDirectlyJoinTID(const CxtStmt &cs, NodeID tid)
maps a context-sensitive join site to a thread id
Definition MHP.h:519
LoopBBs & getJoinLoop(const CallICFGNode *inst)
Get loop for join site.
Definition MHP.h:357
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
Definition MHP.h:467
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition MHP.h:487
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt call)
If lhs is a suffix of rhs, including equal.
Definition MHP.h:480
bool isFullJoin(NodeID tid1, NodeID tid2)
Whether t1 fully joins t2.
Definition MHP.h:349
CxtStmtToTIDMap dirAndIndJoinMap
maps a context-sensitive join site to directly and indirectly joined thread ids
Definition MHP.h:571
void handleCall(const CxtStmt &cts, NodeID rootTid)
Handle call.
Definition MHP.cpp:942
bool hasJoinInSymmetricLoop(const CxtStmt &cs) const
Definition MHP.h:336
bool sameLoopTripCount(const ICFGNode *forkSite, const ICFGNode *joinSite)
Same loop trip count.
Definition MHP.cpp:1160
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition MHP.h:493
void markCxtStmtFlag(const CxtStmt &tgr, ValDomain flag)
Initialize TDAlive and TDDead flags.
Definition MHP.h:408
CxtStmtWorkList cxtStmtList
context-sensitive statement worklist
Definition MHP.h:569
const LoopBBs & getJoinInSymmetricLoop(const CxtStmt &cs) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.h:330
bool isAliasedForkJoin(const CallICFGNode *forkSite, const CallICFGNode *joinSite)
Whether it is a matched fork join pair.
Definition MHP.h:389
void handleIntra(const CxtStmt &cts)
Handle intra.
Definition MHP.cpp:1040
void handleFork(const CxtStmt &cts, NodeID rootTid)
Handle fork.
Definition MHP.cpp:846
NodeBS & getDirectlyJoinedTid(const CxtStmt &cs)
Get directly joined threadIDs based on a context-sensitive join site.
Definition MHP.h:322
void handleJoin(const CxtStmt &cts, NodeID rootTid)
Handle join.
Definition MHP.cpp:873
bool isSameSCEV(const ICFGNode *forkSite, const ICFGNode *joinSite)
Return true if the fork and join have the same SCEV.
Definition MHP.cpp:1136
const CxtStmtSet & getCxtStmtsFromInst(const ICFGNode *inst) const
Get CxtStmtSet for an instruction.
Definition MHP.h:551
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
void getExitBlocksOfLoop(const SVFBasicBlock *bb, BBList &exitbbs) const
const SVFBasicBlock * getEntryBlock() const
iterator OutEdgeEnd()
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
GEdgeSetTy::const_iterator const_iterator
iterator InEdgeBegin()
iterator InEdgeEnd()
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:74
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
Definition ICFGNode.h:80
virtual const std::string toString() const
Definition ICFG.cpp:60
void analyze()
Start analysis here.
Definition MHP.cpp:62
CxtThreadStmtWorkList cxtStmtList
CxtThreadStmt worklist.
Definition MHP.h:267
bool isRecurFullJoin(NodeID parentTid, NodeID curTid)
Thread curTid can be fully joined by parentTid recursively.
Definition MHP.cpp:485
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:631
TCT * tct
TCT.
Definition MHP.h:265
FuncPairToBool nonCandidateFuncMHPRelMap
Definition MHP.h:270
void printInterleaving()
Print interleaving results.
Definition MHP.cpp:686
void updateSiblingThreads(NodeID tid)
Definition MHP.cpp:457
bool matchAndPopCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
Definition MHP.h:216
u32_t numOfTotalQueries
Total number of queries.
Definition MHP.h:274
Set< CxtThreadStmt > CxtThreadStmtSet
Definition MHP.h:51
std::pair< const FunObjVar *, const FunObjVar * > FuncPair
Definition MHP.h:58
void handleNonCandidateFun(const CxtThreadStmt &cts)
Handle non-candidate function.
Definition MHP.cpp:179
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition MHP.h:54
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt call)
If lhs is a suffix of rhs, including equal.
Definition MHP.h:221
void handleJoin(const CxtThreadStmt &cts, NodeID rootTid)
Handle join.
Definition MHP.cpp:231
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
Definition MHP.h:208
ThreadCallGraph * tcg
TCG.
Definition MHP.h:264
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:269
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:555
ThreadStmtToThreadInterleav threadStmtToThreadInterLeav
Definition MHP.h:268
bool isTDFork(const ICFGNode *call)
Whether it is a fork site.
Definition MHP.h:240
void handleRet(const CxtThreadStmt &cts)
Handle return.
Definition MHP.cpp:334
virtual bool executedByTheSameThread(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:665
virtual bool mayHappenInParallel(const ICFGNode *i1, const ICFGNode *i2)
Interface to query whether two instructions may happen-in-parallel.
Definition MHP.cpp:653
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:201
const LoopBBs & getJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.cpp:546
ForkJoinAnalysis * fja
ForJoin Analysis.
Definition MHP.h:266
bool hasJoinInSymmetricLoop(const CallStrCxt &cxt, const ICFGNode *call) const
Whether a context-sensitive join satisfies symmetric loop pattern.
Definition MHP.cpp:539
const CallGraph::FunctionSet & getCallee(const CallICFGNode *inst, CallGraph::FunctionSet &callees)
Definition MHP.h:126
bool hasThreadStmtSet(const ICFGNode *inst) const
Definition MHP.h:115
double interleavingQueriesTime
Definition MHP.h:277
u32_t numOfMHPQueries
Number of queries are answered as may-happen-in-parallel.
Definition MHP.h:275
void updateNonCandidateFunInterleaving()
Definition MHP.cpp:141
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:520
double interleavingTime
Definition MHP.h:276
bool isConnectedfromMain(const FunObjVar *fun)
Whether the function is connected from main function in thread call graph.
Definition MHP.cpp:560
CxtThreadStmt popFromCTSWorkList()
Definition MHP.h:233
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:530
void updateAncestorThreads(NodeID tid)
Update Ancestor and sibling threads.
Definition MHP.cpp:418
virtual bool mayHappenInParallelInst(const ICFGNode *i1, const ICFGNode *i2)
Definition MHP.cpp:595
void handleIntra(const CxtThreadStmt &cts)
Handle intra.
Definition MHP.cpp:403
void handleCall(const CxtThreadStmt &cts, NodeID rootTid)
Handle call.
Definition MHP.cpp:288
bool isTDJoin(const ICFGNode *call)
Whether it is a join site.
Definition MHP.h:246
static const Option< bool > PrintInterLev
Definition Options.h:156
const ICFGNode * front() const
const ICFGNode * back() const
const CallGraph * getCallGraph()
Get CG.
Definition SVFIR.h:178
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:114
static double getClk(bool mark=false)
Definition SVFStat.cpp:48
NodeID getId() const
Get ID.
Definition SVFValue.h:160
virtual const std::string & getName() const
Definition SVFValue.h:186
void set(unsigned Idx)
const CxtThread & getCxtThread() const
Get thread creation context, <fork site, call string context>
Definition TCT.h:101
const NodeBS getAncestorThreads(NodeID tid) const
Get all ancestor threads.
Definition TCT.h:327
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
Definition TCT.h:200
bool isJoinSiteInRecursion(const CallICFGNode *join) const
Whether a join site is in recursion.
Definition TCT.h:429
bool isCallSite(const ICFGNode *inst)
Whether it is a callsite.
Definition TCT.h:265
NodeBS getParentThreads(NodeID tid) const
Get parent threads.
Definition TCT.h:314
Set< const CallGraphNode * > PTACGNodeSet
Definition TCT.h:163
ThreadCreateEdgeSet::const_iterator getChildrenBegin(const TCTNode *node) const
Get children and parent nodes.
Definition TCT.h:211
ThreadCallGraph * getThreadCallGraph() const
Get TCG.
Definition TCT.h:190
const NodeBS getSiblingThread(NodeID tid) const
Get sibling threads.
Definition TCT.h:350
bool isCandidateFun(const CallGraph::FunctionSet &callees) const
Whether it is a candidate function for indirect call.
Definition TCT.h:285
bool isExtCall(const ICFGNode *inst)
Whether it is calling an external function.
Definition TCT.h:258
ThreadCreateEdgeSet::const_iterator getChildrenEnd(const TCTNode *node) const
Definition TCT.h:215
const FunObjVar * getStartRoutineOfCxtThread(const CxtThread &ct) const
get the start routine function of a thread
Definition TCT.h:379
const CallStrCxtSet & getCxtOfCxtThread(const CxtThread &ct) const
get the contexts of a thread at its spawning sites (fork sites)
Definition TCT.h:371
ForkEdgeSet::const_iterator getForkEdgeEnd(const CallICFGNode *cs) const
ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode *cs) const
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:101
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:437
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:149
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:56
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
std::vector< u32_t > CallStrCxt