Skip to content

Commit 9bfa965

Browse files
committed
widening interval_abstract_value lower_bound can be minimum
If new lower bound is already at minimum, or underflows, then explicitly set to min_exprt(type)
1 parent 3756bae commit 9bfa965

File tree

2 files changed

+154
-14
lines changed

2 files changed

+154
-14
lines changed

src/analyses/variable-sensitivity/interval_abstract_value.cpp

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,14 @@ void interval_abstract_valuet::output(
346346
}
347347
}
348348

349-
exprt extend_upper_bound(const exprt &upper_bound, const exprt& range, const namespacet& ns);
349+
exprt extend_lower_bound(
350+
const exprt &lower_bound,
351+
const exprt &range,
352+
const namespacet &ns);
353+
exprt extend_upper_bound(
354+
const exprt &upper_bound,
355+
const exprt &range,
356+
const namespacet &ns);
350357

351358
abstract_object_pointert widening_merge(
352359
const constant_interval_exprt &lhs,
@@ -361,37 +368,61 @@ abstract_object_pointert widening_merge(
361368
auto dummy_namespace = namespacet{dummy_symbol_table};
362369

363370
auto range = plus_exprt(
364-
minus_exprt(upper_bound, lower_bound), from_integer(1, lhs.type()));
371+
minus_exprt(upper_bound, lower_bound), from_integer(1, lhs.type()));
365372

366373
// should extend lower bound?
367-
if(rhs.get_lower() < lhs.get_lower()) lower_bound =
368-
simplify_expr(minus_exprt(lower_bound, range), dummy_namespace);
374+
if(constant_interval_exprt::less_than(rhs.get_lower(), lhs.get_lower()))
375+
lower_bound = extend_lower_bound(lower_bound, range, dummy_namespace);
369376
// should extend upper bound?
370-
if(lhs.get_upper() < rhs.get_upper())
377+
if(constant_interval_exprt::less_than(lhs.get_upper(), rhs.get_upper()))
371378
upper_bound = extend_upper_bound(upper_bound, range, dummy_namespace);
372379

373380
// new interval ...
374381
auto new_interval = constant_interval_exprt(lower_bound, upper_bound);
375382
return interval_abstract_valuet::make_interval(new_interval);
376383
}
377384

378-
bool has_overflowed(const exprt& value)
385+
bool has_underflowed(const exprt &value)
379386
{
380-
return constant_interval_exprt::less_than(value, from_integer(0, value.type()));
387+
return constant_interval_exprt::greater_than(
388+
value, from_integer(0, value.type()));
381389
}
390+
bool has_overflowed(const exprt &value)
391+
{
392+
return constant_interval_exprt::less_than(
393+
value, from_integer(0, value.type()));
394+
}
395+
396+
exprt extend_lower_bound(
397+
const exprt &lower_bound,
398+
const exprt &range,
399+
const namespacet &ns)
400+
{
401+
auto new_lower_bound = simplify_expr(minus_exprt(lower_bound, range), ns);
382402

383-
exprt extend_upper_bound(const exprt &upper_bound, const exprt& range, const namespacet& ns)
403+
if(
404+
constant_interval_exprt::contains_extreme(new_lower_bound) ||
405+
has_underflowed(new_lower_bound))
406+
return min_exprt(lower_bound.type());
407+
408+
return new_lower_bound;
409+
}
410+
411+
exprt extend_upper_bound(
412+
const exprt &upper_bound,
413+
const exprt &range,
414+
const namespacet &ns)
384415
{
385416
auto new_upper_bound = simplify_expr(plus_exprt(upper_bound, range), ns);
386417

387-
if (constant_interval_exprt::contains_extreme(new_upper_bound) ||
388-
has_overflowed(new_upper_bound))
418+
if(
419+
constant_interval_exprt::contains_extreme(new_upper_bound) ||
420+
has_overflowed(new_upper_bound))
389421
return max_exprt(upper_bound.type());
390422

391423
return new_upper_bound;
392424
}
393425

394-
395426
abstract_object_pointert interval_abstract_valuet::merge_with_value(
396427
const abstract_value_pointert &other,
397428
const widen_modet &widen_mode) const

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

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
#include <util/arith_tools.h>
1414
#include <util/bitvector_types.h>
1515

