Skip to content

Need a bit more case-of-case in Inital Phase

This comment in !7997 (merged) describes an infelicity in floating.

In the nofib simple benchmark we have

polynomial degree ... = ....(\xyz. foldr k z [1..degree])....

By the time we get to FloatOut we have (roughly)

polynomial degree ... = ....(\xyz. foldr k z (case degree of I# d# -> build (enum 1# d#))...

Do we float that [1..degree] out of the \xyz? Doing so kills fusion; but it shares the [1..degree] which in general may be a big win.

General principle: trust the programmer: if fusion can happen, do it, even at the cost of floating.

In HEAD

  • Fusion does not happen in InitialPhase because the case gets in between the foldr and the build.
  • The case does not get pulled out of the strict argument because sm_case_case is off in InitialPhase.
  • We don't float because of the bizarre Case [MFEs] in SetLevels (c.f. #19001). It's a strict argument position, headed by a case so we don't float. I'm trying to get rid of this strange special case.
  • So in the subsequent Phase 2 simplification (with sm_case_case on) fusion can happen, quite coincidentally.

So in HEAD we get fusion, but only by a fluke; and !7997 (merged) removes some of the bizarreness, so the fluke no longer happens.

As a result, simple allocates 28% more.


I think the right solution is to make more fusion happen in InitialPhase. Maybe we can make sm_case_case switch off case-of-case only for multi-alternative cases. I think those are the ones that are the true target of sm_case_case=False (a sadly un-documented design).

Edited by Simon Peyton Jones
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information