Skip to content

Commit d9a40e6

Browse files
Add float support to constant propagator domain
1 parent f0b3837 commit d9a40e6

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
@@ -22,6 +22,7 @@ Author: Peter Schrammel
2222
#include <util/cprover_prefix.h>
2323

2424
#include <langapi/language_util.h>
25+
#include <goto-programs/adjust_float_expressions.h>
2526

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

3738
exprt tmp=rhs;
38-
values.replace_const(tmp);
39-
simplify(tmp, ns);
39+
try_evaluate(tmp, ns);
4040

4141
if(tmp.is_constant())
4242
values.set_to(s, tmp);
@@ -99,10 +99,10 @@ void constant_propagator_domaint::transform(
9999
// Comparing iterators is safe as the target must be within the same list
100100
// of instructions because this is a GOTO.
101101
if(from->get_target()==to)
102-
g=simplify_expr(from->guard, ns);
102+
g = from->guard;
103103
else
104-
g=simplify_expr(not_exprt(from->guard), ns);
105-
104+
g = not_exprt(from->guard);
105+
try_evaluate(g, ns);
106106
if(g.is_false())
107107
values.set_to_bottom();
108108
else
@@ -269,10 +269,7 @@ bool constant_propagator_domaint::ai_simplify(
269269
exprt &condition,
270270
const namespacet &ns) const
271271
{
272-
bool b=values.replace_const.replace(condition);
273-
b&=simplify(condition, ns);
274-
275-
return b;
272+
return try_evaluate(condition, ns);
276273
}
277274

278275

@@ -504,6 +501,21 @@ bool constant_propagator_domaint::merge(
504501
return values.merge(other.values);
505502
}
506503

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

530542
if(it->is_goto() || it->is_assume() || it->is_assert())
531543
{
532-
s_it->second.values.replace_const(it->guard);
533-
simplify(it->guard, ns);
544+
s_it->second.try_evaluate(it->guard, ns);
534545
}
535546
else if(it->is_assign())
536547
{
537548
exprt &rhs=to_code_assign(it->code).rhs();
538-
s_it->second.values.replace_const(rhs);
539-
simplify(rhs, ns);
549+
s_it->second.try_evaluate(rhs, ns);
540550
if(rhs.id()==ID_constant)
541551
rhs.add_source_location()=it->code.op0().source_location();
542552
}
543553
else if(it->is_function_call())
544554
{
545-
s_it->second.values.replace_const(
546-
to_code_function_call(it->code).function());
547-
548-
simplify(to_code_function_call(it->code).function(), ns);
555+
exprt &function = to_code_function_call(it->code).function();
556+
s_it->second.try_evaluate(function, ns);
549557

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

553-
for(exprt::operandst::iterator o_it=args.begin();
554-
o_it!=args.end(); ++o_it)
561+
for(auto &arg : args)
555562
{
556-
s_it->second.values.replace_const(*o_it);
557-
simplify(*o_it, ns);
563+
s_it->second.try_evaluate(arg, ns);
558564
}
559565
}
560566
else if(it->is_other())
561567
{
562568
if(it->code.get_statement()==ID_expression)
563-
s_it->second.values.replace_const(it->code);
569+
{
570+
s_it->second.try_evaluate(it->code, ns);
571+
}
564572
}
565573
}
566574
}

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)