BinderInfo(..),
FunOrArg, DuplicationDanger, InsideSCC, -- NB: all abstract (yay!)
- inlineUnconditionally, okToInline,
-
- addBinderInfo, orBinderInfo,
+ addBinderInfo, orBinderInfo, andBinderInfo,
argOccurrence, funOccurrence, dangerousArgOcc, noBinderInfo,
markMany, markDangerousToDup, markInsideSCC,
IMP_Ubiq(){-uitous-}
-import CoreUnfold ( FormSummary(..) )
import Pretty
import Util ( panic )
+#if __GLASGOW_HASKELL__ >= 202
+import Outputable
+#endif
+
\end{code}
The @BinderInfo@ describes how a variable is used in a given scope.
\end{code}
-Predicates
-~~~~~~~~~~
\begin{code}
-okToInline
- :: FormSummary -- What the thing to be inlined is like
- -> BinderInfo -- How the thing to be inlined occurs
- -> Bool -- True => it's small enough to inline
- -> Bool -- True => yes, inline it
-
--- Always inline bottoms
-okToInline BottomForm occ_info small_enough
- = True -- Unless one of the type args is unboxed??
- -- This used to be checked for, but I can't
- -- see why so I've left it out.
-
--- Non-WHNFs can be inlined if they occur once, or are small
-okToInline OtherForm (OneOcc _ _ _ n_alts _) small_enough | n_alts <= 1 = True
-okToInline OtherForm any_occ small_enough = small_enough
-
--- A WHNF can be inlined if it doesn't occur inside a lambda,
--- and occurs exactly once or
--- occurs once in each branch of a case and is small
-okToInline form (OneOcc _ NoDupDanger _ n_alts _) small_enough
- = is_whnf_form form &&
- (n_alts <= 1 || small_enough)
- where
- is_whnf_form VarForm = True
- is_whnf_form ValueForm = True
- is_whnf_form other = False
-
-okToInline form any_occ small_enough = False
+isFun :: FunOrArg -> Bool
+isFun FunOcc = True
+isFun _ = False
+
+isDupDanger :: DuplicationDanger -> Bool
+isDupDanger DupDanger = True
+isDupDanger _ = False
\end{code}
@inlineUnconditionally@ decides whether a let-bound thing can
definitely be inlined.
\begin{code}
+{- NOT USED
+
inlineUnconditionally :: Bool -> BinderInfo -> Bool
--inlineUnconditionally ok_to_dup DeadCode = True
-- damage, e.g., limit to M alternatives.
inlineUnconditionally _ _ = False
-\end{code}
-
-\begin{code}
-isFun :: FunOrArg -> Bool
-isFun FunOcc = True
-isFun _ = False
-
-isDupDanger :: DuplicationDanger -> Bool
-isDupDanger DupDanger = True
-isDupDanger _ = False
+-}
\end{code}
addBinderInfo DeadCode info2 = info2
addBinderInfo info1 DeadCode = info1
addBinderInfo info1 info2
- = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
+ = case (min (getBinderInfoArity info1) (getBinderInfoArity info2)) of
+ (I# i#) -> ManyOcc (I# i#)
+ -- ManyOcc min (getBinderInfoArity info1) (getBinderInfoArity info2))
--- (orBinderInfo orig new) is used in two situations:
--- First, it combines occurrence info from branches of a case
---
--- Second, when a variable whose occurrence
--- info is currently "orig" is bound to a variable whose occurrence info is "new"
--- eg (\new -> e) orig
--- What we want to do is to *worsen* orig's info to take account of new's
+-- (orBinderInfo orig new) is used when combining occurrence
+-- info from branches of a case
orBinderInfo DeadCode info2 = info2
orBinderInfo info1 DeadCode = info1
orBinderInfo (OneOcc posn1 dup1 scc1 n_alts1 ar_1)
- (OneOcc posn2 dup2 scc2 n_alts2 ar_2)
- = OneOcc (combine_posns posn1 posn2)
- (combine_dups dup1 dup2)
- (combine_sccs scc1 scc2)
- (n_alts1 + n_alts2)
- (min ar_1 ar_2)
- where
- combine_dups DupDanger _ = DupDanger -- Too paranoid?? ToDo
- combine_dups _ DupDanger = DupDanger
- combine_dups _ _ = NoDupDanger
-
- combine_sccs InsideSCC _ = InsideSCC -- Too paranoid?? ToDo
- combine_sccs _ InsideSCC = InsideSCC
- combine_sccs _ _ = NotInsideSCC
-
+ (OneOcc posn2 dup2 scc2 n_alts2 ar_2)
+ = let
+ -- Seriously maligned in order to make it stricter,
+ -- let's hope it is worth it..
+ posn = combine_posns posn1 posn2
+ scc = combine_sccs scc1 scc2
+ dup = combine_dups dup1 dup2
+ alts = n_alts1 + n_alts2
+ ar = min ar_1 ar_2
+
+ -- No CSE, please!
+ cont1 = case scc of { InsideSCC -> cont2; _ -> cont2 }
+ cont2 = case dup of { DupDanger -> cont3; _ -> cont3 }
+ cont3 = case alts of { (I# 0#) -> cont4; _ -> cont4 }
+ cont4 = case ar of { (I# 0#) -> cont5; _ -> cont5 }
+ cont5 = OneOcc posn dup scc alts ar
+ in
+ case posn of { FunOcc -> cont1; _ -> cont1 }
orBinderInfo info1 info2
- = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
+ = case (min (getBinderInfoArity info1) (getBinderInfoArity info2)) of
+ (I# i#) -> ManyOcc (I# i#)
+
+-- (andBinderInfo orig new) is used in two situations:
+-- First, when a variable whose occurrence info
+-- is currently "orig" is bound to a variable whose occurrence info is "new"
+-- eg (\new -> e) orig
+-- What we want to do is to *worsen* orig's info to take account of new's
+--
+-- second, when completing a let-binding
+-- let new = ...orig...
+-- we compute the way orig occurs in (...orig...), and then use orBinderInfo
+-- to worsen this info by the way new occurs in the let body; then we use
+-- that to worsen orig's currently recorded occurrence info.
+
+andBinderInfo DeadCode info2 = DeadCode
+andBinderInfo info1 DeadCode = DeadCode
+andBinderInfo (OneOcc posn1 dup1 scc1 (I# n_alts1#) (I# ar_1#))
+ (OneOcc posn2 dup2 scc2 (I# n_alts2#) ar_2)
+ = let
+ -- Perversly maligned in order to make it stricter.
+ posn = combine_posns posn1 posn2
+ scc = combine_sccs scc1 scc2
+ dup = combine_dups dup1 dup2
+ alts = I# (n_alts1# +# n_alts2#)
+
+ -- No CSE, please!
+ cont1 = case scc of { InsideSCC -> cont2; _ -> cont2 }
+ cont2 = case dup of { DupDanger -> cont3; _ -> cont3 }
+ cont3 = case alts of { (I# 0#) -> cont4; _ -> cont4 }
+ cont4 = OneOcc posn dup scc alts (I# ar_1#)
+ in
+ case posn of {FunOcc -> cont1; _ -> cont1}
+
+andBinderInfo info1 info2 =
+ case getBinderInfoArity info1 of
+ (I# i#) -> ManyOcc (I# i#)
+ --ManyOcc (getBinderInfoArity info1)
+
combine_posns FunOcc FunOcc = FunOcc -- see comment at FunOrArg defn
combine_posns _ _ = ArgOcc
-{-
-multiplyBinderInfo orig@(ManyOcc _) new
- = ManyOcc (min (getBinderInfoArity orig) (getBinderInfoArity new))
+combine_dups DupDanger _ = DupDanger -- Too paranoid?? ToDo
+combine_dups _ DupDanger = DupDanger
+combine_dups _ _ = NoDupDanger
-multiplyBinderInfo orig new@(ManyOcc _)
- = ManyOcc (min (getBinderInfoArity orig) (getBinderInfoArity new))
-
-multiplyBinderInfo (OneOcc posn1 dup1 scc1 n_alts1 ar_1)
- (OneOcc posn2 dup2 scc2 n_alts2 ar_2)
- = OneOcc (combine_posns posn1 posn2) ???
--}
+combine_sccs InsideSCC _ = InsideSCC -- Too paranoid?? ToDo
+combine_sccs _ InsideSCC = InsideSCC
+combine_sccs _ _ = NotInsideSCC
setBinderInfoArityToZero :: BinderInfo -> BinderInfo
setBinderInfoArityToZero DeadCode = DeadCode
\begin{code}
instance Outputable BinderInfo where
- ppr sty DeadCode = ppStr "Dead"
- ppr sty (ManyOcc ar) = ppBesides [ ppStr "Many-", ppInt ar ]
+ ppr sty DeadCode = ptext SLIT("Dead")
+ ppr sty (ManyOcc ar) = hcat [ ptext SLIT("Many-"), int ar ]
ppr sty (OneOcc posn dup_danger in_scc n_alts ar)
- = ppBesides [ ppStr "One-", pp_posn posn, ppChar '-', pp_danger dup_danger,
- ppChar '-', pp_scc in_scc, ppChar '-', ppInt n_alts,
- ppChar '-', ppInt ar ]
+ = hcat [ ptext SLIT("One-"), pp_posn posn, char '-', pp_danger dup_danger,
+ char '-', pp_scc in_scc, char '-', int n_alts,
+ char '-', int ar ]
where
- pp_posn FunOcc = ppStr "fun"
- pp_posn ArgOcc = ppStr "arg"
+ pp_posn FunOcc = ptext SLIT("fun")
+ pp_posn ArgOcc = ptext SLIT("arg")
- pp_danger DupDanger = ppStr "*dup*"
- pp_danger NoDupDanger = ppStr "nodup"
+ pp_danger DupDanger = ptext SLIT("*dup*")
+ pp_danger NoDupDanger = ptext SLIT("nodup")
- pp_scc InsideSCC = ppStr "*SCC*"
- pp_scc NotInsideSCC = ppStr "noscc"
+ pp_scc InsideSCC = ptext SLIT("*SCC*")
+ pp_scc NotInsideSCC = ptext SLIT("noscc")
\end{code}