svf-lib 1.0.2677 → 1.0.2678

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/SVF-linux-x86_64/bin/ae +0 -0
  2. package/SVF-linux-x86_64/bin/cfl +0 -0
  3. package/SVF-linux-x86_64/bin/dvf +0 -0
  4. package/SVF-linux-x86_64/bin/mta +0 -0
  5. package/SVF-linux-x86_64/bin/saber +0 -0
  6. package/SVF-linux-x86_64/bin/svf-ex +0 -0
  7. package/SVF-linux-x86_64/include/Graphs/CallGraph.h +18 -0
  8. package/SVF-linux-x86_64/include/Graphs/DOTGraphTraits.h +33 -20
  9. package/SVF-linux-x86_64/include/Graphs/GraphPrinter.h +1 -1
  10. package/SVF-linux-x86_64/include/Graphs/GraphWriter.h +6 -7
  11. package/SVF-linux-x86_64/include/Graphs/ICFG.h +40 -0
  12. package/SVF-linux-x86_64/include/Graphs/SVFG.h +8 -0
  13. package/SVF-linux-x86_64/include/Graphs/SlicedGraphs.h +1801 -0
  14. package/SVF-linux-x86_64/include/Graphs/ThreadCallGraph.h +13 -4
  15. package/SVF-linux-x86_64/include/MSSA/MemRegion.h +17 -0
  16. package/SVF-linux-x86_64/include/MSSA/MemSSA.h +7 -5
  17. package/SVF-linux-x86_64/include/MSSA/SVFGBuilder.h +6 -0
  18. package/SVF-linux-x86_64/include/MTA/FSMPTA.h +91 -0
  19. package/SVF-linux-x86_64/include/MTA/LockAnalysis.h +40 -25
  20. package/SVF-linux-x86_64/include/MTA/MHP.h +54 -21
  21. package/SVF-linux-x86_64/include/MTA/MTA.h +186 -3
  22. package/SVF-linux-x86_64/include/MTA/MTASVFGBuilder.h +176 -0
  23. package/SVF-linux-x86_64/include/MTA/MTASlicer.h +275 -0
  24. package/SVF-linux-x86_64/include/MTA/MTAStat.h +0 -2
  25. package/SVF-linux-x86_64/include/MTA/TCT.h +70 -29
  26. package/SVF-linux-x86_64/include/Util/CommandLine.h +5 -0
  27. package/SVF-linux-x86_64/include/Util/CxtStmt.h +29 -19
  28. package/SVF-linux-x86_64/include/Util/Options.h +12 -6
  29. package/SVF-linux-x86_64/include/Util/ThreadAPI.h +12 -0
  30. package/SVF-linux-x86_64/lib/cmake/SVF/SVFTargets.cmake +1 -1
  31. package/SVF-linux-x86_64/lib/libSvfCore.so.3.4 +0 -0
  32. package/package.json +1 -1
