21 natural_loops(goto_program);
41 for(
auto predecessor : it->incoming_edges)
44 predecessor->location_number > it->location_number &&
54 for(
const auto &loop : natural_loops.
loop_map)
56 std::size_t backedge_count = std::count_if(
57 loop.first->incoming_edges.begin(),
58 loop.first->incoming_edges.end(),
60 return loop.first->location_number < predecessor->location_number;
62 if(backedge_count > 1)
75 unordered_map<goto_programt::const_targett, std::size_t, const_target_hash>
84 std::vector<std::size_t> loop_size_by_id;
86 std::size_t loop_id = 0;
87 for(
const auto &header_and_loop : natural_loops.
loop_map)
89 const auto &loop = header_and_loop.second;
90 loop_size_by_id.push_back(loop.size());
92 for(
const auto &instruction : loop)
94 auto emplace_result = innermost_loop_ids.emplace(instruction, loop_id);
95 if(!emplace_result.second)
99 if(loop_size_by_id.at(emplace_result.first->second) > loop.size())
100 emplace_result.first->second = loop_id;
107 return innermost_loop_ids;
114 auto findit = innermost_loops.find(target);
115 if(findit == innermost_loops.end())
118 return (
long)findit->second;
127 postdominators(goto_program);
139 successors.size() == 1 &&
140 (*successors.begin())->incoming_edges.size() == 1)
143 const auto &instruction_postdoms = postdominators.
get_node(it).dominators;
151 std::size_t closest_exit_index = dominators.cfg.size();
152 for(
const auto &possible_exit : instruction_postdoms)
154 const auto possible_exit_index = dominators.get_node_index(possible_exit);
155 const auto &possible_exit_node = dominators.cfg[possible_exit_index];
156 const auto possible_exit_dominators =
157 possible_exit_node.dominators.size();
160 it != possible_exit && dominators.dominates(it, possible_exit_node) &&
167 closest_exit_index == dominators.cfg.size() ||
168 dominators.cfg[closest_exit_index].dominators.size() >
169 possible_exit_dominators)
171 closest_exit_index = possible_exit_index;
176 if(closest_exit_index < dominators.cfg.size())
178 auto emplace_result =
179 sese_regions.emplace(it, dominators.cfg[closest_exit_index].PC);
181 emplace_result.second,
"should only visit each region entry once");
188 auto rhs_trim_idx = input.size() - 1;
189 while(rhs_trim_idx > 0 &&
isspace(input[rhs_trim_idx]))
192 auto lhs_trim_idx = input.rfind(
'\n', rhs_trim_idx);
193 if(lhs_trim_idx == std::string::npos)
196 while(lhs_trim_idx < input.size() &&
isspace(input[lhs_trim_idx]))
199 return input.substr(lhs_trim_idx, (rhs_trim_idx - lhs_trim_idx) + 1);
203 unordered_map<goto_programt::const_targett, std::size_t, const_target_hash>
209 &program_relative_instruction_indices)
212 std::to_string(program_relative_instruction_indices.at(instruction)) +
221 &program_relative_instruction_indices)
223 std::ostringstream ostr;
224 instruction->output(ostr);
226 instruction, program_relative_instruction_indices) +
236 std::size_t next_index = 0;
241 program_relative_instruction_indices.emplace(it, next_index);
244 <<
" single-entry, single-exit regions:\n";
247 out <<
"Region starting at "
252 program_relative_instruction_indices)
258 program_relative_instruction_indices)
Compute dominators for CFG of goto_function.
const cfgt::nodet & get_node(const T &program_point) const
Get the graph node (which gives dominators, predecessors and successors) for program_point.
A generic container class for the GOTO intermediate representation of one function.
instructionst instructions
The list of instructions in the goto program.
instructionst::const_iterator const_targett
std::list< Target > get_successors(Target target) const
Get control-flow successors of a given instruction.
bool is_loop_header(const T instruction) const
Returns true if instruction is the header of any loop.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
const cfg_dominators_templatet< P, T, false > & get_dominator_info() const
A concretized version of natural_loops_templatet<const goto_programt, goto_programt::const_targett>
void operator()(const goto_programt &goto_program)
void compute_sese_regions(const goto_programt &goto_program, const natural_loopst &natural_loops)
void output(std::ostream &out, const goto_programt &goto_program, const namespacet &ns) const
std::unordered_map< goto_programt::const_targett, goto_programt::const_targett, const_target_hash > sese_regions
Compute natural loops in a goto_function.
static std::string instruction_ordinals(const goto_programt::const_targett &instruction, const program_relative_instruction_indicest &program_relative_instruction_indices)
static long get_innermost_loop(const innermost_loop_mapt &innermost_loops, const goto_programt::const_targett &target)
std::unordered_map< goto_programt::const_targett, std::size_t, const_target_hash > innermost_loop_mapt
static std::string brief_instruction_string(const goto_programt &goto_program, const goto_programt::const_targett &instruction, const namespacet &ns, const program_relative_instruction_indicest &program_relative_instruction_indices)
static innermost_loop_mapt compute_innermost_loop_ids(const natural_loopst &natural_loops)
Builds a map from instructions to the smallest (and therefore innermost) loop they are a member of.
static std::string trimmed_last_line(const std::string &input)
std::unordered_map< goto_programt::const_targett, std::size_t, const_target_hash > program_relative_instruction_indicest
Single-entry, single-exit region analysis.
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.