[GHC] #8763: forM_ [1..N] does not get fused (allocates 50% more)
GHC
ghc-devs at haskell.org
Tue Sep 4 11:57:18 UTC 2018
#8763: forM_ [1..N] does not get fused (allocates 50% more)
-------------------------------------+-------------------------------------
Reporter: nh2 | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone: 8.8.1
Component: Compiler | Version: 7.6.3
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Runtime | Unknown/Multiple
performance bug | Test Case:
Blocked By: | Blocking:
Related Tickets: #7206 | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by sgraf):
----
I can think of another transformation that would save the day here: We
just have to put `c` in the same recursive group as `go_up` and recognize
the mutual recursive join point. Seems like a better way than to mess with
the simplifier and we don't even risk duplication of any code! So
{{{
let c x k s = case (body x s) of (_, s') -> k s'
in ...
let go_up x
| isTrue# (x ># y') = I# x `c` n
| otherwise = I# x `c` go_up (x +# delta)
==> float `c` inwards into the same recursive group, specialise it for
`go_up (x+#delta)` and `n` as `k` (SpecConstr? Would entail seeing tail-
calls as kind-of a pattern match for functions)
join go_up x
| isTrue# (x ># y') = jump c1 (I# x)
| otherwise = c2 (I# x) go_up (x +# delta)
c1 x s = -- k = n
case (body x s) of (_, s') -> n s'
c2 x s = -- k = go_up (x +# delta)
case (body x s) of (_, s') -> go_up (x +# delta) s'
}}}
Well, it's probably not SpecConstr that will do the specialisation. Also,
why specialise when we could just inline `c`? Seems like we risk
duplication of the potentially huge `body` after all.
Although the same weakness doesn't apply to the situation in comment:71:
It's enough to specialise for the `emit` argument (which serves a similar
role as `go_up`) without any specific arguments to see that it's tail
called:
{{{
let c_a2jU x k s = case (body x s) of (_, s') -> k s'
in join emit_a4hf next_ok next =
...
case ==# next_ovf_a3hz delta_ovf_a3h0 of {
__DEFAULT ->
case b_a2jS of { __DEFAULT ->
c_a2jU
(GHC.Types.I# ds_d42Y)
(emit_a3hf GHC.Types.False next_a3hx)
};
1# ->
case b_a2jS of next_ok_a2k8 { __DEFAULT ->
c_a2jU
(GHC.Types.I# ds_d42Y)
(emit_a3hf next_ok_a2k8 next_a3hx)
}
}
==> Specialising `c` for the call pattern
`[ds s next_ok next] |> [I# ds, emit next_ok next, s]`
as `c'`
join c' ds s next_ok next =
case (body (I# ds) s) of (_, s') -> emit_a4hf next_ok next s'
emit_a4hf next_ok next s =
...
case ==# next_ovf_a3hz delta_ovf_a3h0 of {
__DEFAULT ->
case b_a2jS of { __DEFAULT ->
jump c' ds_d42Y GHC.Types.False next_a3hx s
};
1# ->
case b_a2jS of next_ok_a2k8 { __DEFAULT ->
jump c' ds_d42Y next_ok_a2k8 next_a3hx s
}
}
}}}
This latter case is probably a lot easier to handle. Maybe this is worth
some specialised pass?
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8763#comment:75>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list