@@ -16,13 +16,16 @@ Author: Peter Schrammel
1616#include < util/format_expr.h>
1717#endif
1818
19+ #include < util/ieee_float.h>
1920#include < util/find_symbols.h>
2021#include < util/arith_tools.h>
2122#include < util/simplify_expr.h>
2223#include < util/cprover_prefix.h>
2324
2425#include < langapi/language_util.h>
25- #include < goto-programs/adjust_float_expressions.h>
26+
27+ #include < algorithm>
28+ #include < array>
2629
2730void 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,64 @@ 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_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 (
510567 exprt &expr,
511568 const namespacet &ns) const
512569{
513- adjust_float_expressions (expr, ns);
514570 bool did_not_change_anything = values.replace_const .replace (expr);
515571 did_not_change_anything &= simplify (expr, ns);
516572 return did_not_change_anything;
@@ -541,33 +597,33 @@ void constant_propagator_ait::replace(
541597
542598 if (it->is_goto () || it->is_assume () || it->is_assert ())
543599 {
544- s_it->second .try_evaluate (it->guard , ns);
600+ s_it->second .partial_evaluate (it->guard , ns);
545601 }
546602 else if (it->is_assign ())
547603 {
548604 exprt &rhs=to_code_assign (it->code ).rhs ();
549- s_it->second .try_evaluate (rhs, ns);
605+ s_it->second .partial_evaluate (rhs, ns);
550606 if (rhs.id ()==ID_constant)
551607 rhs.add_source_location ()=it->code .op0 ().source_location ();
552608 }
553609 else if (it->is_function_call ())
554610 {
555611 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);
557613
558614 exprt::operandst &args=
559615 to_code_function_call (it->code ).arguments ();
560616
561617 for (auto &arg : args)
562618 {
563- s_it->second .try_evaluate (arg, ns);
619+ s_it->second .partial_evaluate (arg, ns);
564620 }
565621 }
566622 else if (it->is_other ())
567623 {
568624 if (it->code .get_statement ()==ID_expression)
569625 {
570- s_it->second .try_evaluate (it->code , ns);
626+ s_it->second .partial_evaluate (it->code , ns);
571627 }
572628 }
573629 }
0 commit comments