packages feed

futhark-0.15.7: src/Futhark/Pass/ExplicitAllocations/SegOp.hs

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
module Futhark.Pass.ExplicitAllocations.SegOp
       ( allocInKernelBody
       , allocInBinOpLambda
       )
where

import qualified Futhark.Representation.Mem.IxFun as IxFun
import Futhark.Representation.KernelsMem
import Futhark.Pass.ExplicitAllocations

allocInKernelBody :: Allocable fromlore tolore =>
                     KernelBody fromlore
                  -> AllocM fromlore tolore (KernelBody tolore)
allocInKernelBody (KernelBody () stms res) =
  allocInStms stms $ \stms' -> return $ KernelBody () stms' res

allocInLambda :: Allocable fromlore tolore =>
                 [LParam tolore] -> Body fromlore -> [Type]
              -> AllocM fromlore tolore (Lambda tolore)
allocInLambda params body rettype = do
  body' <- localScope (scopeOfLParams params) $
           allocInStms (bodyStms body) $ \bnds' ->
           return $ Body () bnds' $ bodyResult body
  return $ Lambda params body' rettype

allocInBinOpParams :: Allocable fromlore tolore =>
                      SubExp
                   -> PrimExp VName -> PrimExp VName
                   -> [LParam fromlore]
                   -> [LParam fromlore]
                   -> AllocM fromlore tolore ([LParam tolore], [LParam tolore])
allocInBinOpParams num_threads my_id other_id xs ys = unzip <$> zipWithM alloc xs ys
  where alloc x y =
          case paramType x of
            Array bt shape u -> do
              twice_num_threads <-
                letSubExp "twice_num_threads" $
                BasicOp $ BinOp (Mul Int32 OverflowUndef) num_threads $ intConst Int32 2
              let t = paramType x `arrayOfRow` twice_num_threads
              mem <- allocForArray t DefaultSpace
              -- XXX: this iota ixfun is a bit inefficient; leading to
              -- uncoalesced access.
              let base_dims = map (primExpFromSubExp int32) (arrayDims t)
                  ixfun_base = IxFun.iota base_dims
                  ixfun_x = IxFun.slice ixfun_base $
                            fullSliceNum base_dims [DimFix my_id]
                  ixfun_y = IxFun.slice ixfun_base $
                            fullSliceNum base_dims [DimFix other_id]
              return (x { paramAttr = MemArray bt shape u $ ArrayIn mem ixfun_x },
                      y { paramAttr = MemArray bt shape u $ ArrayIn mem ixfun_y })
            Prim bt ->
              return (x { paramAttr = MemPrim bt },
                      y { paramAttr = MemPrim bt })
            Mem space ->
              return (x { paramAttr = MemMem space },
                      y { paramAttr = MemMem space })

allocInBinOpLambda :: Allocable fromlore tolore =>
                      SubExp -> SegSpace -> Lambda fromlore
                   -> AllocM fromlore tolore (Lambda tolore)
allocInBinOpLambda num_threads (SegSpace flat _) lam = do
  let (acc_params, arr_params) =
        splitAt (length (lambdaParams lam) `div` 2) $ lambdaParams lam
      index_x = LeafExp flat int32
      index_y = index_x + primExpFromSubExp int32 num_threads
  (acc_params', arr_params') <-
    allocInBinOpParams num_threads index_x index_y acc_params arr_params

  allocInLambda (acc_params' ++ arr_params')
    (lambdaBody lam) (lambdaReturnType lam)