X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2FsimplCore%2FSimplEnv.lhs;h=960475c0b5c6191475fba50c2c0fc9c5cc9f2067;hb=f37e239fb5e81fc493e0ea1af98178bf1f7ceaba;hp=c91ca58e979e46672b9e7e7aa993630f7da251f3;hpb=dd09857f4b1bb6375ca807ca06f13ab0625e463d;p=ghc-hetmet.git diff --git a/compiler/simplCore/SimplEnv.lhs b/compiler/simplCore/SimplEnv.lhs index c91ca58..960475c 100644 --- a/compiler/simplCore/SimplEnv.lhs +++ b/compiler/simplCore/SimplEnv.lhs @@ -7,6 +7,7 @@ module SimplEnv ( InId, InBind, InExpr, InAlt, InArg, InType, InBinder, OutId, OutTyVar, OutBind, OutExpr, OutAlt, OutArg, OutType, OutBinder, + InCoercion, OutCoercion, -- The simplifier mode setMode, getMode, @@ -21,7 +22,7 @@ module SimplEnv ( SimplEnv, mkSimplEnv, extendIdSubst, extendTvSubst, zapSubstEnv, setSubstEnv, getInScope, setInScope, setInScopeSet, modifyInScope, addNewInScopeIds, - getRules, refineSimplEnv, + getRules, SimplSR(..), mkContEx, substId, @@ -41,12 +42,11 @@ module SimplEnv ( import SimplMonad import Id ( Id, idType, idOccInfo, idUnfolding, setIdUnfolding ) import IdInfo ( IdInfo, vanillaIdInfo, occInfo, setOccInfo, specInfo, setSpecInfo, - arityInfo, setArityInfo, workerInfo, setWorkerInfo, + arityInfo, workerInfo, setWorkerInfo, unfoldingInfo, setUnfoldingInfo, isEmptySpecInfo, - unknownArity, workerExists + workerExists ) import CoreSyn -import Unify ( TypeRefinement ) import Rules ( RuleBase ) import CoreUtils ( needsCaseBinding ) import CostCentre ( CostCentreStack, subsumedCCS ) @@ -58,8 +58,9 @@ import OrdList import qualified CoreSubst ( Subst, mkSubst, substExpr, substSpec, substWorker ) import qualified Type ( substTy, substTyVarBndr ) -import Type ( Type, TvSubst(..), TvSubstEnv, composeTvSubst, +import Type ( Type, TvSubst(..), TvSubstEnv, isUnLiftedType, seqType, tyVarsOfType ) +import Coercion ( Coercion ) import BasicTypes ( OccInfo(..), isFragileOcc ) import DynFlags ( SimplifierMode(..) ) import Util ( mapAccumL ) @@ -73,22 +74,24 @@ import Outputable %************************************************************************ \begin{code} -type InBinder = CoreBndr -type InId = Id -- Not yet cloned -type InType = Type -- Ditto -type InBind = CoreBind -type InExpr = CoreExpr -type InAlt = CoreAlt -type InArg = CoreArg - -type OutBinder = CoreBndr -type OutId = Id -- Cloned -type OutTyVar = TyVar -- Cloned -type OutType = Type -- Cloned -type OutBind = CoreBind -type OutExpr = CoreExpr -type OutAlt = CoreAlt -type OutArg = CoreArg +type InBinder = CoreBndr +type InId = Id -- Not yet cloned +type InType = Type -- Ditto +type InBind = CoreBind +type InExpr = CoreExpr +type InAlt = CoreAlt +type InArg = CoreArg +type InCoercion = Coercion + +type OutBinder = CoreBndr +type OutId = Id -- Cloned +type OutTyVar = TyVar -- Cloned +type OutType = Type -- Cloned +type OutCoercion = Coercion +type OutBind = CoreBind +type OutExpr = CoreExpr +type OutAlt = CoreAlt +type OutArg = CoreArg \end{code} %************************************************************************ @@ -197,38 +200,6 @@ seIdSubst: That's why the "set" is actually a VarEnv Var -Note [GADT type refinement] -~~~~~~~~~~~~~~~~~~~~~~~~~~~ -When we come to a GADT pattern match that refines the in-scope types, we - a) Refine the types of the Ids in the in-scope set, seInScope. - For exmaple, consider - data T a where - Foo :: T (Bool -> Bool) - - (\ (x::T a) (y::a) -> case x of { Foo -> y True } - - Technically this is well-typed, but exprType will barf on the - (y True) unless we refine the type on y's occurrence. - - b) Refine the range of the type substitution, seTvSubst. - Very similar reason to (a). - - NB: we don't refine the range of the SimplIdSubst, because it's always - interpreted relative to the seInScope (see substId) - -For (b) we need to be a little careful. Specifically, we compose the refinement -with the type substitution. Suppose - The substitution was [a->b, b->a] - and the refinement was [b->Int] - Then we want [a->Int, b->a] - -But also if - The substitution was [a->b] - and the refinement was [b->Int] - Then we want [a->Int, b->Int] - becuase b might be both an InTyVar and OutTyVar - - \begin{code} mkSimplEnv :: SimplifierMode -> SwitchChecker -> RuleBase -> SimplEnv mkSimplEnv mode switches rules @@ -309,31 +280,6 @@ getRules :: SimplEnv -> RuleBase getRules = seExtRules \end{code} - GADT stuff - -Given an idempotent substitution, generated by the unifier, use it to -refine the environment - -\begin{code} -refineSimplEnv :: SimplEnv -> TypeRefinement -> SimplEnv --- The TvSubstEnv is the refinement, and it refines OutTyVars into OutTypes -refineSimplEnv env@(SimplEnv { seTvSubst = tv_subst, seInScope = in_scope }) - (refine_tv_subst, all_bound_here) - = env { seTvSubst = composeTvSubst in_scope refine_tv_subst tv_subst, - seInScope = in_scope' } - where - in_scope' - | all_bound_here = in_scope - -- The tvs are the tyvars bound here. If only they - -- are refined, there's no need to do anything - | otherwise = mapInScopeSet refine_id in_scope - - refine_id v -- Only refine its type; any rules will get - -- refined if they are used (I hope) - | isId v = setIdType v (Type.substTy refine_subst (idType v)) - | otherwise = v - refine_subst = TvSubst in_scope refine_tv_subst -\end{code} %************************************************************************ %* * @@ -362,8 +308,7 @@ substId (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v where -- Get the most up-to-date thing from the in-scope set -- Even though it isn't in the substitution, it may be in - -- the in-scope set with a different type (we only use the - -- substitution if the unique changes). + -- the in-scope set better IdInfo refine v = case lookupInScope in_scope v of Just v' -> v' Nothing -> WARN( True, ppr v ) v -- This is an error! @@ -442,7 +387,7 @@ substIdBndr env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst}) -- new_id has the final IdInfo subst = mkCoreSubst env - new_id = maybeModifyIdInfo (substIdInfo subst) id2 + new_id = maybeModifyIdInfo (substIdInfo subst (idInfo old_id)) id2 -- Extend the substitution if the unique has changed -- See the notes with substTyVarBndr for the delSubstEnv @@ -535,19 +480,34 @@ This is important. Manuel found cases where he really, really wanted a RULE for a recursive function to apply in that function's own right-hand side. -NB 2: We do not transfer the arity (see Subst.substIdInfo) -The arity of an Id should not be visible -in its own RHS, else we eta-reduce +NB 2: ARITY. We *do* transfer the arity. This is important, so that +the arity of an Id is visible in its own RHS. For example: + f = \x. ....g (\y. f y).... +We can eta-reduce the arg to g, becuase f is a value. But that +needs to be visible. + +This interacts with the 'state hack' too: + f :: Bool -> IO Int + f = \x. case x of + True -> f y + False -> \s -> ... +Can we eta-expand f? Only if we see that f has arity 1, and then we +take advantage of the 'state hack' on the result of +(f y) :: State# -> (State#, Int) to expand the arity one more. + +There is a disadvantage though. Making the arity visible in the RHA +allows us to eta-reduce f = \x -> f x to f = f -which isn't sound. And it makes the arity in f's IdInfo greater than -the manifest arity, which isn't good. -The arity will get added later. +which technically is not sound. This is very much a corner case, so +I'm not worried about it. Another idea is to ensure that f's arity +never decreases; its arity started as 1, and we should never eta-reduce +below that. -NB 3: It's important that we *do* transer the loop-breaker OccInfo, -because that's what stops the Id getting inlined infinitely, in the body -of the letrec. +NB 3: OccInfo. It's important that we *do* transer the loop-breaker +OccInfo, because that's what stops the Id getting inlined infinitely, +in the body of the letrec. NB 4: does no harm for non-recursive bindings @@ -577,7 +537,7 @@ substIdInfo :: CoreSubst.Subst -> IdInfo -> Maybe IdInfo -- worker info -- Zap the unfolding -- Keep only 'robust' OccInfo --- Zap Arity +-- arity -- -- Seq'ing on the returned IdInfo is enough to cause all the -- substitutions to happen completely @@ -585,21 +545,18 @@ substIdInfo :: CoreSubst.Subst -> IdInfo -> Maybe IdInfo substIdInfo subst info | nothing_to_do = Nothing | otherwise = Just (info `setOccInfo` (if keep_occ then old_occ else NoOccInfo) - `setArityInfo` (if keep_arity then old_arity else unknownArity) `setSpecInfo` CoreSubst.substSpec subst old_rules `setWorkerInfo` CoreSubst.substWorker subst old_wrkr `setUnfoldingInfo` noUnfolding) -- setSpecInfo does a seq -- setWorkerInfo does a seq where - nothing_to_do = keep_occ && keep_arity && + nothing_to_do = keep_occ && isEmptySpecInfo old_rules && not (workerExists old_wrkr) && not (hasUnfolding (unfoldingInfo info)) - keep_occ = not (isFragileOcc old_occ) - keep_arity = old_arity == unknownArity - old_arity = arityInfo info + keep_occ = not (isFragileOcc old_occ) old_occ = occInfo info old_rules = specInfo info old_wrkr = workerInfo info