futhark
Safe HaskellNone
LanguageGHC2021

Futhark.Optimise.Fusion.RulesWithAccs

Description

This module consists of rules for fusion that involves WithAcc constructs. Currently, we support two non-trivial transformations: I. SOAC-through-Trans-into-WithAcc fusion: a SoacNode is fused into a WithAcc atomically when all dependency paths between them go through TransNodes (reshapes/rearranges) that have no other consumers. The canonical example is a map nest producing multi-dimensional index and value arrays that are flattened and consumed by a scatter. This must be done atomically to avoid an infinite loop: absorbing only the TransNode causes simplifyLambda to hoist the cheap reshape back out, recreating the same TransNode and triggering the rule again. The strategy is to prepend the SoacNode and all TransNode statements into the WithAcc lambda body and run doFusionInLambda to fuse further where possible.

II. WithAcc-WithAcc fusion: two withaccs can be fused as long as the common accumulators use the same operator, and as long as the non-accumulator input of an WithAcc is not used as an accumulator in the other. This fusion opens the door for fusing the SOACs appearing inside the WithAccs. This is also intended to demonstrate that it is not so important where exactly the WithAccs were originally introduced in the code, it is more important that they can be transformed by various optimizations passes.

Synopsis

Documentation

tryFuseWithAccs :: (HasScope SOACS m, MonadFreshNames m) => [VName] -> Stm SOACS -> Stm SOACS -> Maybe (m (Stm SOACS)) Source #

Simple case for fusing two withAccs (can be extended): let (b1, ..., bm, x1, ..., xq) = withAcc a1 ... am lam1 let (d1, ..., dn, y1, ..., yp) = withAcc c1 ... cn lam2 Notation: `b1 ... bm` are the accumulator results of the first withAcc and `d1, ..., dn` of the second withAcc. `x1 ... xq` and `y1, ..., yp` are non-accumulator results. Conservative conditions: 1. for any bi (i=1..m) either `bi IN {c1, ..., cm}` OR `bi NOT-IN FV(lam2)`, i.e., perfect producer-consumer relation on accums. Of course the binary-op should be the same. 2. The bs that are also accumulated upon in lam2 do NOT belong to the infusible set (they are destroyed) 3. x1 ... xq do not overlap with c1 ... cn Fusion will create one withacc that accumulates on the union of `a1 ... am` and `c1 ... cn` and returns, in addition to the accumulator arrays the union of regular variables `x1 ... xq` and `y1, ..., yp`

trySoacThroughTransIntoWithAcc :: (HasScope SOACS m, MonadFreshNames m) => (Lambda SOACS -> m (Lambda SOACS, Bool)) -> (NodeT -> m (Maybe NodeT)) -> Node -> DepGraphAug m Source #

See the module-level description of transformation I. The doFusionInLambda and fusedSomething arguments are callbacks from Fusion.hs to avoid a circular import.