Skip to content

Commit 713d2c1

Browse files
committed
Widen merged intervals when widen_modet is could_widen
Extends upper and/or lower bound by the width of the interval. Does not widen in lhs value would be unchanged in non-widening merge - ie only widens if interval is extended by the merge.
1 parent 32e5558 commit 713d2c1

File tree

6 files changed

+366
-21
lines changed

6 files changed

+366
-21
lines changed

regression/goto-analyzer/loop-termination-ne/test-unwind-5-intervals.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^main::1::1::i .* \[5, 5\] @ \[6\]
7-
^main::1::p .* \[2, 20\] @ \[5\]
87
--

src/analyses/variable-sensitivity/interval_abstract_value.cpp

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,13 @@ interval_abstract_valuet::interval_abstract_valuet(
254254
{
255255
}
256256

257+
interval_abstract_valuet::interval_abstract_valuet(
258+
const exprt &lower,
259+
const exprt &upper)
260+
: interval_abstract_valuet(constant_interval_exprt(lower, upper))
261+
{
262+
}
263+
257264
interval_abstract_valuet::interval_abstract_valuet(
258265
const exprt &e,
259266
const abstract_environmentt &environment,
@@ -344,14 +351,34 @@ void interval_abstract_valuet::output(
344351
}
345352
}
346353

347-
/// Merge another interval abstract object with this one
348-
/// \param other The abstract value object to merge with
349-
/// \param widen_mode: Indicates if this is a widening merge
350-
/// \return This if the other interval is subsumed by this,
351-
/// other if this is subsumed by other.
352-
/// Otherwise, a new interval abstract object
353-
/// with the smallest interval that subsumes both
354-
/// this and other
354+
abstract_object_pointert widening_merge(
355+
const constant_interval_exprt &lhs,
356+
const constant_interval_exprt &rhs)
357+
{
358+
auto lower_bound =
359+
constant_interval_exprt::get_min(lhs.get_lower(), rhs.get_lower());
360+
auto upper_bound =
361+
constant_interval_exprt::get_max(lhs.get_upper(), rhs.get_upper());
362+
auto range = plus_exprt(
363+
minus_exprt(upper_bound, lower_bound), from_integer(1, lhs.type()));
364+
365+
auto dummy_symbol_table = symbol_tablet{};
366+
auto dummy_namespace = namespacet{dummy_symbol_table};
367+
368+
// should extend lower bound?
369+
if(rhs.get_lower() < lhs.get_lower())
370+
lower_bound =
371+
simplify_expr(minus_exprt(lower_bound, range), dummy_namespace);
372+
// should extend upper bound?
373+
if(lhs.get_upper() < rhs.get_upper())
374+
upper_bound =
375+
simplify_expr(plus_exprt(upper_bound, range), dummy_namespace);
376+
377+
// new interval ...
378+
auto new_interval = constant_interval_exprt(lower_bound, upper_bound);
379+
return make_interval(new_interval);
380+
}
381+
355382
abstract_object_pointert interval_abstract_valuet::merge_with_value(
356383
const abstract_value_pointert &other,
357384
const widen_modet &widen_mode) const
@@ -367,19 +394,17 @@ abstract_object_pointert interval_abstract_valuet::merge_with_value(
367394
if(interval.contains(other_interval))
368395
return shared_from_this();
369396

370-
return make_interval(constant_interval_exprt(
371-
constant_interval_exprt::get_min(
372-
interval.get_lower(), other_interval.get_lower()),
373-
constant_interval_exprt::get_max(
374-
interval.get_upper(), other_interval.get_upper())));
397+
if(widen_mode == widen_modet::could_widen)
398+
return widening_merge(interval, other_interval);
399+
400+
auto lower_bound = constant_interval_exprt::get_min(
401+
interval.get_lower(), other_interval.get_lower());
402+
auto upper_bound = constant_interval_exprt::get_max(
403+
interval.get_upper(), other_interval.get_upper());
404+
405+
return make_interval(lower_bound, upper_bound);
375406
}
376407

377-
/// Meet another interval abstract object with this one
378-
/// \param other The interval abstract object to meet with
379-
/// \return This if the other interval subsumes this,
380-
/// other if this subsumes other.
381-
/// Otherwise, a new interval abstract object
382-
/// with the intersection interval (of this and other)
383408
abstract_object_pointert interval_abstract_valuet::meet_with_value(
384409
const abstract_value_pointert &other) const
385410
{

src/analyses/variable-sensitivity/interval_abstract_value.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class interval_abstract_valuet : public abstract_value_objectt
2727
interval_abstract_valuet(const typet &t, bool tp, bool bttm);
2828

2929
explicit interval_abstract_valuet(const constant_interval_exprt &e);
30+
interval_abstract_valuet(const exprt &lower, const exprt &upper);
3031

3132
interval_abstract_valuet(
3233
const exprt &e,
@@ -63,10 +64,24 @@ class interval_abstract_valuet : public abstract_value_objectt
6364
protected:
6465
CLONE
6566

67+
/// Merge another interval abstract object with this one
68+
/// \param other The abstract value object to merge with
69+
/// \param widen_mode: Indicates if this is a widening merge
70+
/// \return This if the other interval is subsumed by this,
71+
/// other if this is subsumed by other.
72+
/// Otherwise, a new interval abstract object
73+
/// with the smallest interval that subsumes both
74+
/// this and other
6675
abstract_object_pointert merge_with_value(
6776
const abstract_value_pointert &other,
6877
const widen_modet &widen_mode) const override;
6978

79+
/// Meet another interval abstract object with this one
80+
/// \param other The interval abstract object to meet with
81+
/// \return This if the other interval subsumes this,
82+
/// other if this subsumes other.
83+
/// Otherwise, a new interval abstract object
84+
/// with the intersection interval (of this and other)
7085
abstract_object_pointert
7186
meet_with_value(const abstract_value_pointert &other) const override;
7287

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ SRC += analyses/ai/ai.cpp \
2323
analyses/variable-sensitivity/eval-member-access.cpp \
2424
analyses/variable-sensitivity/interval_abstract_value/meet.cpp \
2525
analyses/variable-sensitivity/interval_abstract_value/merge.cpp \
26+
analyses/variable-sensitivity/interval_abstract_value/widening_merge.cpp \
2627
analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp \
2728
analyses/variable-sensitivity/last_written_location.cpp \
2829
analyses/variable-sensitivity/value_expression_evaluation/assume.cpp \

unit/analyses/variable-sensitivity/interval_abstract_value/merge.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*******************************************************************\
22
3-
Module: Unit tests for intervalabstract_valuet::merge
3+
Module: Unit tests for interval_abstract_valuet::merge
44
55
Author: Jez Higgins.
66

0 commit comments

Comments
 (0)