Skip to content

Commit 4871953

Browse files
committed
loop_analysis.h refactor
Remove redundant P template param. Move the concept of a loop template that calls back to its base analysis into its own class.
1 parent 22e919c commit 4871953

File tree

4 files changed

+87
-52
lines changed

4 files changed

+87
-52
lines changed

src/analyses/lexical_loops.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ Author: Diffblue Ltd
6161
/// * [function] get_target() which returns an object that needs:
6262
/// * [field] location_number which is an unsigned int.
6363
template <class P, class T>
64-
class lexical_loops_templatet : public loop_analysist<P, T>
64+
class lexical_loops_templatet : public loop_analysist<T>
6565
{
66-
typedef loop_analysist<P, T> parentt;
66+
typedef loop_analysist<T> parentt;
6767

6868
public:
6969
typedef typename parentt::loopt lexical_loopt;
@@ -92,11 +92,13 @@ class lexical_loops_templatet : public loop_analysist<P, T>
9292
out << "Note not all loops were in lexical loop form\n";
9393
}
9494

95+
virtual ~lexical_loops_templatet() = default;
96+
9597
protected:
9698
void compute(P &program);
9799
bool compute_lexical_loop(T, T);
98100

99-
bool all_in_lexical_loop_form;
101+
bool all_in_lexical_loop_form = false;
100102
};
101103

102104
typedef lexical_loops_templatet<
@@ -178,7 +180,7 @@ bool lexical_loops_templatet<P, T>::compute_lexical_loop(
178180
}
179181

180182
auto insert_result = parentt::loop_map.emplace(
181-
loop_head, lexical_loopt{*this, std::move(loop_instructions)});
183+
loop_head, lexical_loopt{std::move(loop_instructions)});
182184

183185
// If this isn't a new loop head (i.e. return_result.second is false) then we
184186
// have multiple backedges targeting one loop header: this is not in simple

src/analyses/loop_analysis.h

Lines changed: 77 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,47 +13,33 @@ Author: Diffblue Ltd
1313
#ifndef CPROVER_ANALYSES_LOOP_ANALYSIS_H
1414
#define CPROVER_ANALYSES_LOOP_ANALYSIS_H
1515

16-
template <class P, class T>
16+
#include <memory>
17+
18+
template <class T>
1719
class loop_analysist;
1820

1921
/// A loop, specified as a set of instructions
20-
template <class P, class T>
22+
template <class T>
2123
class loop_templatet
2224
{
23-
typedef loop_analysist<P, T> parent_analysist;
2425
typedef std::set<T> loop_instructionst;
2526
loop_instructionst loop_instructions;
2627

27-
friend loop_analysist<P, T>;
28+
friend loop_analysist<T>;
2829

2930
public:
30-
explicit loop_templatet(parent_analysist &loop_analysis)
31-
: loop_analysis(loop_analysis)
32-
{
33-
}
31+
loop_templatet() = default;
3432

3533
template <typename InstructionSet>
36-
loop_templatet(parent_analysist &loop_analysis, InstructionSet &&instructions)
37-
: loop_instructions(std::forward<InstructionSet>(instructions)),
38-
loop_analysis(loop_analysis)
34+
explicit loop_templatet(InstructionSet &&instructions)
35+
: loop_instructions(std::forward<InstructionSet>(instructions))
3936
{
4037
}
4138

4239
/// Returns true if \p instruction is in this loop
43-
bool contains(const T instruction) const
44-
{
45-
return loop_analysis.loop_contains(*this, instruction);
46-
}
47-
48-
/// Get the \ref parent_analysist analysis this loop relates to
49-
const parent_analysist &get_loop_analysis() const
50-
{
51-
return loop_analysis;
52-
}
53-
/// Get the \ref parent_analysist analysis this loop relates to
54-
parent_analysist &get_loop_analysis()
40+
bool virtual contains(const T instruction) const
5541
{
56-
return loop_analysis;
42+
return !loop_instructions.empty() && loop_instructions.count(instruction);
5743
}
5844

5945
// NOLINTNEXTLINE(readability/identifiers)
@@ -83,58 +69,105 @@ class loop_templatet
8369
return loop_instructions.empty();
8470
}
8571

86-
/// Adds \p instruction to this loop. The caller must verify that the added
87-
/// instruction does not alter loop structure; if it does they must discard
88-
/// and recompute the related \ref parent_analysist instance.
72+
/// Adds \p instruction to this loop.
8973
/// \return true if the instruction is new
9074
bool insert_instruction(const T instruction)
9175
{
9276
return loop_instructions.insert(instruction).second;
9377
}
94-
95-
private:
96-
parent_analysist &loop_analysis;
9778
};
9879

