From: simonpj@microsoft.com Date: Mon, 5 Jun 2006 11:49:00 +0000 (+0000) Subject: Remove InlinePlease and add inline function and RULE X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=commitdiff_plain;h=f2dcf256399e9a2de6343c625630b51f8abf4863 Remove InlinePlease and add inline function and RULE For a long time GHC has had some internal mechanism designed to support a call-site inline directive, thus inline f xs makes f be inlined at the call site even if f is big. However, the surface syntax seems to have gone, and in any case it can be done more neatly using a RULE. This commit: * Removes the InlineCall constructor for Note and InlinePlease for SimplCont * Adds a new known-key Id called 'inline', whose definition in GHC.Base is just the identity function * Adds a built-in RULE in PrelRules that rewrites (inline f) to the body of f, if possible * Adds documentation NOTE: I have not tested this (aeroplane work). Give it a try! --- diff --git a/compiler/coreSyn/CorePrep.lhs b/compiler/coreSyn/CorePrep.lhs index e5165f0..105d248 100644 --- a/compiler/coreSyn/CorePrep.lhs +++ b/compiler/coreSyn/CorePrep.lhs @@ -498,7 +498,6 @@ corePrepExprFloat env expr@(App _ _) ty = exprType fun ignore_note (CoreNote _) = True - ignore_note InlineCall = True ignore_note InlineMe = True ignore_note _other = False -- We don't ignore SCCs, since they require some code generation diff --git a/compiler/coreSyn/CoreSyn.lhs b/compiler/coreSyn/CoreSyn.lhs index 201d866..331a890 100644 --- a/compiler/coreSyn/CoreSyn.lhs +++ b/compiler/coreSyn/CoreSyn.lhs @@ -123,9 +123,6 @@ data Note Type -- The to-type: type of whole coerce expression Type -- The from-type: type of enclosed expression - | InlineCall -- Instructs simplifier to inline - -- the enclosed call - | InlineMe -- Instructs simplifer to treat the enclosed expression -- as very small, and inline it at its call sites diff --git a/compiler/coreSyn/CoreUnfold.lhs b/compiler/coreSyn/CoreUnfold.lhs index e50f304..169c4ec 100644 --- a/compiler/coreSyn/CoreUnfold.lhs +++ b/compiler/coreSyn/CoreUnfold.lhs @@ -500,7 +500,6 @@ StrictAnal.addStrictnessInfoToTopId \begin{code} callSiteInline :: DynFlags -> Bool -- True <=> the Id can be inlined - -> Bool -- 'inline' note at call site -> OccInfo -> Id -- The Id -> [Bool] -- One for each value arg; True if it is interesting @@ -508,7 +507,7 @@ callSiteInline :: DynFlags -> Maybe CoreExpr -- Unfolding, if any -callSiteInline dflags active_inline inline_call occ id arg_infos interesting_cont +callSiteInline dflags active_inline occ id arg_infos interesting_cont = case idUnfolding id of { NoUnfolding -> Nothing ; OtherCon cs -> Nothing ; @@ -547,9 +546,6 @@ callSiteInline dflags active_inline inline_call occ id arg_infos interesting_con -- consider_safe decides whether it's a good idea to -- inline something, given that there's no -- work-duplication issue (the caller checks that). - | inline_call = True - - | otherwise = case guidance of UnfoldNever -> False UnfoldIfGoodArgs n_vals_wanted arg_discounts size res_discount diff --git a/compiler/coreSyn/CoreUtils.lhs b/compiler/coreSyn/CoreUtils.lhs index f82435b..00cce7e 100644 --- a/compiler/coreSyn/CoreUtils.lhs +++ b/compiler/coreSyn/CoreUtils.lhs @@ -165,12 +165,6 @@ mkNote (SCC cc) expr = mkSCC cc expr mkNote InlineMe expr = mkInlineMe expr mkNote note expr = Note note expr #endif - --- Slide InlineCall in around the function --- No longer necessary I think (SLPJ Apr 99) --- mkNote InlineCall (App f a) = App (mkNote InlineCall f) a --- mkNote InlineCall (Var v) = Note InlineCall (Var v) --- mkNote InlineCall expr = expr \end{code} Drop trivial InlineMe's. This is somewhat important, because if we have an unfolding @@ -1106,7 +1100,6 @@ eq_alt env (c1,vs1,r1) (c2,vs2,r2) = c1==c2 && tcEqExprX (rnBndrs2 env vs1 vs2) eq_note env (SCC cc1) (SCC cc2) = cc1 == cc2 eq_note env (Coerce t1 f1) (Coerce t2 f2) = tcEqTypeX env t1 t2 && tcEqTypeX env f1 f2 -eq_note env InlineCall InlineCall = True eq_note env (CoreNote s1) (CoreNote s2) = s1 == s2 eq_note env other1 other2 = False \end{code} @@ -1136,7 +1129,6 @@ exprSize (Type t) = seqType t `seq` 1 noteSize (SCC cc) = cc `seq` 1 noteSize (Coerce t1 t2) = seqType t1 `seq` seqType t2 `seq` 1 -noteSize InlineCall = 1 noteSize InlineMe = 1 noteSize (CoreNote s) = s `seq` 1 -- hdaume: core annotations diff --git a/compiler/coreSyn/MkExternalCore.lhs b/compiler/coreSyn/MkExternalCore.lhs index b4970cc..ce09288 100644 --- a/compiler/coreSyn/MkExternalCore.lhs +++ b/compiler/coreSyn/MkExternalCore.lhs @@ -117,7 +117,6 @@ make_exp (Let b e) = C.Let (make_vdef b) (make_exp e) make_exp (Case e v ty alts) = C.Case (make_exp e) (make_vbind v) (make_ty ty) (map make_alt alts) make_exp (Note (SCC cc) e) = C.Note "SCC" (make_exp e) -- temporary make_exp (Note (Coerce t_to t_from) e) = C.Coerce (make_ty t_to) (make_exp e) -make_exp (Note InlineCall e) = C.Note "InlineCall" (make_exp e) make_exp (Note (CoreNote s) e) = C.Note s (make_exp e) -- hdaume: core annotations make_exp (Note InlineMe e) = C.Note "InlineMe" (make_exp e) make_exp _ = error "MkExternalCore died: make_exp" diff --git a/compiler/coreSyn/PprCore.lhs b/compiler/coreSyn/PprCore.lhs index c834abb..0e3b82d 100644 --- a/compiler/coreSyn/PprCore.lhs +++ b/compiler/coreSyn/PprCore.lhs @@ -232,9 +232,6 @@ ppr_expr add_par (Note (Coerce to_ty from_ty) expr) pprParendExpr expr] #endif -ppr_expr add_par (Note InlineCall expr) - = add_par (ptext SLIT("__inline_call") <+> pprParendExpr expr) - ppr_expr add_par (Note InlineMe expr) = add_par $ ptext SLIT("__inline_me") <+> pprParendExpr expr diff --git a/compiler/deSugar/DsCCall.lhs b/compiler/deSugar/DsCCall.lhs index 8467539..2ee9d08 100644 --- a/compiler/deSugar/DsCCall.lhs +++ b/compiler/deSugar/DsCCall.lhs @@ -32,7 +32,7 @@ import Type ( Type, isUnLiftedType, mkFunTys, mkFunTy, tyVarsOfType, mkForAllTys, mkTyConApp, isPrimitiveType, splitTyConApp_maybe, splitRecNewType_maybe, splitForAllTy_maybe, - isUnboxedTupleType, coreView + isUnboxedTupleType ) import PrimOp ( PrimOp(..) ) @@ -51,7 +51,7 @@ import TysWiredIn ( unitDataConId, ) import BasicTypes ( Boxity(..) ) import Literal ( mkMachInt ) -import PrelNames ( Unique, hasKey, ioTyConKey, boolTyConKey, unitTyConKey, +import PrelNames ( Unique, hasKey, boolTyConKey, unitTyConKey, int8TyConKey, int16TyConKey, int32TyConKey, word8TyConKey, word16TyConKey, word32TyConKey -- dotnet interop diff --git a/compiler/iface/BinIface.hs b/compiler/iface/BinIface.hs index a31988a..6b56119 100644 --- a/compiler/iface/BinIface.hs +++ b/compiler/iface/BinIface.hs @@ -864,8 +864,6 @@ instance Binary IfaceNote where put_ bh (IfaceCoerce ab) = do putByte bh 1 put_ bh ab - put_ bh IfaceInlineCall = do - putByte bh 2 put_ bh IfaceInlineMe = do putByte bh 3 put_ bh (IfaceCoreNote s) = do @@ -878,7 +876,6 @@ instance Binary IfaceNote where return (IfaceSCC aa) 1 -> do ab <- get bh return (IfaceCoerce ab) - 2 -> do return IfaceInlineCall 3 -> do return IfaceInlineMe _ -> do ac <- get bh return (IfaceCoreNote ac) diff --git a/compiler/iface/IfaceSyn.lhs b/compiler/iface/IfaceSyn.lhs index 5309367..608e62a 100644 --- a/compiler/iface/IfaceSyn.lhs +++ b/compiler/iface/IfaceSyn.lhs @@ -215,7 +215,6 @@ data IfaceExpr data IfaceNote = IfaceSCC CostCentre | IfaceCoerce IfaceType - | IfaceInlineCall | IfaceInlineMe | IfaceCoreNote String @@ -411,7 +410,6 @@ pprIfaceApp fun args = sep (pprIfaceExpr parens fun : args) instance Outputable IfaceNote where ppr (IfaceSCC cc) = pprCostCentreCore cc ppr (IfaceCoerce ty) = ptext SLIT("__coerce") <+> pprParendIfaceType ty - ppr IfaceInlineCall = ptext SLIT("__inline_call") ppr IfaceInlineMe = ptext SLIT("__inline_me") ppr (IfaceCoreNote s) = ptext SLIT("__core_note") <+> pprHsString (mkFastString s) @@ -661,7 +659,6 @@ toIfaceExpr ext (Note n e) = IfaceNote (toIfaceNote ext n) (toIfaceExpr ext e --------------------- toIfaceNote ext (SCC cc) = IfaceSCC cc toIfaceNote ext (Coerce t1 _) = IfaceCoerce (toIfaceType ext t1) -toIfaceNote ext InlineCall = IfaceInlineCall toIfaceNote ext InlineMe = IfaceInlineMe toIfaceNote ext (CoreNote s) = IfaceCoreNote s @@ -906,7 +903,6 @@ eq_ifaceConAlt _ _ = False eq_ifaceNote :: EqEnv -> IfaceNote -> IfaceNote -> IfaceEq eq_ifaceNote env (IfaceSCC c1) (IfaceSCC c2) = bool (c1==c2) eq_ifaceNote env (IfaceCoerce t1) (IfaceCoerce t2) = eq_ifType env t1 t2 -eq_ifaceNote env IfaceInlineCall IfaceInlineCall = Equal eq_ifaceNote env IfaceInlineMe IfaceInlineMe = Equal eq_ifaceNote env (IfaceCoreNote s1) (IfaceCoreNote s2) = bool (s1==s2) eq_ifaceNote env _ _ = NotEqual diff --git a/compiler/iface/TcIface.lhs b/compiler/iface/TcIface.lhs index caff95f..7c4c535 100644 --- a/compiler/iface/TcIface.lhs +++ b/compiler/iface/TcIface.lhs @@ -639,7 +639,6 @@ tcIfaceExpr (IfaceNote note expr) IfaceCoerce to_ty -> tcIfaceType to_ty `thenM` \ to_ty' -> returnM (Note (Coerce to_ty' (exprType expr')) expr') - IfaceInlineCall -> returnM (Note InlineCall expr') IfaceInlineMe -> returnM (Note InlineMe expr') IfaceSCC cc -> returnM (Note (SCC cc) expr') IfaceCoreNote n -> returnM (Note (CoreNote n) expr') diff --git a/compiler/prelude/PrelNames.lhs b/compiler/prelude/PrelNames.lhs index 3d57033..9fd1419 100644 --- a/compiler/prelude/PrelNames.lhs +++ b/compiler/prelude/PrelNames.lhs @@ -453,6 +453,9 @@ unpackCStringFoldrName = varQual pREL_BASE FSLIT("unpackFoldrCString#") unpackC unpackCStringUtf8Name = varQual pREL_BASE FSLIT("unpackCStringUtf8#") unpackCStringUtf8IdKey eqStringName = varQual pREL_BASE FSLIT("eqString") eqStringIdKey +-- The 'inline' function +inlineIdName = varQual pREL_BASE FSLIT("inline") inlineIdKey + -- Base classes (Eq, Ord, Functor) eqClassName = clsQual pREL_BASE FSLIT("Eq") eqClassKey eqName = methName eqClassName FSLIT("==") eqClassOpKey @@ -911,6 +914,8 @@ breakpointCondIdKey = mkPreludeMiscIdUnique 63 breakpointJumpIdKey = mkPreludeMiscIdUnique 64 breakpointCondJumpIdKey = mkPreludeMiscIdUnique 65 +inlineIdKey = mkPreludeMiscIdUnique 66 + -- Parallel array functions nullPIdKey = mkPreludeMiscIdUnique 80 lengthPIdKey = mkPreludeMiscIdUnique 81 diff --git a/compiler/prelude/PrelRules.lhs b/compiler/prelude/PrelRules.lhs index 9cdddc9..ae26f84 100644 --- a/compiler/prelude/PrelRules.lhs +++ b/compiler/prelude/PrelRules.lhs @@ -20,7 +20,7 @@ module PrelRules ( primOpRules, builtinRules ) where #include "HsVersions.h" import CoreSyn -import Id ( mkWildId, isPrimOpId_maybe ) +import Id ( mkWildId, isPrimOpId_maybe, idUnfolding ) import Literal ( Literal(..), mkMachInt, mkMachWord , literalType , word2IntLit, int2WordLit @@ -38,7 +38,7 @@ import CoreUtils ( cheapEqExpr, exprIsConApp_maybe ) import Type ( tyConAppTyCon, coreEqType ) import OccName ( occNameFS ) import PrelNames ( unpackCStringFoldrName, unpackCStringFoldrIdKey, hasKey, - eqStringName, unpackCStringIdKey ) + eqStringName, unpackCStringIdKey, inlineIdName ) import Maybes ( orElse ) import Name ( Name ) import Outputable @@ -409,10 +409,12 @@ builtinRules :: [CoreRule] -- Rules for non-primops that can't be expressed using a RULE pragma builtinRules = [ BuiltinRule FSLIT("AppendLitString") unpackCStringFoldrName match_append_lit, - BuiltinRule FSLIT("EqString") eqStringName match_eq_string + BuiltinRule FSLIT("EqString") eqStringName match_eq_string, + BuiltinRule FSLIT("Inline") inlineIdName match_inline ] +--------------------------------------------------- -- The rule is this: -- unpackFoldrCString# "foo" c (unpackFoldrCString# "baz" c n) = unpackFoldrCString# "foobaz" c n @@ -434,6 +436,7 @@ match_append_lit [Type ty1, match_append_lit other = Nothing +--------------------------------------------------- -- The rule is this: -- eqString (unpackCString# (Lit s1)) (unpackCString# (Lit s2) = s1==s2 @@ -444,4 +447,16 @@ match_eq_string [Var unpk1 `App` Lit (MachStr s1), = Just (if s1 == s2 then trueVal else falseVal) match_eq_string other = Nothing + + +--------------------------------------------------- +-- The rule is this: +-- inline (f a b c) = a b c +-- (if f has an unfolding) +match_inline (e:args2) + | (Var f, args1) <- collectArgs e, + Just unf <- maybeUnfoldingTemplate (idUnfolding f) + = Just (mkApps (mkApps unf args1) args2) + +match_inline other = Nothing \end{code} diff --git a/compiler/simplCore/FloatIn.lhs b/compiler/simplCore/FloatIn.lhs index 0e8edb5..0d4e397 100644 --- a/compiler/simplCore/FloatIn.lhs +++ b/compiler/simplCore/FloatIn.lhs @@ -208,11 +208,6 @@ fiExpr to_drop (_, AnnNote note@(SCC cc) expr) = -- Wimp out for now mkCoLets' to_drop (Note note (fiExpr [] expr)) -fiExpr to_drop (_, AnnNote InlineCall expr) - = -- Wimp out for InlineCall; keep it close - -- the the call it annotates - mkCoLets' to_drop (Note InlineCall (fiExpr [] expr)) - fiExpr to_drop (_, AnnNote InlineMe expr) = -- Ditto... don't float anything into an INLINE expression mkCoLets' to_drop (Note InlineMe (fiExpr [] expr)) diff --git a/compiler/simplCore/SimplUtils.lhs b/compiler/simplCore/SimplUtils.lhs index 265ded6..1e51042 100644 --- a/compiler/simplCore/SimplUtils.lhs +++ b/compiler/simplCore/SimplUtils.lhs @@ -78,9 +78,6 @@ data SimplCont -- Strict contexts | CoerceIt OutType -- The To-type, simplified SimplCont - | InlinePlease -- This continuation makes a function very - SimplCont -- keen to inline itelf - | ApplyTo DupFlag InExpr SimplEnv -- The argument, as yet unsimplified, SimplCont -- and its environment @@ -116,7 +113,6 @@ instance Outputable SimplCont where ppr (Select dup bndr alts se cont) = (ptext SLIT("Select") <+> ppr dup <+> ppr bndr) $$ (nest 4 (ppr alts)) $$ ppr cont ppr (CoerceIt ty cont) = (ptext SLIT("CoerceIt") <+> ppr ty) $$ ppr cont - ppr (InlinePlease cont) = ptext SLIT("InlinePlease") $$ ppr cont data DupFlag = OkToDup | NoDup @@ -150,14 +146,12 @@ contIsDupable (Stop _ _ _) = True contIsDupable (ApplyTo OkToDup _ _ _) = True contIsDupable (Select OkToDup _ _ _ _) = True contIsDupable (CoerceIt _ cont) = contIsDupable cont -contIsDupable (InlinePlease cont) = contIsDupable cont contIsDupable other = False ------------------- discardableCont :: SimplCont -> Bool discardableCont (Stop _ _ _) = False discardableCont (CoerceIt _ cont) = discardableCont cont -discardableCont (InlinePlease cont) = discardableCont cont discardableCont other = True discardCont :: SimplCont -- A continuation, expecting @@ -174,7 +168,6 @@ contResultType (Stop to_ty _ _) = to_ty contResultType (ArgOf _ _ to_ty _) = to_ty contResultType (ApplyTo _ _ _ cont) = contResultType cont contResultType (CoerceIt _ cont) = contResultType cont -contResultType (InlinePlease cont) = contResultType cont contResultType (Select _ _ _ _ cont) = contResultType cont ------------------- @@ -199,8 +192,7 @@ pushContArgs env (arg : args) cont = ApplyTo NoDup arg env (pushContArgs env arg getContArgs :: SwitchChecker -> OutId -> SimplCont -> ([(InExpr, SimplEnv, Bool)], -- Arguments; the Bool is true for strict args - SimplCont, -- Remaining continuation - Bool) -- Whether we came across an InlineCall + SimplCont) -- Remaining continuation -- getContArgs id k = (args, k', inl) -- args are the leading ApplyTo items in k -- (i.e. outermost comes first) @@ -213,22 +205,18 @@ getContArgs chkr fun orig_cont stricts | switchIsOn chkr NoCaseOfCase = vanilla_stricts | otherwise = computed_stricts in - go [] stricts False orig_cont + go [] stricts orig_cont where ---------------------------- -- Type argument - go acc ss inl (ApplyTo _ arg@(Type _) se cont) - = go ((arg,se,False) : acc) ss inl cont + go acc ss (ApplyTo _ arg@(Type _) se cont) + = go ((arg,se,False) : acc) ss cont -- NB: don't bother to instantiate the function type -- Value argument - go acc (s:ss) inl (ApplyTo _ arg se cont) - = go ((arg,se,s) : acc) ss inl cont - - -- An Inline continuation - go acc ss inl (InlinePlease cont) - = go acc ss True cont + go acc (s:ss) (ApplyTo _ arg se cont) + = go ((arg,se,s) : acc) ss cont -- We're run out of arguments, or else we've run out of demands -- The latter only happens if the result is guaranteed bottom @@ -240,9 +228,9 @@ getContArgs chkr fun orig_cont -- Then, especially in the first of these cases, we'd like to discard -- the continuation, leaving just the bottoming expression. But the -- type might not be right, so we may have to add a coerce. - go acc ss inl cont - | null ss && discardableCont cont = (reverse acc, discardCont cont, inl) - | otherwise = (reverse acc, cont, inl) + go acc ss cont + | null ss && discardableCont cont = (reverse acc, discardCont cont) + | otherwise = (reverse acc, cont) ---------------------------- vanilla_stricts, computed_stricts :: [Bool] @@ -386,7 +374,6 @@ interestingCallContext :: Bool -- False <=> no args at all interestingCallContext some_args some_val_args cont = interesting cont where - interesting (InlinePlease _) = True interesting (Select _ _ _ _ _) = some_args interesting (ApplyTo _ _ _ _) = True -- Can happen if we have (coerce t (f x)) y -- Perhaps True is a bit over-keen, but I've @@ -431,7 +418,6 @@ interestingArgContext :: Id -> SimplCont -> Bool interestingArgContext fn cont = idHasRules fn || go cont where - go (InlinePlease c) = go c go (Select {}) = False go (ApplyTo {}) = False go (ArgOf {}) = True diff --git a/compiler/simplCore/Simplify.lhs b/compiler/simplCore/Simplify.lhs index 329d326..d8f9506 100644 --- a/compiler/simplCore/Simplify.lhs +++ b/compiler/simplCore/Simplify.lhs @@ -869,9 +869,6 @@ simplNote env (SCC cc) e cont = simplExpr (setEnclosingCC env currentCCS) e `thenSmpl` \ e' -> rebuild env (mkSCC cc e') cont -simplNote env InlineCall e cont - = simplExprF env e (InlinePlease cont) - -- See notes with SimplMonad.inlineMode simplNote env InlineMe e cont | contIsRhsOrArg cont -- Totally boring continuation; see notes above @@ -919,9 +916,9 @@ completeCall env var occ_info cont = -- Simplify the arguments getDOptsSmpl `thenSmpl` \ dflags -> let - chkr = getSwitchChecker env - (args, call_cont, inline_call) = getContArgs chkr var cont - fn_ty = idType var + chkr = getSwitchChecker env + (args, call_cont) = getContArgs chkr var cont + fn_ty = idType var in simplifyArgs env fn_ty (interestingArgContext var call_cont) args (contResultType call_cont) $ \ env args -> @@ -981,7 +978,7 @@ completeCall env var occ_info cont (notNull arg_infos) call_cont active_inline = activeInline env var occ_info - maybe_inline = callSiteInline dflags active_inline inline_call occ_info + maybe_inline = callSiteInline dflags active_inline occ_info var arg_infos interesting_cont in case maybe_inline of { @@ -1255,7 +1252,6 @@ rebuild :: SimplEnv -> OutExpr -> SimplCont -> SimplM FloatsWithExpr rebuild env expr (Stop _ _ _) = rebuildDone env expr rebuild env expr (ArgOf _ _ _ cont_fn) = cont_fn env expr rebuild env expr (CoerceIt to_ty cont) = rebuild env (mkCoerce to_ty expr) cont -rebuild env expr (InlinePlease cont) = rebuild env (Note InlineCall expr) cont rebuild env expr (Select _ bndr alts se cont) = rebuildCase (setInScope se env) expr bndr alts cont rebuild env expr (ApplyTo _ arg se cont) = rebuildApp (setInScope se env) expr arg cont @@ -1806,10 +1802,6 @@ mkDupableCont env (CoerceIt ty cont) = mkDupableCont env cont `thenSmpl` \ (floats, (dup_cont, nondup_cont)) -> returnSmpl (floats, (CoerceIt ty dup_cont, nondup_cont)) -mkDupableCont env (InlinePlease cont) - = mkDupableCont env cont `thenSmpl` \ (floats, (dup_cont, nondup_cont)) -> - returnSmpl (floats, (InlinePlease dup_cont, nondup_cont)) - mkDupableCont env cont@(ArgOf _ arg_ty _ _) = returnSmpl (emptyFloats env, (mkBoringStop arg_ty, cont)) -- Do *not* duplicate an ArgOf continuation diff --git a/compiler/specialise/Rules.lhs b/compiler/specialise/Rules.lhs index b12147d..f70266e 100644 --- a/compiler/specialise/Rules.lhs +++ b/compiler/specialise/Rules.lhs @@ -368,7 +368,7 @@ matchN in_scope tmpl_vars tmpl_es target_es -- from nested matches; see the Let case of match, below -- type SubstEnv = (TvSubstEnv, IdSubstEnv, OrdList CoreBind) -type IdSubstEnv = IdEnv CoreExpr +type IdSubstEnv = IdEnv CoreExpr emptySubstEnv :: SubstEnv emptySubstEnv = (emptyVarEnv, emptyVarEnv, nilOL) diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml index f9cb3f7..8a21368 100644 --- a/docs/users_guide/glasgow_exts.xml +++ b/docs/users_guide/glasgow_exts.xml @@ -5989,6 +5989,74 @@ r) -> + +Special built-in functions +GHC has a few built-in funcions with special behaviour, +described in this section. All are exported by +GHC.Exts. + + The <literal>inline</literal> function + +The inline function is somewhat experimental. + + inline :: a -> a + +The call (inline f) arranges that f +is inlined, regardless of its size. More precisely, the call +(inline f) rewrites to the right-hand side of f's +definition. +This allows the programmer to control inlining from +a particular call site +rather than the definition site of the function +(c.f. INLINE pragmas ). + + +This inlining occurs regardless of the argument to the call +or the size of f's definition; it is unconditional. +The main caveat is that f's definition must be +visible to the compiler. That is, f must be +let-bound in the current scope. +If no inlining takes place, the inline function +expands to the identity function in Phase zero; so its use imposes +no overhead. + + If the function is defined in another +module, GHC only exposes its inlining in the interface file if the +function is sufficiently small that it might be +inlined by the automatic mechanism. There is currently no way to tell +GHC to expose arbitrarily-large functions in the interface file. (This +shortcoming is something that could be fixed, with some kind of pragma.) + + + + The <literal>inline</literal> function + +The lazy function restrains strictness analysis a little: + + lazy :: a -> a + +The call (lazy e) means the same as e, +but lazy has a magical property so far as strictness +analysis is concerned: it is lazy in its first argument, +even though its semantics is strict. After strictness analysis has run, +calls to lazy are inlined to be the identity function. + + +This behaviour is occasionally useful when controlling evaluation order. +Notably, lazy is used in the library definition of +Control.Parallel.par: + + par :: a -> b -> b + par x y = case (par# x) of { _ -> lazy y } + +If lazy were not lazy, par would +look strict in y which would defeat the whole +purpose of par. + + + + + Generic classes