import CmdLineOpts ( switchIsOn, opt_SimplDoEtaReduction,
opt_SimplNoPreInlining,
+ dopt, DynFlag(Opt_D_dump_inlinings),
SimplifierSwitch(..)
)
import SimplMonad
-import SimplUtils ( mkCase, tryRhsTyLam, tryEtaExpansion, findAlt,
- simplBinder, simplBinders, simplIds, findDefault,
+import SimplUtils ( mkCase, tryRhsTyLam, tryEtaExpansion,
+ simplBinder, simplBinders, simplIds,
SimplCont(..), DupFlag(..), mkStop, mkRhsStop,
contResultType, discardInline, countArgs, contIsDupable,
getContArgs, interestingCallContext, interestingArg, isStrictType
)
import Var ( mkSysTyVar, tyVarKind )
import VarEnv
-import VarSet ( elemVarSet )
-import Id ( Id, idType, idInfo, isDataConId,
+import Id ( Id, idType, idInfo, isDataConId, hasNoBinding,
idUnfolding, setIdUnfolding, isExportedId, isDeadBinder,
idDemandInfo, setIdInfo,
- idOccInfo, setIdOccInfo,
+ idOccInfo, setIdOccInfo,
zapLamIdInfo, setOneShotLambda,
)
import IdInfo ( OccInfo(..), isDeadOcc, isLoopBreaker,
dataConSig, dataConArgTys
)
import CoreSyn
-import CoreFVs ( mustHaveLocalBinding, exprFreeVars )
+import PprCore ( pprParendExpr, pprCoreExpr )
+import CoreFVs ( mustHaveLocalBinding )
import CoreUnfold ( mkOtherCon, mkUnfolding, otherCons,
callSiteInline
)
import CoreUtils ( cheapEqExpr, exprIsDupable, exprIsTrivial,
- exprIsConApp_maybe, mkPiType,
+ exprIsConApp_maybe, mkPiType, findAlt, findDefault,
exprType, coreAltsType, exprIsValue,
exprOkForSpeculation, exprArity, exprIsCheap,
mkCoerce, mkSCC, mkInlineMe, mkAltExpr
Nothing -> rebuild (foldl (flip Lam) body' rev_bndrs) cont
where
-- We don't use CoreUtils.etaReduce, because we can be more
- -- efficient here: (a) we already have the binders, (b) we can do
- -- the triviality test before computing the free vars
+ -- efficient here:
+ -- (a) we already have the binders,
+ -- (b) we can do the triviality test before computing the free vars
+ -- [in fact I take the simple path and look for just a variable]
+ -- (c) we don't want to eta-reduce a data con worker or primop
+ -- because we only have to eta-expand them later when we saturate
try_eta body | not opt_SimplDoEtaReduction = Nothing
| otherwise = go rev_bndrs body
go [] body | ok_body body = Just body -- Success!
go _ _ = Nothing -- Failure!
- ok_body body = exprIsTrivial body && not (any (`elemVarSet` exprFreeVars body) rev_bndrs)
- ok_arg b arg = varToCoreExpr b `cheapEqExpr` arg
+ ok_body (Var v) = not (v `elem` rev_bndrs) && not (hasNoBinding v)
+ ok_body other = False
+ ok_arg b arg = varToCoreExpr b `cheapEqExpr` arg
mkLamBndrZapper :: CoreExpr -- Function
-> SimplCont -- The context
-- We're looking at a binding with a trivial RHS, so
-- perhaps we can discard it altogether!
--
- -- NB: a loop breaker never has postInlineUnconditionally True
+ -- NB: a loop breaker has must_keep_binding = True
-- and non-loop-breakers only have *forward* references
-- Hence, it's safe to discard the binding
--
thing_inside
| Note coercion@(Coerce _ inner_ty) inner_rhs <- new_rhs,
- not trivial_rhs
+ not trivial_rhs && not (isUnLiftedType inner_ty)
-- x = coerce t e ==> c = e; x = inline_me (coerce t c)
-- Now x can get inlined, which moves the coercion
-- to the usage site. This is a bit like worker/wrapper stuff,
-- will inline x.
-- Also the full-blown w/w thing isn't set up for non-functions
--
+ -- The (not (isUnLiftedType inner_ty)) avoids the nasty case of
+ -- x::Int = coerce Int Int# (foo y)
+ -- ==>
+ -- v::Int# = foo y
+ -- x::Int = coerce Int Int# v
+ -- which would be bogus because then v will be evaluated strictly.
+ -- How can this arise? Via
+ -- x::Int = case (foo y) of { ... }
+ -- followed by case elimination.
+ --
-- The inline_me note is so that the simplifier doesn't
-- just substitute c back inside x's rhs! (Typically, x will
-- get substituted away, but not if it's exported.)
---------------------------------------------------------
-- Dealing with a call
-completeCall var occ cont
+completeCall var occ_info cont
= getBlackList `thenSmpl` \ black_list_fn ->
getInScope `thenSmpl` \ in_scope ->
getContArgs var cont `thenSmpl` \ (args, call_cont, inline_call) ->
inline_cont | inline_call = discardInline cont
| otherwise = cont
- maybe_inline = callSiteInline dflags black_listed inline_call occ
+ maybe_inline = callSiteInline dflags black_listed inline_call occ_info
var arg_infos interesting_cont
in
-- First, look for an inlining
-- But the black-listing mechanism means that inlining of the wrapper
-- won't occur for things that have specialisations till a later phase, so
-- it's ok to try for inlining first.
+ --
+ -- You might think that we shouldn't apply rules for a loop breaker:
+ -- doing so might give rise to an infinite loop, because a RULE is
+ -- rather like an extra equation for the function:
+ -- RULE: f (g x) y = x+y
+ -- Eqn: f a y = a-y
+ --
+ -- But it's too drastic to disable rules for loop breakers.
+ -- Even the foldr/build rule would be disabled, because foldr
+ -- is recursive, and hence a loop breaker:
+ -- foldr k z (build g) = g k z
+ -- So it's up to the programmer: rules can cause divergence
getSwitchChecker `thenSmpl` \ chkr ->
let
case maybe_rule of {
Just (rule_name, rule_rhs) ->
tick (RuleFired rule_name) `thenSmpl_`
+#ifdef DEBUG
+ (if dopt Opt_D_dump_inlinings dflags then
+ pprTrace "Rule fired" (vcat [
+ text "Rule:" <+> ptext rule_name,
+ text "Before:" <+> ppr var <+> sep (map pprParendExpr args'),
+ text "After: " <+> pprCoreExpr rule_rhs])
+ else
+ id) $
+#endif
simplExprF rule_rhs call_cont ;
Nothing -> -- No rules
-> SimplM OutExprStuff
knownCon expr con args bndr alts se cont
- = tick (KnownBranch bndr) `thenSmpl_`
+ = -- Arguments should be atomic;
+ -- yell if not
+ WARN( not (all exprIsTrivial args),
+ text "knownCon" <+> ppr expr )
+ tick (KnownBranch bndr) `thenSmpl_`
setSubstEnv se (
simplBinder bndr $ \ bndr' ->
completeBinding bndr bndr' False False expr $