Skip to content

Commit 055e588

Browse files
Try all rounding modes when domain is unknown
For rounding modes in constant propagator domain
1 parent d9a40e6 commit 055e588

File tree

6 files changed

+116
-12
lines changed

6 files changed

+116
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <assert.h>
2+
#include <fenv.h>
3+
#include <stdio.h>
4+
5+
int nondet_rounding_mode(void);
6+
7+
int main(void)
8+
{
9+
// slightly bigger than 0.1
10+
float f = 1.0f / 10.0f;
11+
12+
// now we don't know what rounding mode we're in
13+
__CPROVER_rounding_mode = nondet_rounding_mode();
14+
// depending on rounding mode 1.0f/10.0f could
15+
// be greater or smaller than 0.1
16+
17+
// definitely not smaller than -0.1
18+
assert((1.0f / 10.0f) - f < -0.1f);
19+
// might be smaller than 0
20+
assert((1.0f / 10.0f) - f < 0.0f);
21+
// definitely smaller or equal to 0
22+
assert((1.0f / 10.0f) - f <= 0.0f);
23+
// might be greater or equal to 0
24+
assert((1.0f / 10.0f) - f >= 0.0f);
25+
// definitely not greater than 0
26+
assert((1.0f / 10.0f) - f > 0.0f);
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--constants --verify
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
\[main.assertion.1\] file main.c line 18 function main, assertion \(1.0f / 10.0f\) - f < -0.1f: Failure \(if reachable\)
7+
\[main.assertion.2\] file main.c line 20 function main, assertion \(1.0f / 10.0f\) - f < 0.0f: Unknown
8+
\[main.assertion.3\] file main.c line 22 function main, assertion \(1.0f / 10.0f\) - f <= 0.0f: Success
9+
\[main.assertion.4\] file main.c line 24 function main, assertion \(1.0f / 10.0f\) - f >= 0.0f: Unknown
10+
\[main.assertion.5\] file main.c line 26 function main, assertion \(1.0f / 10.0f\) - f > 0.0f: Failure \(if reachable\)
11+
12+
--
13+
^warning: ignoring

src/analyses/constant_propagator.cpp

+63-11
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ Author: Peter Schrammel
2222
#include <util/cprover_prefix.h>
2323

2424
#include <langapi/language_util.h>
25-
#include <goto-programs/adjust_float_expressions.h>
25+
#include <util/ieee_float.h>
26+
27+
#include <algorithm>
28+
#include <array>
2629

2730
void constant_propagator_domaint::assign_rec(
2831
valuest &values,
@@ -36,7 +39,7 @@ void constant_propagator_domaint::assign_rec(
3639
const symbol_exprt &s=to_symbol_expr(lhs);
3740

3841
exprt tmp=rhs;
39-
try_evaluate(tmp, ns);
42+
partial_evaluate(tmp, ns);
4043

4144
if(tmp.is_constant())
4245
values.set_to(s, tmp);
@@ -102,7 +105,7 @@ void constant_propagator_domaint::transform(
102105
g = from->guard;
103106
else
104107
g = not_exprt(from->guard);
105-
try_evaluate(g, ns);
108+
partial_evaluate(g, ns);
106109
if(g.is_false())
107110
values.set_to_bottom();
108111
else
@@ -269,7 +272,7 @@ bool constant_propagator_domaint::ai_simplify(
269272
exprt &condition,
270273
const namespacet &ns) const
271274
{
272-
return try_evaluate(condition, ns);
275+
return partial_evaluate(condition, ns);
273276
}
274277

275278

@@ -506,11 +509,60 @@ bool constant_propagator_domaint::merge(
506509
/// \param expr The expression to evaluate
507510
/// \param ns The namespace for symbols in the expression
508511
/// \return True if the expression is unchanged, false otherwise
509-
bool constant_propagator_domaint::try_evaluate(
512+
bool constant_propagator_domaint::partial_evaluate(
513+
exprt &expr,
514+
const namespacet &ns) const
515+
{
516+
// if the current rounding mode is top we can
517+
// still get a non-top result by trying all rounding
518+
// modes and checking if the results are all the same
519+
if(!values.is_constant(symbol_exprt(ID_cprover_rounding_mode)))
520+
{
521+
return partial_evaluate_with_all_rounding_modes(expr, ns);
522+
}
523+
return replace_constants_and_simplify(expr, ns);
524+
}
525+
526+
bool constant_propagator_domaint::partial_evaluate_with_all_rounding_modes(
527+
exprt &expr,
528+
const namespacet &ns) const
529+
{ // NOLINTNEXTLINE (whitespace/braces)
530+
auto rounding_modes = std::array<ieee_floatt::rounding_modet, 4>{
531+
// NOLINTNEXTLINE (whitespace/braces)
532+
{ieee_floatt::ROUND_TO_EVEN,
533+
ieee_floatt::ROUND_TO_ZERO,
534+
ieee_floatt::ROUND_TO_MINUS_INF,
535+
// NOLINTNEXTLINE (whitespace/braces)
536+
ieee_floatt::ROUND_TO_PLUS_INF}};
537+
exprt first_result;
538+
for(std::size_t i = 0; i < rounding_modes.size(); ++i)
539+
{
540+
constant_propagator_domaint child(*this);
541+
child.values.set_to(
542+
ID_cprover_rounding_mode,
543+
from_integer(rounding_modes[i], integer_typet()));
544+
exprt result = expr;
545+
if(child.replace_constants_and_simplify(result, ns))
546+
{
547+
return true;
548+
}
549+
else if(i == 0)
550+
{
551+
first_result = result;
552+
}
553+
else if(result != first_result)
554+
{
555+
return true;
556+
}
557+
}
558+
expr = first_result;
559+
return false;
560+
}
561+
562+
bool constant_propagator_domaint::replace_constants_and_simplify(
510563
exprt &expr,
511564
const namespacet &ns) const
512565
{
513-
adjust_float_expressions(expr, ns);
514566
bool did_not_change_anything = values.replace_const.replace(expr);
515567
did_not_change_anything &= simplify(expr, ns);
516568
return did_not_change_anything;
@@ -541,33 +593,33 @@ void constant_propagator_ait::replace(
541593

542594
if(it->is_goto() || it->is_assume() || it->is_assert())
543595
{
544-
s_it->second.try_evaluate(it->guard, ns);
596+
s_it->second.partial_evaluate(it->guard, ns);
545597
}
546598
else if(it->is_assign())
547599
{
548600
exprt &rhs=to_code_assign(it->code).rhs();
549-
s_it->second.try_evaluate(rhs, ns);
601+
s_it->second.partial_evaluate(rhs, ns);
550602
if(rhs.id()==ID_constant)
551603
rhs.add_source_location()=it->code.op0().source_location();
552604
}
553605
else if(it->is_function_call())
554606
{
555607
exprt &function = to_code_function_call(it->code).function();
556-
s_it->second.try_evaluate(function, ns);
608+
s_it->second.partial_evaluate(function, ns);
557609

558610
exprt::operandst &args=
559611
to_code_function_call(it->code).arguments();
560612

561613
for(auto &arg : args)
562614
{
563-
s_it->second.try_evaluate(arg, ns);
615+
s_it->second.partial_evaluate(arg, ns);
564616
}
565617
}
566618
else if(it->is_other())
567619
{
568620
if(it->code.get_statement()==ID_expression)
569621
{
570-
s_it->second.try_evaluate(it->code, ns);
622+
s_it->second.partial_evaluate(it->code, ns);
571623
}
572624
}
573625
}

src/analyses/constant_propagator.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class constant_propagator_domaint:public ai_domain_baset
138138

139139
valuest values;
140140

141-
bool try_evaluate(exprt &expr, const namespacet &ns) const;
141+
bool partial_evaluate(exprt &expr, const namespacet &ns) const;
142142

143143
protected:
144144
void assign_rec(
@@ -149,6 +149,12 @@ class constant_propagator_domaint:public ai_domain_baset
149149
bool two_way_propagate_rec(
150150
const exprt &expr,
151151
const namespacet &ns);
152+
153+
bool partial_evaluate_with_all_rounding_modes(
154+
exprt &expr,
155+
const namespacet &ns) const;
156+
157+
bool replace_constants_and_simplify(exprt &expr, const namespacet &ns) const;
152158
};
153159

154160
class constant_propagator_ait:public ait<constant_propagator_domaint>

src/goto-analyzer/goto_analyzer_parse_options.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Author: Daniel Kroening, [email protected]
5656
#include <util/exit_codes.h>
5757

5858
#include <cbmc/version.h>
59+
#include <goto-programs/adjust_float_expressions.h>
5960

6061
#include "taint_analysis.h"
6162
#include "unreachable_instructions.h"
@@ -477,6 +478,7 @@ int goto_analyzer_parse_optionst::doit()
477478
/// Depending on the command line mode, run one of the analysis tasks
478479
int goto_analyzer_parse_optionst::perform_analysis(const optionst &options)
479480
{
481+
adjust_float_expressions(goto_model);
480482
if(options.get_bool_option("taint"))
481483
{
482484
std::string taint_file=cmdline.get_value("taint");

src/util/ieee_float.h

+4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include "mp_arith.h"
1616
#include "format_spec.h"
17+
#include "irep.h"
18+
#include "cprover_prefix.h"
1719

1820
class constant_exprt;
1921
class floatbv_typet;
2022

23+
const irep_idt ID_cprover_rounding_mode = CPROVER_PREFIX "rounding_mode";
24+
2125
class ieee_float_spect
2226
{
2327
public:

0 commit comments

Comments
 (0)