@timed_pass(name='cire')
def cire(clusters, mode, sregistry, options, platform):
    "\n    Cross-iteration redundancies elimination.\n\n    Parameters\n    ----------\n    cluster : Cluster\n        Input Cluster, subject of the optimization pass.\n    mode : str\n        The transformation mode. Accepted: ['invariants', 'sops'].\n        * 'invariants' is for sub-expressions that are invariant w.r.t. one or\n          more Dimensions.\n        * 'sops' stands for sums-of-products, that is redundancies are searched\n          across all expressions in sum-of-product form.\n    sregistry : SymbolRegistry\n        The symbol registry, to create unique temporary names.\n    options : dict\n        The optimization options.\n        Accepted: ['min-storage', 'cire-maxpar', 'cire-rotate', 'cire-maxalias'].\n        * 'min-storage': if True, the pass will try to minimize the amount of\n          storage introduced for the tensor temporaries. This might also reduce\n          the operation count. On the other hand, this might affect fusion and\n          therefore data locality. Defaults to False (legacy).\n        * 'cire-maxpar': if True, privilege parallelism over working set size,\n          that is the pass will try to create as many parallel loops as possible,\n          even though this will require more space (Dimensions) for the temporaries.\n          Defaults to False.\n        * 'cire-rotate': if True, the pass will use modulo indexing for the\n          outermost Dimension iterated over by the temporaries. This will sacrifice\n          a parallel loop for a reduced working set size. Defaults to False (legacy).\n        * 'cire-maxalias': if True, capture the largest redundancies. This will\n          minimize the flop count while maximizing the number of tensor temporaries,\n          thus increasing the working set size.\n    platform : Platform\n        The underlying platform. Used to optimize the shape of the introduced\n        tensor symbols.\n\n    Examples\n    --------\n    1) 'invariants'. Here's an expensive expression invariant w.r.t. `t`\n\n    t0 = (cos(a[x,y,z])*sin(b[x,y,z]))*c[t,x,y,z]\n\n    which after CIRE becomes\n\n    t1[x,y,z] = cos(a[x,y,z])*sin(b[x,y,z])\n    t0 = t1[x,y,z]*c[t,x,y,z]\n\n    2) 'sops'. Below we see two expressions in sum-of-product form (in this\n    case, the sum degenerates to a single product).\n\n    t0 = 2.0*a[x,y,z]*b[x,y,z]\n    t1 = 3.0*a[x,y,z+1]*b[x,y,z+1]\n\n    CIRE detects that these two expressions are actually redundant and rewrites\n    them as:\n\n    t2[x,y,z] = a[x,y,z]*b[x,y,z]\n    t0 = 2.0*t2[x,y,z]\n    t1 = 3.0*t2[x,y,z+1]\n    "
    if (mode == 'invariants'):
        space = ('inv-basic', 'inv-compound')
    elif (mode in ('sops',)):
        space = (mode,)
    else:
        assert False, ('Unknown CIRE mode `%s`' % mode)
    processed = []
    for c in clusters:
        if (not c.is_dense):
            processed.append(c)
            continue
        context = Context(c).process(clusters)
        transformed = _cire(c, context, space, sregistry, options, platform)
        processed.extend(transformed)
    return processed
Cross-iteration redundancies elimination.

Parameters
----------
cluster : Cluster
    Input Cluster, subject of the optimization pass.
mode : str
    The transformation mode. Accepted: ['invariants', 'sops'].
    * 'invariants' is for sub-expressions that are invariant w.r.t. one or
      more Dimensions.
    * 'sops' stands for sums-of-products, that is redundancies are searched
      across all expressions in sum-of-product form.
sregistry : SymbolRegistry
    The symbol registry, to create unique temporary names.
options : dict
    The optimization options.
    Accepted: ['min-storage', 'cire-maxpar', 'cire-rotate', 'cire-maxalias'].
    * 'min-storage': if True, the pass will try to minimize the amount of
      storage introduced for the tensor temporaries. This might also reduce
      the operation count. On the other hand, this might affect fusion and
      therefore data locality. Defaults to False (legacy).
    * 'cire-maxpar': if True, privilege parallelism over working set size,
      that is the pass will try to create as many parallel loops as possible,
      even though this will require more space (Dimensions) for the temporaries.
      Defaults to False.
    * 'cire-rotate': if True, the pass will use modulo indexing for the
      outermost Dimension iterated over by the temporaries. This will sacrifice
      a parallel loop for a reduced working set size. Defaults to False (legacy).
    * 'cire-maxalias': if True, capture the largest redundancies. This will
      minimize the flop count while maximizing the number of tensor temporaries,
      thus increasing the working set size.
