[project @ 2001-02-26 15:42:24 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplCore / Simplify.lhs
index f15edf8..131b56c 100644 (file)
@@ -10,22 +10,22 @@ module Simplify ( simplTopBinds, simplExpr ) where
 
 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,
@@ -38,12 +38,13 @@ import DataCon              ( dataConNumInstArgs, dataConRepStrictness,
                          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
@@ -362,8 +363,12 @@ completeLam rev_bndrs body cont
        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
 
@@ -371,8 +376,9 @@ completeLam rev_bndrs body cont
     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
@@ -516,7 +522,7 @@ completeBinding old_bndr new_bndr top_lvl black_listed new_rhs thing_inside
        -- 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
        --      
@@ -544,7 +550,7 @@ completeBinding old_bndr new_bndr top_lvl black_listed new_rhs thing_inside
     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,
@@ -558,6 +564,16 @@ completeBinding old_bndr new_bndr top_lvl black_listed new_rhs thing_inside
        -- 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.)
@@ -754,7 +770,7 @@ simplVar var cont
 ---------------------------------------------------------
 --     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) ->
@@ -771,7 +787,7 @@ completeCall var occ cont
        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
@@ -799,6 +815,18 @@ completeCall var occ cont
        -- 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
@@ -808,6 +836,15 @@ completeCall var occ cont
     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
@@ -1186,7 +1223,11 @@ knownCon :: OutExpr -> AltCon -> [OutExpr]
         -> 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 $