Skip to content

Commit d236828

Browse files
Add float support to constant propagator domain
1 parent 6e6a30d commit d236828

File tree

6 files changed

+70
-22
lines changed

6 files changed

+70
-22
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <assert.h>
2+
3+
#define ROUND_F(x) ((int)((x) + 0.5f))
4+
int eight = ROUND_F(100.0f / 12.0f);
5+
6+
int main()
7+
{
8+
assert(eight == 8);
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--constants --verify
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] file main.c line 8 function main, assertion eight == 8: Success$
7+
--
8+
^warning: ignoring
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <assert.h>
2+
3+
int main(void)
4+
{
5+
__CPROVER_rounding_mode = 0;
6+
float rounded_up = 1.0f / 10.0f;
7+
__CPROVER_rounding_mode = 1;
8+
float rounded_down = 1.0f / 10.0f;
9+
assert(rounded_up - 0.1f >= 0);
10+
assert(rounded_down - 0.1f < 0);
11+
return 0;
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
--constants --verify
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] file main.c line 9 function main, assertion rounded_up - 0.1f >= 0: Success
7+
^\[main.assertion.2\] file main.c line 10 function main, assertion rounded_down - 0.1f < 0: Success
8+
--
9+
^warning: ignoring

src/analyses/constant_propagator.cpp

+30-22
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Author: Peter Schrammel
2121
#include <util/cprover_prefix.h>
2222

2323
#include <langapi/language_util.h>
24+
#include <goto-programs/adjust_float_expressions.h>
2425

2526
void constant_propagator_domaint::assign_rec(
2627
valuest &values,
@@ -34,8 +35,7 @@ void constant_propagator_domaint::assign_rec(
3435
const symbol_exprt &s=to_symbol_expr(lhs);
3536

3637
exprt tmp=rhs;
37-
values.replace_const(tmp);
38-
simplify(tmp, ns);
38+
try_evaluate(tmp, ns);
3939

4040
if(tmp.is_constant())
4141
values.set_to(s, tmp);
@@ -98,10 +98,10 @@ void constant_propagator_domaint::transform(
9898
// Comparing iterators is safe as the target must be within the same list
9999
// of instructions because this is a GOTO.
100100
if(from->get_target()==to)
101-
g=simplify_expr(from->guard, ns);
101+
g = from->guard;
102102
else
103-
g=simplify_expr(not_exprt(from->guard), ns);
104-
103+
g = not_exprt(from->guard);
104+
try_evaluate(g, ns);
105105
if(g.is_false())
106106
values.set_to_bottom();
107107
else
@@ -268,10 +268,7 @@ bool constant_propagator_domaint::ai_simplify(
268268
exprt &condition,
269269
const namespacet &ns) const
270270
{
271-
bool b=values.replace_const.replace(condition);
272-
b&=simplify(condition, ns);
273-
274-
return b;
271+
return try_evaluate(condition, ns);
275272
}
276273

277274

@@ -503,6 +500,21 @@ bool constant_propagator_domaint::merge(
503500
return values.merge(other.values);
504501
}
505502

503+
/// Attempt to evaluate expression using domain knowledge
504+
/// This function changes the expression that is passed into it.
505+
/// \param expr The expression to evaluate
506+
/// \param ns The namespace for symbols in the expression
507+
/// \return True if the expression is unchanged, false otherwise
508+
bool constant_propagator_domaint::try_evaluate(
509+
exprt &expr,
510+
const namespacet &ns) const
511+
{
512+
adjust_float_expressions(expr, ns);
513+
bool did_not_change_anything = values.replace_const.replace(expr);
514+
did_not_change_anything &= simplify(expr, ns);
515+
return did_not_change_anything;
516+
}
517+
506518
void constant_propagator_ait::replace(
507519
goto_functionst &goto_functions,
508520
const namespacet &ns)
@@ -528,38 +540,34 @@ void constant_propagator_ait::replace(
528540

529541
if(it->is_goto() || it->is_assume() || it->is_assert())
530542
{
531-
s_it->second.values.replace_const(it->guard);
532-
simplify(it->guard, ns);
543+
s_it->second.try_evaluate(it->guard, ns);
533544
}
534545
else if(it->is_assign())
535546
{
536547
exprt &rhs=to_code_assign(it->code).rhs();
537-
s_it->second.values.replace_const(rhs);
538-
simplify(rhs, ns);
548+
s_it->second.try_evaluate(rhs, ns);
539549
if(rhs.id()==ID_constant)
540550
rhs.add_source_location()=it->code.op0().source_location();
541551
}
542552
else if(it->is_function_call())
543553
{
544-
s_it->second.values.replace_const(
545-
to_code_function_call(it->code).function());
546-
547-
simplify(to_code_function_call(it->code).function(), ns);
554+
exprt &function = to_code_function_call(it->code).function();
555+
s_it->second.try_evaluate(function, ns);
548556

549557
exprt::operandst &args=
550558
to_code_function_call(it->code).arguments();
551559

552-
for(exprt::operandst::iterator o_it=args.begin();
553-
o_it!=args.end(); ++o_it)
560+
for(auto &arg : args)
554561
{
555-
s_it->second.values.replace_const(*o_it);
556-
simplify(*o_it, ns);
562+
s_it->second.try_evaluate(arg, ns);
557563
}
558564
}
559565
else if(it->is_other())
560566
{
561567
if(it->code.get_statement()==ID_expression)
562-
s_it->second.values.replace_const(it->code);
568+
{
569+
s_it->second.try_evaluate(it->code, ns);
570+
}
563571
}
564572
}
565573
}

src/analyses/constant_propagator.h

+2
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ class constant_propagator_domaint:public ai_domain_baset
138138

139139
valuest values;
140140

141+
bool try_evaluate(exprt &expr, const namespacet &ns) const;
142+
141143
protected:
142144
void assign_rec(
143145
valuest &values,

0 commit comments

Comments
 (0)