Commit 8b10b896 authored by Simon Peyton Jones's avatar Simon Peyton Jones
Browse files

Inline wrappers earlier

This patch has a single significant change:

  strictness wrapper functions are inlined earlier,
  in phase 2 rather than phase 0.

As shown by Trac #15056, this gives a better chance for RULEs to fire.
Before this change, a function that would have inlined early without
strictness analyss was instead inlining late. Result: applying
"optimisation" made the program worse.

This does not make too much difference in nofib, but I've stumbled
over the problem more than once, so even a "no-change" result would be
quite acceptable.  Here are the headlines:

--------------------------------------------------------------------------------
        Program           Size    Allocs   Runtime   Elapsed  TotalMem
--------------------------------------------------------------------------------
      cacheprof          -0.5%     -0.5%     +2.5%     +2.5%      0.0%
         fulsom          -1.0%     +2.6%     -0.1%     -0.1%      0.0%
           mate          -0.6%     +2.4%     -0.9%     -0.9%      0.0%
        veritas          -0.7%    -23.2%     0.002     0.002      0.0%
--------------------------------------------------------------------------------
            Min          -1.4%    -23.2%    -12.5%    -15.3%      0.0%
            Max          +0.6%     +2.6%     +4.4%     +4.3%    +19.0%
 Geometric Mean          -0.7%     -0.2%     -1.4%     -1.7%     +0.2%

* A worthwhile reduction in binary size.

* Runtimes are not to be trusted much but look as if they
  are moving the right way.

* A really big win in veritas, described in comment:1 of
  Trac #15056; more fusion rules fired.

