@@ -117,9 +117,8 @@ maybe_extract_single_value(const abstract_object_pointert &maybe_singleton);
117117static bool are_any_top (const abstract_object_sett &set);
118118
119119static abstract_object_sett compact_values (const abstract_object_sett &values);
120- static abstract_object_sett
121- non_destructive_compact (const abstract_object_sett &values);
122120static abstract_object_sett widen_value_set (
121+ const abstract_object_sett &values,
123122 const constant_interval_exprt &lhs,
124123 const constant_interval_exprt &rhs);
125124
@@ -230,8 +229,8 @@ abstract_object_pointert value_set_abstract_objectt::merge_with_value(
230229 widen_mode == widen_modet::could_widen && has_values (shared_from_this ()) &&
231230 has_values (other))
232231 {
233- union_values. insert ( widen_value_set ( to_interval (), other-> to_interval ()));
234- union_values = non_destructive_compact (union_values);
232+ union_values =
233+ widen_value_set (union_values, to_interval (), other-> to_interval () );
235234 }
236235
237236 return resolve_values (union_values);
@@ -416,6 +415,9 @@ static abstract_object_sett compact_values(const abstract_object_sett &values)
416415
417416static exprt eval_expr (const exprt &e);
418417static bool is_le (const exprt &lhs, const exprt &rhs);
418+ static abstract_object_sett collapse_values_in_intervals (
419+ const abstract_object_sett &values,
420+ const std::vector<constant_interval_exprt> &intervals);
419421static void
420422collapse_overlapping_intervals (std::vector<constant_interval_exprt> &intervals);
421423
@@ -474,24 +476,31 @@ non_destructive_compact(const abstract_object_sett &values)
474476 if (intervals.empty ())
475477 return values;
476478
477- auto compacted = abstract_object_sett{};
479+ return collapse_values_in_intervals (values, intervals);
480+ }
481+
482+ static abstract_object_sett collapse_values_in_intervals (
483+ const abstract_object_sett &values,
484+ const std::vector<constant_interval_exprt> &intervals)
485+ {
486+ auto collapsed = abstract_object_sett{};
478487 // for each value, including the intervals
479488 // keep it if it is not in any of the intervals
480489 std::copy_if (
481490 values.begin (),
482491 values.end (),
483- std::back_inserter (compacted ),
492+ std::back_inserter (collapsed ),
484493 [&intervals](const abstract_object_pointert &object) {
485494 return value_is_not_contained_in (object, intervals);
486495 });
487496 std::transform (
488497 intervals.begin (),
489498 intervals.end (),
490- std::back_inserter (compacted ),
499+ std::back_inserter (collapsed ),
491500 [](const constant_interval_exprt &interval) {
492501 return interval_abstract_valuet::make_interval (interval);
493502 });
494- return compacted ;
503+ return collapsed ;
495504}
496505
497506static abstract_object_sett
@@ -554,13 +563,14 @@ static bool is_le(const exprt &lhs, const exprt &rhs)
554563}
555564
556565static abstract_object_sett widen_value_set (
566+ const abstract_object_sett &values,
557567 const constant_interval_exprt &lhs,
558568 const constant_interval_exprt &rhs)
559569{
560- auto widened_ends = abstract_object_sett{};
561-
562570 if (lhs.contains (rhs))
563- return widened_ends;
571+ return values;
572+
573+ auto widened_ends = std::vector<constant_interval_exprt>{};
564574
565575 auto lower_bound =
566576 constant_interval_exprt::get_min (lhs.get_lower (), rhs.get_lower ());
@@ -575,19 +585,32 @@ static abstract_object_sett widen_value_set(
575585 // should extend lower bound?
576586 if (rhs.get_lower () < lhs.get_lower ())
577587 {
578- auto widened_lower_bound =
579- simplify_expr (minus_exprt (lower_bound, range), ns);
580- widened_ends.insert (interval_abstract_valuet::make_interval (
581- constant_interval_exprt (widened_lower_bound, lower_bound)));
588+ auto widened_lower_bound = constant_interval_exprt (
589+ simplify_expr (minus_exprt (lower_bound, range), ns), lower_bound);
590+ widened_ends.push_back (widened_lower_bound);
591+ for (auto &obj : values)
592+ {
593+ auto value = std::dynamic_pointer_cast<const abstract_value_objectt>(obj);
594+ auto as_expr = value->to_interval ();
595+ if (is_le (as_expr.get_lower (), lower_bound))
596+ widened_ends.push_back (as_expr);
597+ }
582598 }
583599 // should extend upper bound?
584600 if (lhs.get_upper () < rhs.get_upper ())
585601 {
586- auto widened_upper_bound =
587- simplify_expr (plus_exprt (upper_bound, range), ns);
588- widened_ends.insert (interval_abstract_valuet::make_interval (
589- constant_interval_exprt (upper_bound, widened_upper_bound)));
602+ auto widened_upper_bound = constant_interval_exprt (
603+ upper_bound, simplify_expr (plus_exprt (upper_bound, range), ns));
604+ widened_ends.push_back (widened_upper_bound);
605+ for (auto &obj : values)
606+ {
607+ auto value = std::dynamic_pointer_cast<const abstract_value_objectt>(obj);
608+ auto as_expr = value->to_interval ();
609+ if (is_le (upper_bound, as_expr.get_upper ()))
610+ widened_ends.push_back (as_expr);
611+ }
590612 }
591613
592- return widened_ends;
614+ collapse_overlapping_intervals (widened_ends);
615+ return collapse_values_in_intervals (values, widened_ends);
593616}
0 commit comments