CBMC
all_paths_enumerator.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Loop Acceleration
4 
5 Author: Matt Lewis
6 
7 \*******************************************************************/
8 
11 
12 #include "all_paths_enumerator.h"
13 
15 {
16  if(last_path.empty())
17  {
18  // This is the first time we've been called -- build an initial
19  // path.
20  last_path.push_back(path_nodet(loop_header));
21 
22  // This shouldn't be able to fail.
24 
26  {
27  // If this was a loop path, we're good. If it wasn't,
28  // we'll keep enumerating paths until we hit a looping one.
29  // This case is exactly the same as if someone just called
30  // next() on us.
31  path.clear();
32  path.insert(path.begin(), last_path.begin(), last_path.end());
33  return true;
34  }
35  }
36 
37  do
38  {
39 #ifdef DEBUG
40  std::cout << "Enumerating next path...\n";
41 #endif
42 
43  int decision=backtrack(last_path);
44  complete_path(last_path, decision);
45 
47  {
48  path.clear();
49  path.insert(path.begin(), last_path.begin(), last_path.end());
50  return true;
51  }
52  }
53  while(!last_path.empty());
54 
55  // We've enumerated all the paths.
56  return false;
57 }
58 
60 {
61  // If we have a path of length 1 or 0, we can't backtrack any further.
62  // That means we're done enumerating paths!
63  if(path.size()<2)
64  {
65  path.clear();
66  return 0;
67  }
68 
69  goto_programt::targett node_loc=path.back().loc;
70  path.pop_back();
71 
72  goto_programt::targett parent_loc=path.back().loc;
73  const auto succs=goto_program.get_successors(parent_loc);
74 
75  unsigned int ret=0;
76 
77  for(const auto &succ : succs)
78  {
79  if(succ==node_loc)
80  break;
81 
82  ret++;
83  }
84 
85  if((ret+1)<succs.size())
86  {
87  // We can take the next branch here...
88 
89 #ifdef DEBUG
90  std::cout << "Backtracked to a path of size " << path.size() << '\n';
91 #endif
92 
93  return ret+1;
94  }
95 
96  // Recurse.
97  return backtrack(path);
98 }
99 
101 {
102  if(path.empty())
103  return;
104 
105  goto_programt::targett node_loc=path.back().loc;
106  extend_path(path, node_loc, succ);
107 
108  goto_programt::targett end=path.back().loc;
109 
110  if(end == loop_header || !loop.contains(end))
111  return;
112 
113  complete_path(path, 0);
114 }
115 
117  patht &path,
119  int succ)
120 {
123 
124  for(const auto &s : goto_program.get_successors(t))
125  {
126  if(succ==0)
127  {
128  next=s;
129  break;
130  }
131 
132  succ--;
133  }
134 
135  if(t->is_goto())
136  {
137  guard = not_exprt(t->condition());
138 
139  for(goto_programt::targetst::iterator it=t->targets.begin();
140  it != t->targets.end();
141  ++it)
142  {
143  if(next == *it)
144  {
145  guard = t->condition();
146  break;
147  }
148  }
149  }
150 
151  path.push_back(path_nodet(next, guard));
152 }
153 
155 {
156  return path.size()>1 && path.back().loc==loop_header;
157 }
Loop Acceleration.
static exprt guard(const exprt::operandst &guards, exprt cond)
natural_loops_mutablet::natural_loopt & loop
virtual bool next(patht &path)
void complete_path(patht &path, int succ)
goto_programt::targett loop_header
goto_programt & goto_program
void extend_path(patht &path, goto_programt::targett t, int succ)
Base class for all expressions.
Definition: expr.h:56
instructionst::iterator targett
Definition: goto_program.h:614
std::list< Target > get_successors(Target target) const
Get control-flow successors of a given instruction.
virtual bool contains(const T instruction) const
Returns true if instruction is in this loop.
Definition: loop_analysis.h:40
Boolean negation.
Definition: std_expr.h:2327
The Boolean constant true.
Definition: std_expr.h:3063
std::list< path_nodet > patht
Definition: path.h:44