@@ -10,6 +10,7 @@ Author: Peter Schrammel
1010// / Constant Propagation
1111
1212#include " constant_propagator.h"
13+ #include < util/ieee_float.h>
1314
1415#ifdef DEBUG
1516#include < iostream>
@@ -22,7 +23,10 @@ Author: Peter Schrammel
2223#include < util/cprover_prefix.h>
2324
2425#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>
2630
2731void constant_propagator_domaint::assign_rec (
2832 valuest &values,
@@ -36,7 +40,7 @@ void constant_propagator_domaint::assign_rec(
3640 const symbol_exprt &s=to_symbol_expr (lhs);
3741
3842 exprt tmp=rhs;
39- try_evaluate (tmp, ns);
43+ partial_evaluate (tmp, ns);
4044
4145 if (tmp.is_constant ())
4246 values.set_to (s, tmp);
@@ -102,7 +106,7 @@ void constant_propagator_domaint::transform(
102106 g = from->guard ;
103107 else
104108 g = not_exprt (from->guard );
105- try_evaluate (g, ns);
109+ partial_evaluate (g, ns);
106110 if (g.is_false ())
107111 values.set_to_bottom ();
108112 else
@@ -269,7 +273,7 @@ bool constant_propagator_domaint::ai_simplify(
269273 exprt &condition,
270274 const namespacet &ns) const
271275{
272- return try_evaluate (condition, ns);
276+ return partial_evaluate (condition, ns);
273277}
274278
275279
@@ -506,11 +510,64 @@ bool constant_propagator_domaint::merge(
506510// / \param expr The expression to evaluate
507511// / \param ns The namespace for symbols in the expression
508512// / \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 (
510568 exprt &expr,
511569 const namespacet &ns) const
512570{
513- adjust_float_expressions (expr, ns);
514571 bool did_not_change_anything = values.replace_const .replace (expr);
515572 did_not_change_anything &= simplify (expr, ns);
516573 return did_not_change_anything;
@@ -541,33 +598,33 @@ void constant_propagator_ait::replace(
541598
542599 if (it->is_goto () || it->is_assume () || it->is_assert ())
543600 {
544- s_it->second .try_evaluate (it->guard , ns);
601+ s_it->second .partial_evaluate (it->guard , ns);
545602 }
546603 else if (it->is_assign ())
547604 {
548605 exprt &rhs=to_code_assign (it->code ).rhs ();
549- s_it->second .try_evaluate (rhs, ns);
606+ s_it->second .partial_evaluate (rhs, ns);
550607 if (rhs.id ()==ID_constant)
551608 rhs.add_source_location ()=it->code .op0 ().source_location ();
552609 }
553610 else if (it->is_function_call ())
554611 {
555612 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);
557614
558615 exprt::operandst &args=
559616 to_code_function_call (it->code ).arguments ();
560617
561618 for (auto &arg : args)
562619 {
563- s_it->second .try_evaluate (arg, ns);
620+ s_it->second .partial_evaluate (arg, ns);
564621 }
565622 }
566623 else if (it->is_other ())
567624 {
568625 if (it->code .get_statement ()==ID_expression)
569626 {
570- s_it->second .try_evaluate (it->code , ns);
627+ s_it->second .partial_evaluate (it->code , ns);
571628 }
572629 }
573630 }
0 commit comments