accelerate-1.2.0.0: src/Data/Array/Accelerate/Trafo.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# OPTIONS_HADDOCK hide #-}
-- |
-- Module : Data.Array.Accelerate.Trafo
-- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell
-- License : BSD3
--
-- Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>
-- Stability : experimental
-- Portability : non-portable (GHC extensions)
--
module Data.Array.Accelerate.Trafo (
-- * HOAS -> de Bruijn conversion
Phase(..), phases,
-- ** Array computations
convertAcc, convertAccWith,
-- ** Array functions
Afunction, AfunctionR,
convertAfun, convertAfunWith,
-- ** Sequence computations
-- convertSeq, convertSeqWith,
-- * Fusion
module Data.Array.Accelerate.Trafo.Fusion,
-- * Substitution
module Data.Array.Accelerate.Trafo.Substitution,
-- * Term equality
Match(..), (:~:)(..),
-- ** Auxiliary
matchDelayedOpenAcc, encodeDelayedOpenAcc, hashDelayedOpenAcc,
) where
import Control.DeepSeq
import Data.Typeable
import Data.Array.Accelerate.Smart
import Data.Array.Accelerate.Pretty ( ) -- show instances
import Data.Array.Accelerate.Array.Sugar ( Arrays, Elt )
import Data.Array.Accelerate.Trafo.Base
import Data.Array.Accelerate.Trafo.Fusion hiding ( convertAcc, convertAfun ) -- to export types
import Data.Array.Accelerate.Trafo.Sharing ( Function, FunctionR, Afunction, AfunctionR )
import Data.Array.Accelerate.Trafo.Substitution
import qualified Data.Array.Accelerate.AST as AST
import qualified Data.Array.Accelerate.Trafo.Fusion as Fusion
import qualified Data.Array.Accelerate.Trafo.Rewrite as Rewrite
import qualified Data.Array.Accelerate.Trafo.Simplify as Rewrite
import qualified Data.Array.Accelerate.Trafo.Sharing as Sharing
-- import qualified Data.Array.Accelerate.Trafo.Vectorise as Vectorise
#ifdef ACCELERATE_DEBUG
import Text.Printf
import System.IO.Unsafe
import Data.Array.Accelerate.Debug hiding ( when )
import qualified Data.Array.Accelerate.Debug as Debug
#endif
-- Configuration
-- -------------
data Phase = Phase
{
-- | Recover sharing of array computations?
recoverAccSharing :: Bool
-- | Recover sharing of scalar expressions?
, recoverExpSharing :: Bool
-- | Recover sharing of sequence computations?
, recoverSeqSharing :: Bool
-- | Are array computations floated out of expressions irrespective of
-- whether they are shared or not? Requires 'recoverAccSharing'.
, floatOutAccFromExp :: Bool
-- | Fuse array computations? This also implies simplifying scalar
-- expressions. NOTE: currently always enabled.
, enableAccFusion :: Bool
-- | Convert segment length arrays into segment offset arrays?
, convertOffsetOfSegment :: Bool
-- Vectorise maps and zipwiths in sequence computations to
-- enable chunked execution?
-- , vectoriseSequences :: Bool
}
-- | The default method of converting from HOAS to de Bruijn; incorporating
-- sharing recovery and fusion optimisation.
--
phases :: Phase
phases = Phase
{ recoverAccSharing = True
, recoverExpSharing = True
, recoverSeqSharing = True
, floatOutAccFromExp = True
, enableAccFusion = True
, convertOffsetOfSegment = False
-- , vectoriseSequences = True
}
when :: (a -> a) -> Bool -> a -> a
when f True = f
when _ False = id
-- HOAS -> de Bruijn conversion
-- ----------------------------
-- | Convert a closed array expression to de Bruijn form while also
-- incorporating sharing observation and array fusion.
--
convertAcc :: Arrays arrs => Acc arrs -> DelayedAcc arrs
convertAcc = convertAccWith phases
convertAccWith :: Arrays arrs => Phase -> Acc arrs -> DelayedAcc arrs
convertAccWith Phase{..} acc
= phase "array-fusion" (Fusion.convertAcc enableAccFusion)
-- phase "vectorise-sequences" Vectorise.vectoriseSeqAcc `when` vectoriseSequences
$ phase "rewrite-segment-offset" Rewrite.convertSegments `when` convertOffsetOfSegment
$ phase "sharing-recovery" (Sharing.convertAcc recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)
$ acc
-- | Convert a unary function over array computations, incorporating sharing
-- observation and array fusion
--
convertAfun :: Afunction f => f -> DelayedAfun (AfunctionR f)
convertAfun = convertAfunWith phases
convertAfunWith :: Afunction f => Phase -> f -> DelayedAfun (AfunctionR f)
convertAfunWith Phase{..} acc
= phase "array-fusion" (Fusion.convertAfun enableAccFusion)
-- phase "vectorise-sequences" Vectorise.vectoriseSeqAfun `when` vectoriseSequences
$ phase "rewrite-segment-offset" Rewrite.convertSegmentsAfun `when` convertOffsetOfSegment
$ phase "sharing-recovery" (Sharing.convertAfun recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)
$ acc
-- | Convert a closed scalar expression, incorporating sharing observation and
-- optimisation.
--
convertExp :: Elt e => Exp e -> AST.Exp () e
convertExp
= phase "exp-simplify" Rewrite.simplify
. phase "sharing-recovery" (Sharing.convertExp (recoverExpSharing phases))
-- | Convert closed scalar functions, incorporating sharing observation and
-- optimisation.
--
convertFun :: Function f => f -> AST.Fun () (FunctionR f)
convertFun
= phase "exp-simplify" Rewrite.simplify
. phase "sharing-recovery" (Sharing.convertFun (recoverExpSharing phases))
{--
-- | Convert a closed sequence computation, incorporating sharing observation and
-- optimisation.
--
convertSeq :: Typeable s => Seq s -> DelayedSeq s
convertSeq = convertSeqWith phases
convertSeqWith :: Typeable s => Phase -> Seq s -> DelayedSeq s
convertSeqWith Phase{..} s
= phase "array-fusion" (Fusion.convertSeq enableAccFusion)
-- $ phase "vectorise-sequences" Vectorise.vectoriseSeq `when` vectoriseSequences
$ phase "rewrite-segment-offset" Rewrite.convertSegmentsSeq `when` convertOffsetOfSegment
$ phase "sharing-recovery" (Sharing.convertSeq recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)
$ s
--}
-- Pretty printing
-- ---------------
instance Arrays arrs => Show (Acc arrs) where
show = withSimplStats . show . convertAcc
instance Afunction (Acc a -> f) => Show (Acc a -> f) where
show = withSimplStats . show . convertAfun
instance Elt e => Show (Exp e) where
show = withSimplStats . show . convertExp
instance Function (Exp a -> f) => Show (Exp a -> f) where
show = withSimplStats . show . convertFun
-- instance Typeable a => Show (Seq a) where
-- show = withSimplStats . show . convertSeq
-- Debugging
-- ---------
-- Attach simplifier statistics to the tail of the given string. Since the
-- statistics rely on fully evaluating the expression this is difficult to do
-- generally (without an additional deepseq), but easy enough for our show
-- instances.
--
-- For now, we just reset the statistics at the beginning of a conversion, and
-- leave it to a backend to choose an appropriate moment to dump the summary.
--
withSimplStats :: String -> String
#ifdef ACCELERATE_DEBUG
withSimplStats x = unsafePerformIO $ do
Debug.when dump_simpl_stats $ x `deepseq` dumpSimplStats
return x
#else
withSimplStats x = x
#endif
-- Execute a phase of the compiler and (possibly) print some timing/gc
-- statistics.
--
phase :: NFData b => String -> (a -> b) -> a -> b
#ifdef ACCELERATE_DEBUG
phase n f x = unsafePerformIO $ do
enabled <- getFlag dump_phases
if enabled
then timed dump_phases (\wall cpu -> printf "phase %s: %s" n (elapsed wall cpu)) (return $!! f x)
else return (f x)
#else
phase _ f x = f x
#endif