module Feldspar.Compiler.Optimization.Unroll where
import Feldspar.Compiler.Imperative.Representation hiding (None)
import Feldspar.Compiler.Options
import Feldspar.Compiler.Optimization.Replace
import Prelude
doUnroll :: Options -> [ImpFunction] -> [ImpFunction]
doUnroll opt ps = map (doUnrollOne opt) ps
doUnrollOne :: Options -> ImpFunction -> ImpFunction
doUnrollOne opt p = case unroll opt of
NoUnroll -> p
(Unroll i) -> unrollStruc i p
unrollPossible :: Int -> Program -> Bool
unrollPossible i (ParLoop counter num 1 (CompPrg _ prg) inf) = moduloOk && unrollPossible' prg
where
moduloOk = case num of
Expr (ConstExpr (IntConst x)) _ -> x `mod` i == 0
otherwise -> True
unrollPossible' Empty = True
unrollPossible' (Primitive i s) = True
unrollPossible' (Seq ps si) = and $ map unrollPossible' ps
unrollPossible' _ = False
unrollPossible _ _ = False
collectVars :: [Declaration] -> [String]
collectVars ds = map collectVar ds where
collectVar (Decl (Var s _ _) declType initVal inf) = s
alterVarName :: String -> Int -> String
alterVarName old idx = old ++ "_" ++ show idx
alterVar :: String -> Int -> UntypedExpression
alterVar name idx = FunCall InfixOp "+" [var,const]
where
var = Expr (LeftExpr $ LVar $ Var name Normal int) int
const = Expr (ConstExpr $ IntConst idx) int
int = (Numeric ImpSigned S32)
unrollDecl :: [Declaration] -> String -> Int -> [Declaration]
unrollDecl decllist loopvar i
= unrollDecl' decllist todolists
where
todolists = zip (replicate i ((collectVars decllist),loopvar)) [0,1..(i1)]
unrollDecl' :: [Declaration] -> [(([String],String),Int)] -> [Declaration]
unrollDecl' decllist todolists = foldl (++) [] (map (unrollOneDecl decllist) todolists)
unrollOneDecl:: [Declaration] -> (([String],String),Int) -> [Declaration]
unrollOneDecl decllist ((local_vars,loopvar),idx)
| idx < 1 = foldl (\decllist var -> (replaceVar decllist (var,alterVarName var idx))) decllist local_vars
| otherwise = foldl (\decllist var -> (replaceVar decllist (var,alterVarName var idx)))
(replaceUExpr decllist (loopvar,(alterVar loopvar idx))) local_vars
unrollPrg :: Program -> String -> [String] -> Int -> [Program]
unrollPrg prg loopvar locals num =
map alter $ zip (replicate num prg) [0..] where
alter (p,idx)
| idx < 1 = foldl (\p' tr -> tr p') p (map (alterLocal idx) locals)
| otherwise = foldl (\p' tr -> tr p') (alterLoopVar (p,idx)) (map (alterLocal idx) locals)
alterLoopVar (p,idx) = replaceUExpr p (loopvar, alterVar loopvar idx)
alterLocal idx loc p = replaceVar p (loc, alterVarName loc idx)
unrollRepeatSimple :: Program -> Int -> Program
unrollRepeatSimple p i = urs p i (unrollPossible i p) where
urs (ParLoop (Var v k t) max step cprg inf) i True
= ParLoop (Var v k t) max (step*i) (CompPrg (unrollDecl (locals cprg) v i) (Seq (unrollPrg (body cprg) v (collectVars (locals cprg)) i) inf)) inf
urs (ParLoop (Var v k t) max step cprg inf) i False
= ParLoop (Var v k t) max step cprg{ body = unrollStruc i (body cprg)} inf
urs p i False = p
class Unroll t where
unrollStruc :: Int -> t -> t
instance Unroll ImpFunction where
unrollStruc i f = f{ prg = unrollStruc i $ prg f }
instance Unroll CompleteProgram where
unrollStruc i c = c{ body = unrollStruc i $ body c }
instance Unroll Program where
unrollStruc i (Seq ps inf) = Seq (map (unrollStruc i) ps) inf
unrollStruc i (IfThenElse v cpt cpe inf) = IfThenElse v (unrollStruc i cpt) (unrollStruc i cpe) inf
unrollStruc i for@(ParLoop _ _ _ _ _) = unrollRepeatSimple for i
unrollStruc i (SeqLoop v calc body inf) = SeqLoop v (unrollStruc i calc) (unrollStruc i body) inf
unrollStruc _ x = x