#4941: SpecConstr generates functions that do not use their arguments
---------------------------------+------------------------------------------
Reporter: simonpj | Owner:
Type: task | Status: new
Priority: normal | Milestone: _|_
Component: Compiler | Version: 7.0.1
Keywords: | Testcase:
Blockedby: | Difficulty:
Os: Unknown/Multiple | Blocking:
Architecture: Unknown/Multiple | Failure: Runtime performance bug
---------------------------------+------------------------------------------
Comment(by batterseapower):
Headline numbers for this change after your #4957 fix:
{{{
Min +0.0% -3.2% -4.4% -2.5% +0.0%
Max +0.3% +4.0% +4.5% +4.9% +0.0%
Geometric Mean +0.0% -0.0% +0.2% +0.2% -0.0%
}}}
So a solid reduction in allocations for a few benchmarks (knights,
parstof, simple and sphere are the biggest winners). However, some
benchmarks get worse. I looked at the worst offender (crypytarithm2) and
saw something pretty odd. It looks like the transformation is working
correctly but the output code (post simplification) contains dead let-
bindings for SpecConstr specialisations that have been worker/wrappered,
and those workers have been subsequently inlined into all use sites.
For example, we have a local specialisation within the final body of
permute1:
{{{
sgo_s1lg [InlPrag=INLINE[0], Occ=LoopBreaker!]
:: Main.Digits
-> Main.Digits
-> [(Main.Digits, Main.Digits)]
-> [(GHC.Types.Int, Main.Digits)]
[LclId,
Arity=3,
Str=DmdType U(SL)LL,
Unf=Unf{Src=Worker=$w$sgo_s1mv, TopLvl=False, Arity=3, Value=True,
ConLike=True, Cheap=True, Expandable=True,
Guidance=ALWAYS_IF(unsat_ok=True,boring_ok=False)
Tmpl= \ (w_s1lD [Occ=Once!] :: Main.Digits)
(w1_s1lI [Occ=Once] :: Main.Digits)
(w2_s1lJ [Occ=Once] :: [(Main.Digits,
Main.Digits)]) ->
case w_s1lD
of _ { Main.Digits ww_s1lF [Occ=Once] ww1_s1lG
[Occ=Once] ->
$w$sgo_s1mv ww_s1lF ww1_s1lG w1_s1lI w2_s1lJ
}}]
$sgo_s1lg =
\ (w_s1lD :: Main.Digits)
(w1_s1lI :: Main.Digits)
(w2_s1lJ :: [(Main.Digits, Main.Digits)]) ->
case w_s1lD of _ { Main.Digits ww_s1lF ww1_s1lG ->
$w$sgo_s1mv ww_s1lF ww1_s1lG w1_s1lI w2_s1lJ
};
$w$sgo_s1mv [Occ=LoopBreaker]
:: [GHC.Types.Int]
-> [(GHC.Types.Char, GHC.Types.Int)]
-> Main.Digits
-> [(Main.Digits, Main.Digits)]
-> [(GHC.Types.Int, Main.Digits)]
[LclId, Arity=4, Str=DmdType SLLL]
$w$sgo_s1mv = ... big ...
}}}
But $sgo_s1lg does not occur anywhere in the code! These bindings are
probably the source of the increased allocation as their closures will be
allocated anew for each application of permute1.
I found that changing the final simplification phase to use at least 3
iterations (just like the main simplification phase) did not eliminate
these. Is there any obvious explanation for this behaviour?
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/4941#comment:9>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs