+inlinetoplevel, inlinetopleveltop :: Transform
+-- Any system name is candidate for inlining. Never inline user-defined
+-- functions, to preserver structure.
+inlinetoplevel expr@(Var f) | not $ isUserDefined f = do
+ norm <- isNormalizeable f
+ -- See if this is a top level binding for which we have a body
+ body_maybe <- Trans.lift $ getGlobalBind f
+ if norm && Maybe.isJust body_maybe
+ then do
+ -- Get the normalized version
+ norm <- Trans.lift $ getNormalized f
+ if needsInline norm
+ then do
+ -- Regenerate all uniques in the to-be-inlined expression
+ norm_uniqued <- Trans.lift $ genUniques norm
+ change norm_uniqued
+ else
+ return expr
+ else
+ -- No body or not normalizeable.
+ return expr
+-- Leave all other expressions unchanged
+inlinetoplevel expr = return expr
+inlinetopleveltop = everywhere ("inlinetoplevel", inlinetoplevel)
+
+needsInline :: CoreExpr -> Bool
+needsInline expr = case splitNormalized expr of
+ -- Inline any function that only has a single definition, it is probably
+ -- simple enough. This might inline some stuff that it shouldn't though it
+ -- will never inline user-defined functions (inlinetoplevel only tries
+ -- system names) and inlining should never break things.
+ (args, [bind], res) -> True
+ _ -> False
+