From 95929be07d802527e15124d8d93c2b7ae5de4dd6 Mon Sep 17 00:00:00 2001 From: simonpj <unknown> Date: Wed, 24 May 2000 15:47:13 +0000 Subject: [PATCH] [project @ 2000-05-24 15:47:13 by simonpj] MERGE 4.07 * This fix cures the weird 'ifaceBinds' error that Sven and George tripped over. It was quite obscure! Basically, there was a top level binding f = x lying around, which CoreToStg didn't like. Why hadn't it been substituted away? Because it had a NOINLINE pragma. Why did it have a NOINLINE pragma? Because it's an always-diverging function, so we never want to inline it. --- ghc/compiler/basicTypes/IdInfo.lhs | 11 +++++++++++ ghc/compiler/coreSyn/CoreUnfold.lhs | 21 ++++++++------------- ghc/compiler/main/MkIface.lhs | 7 ++----- ghc/compiler/simplCore/Simplify.lhs | 6 +++--- ghc/compiler/stranal/StrictAnal.lhs | 6 +++--- ghc/compiler/stranal/WorkWrap.lhs | 10 +++++++--- 6 files changed, 34 insertions(+), 27 deletions(-) diff --git a/ghc/compiler/basicTypes/IdInfo.lhs b/ghc/compiler/basicTypes/IdInfo.lhs index c94e81b39f2f..502a904913ea 100644 --- a/ghc/compiler/basicTypes/IdInfo.lhs +++ b/ghc/compiler/basicTypes/IdInfo.lhs @@ -45,6 +45,7 @@ module IdInfo ( -- Inline prags InlinePragInfo(..), inlinePragInfo, setInlinePragInfo, pprInlinePragInfo, + isNeverInlinePrag, neverInlinePrag, -- Occurrence info OccInfo(..), isFragileOccInfo, @@ -324,6 +325,16 @@ data InlinePragInfo (Maybe Int) -- Phase number from pragma, if any -- The True, Nothing case doesn't need to be recorded + -- SEE COMMENTS WITH CoreUnfold.blackListed on the + -- exact significance of the IMustNotBeINLINEd pragma + +isNeverInlinePrag :: InlinePragInfo -> Bool +isNeverInlinePrag (IMustNotBeINLINEd True Nothing) = True +isNeverInlinePrag other = False + +neverInlinePrag :: InlinePragInfo +neverInlinePrag = IMustNotBeINLINEd True Nothing + instance Outputable InlinePragInfo where -- This is now parsed in interface files ppr NoInlinePragInfo = empty diff --git a/ghc/compiler/coreSyn/CoreUnfold.lhs b/ghc/compiler/coreSyn/CoreUnfold.lhs index 774877898ab2..7276e3480d4f 100644 --- a/ghc/compiler/coreSyn/CoreUnfold.lhs +++ b/ghc/compiler/coreSyn/CoreUnfold.lhs @@ -54,7 +54,9 @@ import VarSet import Name ( isLocallyDefined ) import Literal ( isLitLitLit ) import PrimOp ( PrimOp(..), primOpIsDupable, primOpOutOfLine, ccallIsCasm ) -import IdInfo ( ArityInfo(..), InlinePragInfo(..), OccInfo(..), IdFlavour(..), CprInfo(..), insideLam, workerExists ) +import IdInfo ( ArityInfo(..), InlinePragInfo(..), OccInfo(..), IdFlavour(..), CprInfo(..), + insideLam, workerExists, isNeverInlinePrag + ) import TyCon ( tyConFamilySize ) import Type ( splitFunTy_maybe, isUnLiftedType ) import Unique ( Unique, buildIdKey, augmentIdKey ) @@ -435,16 +437,11 @@ certainlyWillInline :: Id -> Bool certainlyWillInline v = case idUnfolding v of - CoreUnfolding _ _ _ is_value _ (UnfoldIfGoodArgs n_vals _ size _) + CoreUnfolding _ _ _ is_value _ g@(UnfoldIfGoodArgs n_vals _ size _) -> is_value && size - (n_vals +1) <= opt_UF_UseThreshold - && not never_inline other -> False - where - never_inline = case idInlinePragma v of - IMustNotBeINLINEd False Nothing -> True - other -> False \end{code} @okToUnfoldInHifile@ is used when emitting unfolding info into an interface @@ -673,7 +670,7 @@ For optimisation we use phase 1,2 and nothing (i.e. no -finline-phase flag) in that order. The meanings of these are determined by the @blackListed@ function here. -The final simplification doesn't have a phase number +The final simplification doesn't have a phase number. Pragmas ~~~~~~~ @@ -696,9 +693,7 @@ blackListed :: IdSet -- Used in transformation rules -- place that the inline phase number is looked at. blackListed rule_vars Nothing -- Last phase - = \v -> case idInlinePragma v of - IMustNotBeINLINEd False Nothing -> True -- An unconditional NOINLINE pragma - other -> False + = \v -> isNeverInlinePrag (idInlinePragma v) blackListed rule_vars (Just phase) = \v -> normal_case rule_vars phase v @@ -712,8 +707,8 @@ normal_case rule_vars phase v | otherwise -> True -- Always blacklisted IMustNotBeINLINEd from_inline (Just threshold) - | from_inline -> phase < threshold && has_rules - | otherwise -> phase < threshold || has_rules + | from_inline -> (phase < threshold && has_rules) + | otherwise -> (phase < threshold || has_rules) where has_rules = v `elemVarSet` rule_vars || not (isEmptyCoreRules (idSpecialisation v)) diff --git a/ghc/compiler/main/MkIface.lhs b/ghc/compiler/main/MkIface.lhs index 6ed5e4c8b5f7..50ebde38374d 100644 --- a/ghc/compiler/main/MkIface.lhs +++ b/ghc/compiler/main/MkIface.lhs @@ -34,7 +34,7 @@ import IdInfo ( IdInfo, StrictnessInfo(..), ArityInfo, InlinePragInfo(..), inli strictnessInfo, ppStrictnessInfo, isBottomingStrictness, cafInfo, ppCafInfo, specInfo, cprInfo, ppCprInfo, pprInlinePragInfo, - occInfo, + occInfo, isNeverInlinePrag, workerExists, workerInfo, ppWorkerInfo, WorkerInfo(..) ) import CoreSyn ( CoreExpr, CoreBind, Bind(..), rulesRules, rulesRhsFreeVars ) @@ -372,10 +372,7 @@ ifaceId get_idinfo needed_ids is_rec id rhs ------------ Unfolding -------------- inline_pragma = inlinePragInfo core_idinfo - dont_inline = case inline_pragma of - IMustNotBeINLINEd False Nothing -> True -- Unconditional NOINLINE - other -> False - + dont_inline = isNeverInlinePrag inline_pragma unfold_pretty | show_unfold = ptext SLIT("__U") <> pprInlinePragInfo inline_pragma <+> pprIfaceUnfolding rhs | otherwise = empty diff --git a/ghc/compiler/simplCore/Simplify.lhs b/ghc/compiler/simplCore/Simplify.lhs index f6ccf6a39ca1..92bb34c85081 100644 --- a/ghc/compiler/simplCore/Simplify.lhs +++ b/ghc/compiler/simplCore/Simplify.lhs @@ -985,9 +985,9 @@ postInlineUnconditionally :: Bool -- Black listed -- we'll get another opportunity when we get to the ocurrence(s) postInlineUnconditionally black_listed occ_info bndr rhs - | isExportedId bndr || - black_listed || - isLoopBreaker occ_info = False -- Don't inline these + | isExportedId bndr = False -- Don't inline these, ever + | black_listed = False + | isLoopBreaker occ_info = False | otherwise = exprIsTrivial rhs -- Duplicating is free -- Don't inline even WHNFs inside lambdas; doing so may -- simply increase allocation when the function is called diff --git a/ghc/compiler/stranal/StrictAnal.lhs b/ghc/compiler/stranal/StrictAnal.lhs index 3e83e2218cd2..032176a6e1dd 100644 --- a/ghc/compiler/stranal/StrictAnal.lhs +++ b/ghc/compiler/stranal/StrictAnal.lhs @@ -17,7 +17,7 @@ import Id ( idType, setIdStrictness, setInlinePragma, idDemandInfo, setIdDemandInfo, isBottomingId, Id ) -import IdInfo ( InlinePragInfo(..) ) +import IdInfo ( neverInlinePrag ) import CoreLint ( beginPass, endPass ) import ErrUtils ( dumpIfSet ) import SaAbsInt @@ -186,12 +186,12 @@ saTopBind str_env abs_env (Rec pairs) in returnSa (new_str_env, new_abs_env, Rec new_pairs) +-- Hack alert! -- Top level divergent bindings are marked NOINLINE -- This avoids fruitless inlining of top level error functions addStrictnessInfoToTopId str_val abs_val bndr = if isBottomingId new_id then - new_id `setInlinePragma` IMustNotBeINLINEd False Nothing - -- This is a NOINLINE pragma + new_id `setInlinePragma` neverInlinePrag else new_id where diff --git a/ghc/compiler/stranal/WorkWrap.lhs b/ghc/compiler/stranal/WorkWrap.lhs index 92eaf088aa0c..15736354b063 100644 --- a/ghc/compiler/stranal/WorkWrap.lhs +++ b/ghc/compiler/stranal/WorkWrap.lhs @@ -23,7 +23,8 @@ import Id ( Id, idType, idStrictness, setIdArityInfo, isOneShotLambda, import VarSet import Type ( Type, isNewType, splitForAllTys, splitFunTys ) import IdInfo ( mkStrictnessInfo, noStrictnessInfo, StrictnessInfo(..), - CprInfo(..), exactArity, InlinePragInfo(..), WorkerInfo(..) + CprInfo(..), exactArity, InlinePragInfo(..), isNeverInlinePrag, + WorkerInfo(..) ) import Demand ( Demand, wwLazy ) import SaLib @@ -189,8 +190,11 @@ tryWW :: Bool -- True <=> a non-recursive binding -- if two, then a worker and a -- wrapper. tryWW non_rec fn_id rhs - | non_rec - && certainlyWillInline fn_id + | not (isNeverInlinePrag inline_prag) + = -- Don't split things that will never be inlined + returnUs [ (fn_id, rhs) ] + + | non_rec && certainlyWillInline fn_id -- No point in worker/wrappering something that is going to be -- INLINEd wholesale anyway. If the strictness analyser is run -- twice, this test also prevents wrappers (which are INLINEd) -- GitLab