@@ -142,7 +142,18 @@ class ThreadCallGraph: public CallGraph
142
142
  {
143
143
 
144
144
  public:
145
- typedef Set<const CallICFGNode*> InstSet;
145
+ /// Order fork/join callsites by ICFG node id, never by pointer value:
146
+ /// thread ids are assigned in discovery order over these sets (TCT), and
147
+ /// the MHP/lock fixed points seed from them, so their iteration order must
148
+ /// be identical across runs (a pointer-hashed set varies with ASLR).
149
+ struct CallSiteIdCmp
150
+ {
151
+ bool operator()(const CallICFGNode* lhs, const CallICFGNode* rhs) const
152
+ {
153
+ return lhs->getId() < rhs->getId();
154
+ }
155
+ };
156
+ typedef OrderedSet<const CallICFGNode*, CallSiteIdCmp> InstSet;
146
157
  typedef InstSet CallSiteSet;
147
158
  typedef Set<CallSiteSet*> CtxSet;
148
159
  typedef ThreadForkEdge::ForkEdgeSet ForkEdgeSet;
@@ -158,9 +169,7 @@ public:
158
169
  ThreadCallGraph(ThreadCallGraph& cg) = delete;
159
170
 
160
171
  /// Destructor
161
- virtual ~ThreadCallGraph()
162
- {
163
- }
172
+ virtual ~ThreadCallGraph();
164
173
 
165
174
  /// ClassOf
166
175
  //@{
@@ -337,6 +337,14 @@ protected:
337
337
  /// Get Mod-Ref of a callee function
338
338
  virtual bool handleCallsiteModRef(NodeBS& mod, NodeBS& ref, const CallICFGNode* cs, const FunObjVar* fun);
339
339
 
340
+ /// Extension hooks for specialised MRGenerators: no-op in the base. They
341
+ /// run during the mod/ref fixpoint, before MemorySSA creates callsite
342
+ /// MU/CHI nodes; subclasses use them when a call boundary needs non-standard
343
+ /// mod/ref effects to expose the right ActualIN/ActualOUT nodes.
344
+ virtual void refineCallsiteModRef(NodeBS& /*mod*/, NodeBS& /*ref*/,
345
+ const CallICFGNode* /*cs*/, const FunObjVar* /*callee*/) {}
346
+ virtual void propagateAdditionalModRef(CallGraphNode* /*callGraphNode*/, WorkList& /*worklist*/) {}
347
+
340
348
 
341
349
  /// Add cpts to store/load
342
350
  //@{
@@ -385,6 +393,15 @@ protected:
385
393
  bool addRefSideEffectOfCallSite(const CallICFGNode* cs, const NodeBS& refs);
386
394
  /// Add indirect def an memory object in the function
387
395
  bool addModSideEffectOfCallSite(const CallICFGNode* cs, const NodeBS& mods);
396
+ /// Add indirect def to a callsite without applying call-argument filtering.
397
+ bool addUnfilteredModSideEffectOfCallSite(const CallICFGNode* cs, const NodeBS& mods);
398
+
399
+ /// The call graph this generator works on (for subclasses, e.g. the
400
+ /// thread-aware MTA MRGenerator that inspects fork/join edges).
401
+ CallGraph* getCallGraph() const
402
+ {
403
+ return callGraph;
404
+ }
388
405
 
389
406
  /// Get indirect refs of a function
390
407
  inline const NodeBS& getRefSideEffectOfFunction(const FunObjVar* fun)
@@ -119,7 +119,7 @@ public:
119
119
 
120
120
  protected:
121
121
  BVDataPTAImpl* pta;
122
- MRGenerator* mrGen;
122
+ std::unique_ptr<MRGenerator> mrGen;
123
123
  MemSSAStat* stat;
124
124
 
125
125
  /// Create mu chi for candidate regions in a function
@@ -294,8 +294,10 @@ private:
294
294
  //@}
295
295
 
296
296
  public:
297
- /// Constructor
298
- MemSSA(BVDataPTAImpl* p, bool ptrOnlyMSSA);
297
+ /// Constructor. The builder (SVFGBuilder::createMRGenerator) supplies the
298
+ /// MRGenerator and decides the partition strategy / thread-awareness; MemSSA
299
+ /// takes ownership of it via unique_ptr. mrGenerator must not be null.
300
+ MemSSA(BVDataPTAImpl* p, std::unique_ptr<MRGenerator> mrGenerator);
299
301
 
300
302
  /// Destructor
301
303
  virtual ~MemSSA()
@@ -309,10 +311,10 @@ public:
309
311
  {
310
312
  return pta;
311
313
  }
312
- /// Return MRGenerator
314
+ /// Return MRGenerator (non-owning; MemSSA retains ownership)
313
315
  inline MRGenerator* getMRGenerator()
314
316
  {
315
- return mrGen;
317
+ return mrGen.get();
316
318
  }
317
319
  /// We start from here
318
320
  virtual void buildMemSSA(const FunObjVar& fun);
@@ -83,6 +83,12 @@ public:
83
83
  virtual std::unique_ptr<MemSSA> buildMSSA(BVDataPTAImpl* pta, bool ptrOnlyMSSA);
84
84
 
85
85
  protected:
86
+ /// Hook supplying the MRGenerator for the MemSSA built above. The default
87
+ /// builds the stock generator selected by Options::MemPar(); MTASVFGBuilder
88
+ /// overrides this to inject a thread-aware (ThreadMRG) generator. Ownership
89
+ /// transfers to the MemSSA constructed in buildMSSA.
90
+ virtual std::unique_ptr<MRGenerator> createMRGenerator(BVDataPTAImpl* pta, bool ptrOnlyMSSA);
91
+
86
92
  /// Create a DDA SVFG. By default actualOut and FormalIN are removed, unless withAOFI is set true.
87
93
  SVFG* build(BVDataPTAImpl* pta, VFG::VFGK kind);
88
94
  /// Can be rewritten by subclasses
@@ -0,0 +1,91 @@
1
+ //===- FSMPTA.h -- Flow-sensitive multithreaded pointer analysis (FSAM) -===//
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
+ * FSMPTA.h
25
+ *
26
+ * Author: Jiawei Yang
27
+ *
28
+ * Sparse flow-sensitive pointer analysis for multithreaded programs (FSAM,
29
+ * Sui/Di/Xue CGO'16). It runs the sparse flow-sensitive solver
30
+ * (`FlowSensitive`) over a *thread-aware* SVFG built by `MTASVFGBuilder`,
31
+ * i.e. the stock thread-oblivious value flow augmented with inter-thread
32
+ * (interference) edges derived from the MHP and lock analyses.
33
+ */
34
+
35
+ #ifndef INCLUDE_MTA_FSMPTA_H_
36
+ #define INCLUDE_MTA_FSMPTA_H_
37
+
38
+ #include "WPA/FlowSensitive.h"
39
+ #include "MTA/MHP.h"
40
+ #include "MTA/LockAnalysis.h"
41
+ #include "MTA/MTASVFGBuilder.h"
42
+ #include "MTA/MTASlicer.h"
43
+ #include <unordered_set>
44
+
45
+ namespace SVF
46
+ {
47
+
48
+ /// One solver for the whole and the sliced SVFG: SVFGGraph is SVFG* (whole;
49
+ /// every node processed) or const SlicedSVFGView* (sliced; nodes outside the
50
+ /// view are propagation barriers). Restriction is answered by
51
+ /// GenericGraphTraits<SVFGGraph>::containsNode, resolved at compile time; the
52
+ /// stock FlowSensitive transfer semantics are untouched.
53
+ template<class SVFGGraph>
54
+ class FSMPTA : public FlowSensitive
55
+ {
56
+ public:
57
+ /// Constructor.
58
+ /// - graph: gates the per-node transfer (the solver runs over the whole
59
+ /// thread-aware SVFG). For SVFGGraph == SVFG* it may be null (every node
60
+ /// is processed). A SlicedSVFGView needs only its ICFG view for membership,
61
+ /// so it can be created before the SVFG itself is built here.
62
+ FSMPTA(MHP* m, LockAnalysis* la, SVFGGraph graph)
63
+ : FlowSensitive(m->getTCT()->getPTA()->getPAG()),
64
+ mhp(m), mtaSVFGBuilder(m, la), graph(graph)
65
+ {
66
+ }
67
+
68
+ ~FSMPTA() override = default;
69
+
70
+ /// Initialise: build the thread-aware SVFG, then solve sparsely on it.
71
+ void initialize() override;
72
+
73
+ /// Restrict the solve to the graph's nodes (whole: no restriction).
74
+ void processNode(NodeID nodeId) override;
75
+
76
+ inline MHP* getMHP() const
77
+ {
78
+ return mhp;
79
+ }
80
+
81
+ private:
82
+ MHP* mhp;
83
+ /// Owns the thread-aware SVFG used by the FS solver (must outlive `svfg`).
84
+ MTASVFGBuilder mtaSVFGBuilder;
85
+ /// The graph the solve is restricted to (see the constructor).
86
+ SVFGGraph graph;
87
+ };
88
+
89
+ } // End namespace SVF
90
+
91
+ #endif /* INCLUDE_MTA_FSMPTA_H_ */
@@ -25,6 +25,11 @@
25
25
  *
26
26
  * Created on: 26 Aug 2015
27
27
  * Author: pengd
28
+ *
29
+ * Lock analysis. One implementation runs on the whole program or a slice:
30
+ * analyze() is templated on the graph handle (SVFIR* or const SlicedSVFIRView*),
31
+ * as used by "Multi-Stage On-Demand Program Slicing for Modular Analysis of
32
+ * Multi-Threaded Programs" (ISSTA 2026).
28
33
  */
29
34
 
30
35
  #ifndef INCLUDE_MTA_LockAnalysis_H_
@@ -35,9 +40,15 @@
35
40
  */
36
41
  #include "MTA/TCT.h"
37
42
 
43
+ #include <memory>
44
+ #include <vector>
45
+
38
46
  namespace SVF
39
47
  {
40
48
 
49
+ // Forward declaration for the sliced-graph handle analyze() can run on.
50
+ class SlicedSVFIRView;
51
+
41
52
  /*!
42
53
  * Lock analysis
43
54
  */
@@ -81,18 +92,23 @@ public:
81
92
  {
82
93
  }
83
94
 
95
+ ~LockAnalysis() = default;
96
+
84
97
  /// context-sensitive forward traversal from each lock site. Generate following results
85
98
  /// (1) context-sensitive lock site,
86
99
  /// (2) maps a context-sensitive lock site to its corresponding lock span.
87
- void analyze();
88
- void analyzeIntraProcedualLock();
89
- bool intraForwardTraverse(const ICFGNode* lock, InstSet& unlockset, InstSet& forwardInsts);
90
- bool intraBackwardTraverse(const InstSet& unlockset, InstSet& backwardInsts);
91
-
92
- void collectCxtLock();
93
- void analyzeLockSpanCxtStmt();
94
-
95
- void collectLockUnlocksites();
100
+ /// One implementation for the whole program and a slice: GraphT is SVFIR*
101
+ /// (whole) or const SlicedSVFIRView* (sliced). Per-graph queries resolve at
102
+ /// compile time via the graph* overloads in Graphs/SlicedGraphs.h.
103
+ template<class ICFGGraph, class CGGraph> void analyze(ICFGGraph icfg, CGGraph cg);
104
+ template<class ICFGGraph, class CGGraph> void analyzeIntraProcedualLock(ICFGGraph icfg, CGGraph cg);
105
+ template<class ICFGGraph, class CGGraph> bool intraForwardTraverse(ICFGGraph icfg, CGGraph cg, const ICFGNode* lock, InstSet& unlockset, InstSet& forwardInsts);
106
+ template<class ICFGGraph, class CGGraph> bool intraBackwardTraverse(ICFGGraph icfg, CGGraph cg, const InstSet& unlockset, InstSet& backwardInsts);
107
+
108
+ template<class ICFGGraph, class CGGraph> void collectCxtLock(ICFGGraph icfg, CGGraph cg);
109
+ template<class ICFGGraph, class CGGraph> void analyzeLockSpanCxtStmt(ICFGGraph icfg, CGGraph cg);
110
+
111
+ template<class ICFGGraph, class CGGraph> void collectLockUnlocksites(ICFGGraph icfg, CGGraph cg);
96
112
  void buildCandidateFuncSetforLock();
97
113
 
98
114
  /// Intraprocedural locks
@@ -135,6 +151,14 @@ public:
135
151
  return instTocondCILocksMap.find(stmt)!=instTocondCILocksMap.end();
136
152
  }
137
153
 
154
+ /// Whether a statement has an (unconditional) intra-procedural lock set, i.e.
155
+ /// getIntraLockSet is valid for it. A statement can be locked (isInsideIntraLock)
156
+ /// via a *conditional* intra lock or a *context* lock without being here.
157
+ inline bool hasIntraLockSet(const ICFGNode* stmt) const
158
+ {
159
+ return instCILocksMap.find(stmt)!=instCILocksMap.end();
160
+ }
161
+
138
162
  inline const InstSet& getIntraLockSet(const ICFGNode* stmt) const
139
163
  {
140
164
  InstToInstSetMap::const_iterator it = instCILocksMap.find(stmt);
@@ -264,8 +288,6 @@ public:
264
288
  }
265
289
  //@}
266
290
 
267
-
268
-
269
291
  /// Check if one instruction's context stmt is in a lock span
270
292
  inline bool hasOneCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
271
293
  {
@@ -297,7 +319,6 @@ public:
297
319
  return true;
298
320
  }
299
321
 
300
-
301
322
  /// Check if two Instructions are protected by common locks
302
323
  /// echo inst may have multiple cxt stmt
303
324
  /// we check whether every cxt stmt of instructions is protected by a common lock.
@@ -323,32 +344,28 @@ public:
323
344
  {
324
345
  return tct;
325
346
  }
326
- private:
347
+ protected:
327
348
  /// Handle fork
328
- void handleFork(const CxtStmt& cts);
349
+ template<class ICFGGraph, class CGGraph> void handleFork(ICFGGraph icfg, CGGraph cg, const CxtStmt& cts);
329
350
 
330
351
  /// Handle call
331
- void handleCall(const CxtStmt& cts);
352
+ template<class ICFGGraph, class CGGraph> void handleCall(ICFGGraph icfg, CGGraph cg, const CxtStmt& cts);
332
353
 
333
354
  /// Handle return
334
- void handleRet(const CxtStmt& cts);
355
+ template<class ICFGGraph, class CGGraph> void handleRet(ICFGGraph icfg, CGGraph cg, const CxtStmt& cts);
335
356
 
336
357
  /// Handle intra
337
- void handleIntra(const CxtStmt& cts);
358
+ template<class ICFGGraph, class CGGraph> void handleIntra(ICFGGraph icfg, CGGraph cg, const CxtStmt& cts);
338
359
 
339
360
  /// Handle call relations
340
- void handleCallRelation(CxtLockProc& clp, const CallGraphEdge* cgEdge, const CallICFGNode* call);
361
+ template<class ICFGGraph, class CGGraph> void handleCallRelation(ICFGGraph icfg, CGGraph cg, CxtLockProc& clp, const CallGraphEdge* cgEdge, const CallICFGNode* call);
341
362
 
342
363
  /// Return true it a lock matches an unlock
343
364
  bool isAliasedLocks(const CxtLock& cl1, const CxtLock& cl2)
344
365
  {
345
366
  return isAliasedLocks(cl1.getStmt(), cl2.getStmt());
346
367
  }
347
- bool isAliasedLocks(const ICFGNode* i1, const ICFGNode* i2)
348
- {
349
- /// todo: must alias
350
- return tct->getPTA()->alias(getLockVal(i1)->getId(), getLockVal(i2)->getId());
351
- }
368
+ bool isAliasedLocks(const ICFGNode* i1, const ICFGNode* i2);
352
369
 
353
370
  /// Mark thread flags for cxtStmt
354
371
  //@{
@@ -488,7 +505,6 @@ private:
488
505
  /// Map a statement to all its context-sensitive statements
489
506
  InstToCxtStmtSet instToCxtStmtSet;
490
507
 
491
-
492
508
  /// Context-sensitive locks
493
509
  CxtLockSet cxtLockset;
494
510
 
@@ -523,7 +539,6 @@ private:
523
539
  InstToInstSetMap instTocondCILocksMap;
524
540
  //@}
525
541
 
526
-
527
542
  public:
528
543
  double lockTime;
529
544
  u32_t numOfTotalQueries;
@@ -25,6 +25,11 @@
25
25
  *
26
26
  * Created on: Jan 21, 2014
27
27
  * Author: Yulei Sui, Peng Di
28
+ *
29
+ * May-happen-in-parallel analysis. One implementation runs on the whole program
30
+ * or a slice: analyze() is templated on the ICFG and CallGraph it traverses
31
+ * (whole graphs or their sliced views), as used by "Multi-Stage On-Demand Program Slicing for
32
+ * Modular Analysis of Multi-Threaded Programs" (ISSTA 2026).
28
33
  */
29
34
 
30
35
  #ifndef MHP_H_
@@ -33,11 +38,16 @@
33
38
  #include "MTA/TCT.h"
34
39
  #include "Util/SVFUtil.h"
35
40
 
41
+ #include <memory>
42
+ #include <vector>
43
+
36
44
  namespace SVF
37
45
  {
38
46
 
39
47
  class ForkJoinAnalysis;
40
48
  class LockAnalysis;
49
+ // Forward declaration for the sliced-graph handle analyze() can run on.
50
+ class SlicedSVFIRView;
41
51
 
42
52
  /*!
43
53
  * This class serves as a base may-happen in parallel analysis for multithreaded program
@@ -65,11 +75,15 @@ public:
65
75
  /// Destructor
66
76
  virtual ~MHP();
67
77
 
68
- /// Start analysis here
69
- void analyze();
78
+ /// Start analysis here. One implementation for the whole program and a
79
+ /// slice: the compute is templated on the two graphs it traverses -- the ICFG
80
+ /// (ICFG* whole / const SlicedICFGView* sliced) and the CallGraph (CallGraph*
81
+ /// whole / const SlicedThreadCallGraphView* sliced) -- and calls their
82
+ /// GenericGraphTraits specialisations directly (no wrapper layer).
83
+ template<class ICFGGraph, class CGGraph> void analyze(ICFGGraph icfg, CGGraph cg);
70
84
 
71
85
  /// Analyze thread interleaving
72
- void analyzeInterleaving();
86
+ template<class ICFGGraph, class CGGraph> void analyzeInterleaving(ICFGGraph icfg, CGGraph cg);
73
87
 
74
88
  /// Get ThreadCallGraph
75
89
  inline ThreadCallGraph* getThreadCallGraph() const
@@ -122,7 +136,7 @@ public:
122
136
  /// Print interleaving results
123
137
  void printInterleaving();
124
138
 
125
- private:
139
+ protected:
126
140
 
127
141
  inline const CallGraph::FunctionSet& getCallee(const CallICFGNode* inst, CallGraph::FunctionSet& callees)
128
142
  {
@@ -131,25 +145,34 @@ private:
131
145
  }
132
146
  /// Update non-candidate functions' interleaving.
133
147
  /// Copy interleaving threads of the entry inst to other insts.
134
- void updateNonCandidateFunInterleaving();
148
+ template<class ICFGGraph, class CGGraph> void updateNonCandidateFunInterleaving(ICFGGraph icfg, CGGraph cg);
135
149
 
136
150
  /// Handle non-candidate function
137
- void handleNonCandidateFun(const CxtThreadStmt& cts);
151
+ template<class ICFGGraph, class CGGraph> void handleNonCandidateFun(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts);
138
152
 
139
153
  /// Handle fork
140
- void handleFork(const CxtThreadStmt& cts, NodeID rootTid);
154
+ template<class ICFGGraph, class CGGraph> void handleFork(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts, NodeID rootTid);
141
155
 
142
156
  /// Handle join
143
- void handleJoin(const CxtThreadStmt& cts, NodeID rootTid);
157
+ template<class ICFGGraph, class CGGraph> void handleJoin(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts, NodeID rootTid);
144
158
 
145
159
  /// Handle call
146
- void handleCall(const CxtThreadStmt& cts, NodeID rootTid);
160
+ template<class ICFGGraph, class CGGraph> void handleCall(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts, NodeID rootTid);
147
161
 
148
162
  /// Handle return
149
- void handleRet(const CxtThreadStmt& cts);
163
+ template<class ICFGGraph, class CGGraph> void handleRet(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts);
150
164
 
151
165
  /// Handle intra
152
- void handleIntra(const CxtThreadStmt& cts);
166
+ template<class ICFGGraph, class CGGraph> void handleIntra(ICFGGraph icfg, CGGraph cg, const CxtThreadStmt& cts);
167
+
168
+ /// Symmetric-join loop-exit kills, applied to EDGE flows (node states stay
169
+ /// pure unions, so paths bypassing the join keep their interleavings).
170
+ //@{
171
+ typedef Map<const SVFBasicBlock*, std::vector<CxtStmt>> BBToSymJoinsMap;
172
+ typedef Map<CxtStmt, Set<const SVFBasicBlock*>> SymJoinToLoopMap;
173
+ void buildSymJoinKillTables();
174
+ NodeBS edgeFlow(const CxtThreadStmt& cts, const ICFGNode* dst);
175
+ //@}
153
176
 
154
177
  /// Add/Remove interleaving thread for statement inst
155
178
  //@{
@@ -170,6 +193,15 @@ private:
170
193
  pushToCTSWorkList(tgr);
171
194
  }
172
195
  }
196
+ inline void addInterleavingBits(const CxtThreadStmt& tgr, const NodeBS& bits)
197
+ {
198
+ bool changed = threadStmtToThreadInterLeav[tgr] |= bits;
199
+ if(changed)
200
+ {
201
+ instToTSMap[tgr.getStmt()].insert(tgr);
202
+ pushToCTSWorkList(tgr);
203
+ }
204
+ }
173
205
  inline void rmInterleavingThread(const CxtThreadStmt& tgr, const NodeBS& tids, const ICFGNode* joinsite)
174
206
  {
175
207
  NodeBS joinedTids;
@@ -187,8 +219,8 @@ private:
187
219
 
188
220
  /// Update Ancestor and sibling threads
189
221
  //@{
190
- void updateAncestorThreads(NodeID tid);
191
- void updateSiblingThreads(NodeID tid);
222
+ template<class ICFGGraph, class CGGraph> void updateAncestorThreads(ICFGGraph icfg, CGGraph cg, NodeID tid);
223
+ template<class ICFGGraph, class CGGraph> void updateSiblingThreads(ICFGGraph icfg, CGGraph cg, NodeID tid);
192
224
  //@}
193
225
 
194
226
  /// Thread curTid can be fully joined by parentTid recursively
@@ -267,10 +299,11 @@ private:
267
299
  ForkJoinAnalysis* fja; ///< ForJoin Analysis
268
300
  CxtThreadStmtWorkList cxtStmtList; ///< CxtThreadStmt worklist
269
301
  ThreadStmtToThreadInterleav threadStmtToThreadInterLeav; /// Map a statement to its thread interleavings
302
+ BBToSymJoinsMap bbToSymJoins; ///< loop block -> symmetric in-loop joins of that loop
303
+ SymJoinToLoopMap symJoinLoop; ///< symmetric in-loop join -> its loop's blocks
270
304
  InstToThreadStmtSetMap instToTSMap; ///< Map an instruction to its ThreadStmtSet
271
305
  FuncPairToBool nonCandidateFuncMHPRelMap;
272
306
 
273
-
274
307
  public:
275
308
  u32_t numOfTotalQueries; ///< Total number of queries
276
309
  u32_t numOfMHPQueries; ///< Number of queries are answered as may-happen-in-parallel
@@ -278,8 +311,6 @@ public:
278
311
  double interleavingQueriesTime;
279
312
  };
280
313
 
281
-
282
-
283
314
  /*!
284
315
  *
285
316
  */
@@ -306,7 +337,6 @@ public:
306
337
  typedef Set<CxtStmt> CxtStmtSet;
307
338
  typedef Map<const ICFGNode*, CxtStmtSet> InstToCxtStmt;
308
339
 
309
-
310
340
  ForkJoinAnalysis(TCT* t) : tct(t)
311
341
  {
312
342
  collectSCEVInfo();
@@ -363,6 +393,11 @@ public:
363
393
  {
364
394
  return tct->hasJoinLoop(inst);
365
395
  }
396
+ /// All SCEV-symmetric in-loop joins and their loop blocks.
397
+ inline const CxtStmtToLoopMap& getSymmetricLoopJoins() const
398
+ {
399
+ return cxtJoinInLoop;
400
+ }
366
401
  private:
367
402
 
368
403
  /// Handle fork
@@ -387,10 +422,8 @@ private:
387
422
  bool sameLoopTripCount(const ICFGNode* forkSite, const ICFGNode* joinSite);
388
423
 
389
424
  /// Whether it is a matched fork join pair
390
- bool isAliasedForkJoin(const CallICFGNode* forkSite, const CallICFGNode* joinSite)
391
- {
392
- return tct->getPTA()->alias(getForkedThread(forkSite)->getId(), getJoinedThread(joinSite)->getId());
393
- }
425
+ bool isAliasedForkJoin(const CallICFGNode* forkSite, const CallICFGNode* joinSite);
426
+ ThreadAPI::ForkJoinAliasCache forkJoinAliasCache;
394
427
  /// Mark thread flags for cxtStmt
395
428
  //@{
396
429
  /// Get the flag for a cxtStmt