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<goto_programt::targett, goto_programt::targett>
102  new_targetst;
103  new_targetst new_targets;
104 
105  // remove skip statements
106 
107  for(goto_programt::instructionst::iterator it = begin; it != end;)
108  {
109  goto_programt::targett old_target=it;
110 
111  // for collecting labels
112  std::list<irep_idt> labels;
113 
114  while(is_skip(goto_program, it, true))
115  {
116  // don't remove the last skip statement,
117  // it could be a target
118  if(
119  it == std::prev(end) ||
120  (std::next(it)->is_end_function() &&
121  (!labels.empty() || !it->labels.empty())))
122  {
123  break;
124  }
125 
126  // save labels
127  labels.splice(labels.end(), it->labels);
128  it++;
129  }
130 
131  goto_programt::targett new_target=it;
132 
133  // save labels
134  it->labels.splice(it->labels.begin(), labels);
135 
136  if(new_target!=old_target)
137  {
138  for(; old_target!=new_target; ++old_target)
139  new_targets[old_target]=new_target; // remember the old targets
140  }
141  else
142  it++;
143  }
144 
145  // adjust gotos across the full goto program body
146  for(auto &ins : goto_program.instructions)
147  {
148  if(ins.is_goto() || ins.is_start_thread() || ins.is_catch())
149  {
150  for(auto &target : ins.targets)
151  {
152  new_targetst::const_iterator result = new_targets.find(target);
153 
154  if(result!=new_targets.end())
155  target = result->second;
156  }
157  }
158  }
159 
160  while(new_targets.find(begin) != new_targets.end())
161  ++begin;
162 
163  // now delete the skips -- we do so after adjusting the
164  // gotos to avoid dangling targets
165  for(const auto &new_target : new_targets)
166  goto_program.instructions.erase(new_target.first);
167 
168  // remove the last skip statement unless it's a target
169  goto_program.compute_target_numbers();
170 
171  if(begin != end)
172  {
173  goto_programt::targett last = std::prev(end);
174  if(begin == last)
175  ++begin;
176 
177  if(is_skip(goto_program, last) && !last->is_target())
178  goto_program.instructions.erase(last);
179  }
180  }
181  while(goto_program.instructions.size()<old_size);
182 }
183 
185 void remove_skip(goto_programt &goto_program)
186 {
187  remove_skip(
188  goto_program,
189  goto_program.instructions.begin(),
190  goto_program.instructions.end());
191 
192  goto_program.update();
193 }
194 
196 void remove_skip(goto_functionst &goto_functions)
197 {
198  for(auto &gf_entry : goto_functions.function_map)
199  {
200  remove_skip(
201  gf_entry.second.body,
202  gf_entry.second.body.instructions.begin(),
203  gf_entry.second.body.instructions.end());
204  }
205 
206  // we may remove targets
207  goto_functions.update();
208 }
209 
210 void remove_skip(goto_modelt &goto_model)
211 {
212  remove_skip(goto_model.goto_functions);
213 }
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
to_code_expression
code_expressiont & to_code_expression(codet &code)
Definition: std_code.h:1428
remove_skip
void remove_skip(goto_programt &goto_program, goto_programt::targett begin, goto_programt::targett end)
remove unnecessary skip statements
Definition: remove_skip.cpp:87
goto_programt::update
void update()
Update all indices.
Definition: goto_program.cpp:617
goto_model.h
exprt
Base class for all expressions.
Definition: expr.h:55
goto_modelt
Definition: goto_model.h:25
goto_functionst::function_map
function_mapt function_map
Definition: goto_functions.h:29
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
goto_programt::compute_target_numbers
void compute_target_numbers()
Compute the target numbers.
Definition: goto_program.cpp:645
irept::id
const irep_idt & id() const
Definition: irep.h:396
std_code.h
goto_programt::instructions
instructionst instructions
The list of instructions in the goto program.
Definition: goto_program.h:592
goto_functionst
A collection of goto functions.
Definition: goto_functions.h:24
goto_modelt::goto_functions
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:33
to_typecast_expr
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2051
goto_functionst::update
void update()
Definition: goto_functions.h:83
goto_programt
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:72
goto_programt::const_targett
instructionst::const_iterator const_targett
Definition: goto_program.h:587
code_expressiont::expression
const exprt & expression() const
Definition: std_code.h:1401
is_skip
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
remove_skip.h
is_constant
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition: std_types.h:29
goto_programt::targett
instructionst::iterator targett
Definition: goto_program.h:586
code_expressiont
codet representation of an expression statement.
Definition: std_code.h:1393