@@ -23,6 +23,10 @@ Author: Peter Schrammel
23
23
24
24
#include < langapi/language_util.h>
25
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,
@@ -510,7 +514,46 @@ bool constant_propagator_domaint::try_evaluate(
510
514
exprt &expr,
511
515
const namespacet &ns) const
512
516
{
517
+ const irep_idt ID_rounding_mode = CPROVER_PREFIX " rounding_mode" ;
513
518
adjust_float_expressions (expr, ns);
519
+
520
+ // if the current rounding mode is top we can
521
+ // still get a non-top result by trying all rounding
522
+ // modes and checking if the results are all the same
523
+ if (!values.is_constant (symbol_exprt (ID_rounding_mode)))
524
+ {
525
+ // NOLINTNEXTLINE (whitespace/braces)
526
+ auto rounding_modes = std::array<ieee_floatt::rounding_modet, 4 >{
527
+ // NOLINTNEXTLINE (whitespace/braces)
528
+ {ieee_floatt::ROUND_TO_EVEN,
529
+ ieee_floatt::ROUND_TO_ZERO,
530
+ ieee_floatt::ROUND_TO_MINUS_INF,
531
+ // NOLINTNEXTLINE (whitespace/braces)
532
+ ieee_floatt::ROUND_TO_PLUS_INF}};
533
+ // instead of 4, we could write rounding_modes.size() here
534
+ // if we dropped Visual Studio 2013 support (no constexpr)
535
+ std::array<exprt, 4 > possible_results;
536
+ for (std::size_t i = 0 ; i < possible_results.size (); ++i)
537
+ {
538
+ constant_propagator_domaint child (*this );
539
+ child.values .set_to (
540
+ ID_rounding_mode, from_integer (rounding_modes[i], integer_typet ()));
541
+ possible_results[i] = expr;
542
+ if (child.try_evaluate (possible_results[i], ns))
543
+ {
544
+ return true ;
545
+ }
546
+ }
547
+ for (auto const &possible_result : possible_results)
548
+ {
549
+ if (possible_result != possible_results.front ())
550
+ {
551
+ return true ;
552
+ }
553
+ }
554
+ expr = possible_results.front ();
555
+ return false ;
556
+ }
514
557
bool did_not_change_anything = values.replace_const .replace (expr);
515
558
did_not_change_anything &= simplify (expr, ns);
516
559
return did_not_change_anything;
0 commit comments