module Lvm.Asm.Inline (asmInline) where
import Data.Maybe
import Lvm.Asm.Data
import Lvm.Asm.Occur ( asmOccur )
import Lvm.Common.Id
import Lvm.Common.IdMap
type Env = IdMap Expr
removeIds :: [Id] -> IdMap a -> IdMap a
removeIds = flip (foldr deleteMap)
asmInline :: AsmModule -> AsmModule
asmInline = fmap inlineTop . asmOccur
inlineTop :: Top -> Top
inlineTop (Top params expr)
= Top params (inlineExpr emptyMap expr)
inlineExpr :: Env -> Expr -> Expr
inlineExpr env expr
= case expr of
Let _ (Note (Occur Never) _) e2
-> inlineExpr env e2
Let x (Note (Occur Once) e1) e2
-> let e1' = inlineExpr env e1
in inlineExpr (extendMap x e1' env) e2
Let x e1 e2 | trivial e1
-> let e1' = inlineExpr env (deAnnotate e1)
in inlineExpr (extendMap x e1' env) e2
Eval x e1 e2 | whnfTrivial e1
-> let e1' = inlineExpr env (deAnnotate e1)
in inlineExpr (extendMap x e1' env) e2
Eval x (Note (Occur Once) e1) e2
-> let e1' = inlineExpr env e1
in if firstuse x e2
then let env' = extendMap x (Eval x e1' (Ap x [])) env
in inlineExpr env' e2
else let e2' = inlineExpr env e2
in if firstuse x e2'
then let env' = extendMap x (Eval x e1' (Ap x [])) emptyMap
in inlineExpr env' e2'
else Eval x (Note (Occur Once) e1') e2'
Let x e1 e2 -> let env' = deleteMap x env
in Let x (inlineExpr env e1) (inlineExpr env' e2)
Eval x e1 e2 -> let env' = deleteMap x env
in Eval x (inlineExpr env e1) (inlineExpr env' e2)
LetRec bs e -> let (bs',env') = inlineBinds env bs
in LetRec bs' (inlineExpr env' e)
Match x alts -> case lookupMap x env of
Just e ->
Eval x (Note (Occur Once) e) (Match x (inlineAlts env alts))
Nothing -> Match x (inlineAlts env alts)
Ap x [] -> fromMaybe (Ap x []) (lookupMap x env)
Ap x args -> let args0 = inlineExprs env args
in case lookupMap x env of
Just e -> case e of
Ap id1 args1 -> Ap id1 (args1 ++ args0)
Eval id1 e1 (Ap id2 []) | id1==id2
-> Eval id1 e1 (Ap id1 args0)
_ -> Let x e (Ap x args)
Nothing -> Ap x args0
Con con args -> Con (inlineCon env con) (inlineExprs env args)
Prim x args -> Prim x (inlineExprs env args)
Lit _ -> expr
Note note e -> Note note (inlineExpr env e)
inlineCon :: Env -> Con Expr -> Con Expr
inlineCon env con
= case con of
ConTag tag arity -> ConTag (inlineExpr env tag) arity
_ -> con
inlineExprs :: Env -> [Expr] -> [Expr]
inlineExprs env exprs
= [inlineExpr env expr | expr <- exprs]
inlineBinds :: Env -> [(Id,Expr)] -> ([(Id,Expr)],Env)
inlineBinds env binds
= let env' = removeIds (map fst binds) env
in ([(x,inlineExpr env' e) | (x,e) <- binds], env')
inlineAlts :: Env -> [Alt] -> [Alt]
inlineAlts env alts
= [inlineAlt env alt | alt <- alts]
inlineAlt :: IdMap Expr -> Alt -> Alt
inlineAlt env (Alt pat expr)
= Alt pat (inlineExpr (removeIds (patIds pat) env) expr)
where
patIds (PatVar x) = [x]
patIds (PatCon _ xs) = xs
patIds (PatLit _) = []
deAnnotate :: Expr -> Expr
deAnnotate expr
= case expr of
Note _ e -> deAnnotate e
_ -> expr
trivial :: Expr -> Bool
trivial expr
= case expr of
Note _ e -> trivial e
Ap _ [] -> True
Con (ConId _) [] -> True
Lit _ -> True
_ -> False
whnfTrivial :: Expr -> Bool
whnfTrivial expr
= case expr of
Note _ e -> whnfTrivial e
Con (ConId _) [] -> True
Lit _ -> True
_ -> False
firstuse :: Id -> Expr -> Bool
firstuse x = first x False
firsts :: Id -> Bool -> [Expr] -> Bool
firsts = foldl . first
first :: Id -> Bool -> Expr -> Bool
first x c expr
= case expr of
LetRec bs e -> firsts x c (map snd bs ++ [e])
Let _ e1 e2 -> firsts x c [e1,e2]
Eval _ e1 _ -> first x False e1
Match _ _ -> False
Prim _ args -> firsts x False args
Ap y args | null args && y == x -> True
| not (null args) -> firsts x c (Ap y [] : args)
Con _ args -> firsts x c args
Note _ e -> first x c e
_ -> c