<div dir="ltr">Hi Conal,<div><br></div><div>so if I understand this right, you'd rather not wanted `exampleC` to be eta-expanded (or the binding of `s` to be floated into the lambda)?</div><div>Or is it that you want CSE to find out that you always supply the same `t` as the first argument and share the partial application and thus the work of computing `s`?</div><div><br></div><div>If it's the former: GHC doesn't normally do this, unless it has found out that no sharing (of work done to evaluate `s`) would be lost through eta-expansion.</div><div>This is the case when `exampleC` is always called with two arguments, so that no binding of `s` is shared, for example.</div><div>Could you maybe post a complete module/expression representative of all uses of `exampleC`?</div><div><br></div><div>If it's the latter, I'm afraid I can't really help, but surely someone else can.</div><div><br></div><div>Cheers,</div><div>Sebastian</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jul 18, 2017 at 5:34 PM, Conal Elliott <span dir="ltr"><<a href="mailto:conal@conal.net" target="_blank">conal@conal.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>I'm seeing what looks like repeated computation under a lambda with `-O` and `-O2`. The following definition:</div><div><br></div><div>> exampleC :: Double -> Double -> Double</div><div>> exampleC = \ t -> let s = sin t in \ x -> x + s</div><div><br></div><div>yields this Core:</div><div><br></div><div>> -- RHS size: {terms: 13, types: 6, coercions: 0}</div><div>> exampleC :: Double -> Double -> Double</div><div>> exampleC =</div><div>>   \ (t_afI6 :: Double) (eta_B1 :: Double) -></div><div>>     case eta_B1 of _ { D# x_aj5c -></div><div>>     case t_afI6 of _ { D# x1_aj5l -></div><div>>     D# (+## x_aj5c (sinDouble# x1_aj5l))</div><div>>     }</div><div>>     }</div><div><br></div><div>The `sinDouble#` here depends only on `t_afI6` (`t`) but still appears under the binding of `eta_B1` (`x`).</div><div><br></div><div><div>I'm concerned because many of my uses of such functions involve computations dependent only on `t` (time) but with millions of uses (space) per `t`. (I'm working on a GHC Core plugin (compiling to categories), with one use generating graphics GPU code.)<br></div><div><br></div><div>Does the optimization I expected somehow happen later in the compilation pipeline?</div><div><br></div><div>Are there Core-manipulating functions in GHC that I can use to make it happen earlier (via a `BuiltinRule`, i.e., Core-to-Core function)?</div></div><div><br></div><div>Thanks,</div><div>-- Conal</div><div><br></div></div>
<br>______________________________<wbr>_________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org">ghc-devs@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/ghc-devs</a><br>
<br></blockquote></div><br></div>