CBMC
remove_skip.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Program Transformation
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "remove_skip.h"
13 #include "goto_model.h"
14 
15 #include <util/std_code.h>
16 
27 bool is_skip(
28  const goto_programt &body,
30  bool ignore_labels)
31 {
32  if(!ignore_labels && !it->labels.empty())
33  return false;
34 
35  if(it->is_skip())
36  return !it->code().get_bool(ID_explicit);
37 
38  if(it->is_goto())
39  {
40  if(it->condition().is_false())
41  return true;
42 
43  goto_programt::const_targett next_it = it;
44  next_it++;
45 
46  if(next_it == body.instructions.end())
47  return false;
48 
49  // A branch to the next instruction is a skip
50  // We also require the guard to be 'true'
51  return it->condition().is_true() && it->get_target() == next_it;
52  }
53 
54  if(it->is_other())
55  {
56  if(it->get_other().is_nil())
57  return true;
58 
59  const irep_idt &statement = it->get_other().get_statement();
60 
61  if(statement==ID_skip)
62  return true;
63  else if(statement==ID_expression)
64  {
65  const code_expressiont &code_expression = to_code_expression(it->code());
66  const exprt &expr=code_expression.expression();
67  if(expr.id()==ID_typecast &&
68  expr.type().id()==ID_empty &&
69  to_typecast_expr(expr).op().is_constant())
70  {
71  // something like (void)0
72  return true;
73  }
74  }
75 
76  return false;
77  }
78 
79  return false;
80 }
81 
88  goto_programt &goto_program,
91 {
92  // This needs to be a fixed-point, as
93  // removing a skip can turn a goto into a skip.
94  std::size_t old_size;
95 
96  do
97  {
98  old_size=goto_program.instructions.size();
99 
100  // maps deleted instructions to their replacement
101  typedef std::map<
105  new_targetst;
106  new_targetst new_targets;
107 
108  // remove skip statements
109 
110  for(goto_programt::instructionst::iterator it = begin; it != end;)
111  {
112  goto_programt::targett old_target=it;
113 
114  // for collecting labels
115  std::list<irep_idt> labels;
116 
117  while(is_skip(goto_program, it, true))
118  {
119  // don't remove the last skip statement,
120  // it could be a target
121  if(
122  it == std::prev(end) ||
123  (std::next(it)->is_end_function() &&
124  (!labels.empty() || !it->labels.empty())))
125  {
126  break;
127  }
128 
129  // save labels
130  labels.splice(labels.end(), it->labels);
131  it++;
132  }
133 
134  goto_programt::targett new_target=it;
135 
136  // save labels
137  it->labels.splice(it->labels.begin(), labels);
138 
139  if(new_target!=old_target)
140  {
141  for(; old_target!=new_target; ++old_target)
142  new_targets[old_target]=new_target; // remember the old targets
143  }
144  else
145  it++;
146  }
147 
148  // adjust gotos across the full goto program body
149  for(auto &ins : goto_program.instructions)
150  {
151  if(ins.is_goto() || ins.is_start_thread() || ins.is_catch())
152  {
153  for(auto &target : ins.targets)
154  {
155  new_targetst::const_iterator result = new_targets.find(target);
156 
157  if(result!=new_targets.end())
158  target = result->second;
159  }
160  }
161  }
162 
163  while(new_targets.find(begin) != new_targets.end())
164  ++begin;
165 
166  // now delete the skips -- we do so after adjusting the
167  // gotos to avoid dangling targets
168  for(const auto &new_target : new_targets)
169  goto_program.instructions.erase(new_target.first);
170 
171  // remove the last skip statement unless it's a target
172  goto_program.compute_target_numbers();
173 
174  if(begin != end)
175  {
176  goto_programt::targett last = std::prev(end);
177  if(begin == last)
178  ++begin;
179 
180  if(is_skip(goto_program, last) && !last->is_target())
181  goto_program.instructions.erase(last);
182  }
183  }
184  while(goto_program.instructions.size()<old_size);
185 }
186 
188 void remove_skip(goto_programt &goto_program)
189 {
190  remove_skip(
191  goto_program,
192  goto_program.instructions.begin(),
193  goto_program.instructions.end());
194 
195  goto_program.update();
196 }
197 
199 void remove_skip(goto_functionst &goto_functions)
200 {
201  for(auto &gf_entry : goto_functions.function_map)
202  {
203  remove_skip(
204  gf_entry.second.body,
205  gf_entry.second.body.instructions.begin(),
206  gf_entry.second.body.instructions.end());
207  }
208 
209  // we may remove targets
210  goto_functions.update();
211 }
212 
213 void remove_skip(goto_modelt &goto_model)
214 {
215  remove_skip(goto_model.goto_functions);
216 }
codet representation of an expression statement.
Definition: std_code.h:1394
const exprt & expression() const
Definition: std_code.h:1401
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
Base class for all expressions.
Definition: expr.h:56
typet & type()
Return the type of the expression.
Definition: expr.h:84
A collection of goto functions.
function_mapt function_map
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
instructionst instructions
The list of instructions in the goto program.
Definition: goto_program.h:622
void update()
Update all indices.
instructionst::iterator targett
Definition: goto_program.h:614
instructionst::const_iterator const_targett
Definition: goto_program.h:615
void compute_target_numbers()
Compute the target numbers.
const irep_idt & id() const
Definition: irep.h:384
Symbol Table + CFG.
void remove_skip(goto_programt &goto_program, goto_programt::targett begin, goto_programt::targett end)
remove unnecessary skip statements
Definition: remove_skip.cpp:87
bool is_skip(const goto_programt &body, goto_programt::const_targett it, bool ignore_labels)
Determine whether the instruction is semantically equivalent to a skip (no-op).
Definition: remove_skip.cpp:27
Program Transformation.
code_expressiont & to_code_expression(codet &code)
Definition: std_code.h:1428
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2102
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition: std_types.h:29
A total order over targett and const_targett.
Definition: goto_program.h:392