platform : Platform
    The underlying platform. Used to optimize the shape of the introduced
    tensor symbols.

Examples
--------
1) 'invariants'. Here's an expensive expression invariant w.r.t. `t`

t0 = (cos(a[x,y,z])*sin(b[x,y,z]))*c[t,x,y,z]

which after CIRE becomes

t1[x,y,z] = cos(a[x,y,z])*sin(b[x,y,z])
t0 = t1[x,y,z]*c[t,x,y,z]

2) 'sops'. Below we see two expressions in sum-of-product form (in this
case, the sum degenerates to a single product).

t0 = 2.0*a[x,y,z]*b[x,y,z]
t1 = 3.0*a[x,y,z+1]*b[x,y,z+1]

CIRE detects that these two expressions are actually redundant and rewrites
them as:

t2[x,y,z] = a[x,y,z]*b[x,y,z]
t0 = 2.0*t2[x,y,z]
t1 = 3.0*t2[x,y,z+1]
@timed_pass(name='cire')
def cire(clusters, mode, sregistry, options, platform):
    "\n    Cross-iteration redundancies elimination.\n\n    Parameters\n    ----------\n    cluster : Cluster\n        Input Cluster, subject of the optimization pass.\n    mode : str\n        The transformation mode. Accepted: ['invariants', 'sops'].\n        * 'invariants' is for sub-expressions that are invariant w.r.t. one or\n          more Dimensions.\n        * 'sops' stands for sums-of-products, that is redundancies are searched\n          across all expressions in sum-of-product form.\n    sregistry : SymbolRegistry\n        The symbol registry, to create unique temporary names.\n    options : dict\n        The optimization options.\n        Accepted: ['min-storage', 'cire-maxpar', 'cire-rotate', 'cire-maxalias'].\n        * 'min-storage': if True, the pass will try to minimize the amount of\n          storage introduced for the tensor temporaries. This might also reduce\n          the operation count. On the other hand, this might affect fusion and\n          therefore data locality. Defaults to False (legacy).\n        * 'cire-maxpar': if True, privilege parallelism over working set size,\n          that is the pass will try to create as many parallel loops as possible,\n          even though this will require more space (Dimensions) for the temporaries.\n          Defaults to False.\n        * 'cire-rotate': if True, the pass will use modulo indexing for the\n          outermost Dimension iterated over by the temporaries. This will sacrifice\n          a parallel loop for a reduced working set size. Defaults to False (legacy).\n        * 'cire-maxalias': if True, capture the largest redundancies. This will\n          minimize the flop count while maximizing the number of tensor temporaries,\n          thus increasing the working set size.\n    platform : Platform\n        The underlying platform. Used to optimize the shape of the introduced\n        tensor symbols.\n\n    Examples\n    --------\n    1) 'invariants'. Here's an expensive expression invariant w.r.t. `t`\n\n    t0 = (cos(a[x,y,z])*sin(b[x,y,z]))*c[t,x,y,z]\n\n    which after CIRE becomes\n\n    t1[x,y,z] = cos(a[x,y,z])*sin(b[x,y,z])\n    t0 = t1[x,y,z]*c[t,x,y,z]\n\n    2) 'sops'. Below we see two expressions in sum-of-product form (in this\n    case, the sum degenerates to a single product).\n\n    t0 = 2.0*a[x,y,z]*b[x,y,z]\n    t1 = 3.0*a[x,y,z+1]*b[x,y,z+1]\n\n    CIRE detects that these two expressions are actually redundant and rewrites\n    them as:\n\n    t2[x,y,z] = a[x,y,z]*b[x,y,z]\n    t0 = 2.0*t2[x,y,z]\n    t1 = 3.0*t2[x,y,z+1]\n    "
    if (mode == 'invariants'):
        space = ('inv-basic', 'inv-compound')
    elif (mode in ('sops',)):
        space = (mode,)
    else:
        assert False, ('Unknown CIRE mode `%s`' % mode)
    processed = []
    for c in clusters:
        if (not c.is_dense):
            processed.append(c)
            continue
        context = Context(c).process(clusters)
        transformed = _cire(c, context, space, sregistry, options, platform)
        processed.extend(transformed)
    return processed