git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: move uncurried calls to optimizer
commit9cdc997d003b3c8acc12f033fc98c80615949620 authorAndy Arvanitis <andyarvanitis@gmail.com> dateSun 4 Sep 2016, 16:49 (10 years ago) parentbf4fd96
5 files changed+86−48
purescript.cabal+1 src/Language/PureScript/CodeGen/Cpp.hs+22−43 src/Language/PureScript/CodeGen/Cpp/Optimizer.hs+7−5 src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+7 src/Language/PureScript/CodeGen/Cpp/Optimizer/Uncurry.hs+49
purescript.cabal+1
@@ -182,6 +182,7 @@ library
182182 Language.PureScript.CodeGen.Cpp.Optimizer.Inliner
183183 Language.PureScript.CodeGen.Cpp.Optimizer.MagicDo
184184 Language.PureScript.CodeGen.Cpp.Optimizer.TCO
185+ Language.PureScript.CodeGen.Cpp.Optimizer.Uncurry
185186 Language.PureScript.CodeGen.Cpp.Optimizer.Unused
186187 Language.PureScript.CodeGen.Cpp.Types
187188 Language.PureScript.Pretty.Cpp
src/Language/PureScript/CodeGen/Cpp.hs+22−43
@@ -71,7 +71,14 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
7171 (snd <$> imps)
7272 let cppImports' = "PureScript" : cppImports
7373 cppDecls <- concat <$> mapM (bindToCpp [CppTopLevel]) decls
74− cppDecls' <- traverse optimize cppDecls
74+ let namesmap = M.toList .
75+ M.mapKeysMonotonic (qualifiedToCpp id) . M.map (\(t, _, _) -> arity t) $
76+ E.names env
77+ datamap = M.toList .
78+ M.mapKeysMonotonic (qualifiedToCpp (Ident . runProperName)) .
79+ M.map (\(_, _, _, fields) -> length fields) $
80+ E.dataConstructors env
81+ cppDecls' <- traverse (optimize $ namesmap ++ datamap) cppDecls
7582 foreignWrappers <- curriedForeigns
7683 let optimized = cppDecls' ++ foreignWrappers
7784 let moduleHeader =
@@ -127,7 +134,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
127134 in return $ CppStruct className [CppEnum Nothing Nothing (sort supers ++ members)]
128135
129136 declToCpp vqs (_, ident) (Abs (_, com, ty, _) arg body) = do
130− fn <- if arity' > 1 && CppTopLevel `elem` vqs
137+ fn <- if CppTopLevel `elem` vqs
131138 then do
132139 argNames <- replicateM (arity' - length args' - 1) freshName
133140 let args'' = zip argNames (repeat aty)
@@ -151,7 +158,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
151158 (curriedName name)
152159 [arg']
153160 rty
154− []
161+ (if arity' == 1 then [CppInline] else [])
155162 (asReturnBlock $
156163 curriedLambda
157164 (fst <$> args' ++ args'')
@@ -210,7 +217,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
210217 CppDataLiteral $
211218 CppAccessor (CppVar name) (CppVar "data") : (CppVar <$> fields'))
212219 ] ++
213− if length fields > 1
220+ if length fields > 0
214221 then
215222 [ CppFunction
216223 (curriedName name)
@@ -263,7 +270,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
263270 rty
264271 []
265272 (asReturnBlock block)
266− ] ++ if arity' > 1
273+ ] ++ if arity' > 0
267274 then [fn']
268275 else []
269276 where
@@ -387,17 +394,14 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
387394 -------------------------------------------------------------------------------------------------
388395 valueToCpp :: Expr Ann -> m Cpp
389396 -------------------------------------------------------------------------------------------------
390− valueToCpp (Var (_, _, _, Just (IsConstructor _ [])) ident) =
391− return $ CppApp (varToCpp ident) []
392−
393− valueToCpp (Var (_, _, _, Just (IsConstructor _ [_])) ident) =
397+ valueToCpp (Var (_, _, _, Just IsNewtype) ident) =
394398 return $ varToCpp ident
395399
396− valueToCpp (Var (_, _, _, Just (IsConstructor _ _)) ident) =
397− return . curriedName' $ varToCpp ident
400+ valueToCpp (Var (_, _, _, Just (IsConstructor _ [])) ident) =
401+ return $ CppApp (varToCpp ident) []
398402
399403 valueToCpp (Var (_, _, Just ty, _) ident@(Qualified (Just _) _))
400− | arity ty > 1 =
404+ | arity ty > 0 =
401405 return . curriedName' $ varToCpp ident
402406
403407 valueToCpp (Var _ ident) =
@@ -460,34 +464,16 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
460464 args' <- mapM valueToCpp args
461465 case f of
462466 Var (_, _, _, Just IsNewtype) _ -> return (head args')
463− Var (_, _, _, Just (IsConstructor _ fields)) ident
464− | length args == length fields ->
465− return $ CppApp (uncurried' $ qualifiedToCpp id ident) args'
466467 Var (_, _, _, Just IsTypeClassConstructor) (Qualified mn' (Ident classname)) ->
467468 let Just (_, constraints, fns) = findClass (Qualified mn' (ProperName classname)) in
468469 return . CppObjectLiteral CppInstance $
469470 zip
470471 ((sort $ superClassDictionaryNames constraints) ++ (fst <$> fns))
471472 args'
472− Var ann (Qualified (Just mn') ident)
473− | arity' <- maybe 0 arity ty,
474− arity' > 1 -> do
475− f' <- valueToCpp f
476− let (uncurriedArgs, curriedArgs) =
477− if length args' >= arity'
478− then splitAt arity' args'
479− else ([], args')
480− fn' =
481− if null uncurriedArgs
482− then curriedName' f'
483− else CppApp (uncurried' f') uncurriedArgs
484− return $ foldl (\fn a -> CppApp fn [a]) fn' curriedArgs
485− where
486− ty | (_, _, Just t, _) <- ann = Just t
487− | Just (t, _, _) <- M.lookup (Qualified (Just mn') ident) (E.names env) = Just t
488− | otherwise = Nothing
489− _ ->
490− flip (foldl (\fn a -> CppApp fn [a])) args' <$> valueToCpp f
473+ Var _ (Qualified (Just _) _) -> applied f args' curriedName'
474+ _ -> applied f args' id
475+ where
476+ applied f args g = flip (foldl (\fn a -> CppApp (g fn) [a])) args <$> valueToCpp f
491477
492478 valueToCpp (Case (maybeSpan, _, ty, _) values binders) = do
493479 vals <- mapM valueToCpp values
@@ -792,7 +778,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
792778 where
793779 go (ident, ty)
794780 | arity' <- arity ty,
795− arity' > 1 = do
781+ arity' > 0 = do
796782 let name = identToCpp ident
797783 argNames <- replicateM arity' freshName
798784 return $
@@ -800,7 +786,7 @@ moduleToCpp env (Module _ mn imps _ foreigns decls) = do
800786 (curriedName name)
801787 [(head argNames, Just $ CppAny [CppConst, CppRef])]
802788 (Just $ CppAny [])
803− []
789+ (if arity' == 1 then [CppInline] else [])
804790 (asReturnBlock $
805791 curriedLambda
806792 (tail argNames)
@@ -876,13 +862,6 @@ curriedName :: String -> String
876862curriedName name@('$' : _) = name
877863curriedName name = '$' : name
878864
879−---------------------------------------------------------------------------------------------------
880−uncurried' :: Cpp -> Cpp
881−---------------------------------------------------------------------------------------------------
882−uncurried' (CppVar ('$':name)) = CppVar name
883−uncurried' (CppAccessor a b) = CppAccessor (uncurried' a) b
884−uncurried' cpp = cpp
885−
886865---------------------------------------------------------------------------------------------------
887866curriedName' :: Cpp -> Cpp
888867---------------------------------------------------------------------------------------------------
src/Language/PureScript/CodeGen/Cpp/Optimizer.hs+7−5
@@ -55,23 +55,25 @@ import Language.PureScript.CodeGen.Cpp.Optimizer.Common
5555import Language.PureScript.CodeGen.Cpp.Optimizer.Inliner
5656import Language.PureScript.CodeGen.Cpp.Optimizer.MagicDo
5757import Language.PureScript.CodeGen.Cpp.Optimizer.TCO
58+import Language.PureScript.CodeGen.Cpp.Optimizer.Uncurry
5859import Language.PureScript.CodeGen.Cpp.Optimizer.Unused
5960
6061-- |
6162-- Apply a series of optimizer passes to simplified C++11 code
6263--
63−optimize :: (Monad m, MonadReader Options m, Applicative m, MonadSupply m) => Cpp -> m Cpp
64−optimize cpp = do
64+optimize :: (Monad m, MonadReader Options m, Applicative m, MonadSupply m) => NamesMap -> Cpp -> m Cpp
65+optimize nm cpp = do
6566 noOpt <- asks optionsNoOptimizations
66− if noOpt then return cpp else optimize' cpp
67+ if noOpt then return cpp else optimize' nm cpp
6768
68−optimize' :: (Monad m, MonadReader Options m, Applicative m, MonadSupply m) => Cpp -> m Cpp
69−optimize' cpp = do
69+optimize' :: (Monad m, MonadReader Options m, Applicative m, MonadSupply m) => NamesMap -> Cpp -> m Cpp
70+optimize' nm cpp = do
7071 opts <- ask
7172 untilFixedPoint (inlineFnComposition . applyAll
7273 [ collapseNestedBlocks
7374 , collapseNestedIfs
7475 , collapseIfElses
76+ , removeCurrying nm
7577 , toAutoVars
7678 , tco opts
7779 , magicDo opts
src/Language/PureScript/CodeGen/Cpp/Optimizer/Inliner.hs+7
@@ -281,6 +281,13 @@ inlineFnComposition = everywhereOnCppTopDownM convert
281281 | isFnComposeFlipped dict' fn = do
282282 arg <- freshName
283283 return $ CppLambda [CppCaptureAll] [(arg, constAnyRef)] Nothing (CppBlock [CppReturn $ CppApp y [CppApp x [CppVar arg]]])
284+ convert (CppApp (CppApp (CppApp fn [dict']) [x]) [y])
285+ | isFnCompose dict' fn = do
286+ arg <- freshName
287+ return $ CppLambda [CppCaptureAll] [(arg, constAnyRef)] Nothing (CppBlock [CppReturn $ CppApp x [CppApp y [CppVar arg]]])
288+ | isFnComposeFlipped dict' fn = do
289+ arg <- freshName
290+ return $ CppLambda [CppCaptureAll] [(arg, constAnyRef)] Nothing (CppBlock [CppReturn $ CppApp y [CppApp x [CppVar arg]]])
284291 convert other = return other
285292 isFnCompose :: Cpp -> Cpp -> Bool
286293 isFnCompose dict' fn = isDict semigroupoidFn dict' && isFn fnCompose fn
src/Language/PureScript/CodeGen/Cpp/Optimizer/Uncurry.hsnew file+49
@@ -0,0 +1,49 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CodeGen.Cpp.Optimizer.Uncurry
4+-- Copyright : (c) Andy Arvanitis 2016
5+-- License : MIT
6+--
7+-- Maintainer : Andy Arvanitis
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- |
12+-- Removes unused variables
13+--
14+-----------------------------------------------------------------------------
15+
16+module Language.PureScript.CodeGen.Cpp.Optimizer.Uncurry where
17+
18+import Prelude.Compat
19+
20+import Language.PureScript.CodeGen.Cpp.AST
21+import qualified Language.PureScript.Types as T
22+
23+type NamesMap = [(Cpp, Int)]
24+
25+removeCurrying :: NamesMap -> Cpp -> Cpp
26+removeCurrying nm = everywhereOnCpp convert
27+ where
28+ convert cpp@(CppApp {})
29+ | (f, args@(_:_)) <- unApp cpp [],
30+ Just f' <- unCurried f,
31+ Just arity' <- lookup f' nm,
32+ arity' > 0 && length args >= arity' =
33+ foldl
34+ (\fn a -> CppApp fn [a])
35+ (CppApp f' (take arity' args))
36+ (drop arity' args)
37+ where
38+ unCurried :: Cpp -> Maybe Cpp
39+ unCurried (CppAccessor var mn)
40+ | Just var' <- unCurried var = Just $ CppAccessor var' mn
41+ unCurried (CppVar ('$':name)) = Just $ CppVar name
42+ unCurried _ = Nothing
43+ convert cpp = cpp
44+
45+-------------------------------------------------------------------------------------------------
46+unApp :: Cpp -> [Cpp] -> (Cpp, [Cpp])
47+-------------------------------------------------------------------------------------------------
48+unApp (CppApp val args) args' = unApp val (args ++ args')
49+unApp other args' = (other, args')