@@ -16,13 +16,16 @@ Author: Peter Schrammel
16
16
#include < util/format_expr.h>
17
17
#endif
18
18
19
+ #include < util/ieee_float.h>
19
20
#include < util/find_symbols.h>
20
21
#include < util/arith_tools.h>
21
22
#include < util/simplify_expr.h>
22
23
#include < util/cprover_prefix.h>
23
24
24
25
#include < langapi/language_util.h>
25
- #include < goto-programs/adjust_float_expressions.h>
26
+
27
+ #include < algorithm>
28
+ #include < array>
26
29
27
30
void constant_propagator_domaint::assign_rec (
28
31
valuest &values,
@@ -36,7 +39,7 @@ void constant_propagator_domaint::assign_rec(
36
39
const symbol_exprt &s=to_symbol_expr (lhs);
37
40
38
41
exprt tmp=rhs;
39
- try_evaluate (tmp, ns);
42
+ partial_evaluate (tmp, ns);
40
43
41
44
if (tmp.is_constant ())
42
45
values.set_to (s, tmp);
@@ -102,7 +105,7 @@ void constant_propagator_domaint::transform(
102
105
g = from->guard ;
103
106
else
104
107
g = not_exprt (from->guard );
105
- try_evaluate (g, ns);
108
+ partial_evaluate (g, ns);
106
109
if (g.is_false ())
107
110
values.set_to_bottom ();
108
111
else
@@ -269,7 +272,7 @@ bool constant_propagator_domaint::ai_simplify(
269
272
exprt &condition,
270
273
const namespacet &ns) const
271
274
{
272
- return try_evaluate (condition, ns);
275
+ return partial_evaluate (condition, ns);
273
276
}
274
277
275
278
@@ -506,11 +509,64 @@ bool constant_propagator_domaint::merge(
506
509
// / \param expr The expression to evaluate
507
510
// / \param ns The namespace for symbols in the expression
508
511
// / \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_str)))
520
+ {
521
+ return partial_evaluate_with_all_rounding_modes (expr, ns);
522
+ }
523
+ return replace_constants_and_simplify (expr, ns);
524
+ }
525
+
526
+ // / Attempt to evaluate an expression in all rounding modes.
527
+ // /
528
+ // / If the result is the same for all rounding modes, change
529
+ // / expr to that result and return false. Otherwise, return true.
530
+ bool constant_propagator_domaint::partial_evaluate_with_all_rounding_modes (
531
+ exprt &expr,
532
+ const namespacet &ns) const
533
+ { // NOLINTNEXTLINE (whitespace/braces)
534
+ auto rounding_modes = std::array<ieee_floatt::rounding_modet, 4 >{
535
+ // NOLINTNEXTLINE (whitespace/braces)
536
+ {ieee_floatt::ROUND_TO_EVEN,
537
+ ieee_floatt::ROUND_TO_ZERO,
538
+ ieee_floatt::ROUND_TO_MINUS_INF,
539
+ // NOLINTNEXTLINE (whitespace/braces)
540
+ ieee_floatt::ROUND_TO_PLUS_INF}};
541
+ exprt first_result;
542
+ for (std::size_t i = 0 ; i < rounding_modes.size (); ++i)
543
+ {
544
+ constant_propagator_domaint child (*this );
545
+ child.values .set_to (
546
+ ID_cprover_rounding_mode_str,
547
+ from_integer (rounding_modes[i], integer_typet ()));
548
+ exprt result = expr;
549
+ if (child.replace_constants_and_simplify (result, ns))
550
+ {
551
+ return true ;
552
+ }
553
+ else if (i == 0 )
554
+ {
555
+ first_result = result;
556
+ }
557
+ else if (result != first_result)
558
+ {
559
+ return true ;
560
+ }
561
+ }
562
+ expr = first_result;
563
+ return false ;
564
+ }
565
+
566
+ bool constant_propagator_domaint::replace_constants_and_simplify (
510
567
exprt &expr,
511
568
const namespacet &ns) const
512
569
{
513
- adjust_float_expressions (expr, ns);
514
570
bool did_not_change_anything = values.replace_const .replace (expr);
515
571
did_not_change_anything &= simplify (expr, ns);
516
572
return did_not_change_anything;
@@ -541,33 +597,33 @@ void constant_propagator_ait::replace(
541
597
542
598
if (it->is_goto () || it->is_assume () || it->is_assert ())
543
599
{
544
- s_it->second .try_evaluate (it->guard , ns);
600
+ s_it->second .partial_evaluate (it->guard , ns);
545
601
}
546
602
else if (it->is_assign ())
547
603
{
548
604
exprt &rhs=to_code_assign (it->code ).rhs ();
549
- s_it->second .try_evaluate (rhs, ns);
605
+ s_it->second .partial_evaluate (rhs, ns);
550
606
if (rhs.id ()==ID_constant)
551
607
rhs.add_source_location ()=it->code .op0 ().source_location ();
552
608
}
553
609
else if (it->is_function_call ())
554
610
{
555
611
exprt &function = to_code_function_call (it->code ).function ();
556
- s_it->second .try_evaluate (function, ns);
612
+ s_it->second .partial_evaluate (function, ns);
557
613
558
614
exprt::operandst &args=
559
615
to_code_function_call (it->code ).arguments ();
560
616
561
617
for (auto &arg : args)
562
618
{
563
- s_it->second .try_evaluate (arg, ns);
619
+ s_it->second .partial_evaluate (arg, ns);
564
620
}
565
621
}
566
622
else if (it->is_other ())
567
623
{
568
624
if (it->code .get_statement ()==ID_expression)
569
625
{
570
- s_it->second .try_evaluate (it->code , ns);
626
+ s_it->second .partial_evaluate (it->code , ns);
571
627
}
572
628
}
573
629
}
0 commit comments