99-
template <class P, class T>
80+
template <class T>
10081
class loop_analysist
10182
{
10283
public:
103-
typedef loop_templatet<P, T> loopt;
84+
typedef loop_templatet<T> loopt;
10485
// map loop headers to loops
10586
typedef std::map<T, loopt> loop_mapt;
10687

10788
loop_mapt loop_map;
10889

109-
void output(std::ostream &) const;
90+
virtual void output(std::ostream &) const;
91+
92+
/// Returns true if \p instruction is the header of any loop
93+
bool is_loop_header(const T instruction) const
94+
{
95+
return loop_map.count(instruction);
96+
}
97+
98+
loop_analysist() = default;
99+
};
100+
101+
template <typename T>
102+
class loop_with_parent_analysis_templatet : loop_templatet<T>
103+
{
104+
typedef loop_analysist<T> parent_analysist;
105+
106+
public:
107+
explicit loop_with_parent_analysis_templatet(parent_analysist &loop_analysis)
108+
: loop_analysis(loop_analysis)
109+
{
110+
}
111+
112+
template <typename InstructionSet>
113+
explicit loop_with_parent_analysis_templatet(
114+
parent_analysist &loop_analysis,
115+
InstructionSet &&instructions)
116+
: loop_templatet<T>(std::forward<InstructionSet>(instructions)),
117+
loop_analysis(loop_analysis)
118+
{
119+
}
110120

111121
/// Returns true if \p instruction is in \p loop
112-
bool loop_contains(const loopt &loop, const T instruction) const
122+
bool loop_contains(
123+
const typename loop_analysist<T>::loopt &loop,
124+
const T instruction) const
113125
{
114126
return loop.loop_instructions.count(instruction);
115127
}
116128

117-
/// Returns true if \p instruction is the header of any loop
118-
bool is_loop_header(const T instruction) const
129+
/// Get the \ref parent_analysist analysis this loop relates to
130+
const parent_analysist &get_loop_analysis() const
119131
{
120-
return loop_map.count(instruction);
132+
return loop_analysis;
133+
}
134+
/// Get the \ref parent_analysist analysis this loop relates to
135+
parent_analysist &get_loop_analysis()
136+
{
137+
return loop_analysis;
121138
}
122139

123-
loop_analysist() = default;
140+
private:
141+
parent_analysist &loop_analysis;
142+
};
143+
144+
template <class T>
145+
class linked_loop_analysist : loop_analysist<T>
146+
{
147+
public:
148+
linked_loop_analysist() = default;
149+
150+
/// Returns true if \p instruction is in \p loop
151+
bool loop_contains(
152+
const typename loop_analysist<T>::loopt &loop,
153+
const T instruction) const
154+
{
155+
return loop.loop_instructions.count(instruction);
156+
}
124157

125158
// The loop structures stored in `loop_map` contain back-pointers to this
126159
// class, so we forbid copying or moving the analysis struct. If this becomes
127160
// necessary then either add a layer of indirection or update the loop_map
128161
// back-pointers on copy/move.
129-
loop_analysist(const loop_analysist &) = delete;
130-
loop_analysist(loop_analysist &&) = delete;
131-
loop_analysist &operator=(const loop_analysist &) = delete;
132-
loop_analysist &operator=(loop_analysist &&) = delete;
162+
linked_loop_analysist(const linked_loop_analysist &) = delete;
163+
linked_loop_analysist(linked_loop_analysist &&) = delete;
164+
linked_loop_analysist &operator=(const linked_loop_analysist &) = delete;
165+
linked_loop_analysist &operator=(linked_loop_analysist &&) = delete;
133166
};
134167

135168
/// Print all natural loops that were found
136-
template <class P, class T>
137-
void loop_analysist<P, T>::output(std::ostream &out) const
169+
template <class T>
170+
void loop_analysist<T>::output(std::ostream &out) const
138171
{
139172
for(const auto &loop : loop_map)
140173
{

src/analyses/natural_loops.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ Author: Georg Weissenbacher, georg@weissenbacher.name
4444
/// * [function] get_target() which returns an object that needs:
4545
/// * [field] location_number which is an unsigned int.
4646
template <class P, class T>
47-
class natural_loops_templatet : public loop_analysist<P, T>
47+
class natural_loops_templatet : public loop_analysist<T>
4848
{
49-
typedef loop_analysist<P, T> parentt;
49+
typedef loop_analysist<T> parentt;
5050

5151
public:
5252
typedef typename parentt::loopt natural_loopt;
@@ -140,7 +140,7 @@ void natural_loops_templatet<P, T>::compute_natural_loop(T m, T n)
140140

141141
std::stack<T> stack;
142142

143-
auto insert_result = parentt::loop_map.emplace(n, natural_loopt{*this});
143+
auto insert_result = parentt::loop_map.emplace(n, natural_loopt{});
144144
// Note the emplace *may* access a loop that already exists: this happens when
145145
// a given header has more than one incoming edge, such as
146146
// head: if(x) goto head; else goto head;

src/goto-instrument/loop_utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Author: Daniel Kroening, kroening@kroening.com
1717
class local_may_aliast;
1818

1919
typedef std::set<exprt> modifiest;
20-
typedef const natural_loops_mutablet::natural_loopt loopt;
20+
typedef natural_loops_mutablet::natural_loopt loopt;
2121

2222
void get_modifies(
2323
const local_may_aliast &local_may_alias,

0 commit comments

Comments
 (0)