Skip to content

Fixpoint not reached because narrowing for Enums does not guarantee termination #1673

Closed
@michael-schwarz

Description

@michael-schwarz

@jerhard and I debugged one of the issues where fixpoint refinement does not terminate identified by our students in #1671 . It turns out the non-termination is due to infinite descending chains encountered during narrowing in the Enum domain after refining with Def_Exc.

// PARAM: --set ana.int.refinement fixpoint --enable ana.int.enums --enable ana.int.def_exc  --enable ana.int.interval --set sem.int.signed_overflow assume_none
int main() {
   int count = 0;
   while (1) {
     count++;
     count++;
   }
 }

In detail the following happens:

  • Widening terminates and a switch to narrowing is performed
  • Def_exc benefits from the Interval information [1,infty] and infers a value of Exc {0} after the first increment
  • The next increment turns this into Exc {1}
  • The information is transferred to Enum
  • At the loop head narrowing happens by meet in the Enum domain leading to Exc {1}
  • The first increment and refinement with interval information leads to a value Exc {0,2} in Def_Exc
  • The second increment action turns this into Exc {1,3}
  • This information is propagated to enums
  • ...

Without refinement, these issues do not surface as:

  • Def_exc does no narrowing of exclusion sets
  • Enum does not do computations

The second point is why Enums gets away with setting narrow to meet: Without refinement the only values that can become part of the exclusion set are given by constants in the program. Such guarantees go away when performing refinement.

There are multiple solutions:

  • a) Do not refine to Exc {0} for intervals that do not contain 0
  • b) Set narrow in Enums to return its left argument
  • c) Do not refine between Enums and Def_Exc
  • d) Fix narrowing in Enums to satisfy descending chain condition, but unlike b) maintain some precision, e.g., by bounding the size of exclusion sets created during narrowing by a constant k, and return the left argument during narrowing if it already has k or more elements.

@jerhard and I would propose to go for solution d).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions