@@ -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 >
1719class loop_analysist ;
1820
1921// / A loop, specified as a set of instructions
20- template <class P , class T >
22+ template <class T >
2123class 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
2930public:
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 >
10081class loop_analysist
10182{
10283public:
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 {
0 commit comments