@@ -22,7 +22,10 @@ Author: Peter Schrammel
22
22
#include < util/cprover_prefix.h>
23
23
24
24
#include < langapi/language_util.h>
25
- #include < goto-programs/adjust_float_expressions.h>
25
+ #include < util/ieee_float.h>
26
+
27
+ #include < algorithm>
28
+ #include < array>
26
29
27
30
void constant_propagator_domaint::assign_rec (
28
31
valuest &values,
@@ -36,7 +39,7 @@ void constant_propagator_domaint::assign_rec(
36
39
const symbol_exprt &s=to_symbol_expr (lhs);
37
40
38
41
exprt tmp=rhs;
39
- try_evaluate (tmp, ns);
42
+ partial_evaluate (tmp, ns);
40
43
41
44
if (tmp.is_constant ())
42
45
values.set_to (s, tmp);
@@ -102,7 +105,7 @@ void constant_propagator_domaint::transform(
102
105
g = from->guard ;
103
106
else
104
107
g = not_exprt (from->guard );
105
- try_evaluate (g, ns);
108
+ partial_evaluate (g, ns);
106
109
if (g.is_false ())
107
110
values.set_to_bottom ();
108
111
else
@@ -269,7 +272,7 @@ bool constant_propagator_domaint::ai_simplify(
269
272
exprt &condition,
270
273
const namespacet &ns) const
271
274
{
272
- return try_evaluate (condition, ns);
275
+ return partial_evaluate (condition, ns);
273
276
}
274
277
275
278
@@ -506,11 +509,60 @@ bool constant_propagator_domaint::merge(
506
509
// / \param expr The expression to evaluate
507
510
// / \param ns The namespace for symbols in the expression
508
511
// / \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)))
520
+ {
521
+ return partial_evaluate_with_all_rounding_modes (expr, ns);
522
+ }
523
+ return replace_constants_and_simplify (expr, ns);
524
+ }
525
+
526
+ bool constant_propagator_domaint::partial_evaluate_with_all_rounding_modes (
527
+ exprt &expr,
528
+ const namespacet &ns) const
529
+ { // NOLINTNEXTLINE (whitespace/braces)
530
+ auto rounding_modes = std::array<ieee_floatt::rounding_modet, 4 >{
531
+ // NOLINTNEXTLINE (whitespace/braces)
532
+ {ieee_floatt::ROUND_TO_EVEN,
533
+ ieee_floatt::ROUND_TO_ZERO,
534
+ ieee_floatt::ROUND_TO_MINUS_INF,
535
+ // NOLINTNEXTLINE (whitespace/braces)
536
+ ieee_floatt::ROUND_TO_PLUS_INF}};
537
+ exprt first_result;
538
+ for (std::size_t i = 0 ; i < rounding_modes.size (); ++i)
539
+ {
540
+ constant_propagator_domaint child (*this );
541
+ child.values .set_to (
542
+ ID_cprover_rounding_mode,
543
+ from_integer (rounding_modes[i], integer_typet ()));
544
+ exprt result = expr;
545
+ if (child.replace_constants_and_simplify (result, ns))
546
+ {
547
+ return true ;
548
+ }
549
+ else if (i == 0 )
550
+ {
551
+ first_result = result;
552
+ }
553
+ else if (result != first_result)
554
+ {
555
+ return true ;
556
+ }
557
+ }
558
+ expr = first_result;
559
+ return false ;
560
+ }
561
+
562
+ bool constant_propagator_domaint::replace_constants_and_simplify (
510
563
exprt &expr,
511
564
const namespacet &ns) const
512
565
{
513
- adjust_float_expressions (expr, ns);
514
566
bool did_not_change_anything = values.replace_const .replace (expr);
515
567
did_not_change_anything &= simplify (expr, ns);
516
568
return did_not_change_anything;
@@ -541,33 +593,33 @@ void constant_propagator_ait::replace(
541
593
542
594
if (it->is_goto () || it->is_assume () || it->is_assert ())
543
595
{
544
- s_it->second .try_evaluate (it->guard , ns);
596
+ s_it->second .partial_evaluate (it->guard , ns);
545
597
}
546
598
else if (it->is_assign ())
547
599
{
548
600
exprt &rhs=to_code_assign (it->code ).rhs ();
549
- s_it->second .try_evaluate (rhs, ns);
601
+ s_it->second .partial_evaluate (rhs, ns);
550
602
if (rhs.id ()==ID_constant)
551
603
rhs.add_source_location ()=it->code .op0 ().source_location ();
552
604
}
553
605
else if (it->is_function_call ())
554
606
{
555
607
exprt &function = to_code_function_call (it->code ).function ();
556
- s_it->second .try_evaluate (function, ns);
608
+ s_it->second .partial_evaluate (function, ns);
557
609
558
610
exprt::operandst &args=
559
611
to_code_function_call (it->code ).arguments ();
560
612
561
613
for (auto &arg : args)
562
614
{
563
- s_it->second .try_evaluate (arg, ns);
615
+ s_it->second .partial_evaluate (arg, ns);
564
616
}
565
617
}
566
618
else if (it->is_other ())
567
619
{
568
620
if (it->code .get_statement ()==ID_expression)
569
621
{
570
- s_it->second .try_evaluate (it->code , ns);
622
+ s_it->second .partial_evaluate (it->code , ns);
571
623
}
572
624
}
573
625
}
0 commit comments