Skip to content

Commit 251245e

Browse files
authored
Merge pull request #2221 from tautschnig/is-constantt
Move definition of can-be-constant-propagated to a central location
2 parents a1e86d3 + be11b36 commit 251245e

File tree

4 files changed

+110
-122
lines changed

4 files changed

+110
-122
lines changed

src/goto-symex/goto_symex_state.cpp

+37-117
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, [email protected]
1616

1717
#include <util/base_exceptions.h>
1818
#include <util/exception_utils.h>
19+
#include <util/expr_util.h>
1920
#include <util/invariant.h>
2021
#include <util/prefix.h>
2122
#include <util/std_expr.h>
@@ -79,122 +80,6 @@ void goto_symex_statet::level1t::operator()(ssa_exprt &ssa_expr)
7980
ssa_expr.set_level_1(it->second.second);
8081
}
8182

82-
/// This function determines what expressions are to be propagated as
83-
/// "constants"
84-
bool goto_symex_statet::constant_propagation(const exprt &expr) const
85-
{
86-
if(expr.is_constant())
87-
return true;
88-
89-
if(expr.id()==ID_address_of)
90-
{
91-
const address_of_exprt &address_of_expr=to_address_of_expr(expr);
92-
93-
return constant_propagation_reference(address_of_expr.object());
94-
}
95-
else if(expr.id()==ID_typecast)
96-
{
97-
const typecast_exprt &typecast_expr=to_typecast_expr(expr);
98-
99-
return constant_propagation(typecast_expr.op());
100-
}
101-
else if(expr.id()==ID_plus)
102-
{
103-
forall_operands(it, expr)
104-
if(!constant_propagation(*it))
105-
return false;
106-
107-
return true;
108-
}
109-
else if(expr.id()==ID_mult)
110-
{
111-
// propagate stuff with sizeof in it
112-
forall_operands(it, expr)
113-
{
114-
if(it->find(ID_C_c_sizeof_type).is_not_nil())
115-
return true;
116-
else if(!constant_propagation(*it))
117-
return false;
118-
}
119-
120-
return true;
121-
}
122-
else if(expr.id()==ID_array)
123-
{
124-
forall_operands(it, expr)
125-
if(!constant_propagation(*it))
126-
return false;
127-
128-
return true;
129-
}
130-
else if(expr.id()==ID_array_of)
131-
{
132-
return constant_propagation(expr.op0());
133-
}
134-
else if(expr.id()==ID_with)
135-
{
136-
// this is bad
137-
/*
138-
forall_operands(it, expr)
139-
if(!constant_propagation(expr.op0()))
140-
return false;
141-
142-
return true;
143-
*/
144-
return false;
145-
}
146-
else if(expr.id()==ID_struct)
147-
{
148-
forall_operands(it, expr)
149-
if(!constant_propagation(*it))
150-
return false;
151-
152-
return true;
153-
}
154-
else if(expr.id()==ID_union)
155-
{
156-
forall_operands(it, expr)
157-
if(!constant_propagation(*it))
158-
return false;
159-
160-
return true;
161-
}
162-
// byte_update works, byte_extract may be out-of-bounds
163-
else if(expr.id()==ID_byte_update_big_endian ||
164-
expr.id()==ID_byte_update_little_endian)
165-
{
166-
forall_operands(it, expr)
167-
if(!constant_propagation(*it))
168-
return false;
169-
170-
return true;
171-
}
172-
173-
return false;
174-
}
175-
176-
/// this function determines which reference-typed expressions are constant
177-
bool goto_symex_statet::constant_propagation_reference(const exprt &expr) const
178-
{
179-
if(expr.id()==ID_symbol)
180-
return true;
181-
else if(expr.id()==ID_index)
182-
{
183-
const index_exprt &index_expr=to_index_expr(expr);
184-
185-
return constant_propagation_reference(index_expr.array()) &&
186-
constant_propagation(index_expr.index());
187-
}
188-
else if(expr.id()==ID_member)
189-
{
190-
return constant_propagation_reference(to_member_expr(expr).compound());
191-
}
192-
else if(expr.id()==ID_string_constant)
193-
return true;
194-
195-
return false;
196-
}
197-
19883
/// write to a variable
19984
static bool check_renaming(const exprt &expr);
20085

@@ -297,6 +182,41 @@ static void assert_l2_renaming(const exprt &expr)
297182
#endif
298183
}
299184

