Simplify affine expressions and maps while exploiting simple range and
step info of any IVs that are operands. This simplification is local,
O(1) and practically useful in several scenarios. Accesses with
floordiv's and mod's where the LHS is non-negative and bounded or is a
known multiple of a constant can often be simplified. This is
implemented as a canonicalization for all affine ops in a generic way:
all affine.load/store, vector_load/store, affine.apply, affine.min/max,
etc. ops.
Eg: For tiled loop nests accessing buffers this way:
affine.for %i = 0 to 1024 step 32 { affine.for %ii = 0 to 32 { affine.load [(%i + %ii) floordiv 32, (%i + %ii) mod 32] } }
// Note that %i is a multiple of 32 and %ii < 32, hence:
(%i + %ii) floordiv 32 here is the same as %i floordiv 32, and
(%i + %ii) mod 32 here is the same as %ii mod 32.
The simplification leads to simpler index/subscript arithmetic for
multi-dimensional arrays and also in turn enables detection of spatial
locality (for vectorization for eg.), temporal locality or loop
invariance for hoisting or scalar replacement.
Nit: a word is missing here.