Skip to content
STIMSMITH

array constraint handling

Concept WIKI v1 · 6/3/2026

Array constraint handling is an approach to representing and solving constraints over indexed storage without expanding every array update into constraints over every element. In the cited ST processor test-generation work, a naive SSA-style translation is rejected as impractical for large memories; two alternatives are discussed: solver-level read/write constraints (`tabRead` and `tabWrite`) and a two-step alias-based strategy that first fixes equality relationships between array indices and then posts the corresponding constraints.

Overview

Array constraint handling addresses how reads and writes to arrays are represented in a constraint store. The motivating problem is that an array update can affect the value seen by later reads, especially when two array indices may alias, i.e. refer to the same element.

The cited work contrasts a direct element-wise translation with specialized array-handling strategies. In an SSA-like construction, each assignment to one element of an array of size n introduces 2n - 1 element constraints: two constraints for each of the n - 1 elements not assigned, plus one for the assigned element. For a memory addressed by 24-bit index registers, this leads to a very large number of constraints and is described as impractical in the ST processor setting.

Solver-level read and write constraints

One proposed strategy is to introduce an array type directly in the solver, together with two constraints for array access:

  • tabRead, for read access to array elements;
  • tabWrite, for write access to array elements.

These constraints are responsible for maintaining consistency between index relationships and value relationships. The paper describes propagation in both directions, from equal indices to equal array values and from equal array values to index equality:

i = j       => T[i] = T[j]
T[i] = T[j] => i = j

For example, in a sequence that reads mem[X], writes mem[Y] = 2, and then reads mem[X] again, if Y is equal to X, the second read of mem[X] must reflect the write. This requires two tabRead constraints and one tabWrite constraint in the store.

The drawback of this direct solver-level approach is order dependence: the order of accesses in the original code must be preserved, which conflicts with the usual order-independent nature of constraint solving. The paper also notes that static dependency analysis is limited because index relationships are only known dynamically.

Alias-based two-step strategy

The alternative strategy separates array manipulation into two steps:

  1. fix equality or inequality relationships between indices; then
  2. post constraints that enforce the chosen relationships.

In the example with three array accesses, the relevant question is which accesses alias the same memory location. The number of possible equality relationships among n indices is the number of partitions of an n-element set, i.e. the nth Bell number. Although Bell numbers grow exponentially, the cited work argues that this is acceptable in context because the solver searches for only a correct combination of index relationships.

This strategy enables an alias coverage criterion, which can estimate how well the different choices of index relationships have been covered. The paper specifically motivates this criterion with self-referential memory expressions such as mem[mem[i]] when mem[i] = i.

Benefits and limitations

The alias-based approach has two stated advantages:

  • variable independence can be analyzed so that the constraint store can be split into independent groups of variables;
  • graph analysis can be used to infer heuristics for variable ordering, improving solving performance.

Its main drawback is that a chosen set of index relationships may be inconsistent with other constraints already in the store. The cited work relies on the constraint solver's backtracking mechanism to recover from such failures, and notes that symbolic solving can avoid inconsistent choices in many cases.

CITATIONS

9 sources
9 citations
[1] SSA-like array translation creates 2n - 1 element constraints per assignment, which becomes impractical for large memories such as 24-bit-addressed ST processor memory. { Fabrice.Baray,Henri.Michel}
[2] The direct solver-level strategy introduces an array type with tabRead and tabWrite constraints for read and write accesses. { Fabrice.Baray,Henri.Michel}
[3] tabRead and tabWrite maintain consistency through propagations between index equality and array-value equality. { Fabrice.Baray,Henri.Michel}
[4] The direct tabRead/tabWrite approach is order-dependent and limits static dependency analysis because indices are known dynamically. { Fabrice.Baray,Henri.Michel}
[5] The alternative array-manipulation strategy first fixes equality relationships between indices and then posts constraints enforcing those relationships. { Fabrice.Baray,Henri.Michel}
[6] The number of possible relationships among n indices is the nth Bell number, and the paper treats the exponential complexity as acceptable because only a correct combination is searched for. { Fabrice.Baray,Henri.Michel}
[7] An alias coverage criterion is proposed to estimate coverage of different index-relationship choices, with self-referential memory such as mem[mem[i]] where mem[i] = i as a motivating case. { Fabrice.Baray,Henri.Michel}
[8] The alias-based strategy supports splitting the constraint store into independent variable groups and using graph analysis for variable-ordering heuristics. { Fabrice.Baray,Henri.Michel}
[9] A limitation of the alias-based strategy is that selected index relationships can be inconsistent with other constraints; the work relies on solver backtracking and sometimes symbolic solving to recover or avoid such cases. { Fabrice.Baray,Henri.Michel}