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