feldspar-compiler-0.6.0.2: lib/Feldspar/Compiler/Imperative/Plugin/Unroll.hs
--
-- Copyright (c) 2009-2011, ERICSSON AB
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- * Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
-- * Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
-- * Neither the name of the ERICSSON AB nor the names of its contributors
-- may be used to endorse or promote products derived from this software
-- without specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Feldspar.Compiler.Imperative.Plugin.Unroll where
import Feldspar.Compiler.Backend.C.Options
import Feldspar.Transformation
-- ============================
-- == Unroll's Semantic info ==
-- ============================
data SemInfPrg = SemInfPrg
{ position :: Int
, varNames :: [String]
, loopVar :: String
} deriving (Eq, Show)
data UnrollSemInf
instance Annotation UnrollSemInf Module where
type Label UnrollSemInf Module = ()
instance Annotation UnrollSemInf Entity where
type Label UnrollSemInf Entity = ()
instance Annotation UnrollSemInf Struct where
type Label UnrollSemInf Struct = ()
instance Annotation UnrollSemInf StructMember where
type Label UnrollSemInf StructMember = ()
instance Annotation UnrollSemInf ProcDef where
type Label UnrollSemInf ProcDef = ()
instance Annotation UnrollSemInf ProcDecl where
type Label UnrollSemInf ProcDecl = ()
instance Annotation UnrollSemInf Block where
type Label UnrollSemInf Block = ()
instance Annotation UnrollSemInf Program where
type Label UnrollSemInf Program = Maybe SemInfPrg
instance Annotation UnrollSemInf Empty where
type Label UnrollSemInf Empty = ()
instance Annotation UnrollSemInf Comment where
type Label UnrollSemInf Comment = ()
instance Annotation UnrollSemInf Assign where
type Label UnrollSemInf Assign = ()
instance Annotation UnrollSemInf ProcedureCall where
type Label UnrollSemInf ProcedureCall = ()
instance Annotation UnrollSemInf Spawn where
type Label UnrollSemInf Spawn = ()
instance Annotation UnrollSemInf Run where
type Label UnrollSemInf Run = ()
instance Annotation UnrollSemInf Sequence where
type Label UnrollSemInf Sequence = ()
instance Annotation UnrollSemInf Branch where
type Label UnrollSemInf Branch = ()
instance Annotation UnrollSemInf SeqLoop where
type Label UnrollSemInf SeqLoop = ()
instance Annotation UnrollSemInf ParLoop where
type Label UnrollSemInf ParLoop = ()
instance Annotation UnrollSemInf ActualParameter where
type Label UnrollSemInf ActualParameter = ()
instance Annotation UnrollSemInf Declaration where
type Label UnrollSemInf Declaration = ()
instance Annotation UnrollSemInf Expression where
type Label UnrollSemInf Expression = ()
instance Annotation UnrollSemInf FunctionCall where
type Label UnrollSemInf FunctionCall = ()
instance Annotation UnrollSemInf Cast where
type Label UnrollSemInf Cast = ()
instance Annotation UnrollSemInf SizeOf where
type Label UnrollSemInf SizeOf = ()
instance Annotation UnrollSemInf ArrayElem where
type Label UnrollSemInf ArrayElem = ()
instance Annotation UnrollSemInf StructField where
type Label UnrollSemInf StructField = ()
instance Annotation UnrollSemInf Constant where
type Label UnrollSemInf Constant = ()
instance Annotation UnrollSemInf IntConst where
type Label UnrollSemInf IntConst = ()
instance Annotation UnrollSemInf FloatConst where
type Label UnrollSemInf FloatConst = ()
instance Annotation UnrollSemInf BoolConst where
type Label UnrollSemInf BoolConst = ()
instance Annotation UnrollSemInf ArrayConst where
type Label UnrollSemInf ArrayConst = ()
instance Annotation UnrollSemInf ComplexConst where
type Label UnrollSemInf ComplexConst = ()
instance Annotation UnrollSemInf Variable where
type Label UnrollSemInf Variable = ()
-- ==
-- == Plugin
-- ==
instance Default Bool where
def = False
instance Combine Bool where
combine = (||)
instance Default (Maybe SemInfPrg) where def = Nothing
instance Plugin UnrollPlugin where
type ExternalInfo UnrollPlugin = UnrollStrategy
executePlugin UnrollPlugin ei p = case ei of
NoUnroll -> p
Unroll unrollCount -> result $ transform Unroll2 () Nothing $ result $ transform Unroll1 () unrollCount p
data UnrollPlugin = UnrollPlugin
instance Transformation UnrollPlugin where
type From UnrollPlugin = ()
type To UnrollPlugin = ()
type Down UnrollPlugin = ()
type Up UnrollPlugin = ()
type State UnrollPlugin = ()
data Unroll1 = Unroll1
instance Transformation Unroll1 where
type From Unroll1 = ()
type To Unroll1 = UnrollSemInf
type Down Unroll1 = Int
type Up Unroll1 = Bool
type State Unroll1 = ()
instance Transformable Unroll1 Program where
transform t s d p@ParLoop{}
| not (up tr)
, unrollPossible = tr'
| otherwise = tr
where
tr = defaultTransform t s d p
tr' = tr
{ result = (result tr)
{ pLoopStep = d
, pLoopBlock = loopCore
{ locals = unrollDecls
, blockBody = Sequence prgs () Nothing
}
}
, up = True
}
prgs = map (\(i,prg) -> prg{ programLabel = Just (SemInfPrg i vns loopCounter) }) $ zip [0,1..] replPrg
replPrg = replicate d $ blockBody loopCore
unrollDecls = concatMap (uncurry renameDecls) $ zip [0..] replDecls
renameDecls (i :: Int) = map (\decl -> renameDeclaration decl (getVarNameDecl decl ++ "_u" ++ show i))
replDecls = replicate d $ locals loopCore
loopCore = pLoopBlock $ result tr
loopBound = pLoopBound $ result tr
loopCounter = varName $ pLoopCounter $ result tr
vns = map getVarNameDecl $ locals loopCore
unrollPossible = case loopBound of
(ConstExpr (IntConst i _ _ _) _) -> mod i (toInteger d) == 0
_ -> False
transform t s d p = defaultTransform t s d p
data Unroll2 = Unroll2
instance Transformation Unroll2 where
type From Unroll2 = UnrollSemInf
type To Unroll2 = ()
type Down Unroll2 = Maybe SemInfPrg
type Up Unroll2 = ()
type State Unroll2 = ()
instance Transformable Unroll2 Program where
transform t s d p = defaultTransform t s d' p where
d' = case programLabel p of
Nothing -> d
x -> x
instance Transformable Unroll2 Expression where
transform t s d l = case d of
Nothing -> tr
Just x -> case l of
VarExpr n _
| varName n == loopVar x -> tr
{ result = FunctionCall
{ function = Function
{ funName = "+"
, returnType = NumType Signed S32
, funMode = Infix
}
, funCallParams =
[ result tr
, ConstExpr (IntConst (toInteger $ position x) (NumType Signed S32) () ()) ()
]
, funCallLabel = ()
, exprLabel = ()
}
}
| otherwise -> tr
_ -> tr
where
tr = defaultTransform t s d l
instance Transformable Unroll2 Variable where
transform t s d v = case d of
Just x
| varName v `elem` varNames x -> tr
{ result = (result tr)
{ varName = varName v ++ "_u" ++ show (position x)
, varLabel = ()
}
}
| otherwise -> tr
Nothing -> tr
where
tr = defaultTransform t s d v
-- helper functions :
isJust :: Maybe t -> Bool
isJust (Just _) = True
isJust _ = False
getVarNameDecl :: Declaration t -> String
getVarNameDecl d = varName $ declVar d
renameDeclaration :: Declaration t -> String -> Declaration t
renameDeclaration d n = d { declVar = renameVariable (declVar d) n }
renameVariable :: Variable t -> String -> Variable t
renameVariable v n = v { varName = n }