185+
class goto_symex_is_constantt : public is_constantt
186+
{
187+
protected:
188+
bool is_constant(const exprt &expr) const override
189+
{
190+
if(expr.id() == ID_mult)
191+
{
192+
// propagate stuff with sizeof in it
193+
forall_operands(it, expr)
194+
{
195+
if(it->find(ID_C_c_sizeof_type).is_not_nil())
196+
return true;
197+
else if(!is_constant(*it))
198+
return false;
199+
}
200+
201+
return true;
202+
}
203+
else if(expr.id() == ID_with)
204+
{
205+
// this is bad
206+
/*
207+
forall_operands(it, expr)
208+
if(!is_constant(expr.op0()))
209+
return false;
210+
211+
return true;
212+
*/
213+
return false;
214+
}
215+
216+
return is_constantt::is_constant(expr);
217+
}
218+
};
219+
300220
void goto_symex_statet::assignment(
301221
ssa_exprt &lhs, // L0/L1
302222
const exprt &rhs, // L2
@@ -341,7 +261,7 @@ void goto_symex_statet::assignment(
341261

342262
// for value propagation -- the RHS is L2
343263

344-
if(!is_shared && record_value && constant_propagation(rhs))
264+
if(!is_shared && record_value && goto_symex_is_constantt()(rhs))
345265
propagation.values[l1_identifier]=rhs;
346266
else
347267
propagation.remove(l1_identifier);

src/goto-symex/goto_symex_state.h

-4
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,6 @@ class goto_symex_statet final
179179
bool record_value,
180180
bool allow_pointer_unsoundness=false);
181181

182-
// what to propagate
183-
bool constant_propagation(const exprt &expr) const;
184-
bool constant_propagation_reference(const exprt &expr) const;
185-
186182
// undoes all levels of renaming
187183
void get_original_name(exprt &expr) const;
188184
void get_original_name(typet &type) const;

src/util/expr_util.cpp

+54-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ Author: Daniel Kroening, [email protected]
66
77
\*******************************************************************/
88

9-
109
#include "expr_util.h"
1110

11+
#include <algorithm>
1212
#include <unordered_set>
13+
1314
#include "expr.h"
1415
#include "expr_iterator.h"
1516
#include "fixedbv.h"
@@ -222,3 +223,55 @@ const exprt &skip_typecast(const exprt &expr)
222223

223224
return skip_typecast(to_typecast_expr(expr).op());
224225
}
226+
227+
/// This function determines what expressions are to be propagated as
228+
/// "constants"
229+
bool is_constantt::is_constant(const exprt &expr) const
230+
{
231+
if(expr.is_constant())
232+
return true;
233+
234+
if(expr.id() == ID_address_of)
235+
{
236+
return is_constant_address_of(to_address_of_expr(expr).object());
237+
}
238+
else if(
239+
expr.id() == ID_typecast || expr.id() == ID_array_of ||
240+
expr.id() == ID_plus || expr.id() == ID_mult || expr.id() == ID_array ||
241+
expr.id() == ID_with || expr.id() == ID_struct || expr.id() == ID_union ||
242+
// byte_update works, byte_extract may be out-of-bounds
243+
expr.id() == ID_byte_update_big_endian ||
244+
expr.id() == ID_byte_update_little_endian)
245+
{
246+
return std::all_of(
247+
expr.operands().begin(), expr.operands().end(), [this](const exprt &e) {
248+
return is_constant(e);
249+
});
250+
}
251+
252+
return false;
253+
}
254+
255+
/// this function determines which reference-typed expressions are constant
256+
bool is_constantt::is_constant_address_of(const exprt &expr) const
257+
{
258+
if(expr.id() == ID_symbol)
259+
{
260+
return true;
261+
}
262+
else if(expr.id() == ID_index)
263+
{
264+
const index_exprt &index_expr = to_index_expr(expr);
265+
266+
return is_constant_address_of(index_expr.array()) &&
267+
is_constant(index_expr.index());
268+
}
269+
else if(expr.id() == ID_member)
270+
{
271+
return is_constant_address_of(to_member_expr(expr).compound());
272+
}
273+
else if(expr.id() == ID_string_constant)
274+
return true;
275+
276+
return false;
277+
}

src/util/expr_util.h

+19
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,23 @@ if_exprt lift_if(const exprt &, std::size_t operand_number);
7878
/// find the expression nested inside typecasts, if any
7979
const exprt &skip_typecast(const exprt &expr);
8080

81+
/// Determine whether an expression is constant. A literal constant is
82+
/// constant, but so are, e.g., sums over constants or addresses of objects.
83+
/// An implementation derive from this class to refine what it considers
84+
/// constant in a particular context by overriding is_constant and/or
85+
/// is_constant_address_of.
86+
class is_constantt
87+
{
88+
public:
89+
/// returns true iff the expression can be considered constant
90+
bool operator()(const exprt &e) const
91+
{
92+
return is_constant(e);
93+
}
94+
95+
protected:
96+
virtual bool is_constant(const exprt &) const;
97+
virtual bool is_constant_address_of(const exprt &) const;
98+
};
99+
81100
#endif // CPROVER_UTIL_EXPR_UTIL_H

0 commit comments

Comments
 (0)