16-
static merge_result<const interval_abstract_valuet>
17-
widening_merge(const abstract_object_pointert &op1, const abstract_object_pointert &op2)
16+
static merge_result<const interval_abstract_valuet> widening_merge(
17+
const abstract_object_pointert &op1,
18+
const abstract_object_pointert &op2)
1819
{
1920
auto result = abstract_objectt::merge(op1, op2, widen_modet::could_widen);
2021

@@ -319,7 +320,7 @@ SCENARIO(
319320
}
320321
WHEN("merging [0, 1] with [1, very_large]")
321322
{
322-
auto veryLarge = from_integer(2<<29, type);
323+
auto veryLarge = from_integer(2 << 29, type);
323324
auto op1 = make_interval(val0, val1, environment, ns);
324325
auto op2 = make_interval(val1, veryLarge, environment, ns);
325326

@@ -330,5 +331,113 @@ SCENARIO(
330331
EXPECT_MODIFIED(merged, val0, valMax);
331332
}
332333
}
334+
335+
WHEN("merging [1, 10] with [MIN, 1]")
336+
{
337+
auto op1 = make_interval(val1, val10, environment, ns);
338+
auto op2 = make_interval(valMin, val1, environment, ns);
339+
340+
auto merged = widening_merge(op1, op2);
341+
342+
THEN("result is [MIN, 10]")
343+
{
344+
EXPECT_MODIFIED(merged, valMin, val10);
345+
}
346+
}
347+
WHEN("merging [0, 1] with [-very_large, 1]")
348+
{
349+
auto veryLargeMinus = from_integer(-(2 << 29), type);
350+
auto op1 = make_interval(val0, val1, environment, ns);
351+
auto op2 = make_interval(veryLargeMinus, val1, environment, ns);
352+
353+
auto merged = widening_merge(op1, op2);
354+
355+
THEN("result is [MIN, 1]")
356+
{
357+
EXPECT_MODIFIED(merged, valMin, val1);
358+
}
359+
}
360+
361+
WHEN("merging [1, MAX] with [MIN, 1]")
362+
{
363+
auto op1 = make_interval(val1, valMax, environment, ns);
364+
auto op2 = make_interval(valMin, val1, environment, ns);
365+
366+
auto merged = widening_merge(op1, op2);
367+
368+
THEN("result is TOP - ie [MIN, MAX]")
369+
{
370+
EXPECT_MODIFIED_TOP(merged);
371+
}
372+
}
373+
WHEN("merging [MIN, 1] with [1, MAX]")
374+
{
375+
auto op1 = make_interval(valMin, val1, environment, ns);
376+
auto op2 = make_interval(val1, valMax, environment, ns);
377+
378+
auto merged = widening_merge(op1, op2);
379+
380+
THEN("result is TOP - ie [MIN, MAX]")
381+
{
382+
EXPECT_MODIFIED_TOP(merged);
383+
}
384+
}
385+
WHEN("merging [0, very_large] with [-very_large, 0]")
386+
{
387+
auto veryLarge = from_integer(2 << 29, type);
388+
auto veryLargeMinus = from_integer(-(2 << 29), type);
389+
auto op1 = make_interval(val0, veryLarge, environment, ns);
390+
auto op2 = make_interval(veryLargeMinus, val0, environment, ns);
391+
392+
auto merged = widening_merge(op1, op2);
393+
394+
THEN("result is [MIN, very_large]")
395+
{
396+
EXPECT_MODIFIED(merged, valMin, veryLarge);
397+
}
398+
}
399+
WHEN("merging [-very_large, 0] with [0, very_large]")
400+
{
401+
auto veryLarge = from_integer(2 << 29, type);
402+
auto veryLargeMinus = from_integer(-(2 << 29), type);
403+
auto op1 = make_interval(veryLargeMinus, val0, environment, ns);
404+
auto op2 = make_interval(val0, veryLarge, environment, ns);
405+
406+
auto merged = widening_merge(op1, op2);
407+
408+
THEN("result is [-very_large, MAX]")
409+
{
410+
EXPECT_MODIFIED(merged, veryLargeMinus, valMax);
411+
}
412+
}
413+
414+
WHEN("merging [-very_large, very_large] with [0, 1]")
415+
{
416+
auto veryLarge = from_integer(2 << 29, type);
417+
auto veryLargeMinus = from_integer(-(2 << 29), type);
418+
auto op1 = make_interval(veryLargeMinus, veryLarge, environment, ns);
419+
auto op2 = make_interval(val0, val1, environment, ns);
420+
421+
auto merged = widening_merge(op1, op2);
422+
423+
THEN("result is [-very_large, very_large]")
424+
{
425+
EXPECT_UNMODIFIED(merged, veryLargeMinus, veryLarge);
426+
}
427+
}
428+
WHEN("merging [0, 1] with [-very_large, very_large]")
429+
{
430+
auto veryLarge = from_integer(2 << 29, type);
431+
auto veryLargeMinus = from_integer(-(2 << 29), type);
432+
auto op1 = make_interval(val0, val1, environment, ns);
433+
auto op2 = make_interval(veryLargeMinus, veryLarge, environment, ns);
434+
435+
auto merged = widening_merge(op1, op2);
436+
437+
THEN("result is TOP, ie [MIN, MAX]")
438+
{
439+
EXPECT_MODIFIED_TOP(merged);
440+
}
441+
}
333442
}
334443
}

0 commit comments

Comments
 (0)