[GHC] #13143: NOINLINE and worker/wrapper

GHC ghc-devs at haskell.org
Mon Feb 6 03:55:52 UTC 2017


#13143: NOINLINE and worker/wrapper
-------------------------------------+-------------------------------------
        Reporter:  simonpj           |                Owner:
            Type:  bug               |               Status:  closed
        Priority:  normal            |            Milestone:  8.2.1
       Component:  Compiler          |              Version:  8.0.1
      Resolution:  fixed             |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):  D3046
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Changes (by bgamari):

 * status:  patch => closed
 * resolution:   => fixed
 * milestone:   => 8.2.1


Comment:

 This was committed as,

 {{{
 commit b572aadb20c2e41e2f6d7b48401bd0b4239ce9f8
 Author: Eric Seidel <eric at seidel.io>
 Date:   Sun Feb 5 21:29:37 2017 -0500

     Do Worker/Wrapper for NOINLINE things

     Disabling worker/wrapper for NOINLINE things can cause unnecessary
     reboxing of values. Consider

         {-# NOINLINE f #-}
         f :: Int -> a
         f x = error (show x)

         g :: Bool -> Bool -> Int -> Int
         g True  True  p = f p
         g False True  p = p + 1
         g b     False p = g b True p

     the strictness analysis will discover f and g are strict, but because
 f
     has no wrapper, the worker for g will rebox p. So we get

         $wg x y p# =
           let p = I# p# in  -- Yikes! Reboxing!
           case x of
             False ->
               case y of
                 False -> $wg False True p#
                 True -> +# p# 1#
             True ->
               case y of
                 False -> $wg True True p#
                 True -> case f p of { }

         g x y p = case p of (I# p#) -> $wg x y p#

     Now, in this case the reboxing will float into the True branch, an so
     the allocation will only happen on the error path. But it won't float
     inwards if there are multiple branches that call (f p), so the
 reboxing
     will happen on every call of g. Disaster.

     Solution: do worker/wrapper even on NOINLINE things; but move the
     NOINLINE pragma to the worker.

     Test Plan: make test TEST="13143"

     Reviewers: simonpj, bgamari, dfeuer, austin

     Reviewed By: simonpj, bgamari

     Subscribers: dfeuer, thomie

     Differential Revision: https://phabricator.haskell.org/D3046
 }}}

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13143#comment:4>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list