Skip to content

Lambda lifting

Dan Rosen asks whether GHC has a lambda lifter. Yes, it does: GHC's full-laziness pass also doubles as a lambda lifter

  • It's controlled by the floatOutLambdas field of CoreMonad.FloatOutSwitches
  • This in turn is set from the floatLamArgs field of DynFlags in SimplCore
  • The DynFlags are set in module DynFlags (see -ffloat-all-lams, -ffloat-lam-args)

However on trying a small experiment on

	f x = map (\y -> (x,y))

I see a bug and an infelicity.

  • Bug: the comment with the floatOutLambdas field definition claims that Nothing means float all lambdas to the top. But the code in SetLevels.destLevel treats (Just 0) and Nothing identically, which contradicts the comment. Workaround: use (Just 100)
  • Infelicity: with -ffloat-lam-args=100 we get
lvl_sdQ =
  \ (@ t_acm) (@ t_acn) (x_a9H :: t_acm) (y_a9I :: t_acn) ->
    (x_a9H, y_a9I)

Foo.f =
  \ (@ t_acm)
    (@ t_acn)
    (x_a9H [Dmd=Just L] :: t_acm)
    (eta_B1 :: [t_acn]) ->
    GHC.Base.map
      @ t_acn @ (t_acm, t_acn) (lvl_sdQ @ t_acm @ t_acn x_a9H) eta_B1

which is good, but then the next simplifier run inlines it straight back in again, via SimplUtils.preInlineUnconditionally.

I think preInlineUnconditionally should be a bit less gung-ho, perhaps, but I don't want to change it until I've see if there are any performance regressions.

Trac metadata
Trac field Value
Version 7.4.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information