Inline all simple top level functions, not just compiler-generated ones.
authorMatthijs Kooijman <matthijs@stdin.nl>
Wed, 31 Mar 2010 09:28:51 +0000 (11:28 +0200)
committerMatthijs Kooijman <matthijs@stdin.nl>
Wed, 31 Mar 2010 09:28:51 +0000 (11:28 +0200)
The checking for compiler generated functions wasn't watertight, so
let's just don't check at all. There is no risk for loops with
funextract anymore, since we only inline functions applied in let
bindings now.

cλash/CLasH/Normalize.hs

index 999704f38d79b05b5c2936bde593236ccc5af137..89b5a8118691d99d9eb63077be7f761734478146 100644 (file)
@@ -327,35 +327,35 @@ inlinenonreptop = everywhere ("inlinenonrep", inlinebind ((Monad.liftM not) . is
 --------------------------------
 -- Top level function inlining
 --------------------------------
--- This transformation inlines top level bindings that have been generated by
--- the compiler and are really simple. Really simple currently means that the
--- normalized form only contains a single binding, which catches most of the
+-- This transformation inlines simple top level bindings. Simple
+-- currently means that the body is only a single application (though
+-- the complexity of the arguments is not currently checked) or that the
+-- normalized form only contains a single binding. This should catch most of the
 -- cases where a top level function is created that simply calls a type class
 -- method with a type and dictionary argument, e.g.
 --   fromInteger = GHC.Num.fromInteger (SizedWord D8) $dNum
 -- which is later called using simply
 --   fromInteger (smallInteger 10)
--- By inlining such calls to simple, compiler generated functions, we prevent
--- huge amounts of trivial components in the VHDL output, which the user never
--- wanted. We never inline user-defined functions, since we want to preserve
--- all structure defined by the user. Currently this includes all functions
--- that were created by funextract, since we would get loops otherwise.
+--
+-- These useless wrappers are created by GHC automatically. If we don't
+-- inline them, we get loads of useless components cluttering the
+-- generated VHDL.
+--
+-- Note that the inlining could also inline simple functions defined by
+-- the user, not just GHC generated functions. It turns out to be near
+-- impossible to reliably determine what functions are generated and
+-- what functions are user-defined. Instead of guessing (which will
+-- inline less than we want) we will just inline all simple functions.
 --
 -- Only functions that are actually completely applied and bound by a
 -- variable in a let expression are inlined. These are the expressions
 -- that will eventually generate instantiations of trivial components.
 -- By not inlining any other reference, we also prevent looping problems
 -- with funextract and inlinedict.
---
--- Note that "defined by the compiler" isn't completely watertight, since GHC
--- doesn't seem to set all those names as "system names", we apply some
--- guessing here.
 inlinetoplevel, inlinetopleveltop :: Transform
 inlinetoplevel (LetBinding:_) expr =
   case collectArgs expr of
-       -- Any system name is candidate for inlining. Never inline
-       -- user-defined functions, to preserve structure.
-       (Var f, args) | not $ isUserDefined f -> do
+       (Var f, args) -> do
          body_maybe <- needsInline f
          case body_maybe of
                Just body -> do