@@ -22,6 +22,10 @@ Author: Peter Schrammel
2222
2323#include < langapi/language_util.h>
2424#include < goto-programs/adjust_float_expressions.h>
25+ #include < util/ieee_float.h>
26+
27+ #include < algorithm>
28+ #include < array>
2529
2630void constant_propagator_domaint::assign_rec (
2731 valuest &values,
@@ -509,7 +513,46 @@ bool constant_propagator_domaint::try_evaluate(
509513 exprt &expr,
510514 const namespacet &ns) const
511515{
516+ const irep_idt ID_rounding_mode = CPROVER_PREFIX " rounding_mode" ;
512517 adjust_float_expressions (expr, ns);
518+
519+ // if the current rounding mode is top we can
520+ // still get a non-top result by trying all rounding
521+ // modes and checking if the results are all the same
522+ if (!values.is_constant (symbol_exprt (ID_rounding_mode)))
523+ {
524+ // NOLINTNEXTLINE (whitespace/braces)
525+ auto rounding_modes = std::array<ieee_floatt::rounding_modet, 4 >{
526+ // NOLINTNEXTLINE (whitespace/braces)
527+ {ieee_floatt::ROUND_TO_EVEN,
528+ ieee_floatt::ROUND_TO_ZERO,
529+ ieee_floatt::ROUND_TO_MINUS_INF,
530+ // NOLINTNEXTLINE (whitespace/braces)
531+ ieee_floatt::ROUND_TO_PLUS_INF}};
532+ // instead of 4, we could write rounding_modes.size() here
533+ // if we dropped Visual Studio 2013 support (no constexpr)
534+ std::array<exprt, 4 > possible_results;
535+ for (std::size_t i = 0 ; i < possible_results.size (); ++i)
536+ {
537+ constant_propagator_domaint child (*this );
538+ child.values .set_to (
539+ ID_rounding_mode, from_integer (rounding_modes[i], integer_typet ()));
540+ possible_results[i] = expr;
541+ if (child.try_evaluate (possible_results[i], ns))
542+ {
543+ return true ;
544+ }
545+ }
546+ for (auto const &possible_result : possible_results)
547+ {
548+ if (possible_result != possible_results.front ())
549+ {
550+ return true ;
551+ }
552+ }
553+ expr = possible_results.front ();
554+ return false ;
555+ }
513556 bool did_not_change_anything = values.replace_const .replace (expr);
514557 did_not_change_anything &= simplify (expr, ns);
515558 return did_not_change_anything;
0 commit comments