* I investigated the losses in 'mate' and 'fulsom'; see #15056.
parent 2fbe0b51
......@@ -242,8 +242,8 @@ NOINLINE pragma to the worker.
(See Trac #13143 for a real-world example.)
Note [Activation for workers]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note [Worker activation]
~~~~~~~~~~~~~~~~~~~~~~~~
Follows on from Note [Worker-wrapper for INLINABLE functions]
It is *vital* that if the worker gets an INLINABLE pragma (from the
......@@ -260,7 +260,9 @@ original activation. Consider
f y = let z = expensive y in ...
If expensive's worker inherits the wrapper's activation, we'll get
If expensive's worker inherits the wrapper's activation,
we'll get this (because of the compromise in point (2) of
Note [Wrapper activation])
{-# NOINLINE[0] $wexpensive #-}
$wexpensive x = x + 1
......@@ -346,40 +348,63 @@ call:
Note [Wrapper activation]
~~~~~~~~~~~~~~~~~~~~~~~~~
When should the wrapper inlining be active? It must not be active
earlier than the current Activation of the Id (eg it might have a
NOINLINE pragma). But in fact strictness analysis happens fairly
late in the pipeline, and we want to prioritise specialisations over
strictness. Eg if we have
module Foo where
f :: Num a => a -> Int -> a
f n 0 = n -- Strict in the Int, hence wrapper
f n x = f (n+n) (x-1)
g :: Int -> Int
g x = f x x -- Provokes a specialisation for f
module Bar where
import Foo
h :: Int -> Int
h x = f 3 x
Then we want the specialisation for 'f' to kick in before the wrapper does.
Now in fact the 'gentle' simplification pass encourages this, by
having rules on, but inlinings off. But that's kind of lucky. It seems
more robust to give the wrapper an Activation of (ActiveAfter 0),
so that it becomes active in an importing module at the same time that
it appears in the first place in the defining module.
At one stage I tried making the wrapper inlining always-active, and
that had a very bad effect on nofib/imaginary/x2n1; a wrapper was
inlined before the specialisation fired.
The use an inl_inline of NoUserInline to distinguish this pragma from one
that was given by the user. In particular, CSE will not happen if there is a
user-specified pragma, but should happen for w/w’ed things (#14186).
When should the wrapper inlining be active?
1. It must not be active earlier than the current Activation of the
Id
2. It should be active at some point, despite (1) because of
Note [Worker-wrapper for NOINLINE functions]
3. For ordinary functions with no pragmas we want to inline the
wrapper as early as possible (Trac #15056). Suppose another module
defines f x = g x x
and suppose there is some RULE for (g True True). Then if we have
a call (f True), we'd expect to inline 'f' and the RULE will fire.
But if f is w/w'd (which it might be), we want the inlining to
occur just as if it hadn't been.
(This only matters if f's RHS is big enough to w/w, but small
enough to inline given the call site, but that can happen.)
4. We do not want to inline the wrapper before specialisation.
module Foo where
f :: Num a => a -> Int -> a
f n 0 = n -- Strict in the Int, hence wrapper
f n x = f (n+n) (x-1)
g :: Int -> Int
g x = f x x -- Provokes a specialisation for f
module Bar where
import Foo
h :: Int -> Int
h x = f 3 x
In module Bar we want to give specialisations a chance to fire
before inlining f's wrapper.
Reminder: Note [Don't w/w INLINE things], so we don't need to worry
about INLINE things here.
Conclusion:
- If the user said NOINLINE[n], respect that
- If the user said NOINLINE, inline the wrapper as late as
poss (phase 0). This is a compromise driven by (2) above
- Otherwise inline wrapper in phase 2. That allows the
'gentle' simplification pass to apply specialisation rules
Historical note: At one stage I tried making the wrapper inlining
always-active, and that had a very bad effect on nofib/imaginary/x2n1;
a wrapper was inlined before the specialisation fired.
Note [Wrapper NoUserInline]
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The use an inl_inline of NoUserInline on the wrapper distinguishes
this pragma from one that was given by the user. In particular, CSE
will not happen if there is a user-specified pragma, but should happen
for w/w’ed things (#14186).
-}
tryWW :: DynFlags
......@@ -475,23 +500,24 @@ splitFun dflags fam_envs fn_id fn_info wrap_dmds res_info rhs
Just (work_demands, join_arity, wrap_fn, work_fn) -> do
work_uniq <- getUniqueM
let work_rhs = work_fn rhs
work_inline = inl_inline inl_prag
work_act = case work_inline of
-- See Note [Activation for workers]
NoInline -> inl_act inl_prag
_ -> wrap_act
work_act = case fn_inline_spec of -- See Note [Worker activation]
NoInline -> fn_act
_ -> wrap_act
work_prag = InlinePragma { inl_src = SourceText "{-# INLINE"
, inl_inline = work_inline
, inl_inline = fn_inline_spec
, inl_sat = Nothing
, inl_act = work_act
, inl_rule = FunLike }
-- idl_inline: copy from fn_id; see Note [Worker-wrapper for INLINABLE functions]
-- idl_act: see Note [Activation for workers]
-- inl_rule: it does not make sense for workers to be constructorlike.
-- inl_inline: copy from fn_id; see Note [Worker-wrapper for INLINABLE functions]
-- inl_act: see Note [Worker activation]
-- inl_rule: it does not make sense for workers to be constructorlike.
work_join_arity | isJoinId fn_id = Just join_arity
| otherwise = Nothing
-- worker is join point iff wrapper is join point
-- (see Note [Don't CPR join points])
work_id = mkWorkerId work_uniq fn_id (exprType work_rhs)
`setIdOccInfo` occInfo fn_info
-- Copy over occurrence info from parent
......@@ -523,16 +549,19 @@ splitFun dflags fam_envs fn_id fn_info wrap_dmds res_info rhs
worker_demand | single_call = mkWorkerDemand work_arity
| otherwise = topDmd
wrap_act = ActiveAfter NoSourceText 0
wrap_rhs = wrap_fn work_id
wrap_prag = InlinePragma { inl_src = SourceText "{-# INLINE"
wrap_act = case fn_act of -- See Note [Wrapper activation]
ActiveAfter {} -> fn_act
NeverActive -> ActiveAfter NoSourceText 0
_ -> ActiveAfter NoSourceText 2
wrap_prag = InlinePragma { inl_src = SourceText "{-# INLINE"
, inl_inline = NoUserInline
, inl_sat = Nothing
, inl_act = wrap_act
, inl_rule = rule_match_info }
-- See Note [Wrapper activation]
-- The RuleMatchInfo is (and must be) unaffected
-- inl_act: see Note [Wrapper activation]
-- inl_inline: see Note [Wrapper NoUserInline]
-- inl_rule: RuleMatchInfo is (and must be) unaffected
wrap_id = fn_id `setIdUnfolding` mkWwInlineRule wrap_rhs arity
`setInlinePragma` wrap_prag
......@@ -550,8 +579,10 @@ splitFun dflags fam_envs fn_id fn_info wrap_dmds res_info rhs
mb_join_arity = isJoinId_maybe fn_id
rhs_fvs = exprFreeVars rhs
fun_ty = idType fn_id
inl_prag = inlinePragInfo fn_info
rule_match_info = inlinePragmaRuleMatchInfo inl_prag
fn_inl_prag = inlinePragInfo fn_info
fn_inline_spec = inl_inline fn_inl_prag
fn_act = inl_act fn_inl_prag
rule_match_info = inlinePragmaRuleMatchInfo fn_inl_prag
arity = arityInfo fn_info
-- The arity is set by the simplifier using exprEtaExpandArity
-- So it may be more than the number of top-level-visible lambdas
......
......@@ -74,7 +74,7 @@ lvl = T13143.$wf @ Int GHC.Prim.void#
Rec {
-- RHS size: {terms: 28, types: 7, coercions: 0, joins: 0/0}
T13143.$wg [InlPrag=NOUSERINLINE[0], Occ=LoopBreaker]
T13143.$wg [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker]
:: Bool -> Bool -> GHC.Prim.Int# -> GHC.Prim.Int#
[GblId, Arity=3, Str=<S,1*U><S,1*U><S,U>, Unf=OtherCon []]
T13143.$wg
......@@ -94,7 +94,7 @@ T13143.$wg
end Rec }
-- RHS size: {terms: 14, types: 6, coercions: 0, joins: 0/0}
g [InlPrag=NOUSERINLINE[0]] :: Bool -> Bool -> Int -> Int
g [InlPrag=NOUSERINLINE[2]] :: Bool -> Bool -> Int -> Int
[GblId,
Arity=3,
Str=<S,1*U><S,1*U><S(S),1*U(U)>m,
......
module T15056 where
import T15056a
blam x = foo 3 [1..x]
-- We expect fold/build to fire
Rule fired: Class op - (BUILTIN)
Rule fired: Class op + (BUILTIN)
Rule fired: Class op + (BUILTIN)
Rule fired: Class op enumFromTo (BUILTIN)
Rule fired: Class op foldr (BUILTIN)
Rule fired: Class op foldr (BUILTIN)
Rule fired: +# (BUILTIN)
Rule fired: Class op foldr (BUILTIN)
Rule fired: fold/build (GHC.Base)
module T15056a where
test :: Int -> Bool
test 0 = True
test n = test (n-1)
foo :: Foldable t => Int -> t Int -> Int
foo n xs | test n
= foldr (+) n xs
| otherwise
= n+7
......@@ -49,7 +49,7 @@ T3717.$trModule
Rec {
-- RHS size: {terms: 10, types: 2, coercions: 0, joins: 0/0}
T3717.$wfoo [InlPrag=NOUSERINLINE[0], Occ=LoopBreaker]
T3717.$wfoo [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker]
:: GHC.Prim.Int# -> GHC.Prim.Int#
[GblId, Arity=1, Caf=NoCafRefs, Str=<S,1*U>, Unf=OtherCon []]
T3717.$wfoo
......@@ -61,7 +61,7 @@ T3717.$wfoo
end Rec }
-- RHS size: {terms: 10, types: 4, coercions: 0, joins: 0/0}
foo [InlPrag=NOUSERINLINE[0]] :: Int -> Int
foo [InlPrag=NOUSERINLINE[2]] :: Int -> Int
[GblId,
Arity=1,
Caf=NoCafRefs,
......
......@@ -68,7 +68,7 @@ T4908.f_$s$wf
end Rec }
-- RHS size: {terms: 24, types: 13, coercions: 0, joins: 0/0}
T4908.$wf [InlPrag=NOUSERINLINE[0]] :: Int# -> (Int, Int) -> Bool
T4908.$wf [InlPrag=NOUSERINLINE[2]] :: Int# -> (Int, Int) -> Bool
[GblId,
Arity=2,
Caf=NoCafRefs,
......@@ -91,7 +91,7 @@ T4908.$wf
}
-- RHS size: {terms: 8, types: 6, coercions: 0, joins: 0/0}
f [InlPrag=NOUSERINLINE[0]] :: Int -> (Int, Int) -> Bool
f [InlPrag=NOUSERINLINE[2]] :: Int -> (Int, Int) -> Bool
[GblId,
Arity=2,
Caf=NoCafRefs,
......@@ -106,7 +106,7 @@ f = \ (w :: Int) (w1 :: (Int, Int)) ->
------ Local rules for imported ids --------
"SC:$wf0" [0]
"SC:$wf0" [2]
forall (sc :: Int) (sc1 :: Int#) (sc2 :: Int#).
T4908.$wf sc2 (sc, GHC.Types.I# sc1)
= T4908.f_$s$wf sc sc1 sc2
......
......@@ -49,7 +49,7 @@ T4930.$trModule
Rec {
-- RHS size: {terms: 17, types: 3, coercions: 0, joins: 0/0}
T4930.$wfoo [InlPrag=NOUSERINLINE[0], Occ=LoopBreaker]
T4930.$wfoo [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker]
:: GHC.Prim.Int# -> GHC.Prim.Int#
[GblId, Arity=1, Caf=NoCafRefs, Str=<S,U>, Unf=OtherCon []]
T4930.$wfoo
......@@ -61,7 +61,7 @@ T4930.$wfoo
end Rec }
-- RHS size: {terms: 10, types: 4, coercions: 0, joins: 0/0}
foo [InlPrag=NOUSERINLINE[0]] :: Int -> Int
foo [InlPrag=NOUSERINLINE[2]] :: Int -> Int
[GblId,
Arity=1,
Caf=NoCafRefs,
......
Rule fired: SPEC/T6056 $wsmallerAndRest @ Int (T6056)
Rule fired: Class op < (BUILTIN)
Rule fired: SPEC/T6056 $wsmallerAndRest @ Int (T6056)
Rule fired: Class op < (BUILTIN)
Rule fired: SPEC/T6056 $wsmallerAndRest @ Int (T6056)
Rule fired: SPEC/T6056 $wsmallerAndRest @ Int (T6056)
......@@ -303,3 +303,4 @@ test('T14978',
['$MAKE -s --no-print-directory T14978'])
test('T15002', [ req_profiling ], compile, ['-O -fprof-auto -prof'])
test('T15005', normal, compile, ['-O'])
test('T15056', [extra_files(['T15056a.hs'])], multimod_compile, ['T15056', '-O -v0 -ddump-rule-firings'])
......@@ -90,7 +90,7 @@ Roman.foo_$s$wgo
end Rec }
-- RHS size: {terms: 71, types: 19, coercions: 0, joins: 0/1}
Roman.$wgo [InlPrag=NOUSERINLINE[0]]
Roman.$wgo [InlPrag=NOUSERINLINE[2]]
:: Maybe Int -> Maybe Int -> GHC.Prim.Int#
[GblId,
Arity=2,
......@@ -135,7 +135,7 @@ Roman.$wgo
}
-- RHS size: {terms: 9, types: 5, coercions: 0, joins: 0/0}
Roman.foo_go [InlPrag=NOUSERINLINE[0]]
Roman.foo_go [InlPrag=NOUSERINLINE[2]]
:: Maybe Int -> Maybe Int -> Int
[GblId,
Arity=2,
......@@ -188,7 +188,7 @@ foo
------ Local rules for imported ids --------
"SC:$wgo0" [0]
"SC:$wgo0" [2]
forall (sc :: GHC.Prim.Int#) (sc1 :: GHC.Prim.Int#).
Roman.$wgo (GHC.Base.Just @ Int (GHC.Types.I# sc1))
(GHC.Base.Just @ Int (GHC.Types.I# sc))
......
......@@ -10,13 +10,13 @@ T10482.$WFooPair [InlPrag=INLINE[2]] :: forall a b. Foo a -> Foo b -> Foo (a, b)
Str=<S,U><S,U>m,
Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False)
Tmpl= \ (@ a_aWY) (@ b_aWZ) (dt_a2p0 [Occ=Once] :: Foo a_aWY[sk:1]) (dt_a2p1 [Occ=Once] :: Foo b_aWZ[sk:1]) ->
(case dt_a2p0 of dt_X2p5 { __DEFAULT -> case dt_a2p1 of dt_X2p7 { __DEFAULT -> T10482.FooPair @ a_aWY @ b_aWZ dt_X2p5 dt_X2p7 } })
`cast` (Sym (T10482.D:R:Foo(,)0[0] <a_aWY>_N <b_aWZ>_N) :: (T10482.R:Foo(,) a_aWY b_aWZ :: *) ~R# (Foo (a_aWY, b_aWZ) :: *))}]
Tmpl= \ (@ a_aX9) (@ b_aXa) (dt_a2pg [Occ=Once] :: Foo a_aX9[sk:2]) (dt_a2ph [Occ=Once] :: Foo b_aXa[sk:2]) ->
(case dt_a2pg of dt_X2pl { __DEFAULT -> case dt_a2ph of dt_X2pn { __DEFAULT -> T10482.FooPair @ a_aX9 @ b_aXa dt_X2pl dt_X2pn } })
`cast` (Sym (T10482.D:R:Foo(,)0[0] <a_aX9>_N <b_aXa>_N) :: (T10482.R:Foo(,) a_aX9 b_aXa :: *) ~R# (Foo (a_aX9, b_aXa) :: *))}]
T10482.$WFooPair
= \ (@ a_aWY) (@ b_aWZ) (dt_a2p0 [Occ=Once] :: Foo a_aWY[sk:1]) (dt_a2p1 [Occ=Once] :: Foo b_aWZ[sk:1]) ->
(case dt_a2p0 of dt_X2p5 { __DEFAULT -> case dt_a2p1 of dt_X2p7 { __DEFAULT -> T10482.FooPair @ a_aWY @ b_aWZ dt_X2p5 dt_X2p7 } })
`cast` (Sym (T10482.D:R:Foo(,)0[0] <a_aWY>_N <b_aWZ>_N) :: (T10482.R:Foo(,) a_aWY b_aWZ :: *) ~R# (Foo (a_aWY, b_aWZ) :: *))
= \ (@ a_aX9) (@ b_aXa) (dt_a2pg [Occ=Once] :: Foo a_aX9[sk:2]) (dt_a2ph [Occ=Once] :: Foo b_aXa[sk:2]) ->
(case dt_a2pg of dt_X2pl { __DEFAULT -> case dt_a2ph of dt_X2pn { __DEFAULT -> T10482.FooPair @ a_aX9 @ b_aXa dt_X2pl dt_X2pn } })
`cast` (Sym (T10482.D:R:Foo(,)0[0] <a_aX9>_N <b_aXa>_N) :: (T10482.R:Foo(,) a_aX9 b_aXa :: *) ~R# (Foo (a_aX9, b_aXa) :: *))
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
T10482.$trModule4 :: GHC.Prim.Addr#
......@@ -57,34 +57,34 @@ T10482.$trModule :: GHC.Types.Module
T10482.$trModule = GHC.Types.Module T10482.$trModule3 T10482.$trModule1
-- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0}
$krep_r2Pm :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1]
$krep_r2Pm = GHC.Types.KindRepTyConApp GHC.Types.$tcInt (GHC.Types.[] @ GHC.Types.KindRep)
$krep_r2Q4 :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []]
$krep_r2Q4 = GHC.Types.KindRepTyConApp GHC.Types.$tcInt (GHC.Types.[] @ GHC.Types.KindRep)
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
$krep1_r2Pn :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m2]
$krep1_r2Pn = GHC.Types.KindRepVar 1#
$krep1_r2Q5 :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []]
$krep1_r2Q5 = GHC.Types.KindRepVar 1#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
$krep2_r2Po :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m2]
$krep2_r2Po = GHC.Types.KindRepVar 0#
$krep2_r2Q6 :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []]
$krep2_r2Q6 = GHC.Types.KindRepVar 0#
-- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0}
$krep3_r2Pp :: [GHC.Types.KindRep]
[GblId, Caf=NoCafRefs, Str=m2]
$krep3_r2Pp = GHC.Types.: @ GHC.Types.KindRep $krep1_r2Pn (GHC.Types.[] @ GHC.Types.KindRep)
$krep3_r2Q7 :: [GHC.Types.KindRep]
[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []]
$krep3_r2Q7 = GHC.Types.: @ GHC.Types.KindRep $krep1_r2Q5 (GHC.Types.[] @ GHC.Types.KindRep)
-- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0}
$krep4_r2Pq :: [GHC.Types.KindRep]
[GblId, Caf=NoCafRefs, Str=m2]
$krep4_r2Pq = GHC.Types.: @ GHC.Types.KindRep $krep2_r2Po $krep3_r2Pp
$krep4_r2Q8 :: [GHC.Types.KindRep]
[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []]
$krep4_r2Q8 = GHC.Types.: @ GHC.Types.KindRep $krep2_r2Q6 $krep3_r2Q7
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
$krep5_r2Pr :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1]
$krep5_r2Pr = GHC.Types.KindRepTyConApp GHC.Tuple.$tc(,) $krep4_r2Pq
$krep5_r2Q9 :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []]
$krep5_r2Q9 = GHC.Types.KindRepTyConApp GHC.Tuple.$tc(,) $krep4_r2Q8
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
T10482.$tcFoo2 :: GHC.Prim.Addr#
......@@ -110,54 +110,54 @@ T10482.$tcFoo :: GHC.Types.TyCon
T10482.$tcFoo = GHC.Types.TyCon 3311038889639791302## 7944995683507700778## T10482.$trModule T10482.$tcFoo1 0# GHC.Types.krep$*Arr*
-- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0}
$krep6_r2Ps :: [GHC.Types.KindRep]
[GblId, Caf=NoCafRefs, Str=m2]
$krep6_r2Ps = GHC.Types.: @ GHC.Types.KindRep $krep2_r2Po (GHC.Types.[] @ GHC.Types.KindRep)
$krep6_r2Qa :: [GHC.Types.KindRep]
[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []]
$krep6_r2Qa = GHC.Types.: @ GHC.Types.KindRep $krep2_r2Q6 (GHC.Types.[] @ GHC.Types.KindRep)
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
$krep7_r2Pt :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1]
$krep7_r2Pt = GHC.Types.KindRepTyConApp T10482.$tcFoo $krep6_r2Ps
$krep7_r2Qb :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []]
$krep7_r2Qb = GHC.Types.KindRepTyConApp T10482.$tcFoo $krep6_r2Qa
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
$krep8_r2Pu :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1]
$krep8_r2Pu = GHC.Types.KindRepTyConApp T10482.$tcFoo $krep3_r2Pp
$krep8_r2Qc :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []]
$krep8_r2Qc = GHC.Types.KindRepTyConApp T10482.$tcFoo $krep3_r2Q7
-- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0}
$krep9_r2Pv :: [GHC.Types.KindRep]
[GblId, Caf=NoCafRefs, Str=m2]
$krep9_r2Pv = GHC.Types.: @ GHC.Types.KindRep $krep5_r2Pr (GHC.Types.[] @ GHC.Types.KindRep)
$krep9_r2Qd :: [GHC.Types.KindRep]
[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []]
$krep9_r2Qd = GHC.Types.: @ GHC.Types.KindRep $krep5_r2Q9 (GHC.Types.[] @ GHC.Types.KindRep)
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
$krep10_r2Pw :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1]
$krep10_r2Pw = GHC.Types.KindRepTyConApp T10482.$tcFoo $krep9_r2Pv
$krep10_r2Qe :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []]
$krep10_r2Qe = GHC.Types.KindRepTyConApp T10482.$tcFoo $krep9_r2Qd
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
$krep11_r2Px :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m4]
$krep11_r2Px = GHC.Types.KindRepFun $krep8_r2Pu $krep10_r2Pw
$krep11_r2Qf :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m4, Unf=OtherCon []]
$krep11_r2Qf = GHC.Types.KindRepFun $krep8_r2Qc $krep10_r2Qe
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
T10482.$tc'FooPair1 [InlPrag=NOUSERINLINE[~]] :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m4]
T10482.$tc'FooPair1 = GHC.Types.KindRepFun $krep7_r2Pt $krep11_r2Px
[GblId, Caf=NoCafRefs, Str=m4, Unf=OtherCon []]
T10482.$tc'FooPair1 = GHC.Types.KindRepFun $krep7_r2Qb $krep11_r2Qf
-- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0}
$krep12_r2Py :: [GHC.Types.KindRep]
[GblId, Caf=NoCafRefs, Str=m2]
$krep12_r2Py = GHC.Types.: @ GHC.Types.KindRep $krep_r2Pm (GHC.Types.[] @ GHC.Types.KindRep)
$krep12_r2Qg :: [GHC.Types.KindRep]
[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []]
$krep12_r2Qg = GHC.Types.: @ GHC.Types.KindRep $krep_r2Q4 (GHC.Types.[] @ GHC.Types.KindRep)
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
$krep13_r2Pz :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1]
$krep13_r2Pz = GHC.Types.KindRepTyConApp T10482.$tcFoo $krep12_r2Py
$krep13_r2Qh :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []]
$krep13_r2Qh = GHC.Types.KindRepTyConApp T10482.$tcFoo $krep12_r2Qg
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
T10482.$tc'Foo1 [InlPrag=NOUSERINLINE[~]] :: GHC.Types.KindRep
[GblId, Caf=NoCafRefs, Str=m4]
T10482.$tc'Foo1 = GHC.Types.KindRepFun $krep_r2Pm $krep13_r2Pz
[GblId, Caf=NoCafRefs, Str=m4, Unf=OtherCon []]
T10482.$tc'Foo1 = GHC.Types.KindRepFun $krep_r2Q4 $krep13_r2Qh
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
T10482.$tc'FooPair3 :: GHC.Prim.Addr#
......@@ -208,53 +208,53 @@ T10482.$tc'Foo = GHC.Types.TyCon 5096937192618987042## 15136671864408054946## T1
Rec {
-- RHS size: {terms: 19, types: 4, coercions: 0, joins: 0/0}
T10482.$wfoo [InlPrag=NOUSERINLINE[0], Occ=LoopBreaker] :: GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Prim.Int#
[GblId, Arity=2, Caf=NoCafRefs, Str=<L,1*U><S,1*U>]
T10482.$wfoo [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker] :: GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Prim.Int#
[GblId, Arity=2, Caf=NoCafRefs, Str=<L,1*U><S,1*U>, Unf=OtherCon []]
T10482.$wfoo
= \ (ww_s2NS :: GHC.Prim.Int#) (ww1_s2O0 :: GHC.Prim.Int#) ->
case ww1_s2O0 of wild_X1r {
= \ (ww_s2OA :: GHC.Prim.Int#) (ww1_s2OI :: GHC.Prim.Int#) ->
case ww1_s2OI of wild_X1r {
__DEFAULT ->
case GHC.Prim.remInt# wild_X1r 2# of {
__DEFAULT -> ww_s2NS;
0# -> T10482.$wfoo ww_s2NS (GHC.Prim.-# wild_X1r 1#)
__DEFAULT -> ww_s2OA;
0# -> T10482.$wfoo ww_s2OA (GHC.Prim.-# wild_X1r 1#)
};
0# -> 0#
}
end Rec }
-- RHS size: {terms: 21, types: 30, coercions: 11, joins: 0/0}
foo [InlPrag=NOUSERINLINE[0]] :: Foo ((Int, Int), Int) -> Int -> Int
foo [InlPrag=NOUSERINLINE[2]] :: Foo ((Int, Int), Int) -> Int -> Int
[GblId,
Arity=2,
Caf=NoCafRefs,
Str=<S(S(S(S)L)L),1*U(U(U(1*U),A),A)><S(S),1*U(1*U)>m,
Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False)
Tmpl= \ (w_s2NI [Occ=Once] :: Foo ((Int, Int), Int)) (w1_s2NJ [Occ=Once!] :: Int) ->
case w_s2NI
Tmpl= \ (w_s2Oq [Occ=Once] :: Foo ((Int, Int), Int)) (w1_s2Or [Occ=Once!] :: Int) ->
case w_s2Oq
`cast` (T10482.D:R:Foo(,)0[0] <(Int, Int)>_N <Int>_N :: (Foo ((Int, Int), Int) :: *) ~R# (T10482.R:Foo(,) (Int, Int) Int :: *))
of
{ FooPair ww1_s2NM [Occ=Once] _ [Occ=Dead] ->
case ww1_s2NM `cast` (T10482.D:R:Foo(,)0[0] <Int>_N <Int>_N :: (Foo (Int, Int) :: *) ~R# (T10482.R:Foo(,) Int Int :: *)) of
{ FooPair ww4_s2NP [Occ=Once] _ [Occ=Dead] ->
case ww4_s2NP `cast` (T10482.D:R:FooInt0[0] ; T10482.N:R:FooInt[0] :: (Foo Int :: *) ~R# (Int :: *)) of
{ GHC.Types.I# ww7_s2NS [Occ=Once] ->
case w1_s2NJ of { GHC.Types.I# ww9_s2O0 [Occ=Once] ->
case T10482.$wfoo ww7_s2NS ww9_s2O0 of ww10_s2O4 { __DEFAULT -> GHC.Types.I# ww10_s2O4 }
{ FooPair ww1_s2Ou [Occ=Once] _ [Occ=Dead] ->
case ww1_s2Ou `cast` (T10482.D:R:Foo(,)0[0] <Int>_N <Int>_N :: (Foo (Int, Int) :: *) ~R# (T10482.R:Foo(,) Int Int :: *)) of
{ FooPair ww4_s2Ox [Occ=Once] _ [Occ=Dead] ->
case ww4_s2Ox `cast` (T10482.D:R:FooInt0[0] ; T10482.N:R:FooInt[0] :: (Foo Int :: *) ~R# (Int :: *)) of
{ GHC.Types.I# ww7_s2OA [Occ=Once] ->
case w1_s2Or of { GHC.Types.I# ww9_s2OI [Occ=Once] ->
case T10482.$wfoo ww7_s2OA ww9_s2OI of ww10_s2OM { __DEFAULT -> GHC.Types.I# ww10_s2OM }
}
}
}
}}]
foo
= \ (w_s2NI :: Foo ((Int, Int), Int)) (w1_s2NJ :: Int) ->
case w_s2NI
= \ (w_s2Oq :: Foo ((Int, Int), Int)) (w1_s2Or :: Int) ->
case w_s2Oq
`cast` (T10482.D:R:Foo(,)0[0] <(Int, Int)>_N <Int>_N :: (Foo ((Int, Int), Int) :: *) ~R# (T10482.R:Foo(,) (Int, Int) Int :: *))
of
{ FooPair ww1_s2NM ww2_s2NW ->
case ww1_s2NM `cast` (T10482.D:R:Foo(,)0[0] <Int>_N <Int>_N :: (Foo (Int, Int) :: *) ~R# (T10482.R:Foo(,) Int Int :: *)) of
{ FooPair ww4_s2OE ww5_s2OF ->
case ww4_s2OE `cast` (T10482.D:R:FooInt0[0] ; T10482.N:R:FooInt[0] :: (Foo Int :: *) ~R# (Int :: *)) of { GHC.Types.I# ww7_s2OI ->
case w1_s2NJ of { GHC.Types.I# ww9_s2O0 -> case T10482.$wfoo ww7_s2OI ww9_s2O0 of ww10_s2O4 { __DEFAULT -> GHC.Types.I# ww10_s2O4 } }
{ FooPair ww1_s2Ou ww2_s2OE ->
case ww1_s2Ou `cast` (T10482.D:R:Foo(,)0[0] <Int>_N <Int>_N :: (Foo (Int, Int) :: *) ~R# (T10482.R:Foo(,) Int Int :: *)) of
{ FooPair ww4_s2Pm ww5_s2Pn ->
case ww4_s2Pm `cast` (T10482.D:R:FooInt0[0] ; T10482.N:R:FooInt[0] :: (Foo Int :: *) ~R# (Int :: *)) of { GHC.Types.I# ww7_s2Pq ->
case w1_s2Or of { GHC.Types.I# ww9_s2OI -> case T10482.$wfoo ww7_s2Pq ww9_s2OI of ww10_s2OM { __DEFAULT -> GHC.Types.I# ww10_s2OM } }
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment