Opened 2 years ago

Closed 2 years ago

#13413 closed bug (fixed)

GHC HEAD panic: collectNBinders

Reported by: RyanGlScott Owned by: simonpj
Priority: highest Milestone: 8.2.1
Component: Compiler Version: 8.1
Keywords: JoinPoints Cc: lukemauer
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: GHC rejects valid program Test Case: simplCore/should_compile/T13413
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

repa-eval-4.2.3.1 currently fails to build on GHC HEAD because of this issue. Trying to build it leads to several collectNBinders panics is various modules. You can reproduce this by compiling this module:

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
module Data.Repa.Eval.Generic.Seq.Chunked where

import GHC.Exts (Int#, (+#), (*#), (>=#))

-------------------------------------------------------------------------------
-- | Fill a block in a rank-2 array, sequentially.
--
--   * Blockwise filling can be more cache-efficient than linear filling for
--     rank-2 arrays.
--
--   * The block is filled in row major order from top to bottom.
--
fillBlock2
        :: (Int# -> a -> IO ()) -- ^ Update function to write into result buffer.
        -> (Int# -> Int# -> a)  -- ^ Function to get the value at an (x, y) index.
        -> Int#                 -- ^ Width of the whole array.
        -> Int#                 -- ^ x0 lower left corner of block to fill.
        -> Int#                 -- ^ y0
        -> Int#                 -- ^ w0 width of block to fill
        -> Int#                 -- ^ h0 height of block to fill
        -> IO ()

fillBlock2
        write getElem
        !imageWidth !x0 !y0 !w0 h0

 = do   fillBlock y0 ix0
 where  !x1     = x0 +# w0
        !y1     = y0 +# h0
        !ix0    = x0 +# (y0 *# imageWidth)

        {-# INLINE fillBlock #-}
        fillBlock !y !ix
         | 1# <- y >=# y1     = return ()
         | otherwise
         = do   fillLine1 x0 ix
                fillBlock (y +# 1#) (ix +# imageWidth)

         where  {-# INLINE fillLine1 #-}
                fillLine1 !x !ix'
                 | 1# <- x >=# x1             = return ()
                 | otherwise
                 = do   write ix' (getElem x y)
                        fillLine1 (x +# 1#) (ix' +# 1#)

{-# INLINE [0] fillBlock2 #-}

This compiles on GHC 8.0.2, but on GHC HEAD:

$ ~/Software/ghc4/inplace/bin/ghc-stage2 -fforce-recomp Bug.hs
[1 of 1] Compiling Data.Repa.Eval.Generic.Seq.Chunked ( Bug.hs, Bug.o )
ghc-stage2: panic! (the 'impossible' happened)
  (GHC version 8.1.20170201 for x86_64-unknown-linux):
        collectNBinders
  2
  Call stack:
      CallStack (from HasCallStack):
        prettyCurrentCallStack, called at compiler/utils/Outputable.hs:1179:58 in ghc:Outputable
        callStackDoc, called at compiler/utils/Outputable.hs:1183:37 in ghc:Outputable
        pprPanic, called at compiler/coreSyn/CoreSyn.hs:1970:25 in ghc:CoreSyn

Interestingly, compiling this triggers the panic at any optimization level, but loading the module into GHCi does not cause it to panic.

This regression was introduced in 8d5cf8bf584fd4849917c29d82dcf46ee75dd035 (Join points).

Change History (9)

comment:1 Changed 2 years ago by bgamari

Cc: lukemauer added

Luke, do you think you could look at this?

comment:2 Changed 2 years ago by bgamari

Owner: set to simonpj

Simon has said he is on this.

comment:3 Changed 2 years ago by Lemming

storablevector:Data.StorableVector.ST.Strict has the same problem. http://hackage.haskell.org/package/storablevector-0.2.11/docs/Data-StorableVector-ST-Strict.html

comment:4 Changed 2 years ago by Simon Peyton Jones <simonpj@…>

In a7dbafe/ghc:

No join-point from an INLINE function with wrong arity

The main payload of this patch is NOT to make a join-point
from a function with an INLINE pragma and the wrong arity;
see Note [Join points and INLINE pragmas] in CoreOpt.
This is what caused Trac #13413.

But we must do the exact same thing in simpleOptExpr,
which drove me to the following refactoring:

* Move simpleOptExpr and simpleOptPgm from CoreSubst to a new
  module CoreOpt along with a few others (exprIsConApp_maybe,
  pushCoArg, etc)

  This eliminates a module loop altogether (delete
  CoreArity.hs-boot), and stops CoreSubst getting too huge.

* Rename Simplify.matchOrConvertToJoinPoint
     to joinPointBinding_maybe
  Move it to the new CoreOpt
  Use it in simpleOptExpr as well as in Simplify

* Define CoreArity.joinRhsArity and use it

comment:5 Changed 2 years ago by simonpj

This fixes the crashes.

But the INLINE pragams on fillBlock and fillLine are silly -- recursive functions are never inlined. And now they are (very mildly) harmful since they stop me turning the function into a join point. See the Note mentioned above.

Best to remove the pragmas.

I have not tested the storablevector crash; might someone do that?

comment:6 Changed 2 years ago by simonpj

Test Case: simplCore/should_compile/T13413

Merge to 8.2

comment:7 Changed 2 years ago by RyanGlScott

storablevector now builds for me without issue on GHC HEAD.

comment:8 Changed 2 years ago by bgamari

Status: newmerge

comment:9 Changed 2 years ago by bgamari

Resolution: fixed
Status: mergeclosed
Note: See TracTickets for help on using tickets.