mkOtherCon, otherCons,
unfoldingTemplate, maybeUnfoldingTemplate,
isEvaldUnfolding, isValueUnfolding, isCheapUnfolding, isCompulsoryUnfolding,
- hasUnfolding, hasSomeUnfolding,
+ hasUnfolding, hasSomeUnfolding, neverUnfold,
couldBeSmallEnoughToInline,
certainlyWillInline,
import PprCore ( pprCoreExpr )
import OccurAnal ( occurAnalyseGlobalExpr )
import CoreUtils ( exprIsValue, exprIsCheap, exprIsTrivial )
-import Id ( Id, idType, idFlavour, isId,
+import Id ( Id, idType, isId,
idSpecialisation, idInlinePragma, idUnfolding,
- isPrimOpId_maybe
+ isPrimOpId_maybe, globalIdDetails
)
import VarSet
-import Literal ( isLitLitLit, litIsDupable )
+import Literal ( isLitLitLit, litSize )
import PrimOp ( PrimOp(..), primOpIsDupable, primOpOutOfLine, ccallIsCasm )
-import IdInfo ( InlinePragInfo(..), OccInfo(..), IdFlavour(..),
+import IdInfo ( InlinePragInfo(..), OccInfo(..), GlobalIdDetails(..),
isNeverInlinePrag
)
import Type ( isUnLiftedType )
size_up (Type t) = sizeZero -- Types cost nothing
size_up (Var v) = sizeOne
- size_up (Note _ body) = size_up body -- Notes cost nothing
+ size_up (Note InlineMe body) = sizeOne -- Inline notes make it look very small
+ -- This can be important. If you have an instance decl like this:
+ -- instance Foo a => Foo [a] where
+ -- {-# INLINE op1, op2 #-}
+ -- op1 = ...
+ -- op2 = ...
+ -- then we'll get a dfun which is a pair of two INLINE lambdas
- size_up (App fun (Type t)) = size_up fun
- size_up (App fun arg) = size_up_app fun [arg]
+ size_up (Note _ body) = size_up body -- Other notes cost nothing
- size_up (Lit lit) | litIsDupable lit = sizeOne
- | otherwise = sizeN opt_UF_DearOp -- For lack of anything better
+ size_up (App fun (Type t)) = size_up fun
+ size_up (App fun arg) = size_up_app fun [arg]
+
+ size_up (Lit lit) = sizeN (litSize lit)
size_up (Lam b e) | isId b = lamScrutDiscount (size_up e `addSizeN` 1)
| otherwise = size_up e
(a) It's too eager. We don't want to inline a wrapper into a
context with no benefit.
- E.g. \ x. f (x+x) o point in inlining (+) here!
+ E.g. \ x. f (x+x) no point in inlining (+) here!
(b) It's ineffective. Once g's wrapper is inlined, its case-expressions
aren't scrutinising arguments any more
| fun `hasKey` buildIdKey = buildSize
| fun `hasKey` augmentIdKey = augmentSize
| otherwise
- = case idFlavour fun of
+ = case globalIdDetails fun of
DataConId dc -> conSizeN (valArgCount args)
PrimOpId op -> primOpSize op (valArgCount args)
FastInt -- Size to subtract if result is scrutinised
-- by a case expression
-isTooBig TooBig = True
-isTooBig _ = False
maxSize TooBig _ = TooBig
maxSize _ TooBig = TooBig
primOpSize op n_args
| not (primOpIsDupable op) = sizeN opt_UF_DearOp
- | not (primOpOutOfLine op) = sizeZero -- These are good to inline
+ | not (primOpOutOfLine op) = sizeN (1 - n_args)
+ -- Be very keen to inline simple primops.
+ -- We give a discount of 1 for each arg so that (op# x y z) costs 1.
+ -- I found occasions where we had
+ -- f x y z = case op# x y z of { s -> (# s, () #) }
+ -- and f wasn't getting inlined
| otherwise = sizeOne
buildSize = SizeIs (-2#) emptyBag 4#
-- Note: there used to be a '&& not top_level' in the guard above,
-- but that stopped us inlining top-level functions used only once,
-- which is stupid
- = not in_lam || not (null arg_infos) || interesting_cont
+ = WARN( not in_lam, ppr id ) -- If (not in_lam) && one_br then PreInlineUnconditionally
+ -- should have caught it, shouldn't it?
+ not (null arg_infos) || interesting_cont
| otherwise
= case guidance of
arg_infos really_interesting_cont
in
-#ifdef DEBUG
if dopt Opt_D_dump_inlinings dflags then
pprTrace "Considering inlining"
(ppr id <+> vcat [text "black listed:" <+> ppr black_listed,
else empty])
result
else
-#endif
result
}