@@ -22,6 +22,10 @@ Author: Peter Schrammel
22
22
23
23
#include < langapi/language_util.h>
24
24
#include < goto-programs/adjust_float_expressions.h>
25
+ #include < util/ieee_float.h>
26
+
27
+ #include < algorithm>
28
+ #include < array>
25
29
26
30
void constant_propagator_domaint::assign_rec (
27
31
valuest &values,
@@ -509,7 +513,46 @@ bool constant_propagator_domaint::try_evaluate(
509
513
exprt &expr,
510
514
const namespacet &ns) const
511
515
{
516
+ const irep_idt ID_rounding_mode = CPROVER_PREFIX " rounding_mode" ;
512
517
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
+ }
513
556
bool did_not_change_anything = values.replace_const .replace (expr);
514
557
did_not_change_anything &= simplify (expr, ns);
515
558
return did_not_change_anything;
0 commit comments