28
28
29
29
#include " cfg_dominators.h"
30
30
31
+ template <class , class >
32
+ class natural_loops_templatet ;
33
+
34
+ // / A natural loop, specified as a set of instructions
35
+ template <class P , class T >
36
+ class natural_loop_templatet
37
+ {
38
+ typedef natural_loops_templatet<P, T> natural_loopst;
39
+ // For natural_loopst to directly manipulate loop_instructions, cf. clients
40
+ // which should use the public iterface:
41
+ friend natural_loopst;
42
+
43
+ typedef std::set<T> loop_instructionst;
44
+ loop_instructionst loop_instructions;
45
+
46
+ public:
47
+ explicit natural_loop_templatet (natural_loopst &natural_loops)
48
+ : natural_loops(natural_loops)
49
+ {
50
+ }
51
+
52
+ // / Returns true if \p instruction is in this loop
53
+ bool contains (const T instruction) const
54
+ {
55
+ return natural_loops.loop_contains (*this , instruction);
56
+ }
57
+
58
+ // / Get the \ref natural_loopst analysis this loop relates to
59
+ const natural_loopst &get_natural_loops () const
60
+ {
61
+ return natural_loops;
62
+ }
63
+ // / Get the \ref natural_loopst analysis this loop relates to
64
+ natural_loopst &get_natural_loops ()
65
+ {
66
+ return natural_loops;
67
+ }
68
+
69
+ // NOLINTNEXTLINE(readability/identifiers)
70
+ typedef typename loop_instructionst::const_iterator const_iterator;
71
+
72
+ // / Iterator over this loop's instructions
73
+ const_iterator begin () const
74
+ {
75
+ return loop_instructions.begin ();
76
+ }
77
+
78
+ // / Iterator over this loop's instructions
79
+ const_iterator end () const
80
+ {
81
+ return loop_instructions.end ();
82
+ }
83
+
84
+ // / Number of instructions in this loop
85
+ std::size_t size () const
86
+ {
87
+ return loop_instructions.size ();
88
+ }
89
+
90
+ // / Returns true if this loop contains no instructions
91
+ bool empty () const
92
+ {
93
+ return loop_instructions.empty ();
94
+ }
95
+
96
+ // / Adds \p instruction to this loop. The caller must verify that the added
97
+ // / instruction does not alter loop structure; if it does they must discard
98
+ // / and recompute the related \ref natural_loopst instance.
99
+ void insert_instruction (const T instruction)
100
+ {
101
+ loop_instructions.insert (instruction);
102
+ }
103
+
104
+ private:
105
+ natural_loopst &natural_loops;
106
+ };
107
+
31
108
// / Main driver for working out if a class (normally goto_programt) has any natural loops.
32
109
// / \ref compute takes an entire goto_programt, iterates over the instructions and for
33
110
// / any backwards jumps attempts to find out if it's a natural loop.
@@ -46,8 +123,7 @@ template<class P, class T>
46
123
class natural_loops_templatet
47
124
{
48
125
public:
49
- typedef std::set<T> natural_loopt;
50
-
126
+ typedef natural_loop_templatet<P, T> natural_loopt;
51
127
// map loop headers to loops
52
128
typedef std::map<T, natural_loopt> loop_mapt;
53
129
@@ -65,6 +141,18 @@ class natural_loops_templatet
65
141
return cfg_dominators;
66
142
}
67
143
144
+ // / Returns true if \p instruction is in \p loop
145
+ bool loop_contains (const natural_loopt &loop, const T instruction) const
146
+ {
147
+ return loop.loop_instructions .count (instruction);
148
+ }
149
+
150
+ // / Returns true if \p instruction is the header of any loop
151
+ bool is_loop_header (const T instruction) const
152
+ {
153
+ return loop_map.count (instruction);
154
+ }
155
+
68
156
natural_loops_templatet ()
69
157
{
70
158
}
@@ -74,6 +162,15 @@ class natural_loops_templatet
74
162
compute (program);
75
163
}
76
164
165
+ // The loop structures stored in `loop_map` contain back-pointers to this
166
+ // class, so we forbid copying or moving the analysis struct. If this becomes
167
+ // necessary then either add a layer of indirection or update the loop_map
168
+ // back-pointers on copy/move.
169
+ natural_loops_templatet (const natural_loops_templatet &) = delete ;
170
+ natural_loops_templatet (natural_loops_templatet &&) = delete ;
171
+ natural_loops_templatet &operator =(const natural_loops_templatet &) = delete ;
172
+ natural_loops_templatet &operator =(natural_loops_templatet &&) = delete ;
173
+
77
174
protected:
78
175
cfg_dominators_templatet<P, T, false > cfg_dominators;
79
176
typedef typename cfg_dominators_templatet<P, T, false >::cfgt::nodet nodet;
@@ -143,10 +240,12 @@ void natural_loops_templatet<P, T>::compute_natural_loop(T m, T n)
143
240
144
241
std::stack<T> stack;
145
242
146
- natural_loopt &loop=loop_map[n];
243
+ auto insert_result = loop_map.emplace (n, natural_loopt{*this });
244
+ INVARIANT (insert_result.second , " each loop head should only be visited once" );
245
+ natural_loopt &loop = insert_result.first ->second ;
147
246
148
- loop.insert (n);
149
- loop.insert (m);
247
+ loop.insert_instruction (n);
248
+ loop.insert_instruction (m);
150
249
151
250
if (n!=m)
152
251
stack.push (m);
@@ -161,8 +260,8 @@ void natural_loops_templatet<P, T>::compute_natural_loop(T m, T n)
161
260
for (const auto &edge : node.in )
162
261
{
163
262
T q=cfg_dominators.cfg [edge.first ].PC ;
164
- std::pair<typename natural_loopt::const_iterator, bool > result=
165
- loop.insert (q);
263
+ std::pair<typename natural_loopt::const_iterator, bool > result =
264
+ loop. loop_instructions .insert (q);
166
265
if (result.second )
167
266
stack.push (q);
168
267
}
0 commit comments