@@ -117,9 +117,8 @@ maybe_extract_single_value(const abstract_object_pointert &maybe_singleton);
117
117
static bool are_any_top (const abstract_object_sett &set);
118
118
119
119
static abstract_object_sett compact_values (const abstract_object_sett &values);
120
- static abstract_object_sett
121
- non_destructive_compact (const abstract_object_sett &values);
122
120
static abstract_object_sett widen_value_set (
121
+ const abstract_object_sett &values,
123
122
const constant_interval_exprt &lhs,
124
123
const constant_interval_exprt &rhs);
125
124
@@ -230,8 +229,8 @@ abstract_object_pointert value_set_abstract_objectt::merge_with_value(
230
229
widen_mode == widen_modet::could_widen && has_values (shared_from_this ()) &&
231
230
has_values (other))
232
231
{
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 () );
235
234
}
236
235
237
236
return resolve_values (union_values);
@@ -416,6 +415,9 @@ static abstract_object_sett compact_values(const abstract_object_sett &values)
416
415
417
416
static exprt eval_expr (const exprt &e);
418
417
static 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);
419
421
static void
420
422
collapse_overlapping_intervals (std::vector<constant_interval_exprt> &intervals);
421
423
@@ -474,24 +476,31 @@ non_destructive_compact(const abstract_object_sett &values)
474
476
if (intervals.empty ())
475
477
return values;
476
478
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{};
478
487
// for each value, including the intervals
479
488
// keep it if it is not in any of the intervals
480
489
std::copy_if (
481
490
values.begin (),
482
491
values.end (),
483
- std::back_inserter (compacted ),
492
+ std::back_inserter (collapsed ),
484
493
[&intervals](const abstract_object_pointert &object) {
485
494
return value_is_not_contained_in (object, intervals);
486
495
});
487
496
std::transform (
488
497
intervals.begin (),
489
498
intervals.end (),
490
- std::back_inserter (compacted ),
499
+ std::back_inserter (collapsed ),
491
500
[](const constant_interval_exprt &interval) {
492
501
return interval_abstract_valuet::make_interval (interval);
493
502
});
494
- return compacted ;
503
+ return collapsed ;
495
504
}
496
505
497
506
static abstract_object_sett
@@ -554,13 +563,14 @@ static bool is_le(const exprt &lhs, const exprt &rhs)
554
563
}
555
564
556
565
static abstract_object_sett widen_value_set (
566
+ const abstract_object_sett &values,
557
567
const constant_interval_exprt &lhs,
558
568
const constant_interval_exprt &rhs)
559
569
{
560
- auto widened_ends = abstract_object_sett{};
561
-
562
570
if (lhs.contains (rhs))
563
- return widened_ends;
571
+ return values;
572
+
573
+ auto widened_ends = std::vector<constant_interval_exprt>{};
564
574
565
575
auto lower_bound =
566
576
constant_interval_exprt::get_min (lhs.get_lower (), rhs.get_lower ());
@@ -575,19 +585,32 @@ static abstract_object_sett widen_value_set(
575
585
// should extend lower bound?
576
586
if (rhs.get_lower () < lhs.get_lower ())
577
587
{
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
+ }
582
598
}
583
599
// should extend upper bound?
584
600
if (lhs.get_upper () < rhs.get_upper ())
585
601
{
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
+ }
590
612
}
591
613
592
- return widened_ends;
614
+ collapse_overlapping_intervals (widened_ends);
615
+ return collapse_values_in_intervals (values, widened_ends);
593
616
}
0 commit comments