shrinkE :: PreOpenExp acc env aenv t -> PreOpenExp acc env aenv t
shrinkE exp =
  case exp of
    Let bnd body
      | Var _ <- bnd                    -> shrinkE (inline body  bnd)
      | usesOfE ZeroIdx body' <= lIMIT  -> shrinkE (inline body' bnd')
      | otherwise                       -> Let bnd' body'
      where
        bnd'    = shrinkE bnd
        body'   = shrinkE body

        -- Allow inlining and dead-code elimination
        --
        lIMIT   = 1
    --
    Var idx             -> Var idx
    Const c             -> Const c
    Tuple t             -> Tuple (shrinkTE t)
    Prj tup e           -> Prj tup (shrinkE e)
    IndexNil            -> IndexNil
    IndexCons sl sz     -> IndexCons (shrinkE sl) (shrinkE sz)
    IndexHead sh        -> IndexHead (shrinkE sh)
    IndexTail sh        -> IndexTail (shrinkE sh)
    IndexSlice x ix sh  -> IndexSlice x (shrinkE ix) (shrinkE sh)
    IndexFull x ix sl   -> IndexFull x (shrinkE ix) (shrinkE sl)
    IndexAny            -> IndexAny
    ToIndex sh ix       -> ToIndex (shrinkE sh) (shrinkE ix)
    FromIndex sh i      -> FromIndex (shrinkE sh) (shrinkE i)
    Cond p t e          -> Cond (shrinkE p) (shrinkE t) (shrinkE e)
    Iterate n f x       -> Iterate (shrinkE n) (shrinkE f) (shrinkE x)
    PrimConst c         -> PrimConst c
    PrimApp f x         -> PrimApp f (shrinkE x)
    Index a sh          -> Index a (shrinkE sh)
    LinearIndex a i     -> LinearIndex a (shrinkE i)
    Shape a             -> Shape a
    ShapeSize sh        -> ShapeSize (shrinkE sh)
    Intersect sh sz     -> Intersect (shrinkE sh) (shrinkE sz)
shrinkE :: PreOpenExp acc env aenv t -> PreOpenExp acc env aenv t
shrinkE exp =
  case exp of
    Let bnd body
      | Var _ <- bnd                    -> shrinkE (inline body  bnd)
      | usesOfE ZeroIdx body' <= lIMIT  -> shrinkE (inline body' bnd')
      | otherwise                       -> Let bnd' body'
      where
        bnd'    = shrinkE bnd
        body'   = shrinkE body

        -- Allow inlining and dead-code elimination
        --
        lIMIT   = 1
    --
    Var idx             -> Var idx
    Const c             -> Const c
    Tuple t             -> Tuple (shrinkTE t)
    Prj tup e           -> Prj tup (shrinkE e)
    IndexNil            -> IndexNil
    IndexCons sl sz     -> IndexCons (shrinkE sl) (shrinkE sz)
    IndexHead sh        -> IndexHead (shrinkE sh)
    IndexTail sh        -> IndexTail (shrinkE sh)
    IndexSlice x ix sh  -> IndexSlice x (shrinkE ix) (shrinkE sh)
    IndexFull x ix sl   -> IndexFull x (shrinkE ix) (shrinkE sl)
    IndexAny            -> IndexAny
    ToIndex sh ix       -> ToIndex (shrinkE sh) (shrinkE ix)
    FromIndex sh i      -> FromIndex (shrinkE sh) (shrinkE i)
    Cond p t e          -> Cond (shrinkE p) (shrinkE t) (shrinkE e)
    Iterate n f x       -> Iterate (shrinkE n) (shrinkE f) (shrinkE x)
    PrimConst c         -> PrimConst c
    PrimApp f x         -> PrimApp f (shrinkE x)
    Index a sh          -> Index a (shrinkE sh)
    LinearIndex a i     -> LinearIndex a (shrinkE i)
    Shape a             -> Shape a
    ShapeSize sh        -> ShapeSize (shrinkE sh)
    Intersect sh sz     -> Intersect (shrinkE sh) (shrinkE sz)
shrinkE exp =
  case exp of
    Let bnd body
      | Var _ <- bnd                    -> shrinkE (inline body  bnd)
      | usesOfE ZeroIdx body' <= lIMIT  -> shrinkE (inline body' bnd')
      | otherwise                       -> Let bnd' body'
      where
        bnd'    = shrinkE bnd
        body'   = shrinkE body

        -- Allow inlining and dead-code elimination
        --
        lIMIT   = 1
    --
    Var idx             -> Var idx
    Const c             -> Const c
    Tuple t             -> Tuple (shrinkTE t)
    Prj tup e           -> Prj tup (shrinkE e)
    IndexNil            -> IndexNil
    IndexCons sl sz     -> IndexCons (shrinkE sl) (shrinkE sz)
    IndexHead sh        -> IndexHead (shrinkE sh)
    IndexTail sh        -> IndexTail (shrinkE sh)
    IndexSlice x ix sh  -> IndexSlice x (shrinkE ix) (shrinkE sh)
    IndexFull x ix sl   -> IndexFull x (shrinkE ix) (shrinkE sl)
    IndexAny            -> IndexAny
    ToIndex sh ix       -> ToIndex (shrinkE sh) (shrinkE ix)
    FromIndex sh i      -> FromIndex (shrinkE sh) (shrinkE i)
    Cond p t e          -> Cond (shrinkE p) (shrinkE t) (shrinkE e)
    Iterate n f x       -> Iterate (shrinkE n) (shrinkE f) (shrinkE x)
    PrimConst c         -> PrimConst c
    PrimApp f x         -> PrimApp f (shrinkE x)
    Index a sh          -> Index a (shrinkE sh)
    LinearIndex a i     -> LinearIndex a (shrinkE i)
    Shape a             -> Shape a
    ShapeSize sh        -> ShapeSize (shrinkE sh)
    Intersect sh sz     -> Intersect (shrinkE sh) (shrinkE sz)