[GHC] #12274: GHC panic: simplifier ticks exhausted

#12274: GHC panic: simplifier ticks exhausted -------------------------------------+------------------------------------- Reporter: mrkkrp | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Keywords: | Operating System: Linux Architecture: x86_64 | Type of failure: Compile-time (amd64) | crash Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- While compiling a project, I ran into this: {{{ Preprocessing library stache-0.1.0... [1 of 6] Compiling Text.Mustache.Type ( Text/Mustache/Type.hs, .stack- work/dist/x86_64-linux/Cabal-1.24.0.0/build/Text/Mustache/Type.o ) [.stack-work/dist/x86_64-linux/Cabal-1.24.0.0/build/autogen/cabal_macros.h changed] [2 of 6] Compiling Text.Mustache.Parser ( Text/Mustache/Parser.hs, .stack- work/dist/x86_64-linux/Cabal-1.24.0.0/build/Text/Mustache/Parser.o ) ghc: panic! (the 'impossible' happened) (GHC version 8.0.1 for x86_64-unknown-linux): Simplifier ticks exhausted When trying RuleFired Class op HEq_sc To increase the limit, use -fsimpl-tick-factor=N (default 100) If you need to do this, let GHC HQ know, and what factor you needed To see detailed counts use -ddump-simpl-stats Total ticks: 189602 Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug }}} The code is available here: https://github.com/stackbuilders/stache This only happens with GHC 8.0, with 7.10 it just takes forever (which should be a known issue, with 7.8 it's much faster), but nevertheless finishes. With `-fsimpl-tick-factor=150` the build suceeded. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12274 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12274: GHC panic: simplifier ticks exhausted -------------------------------------+------------------------------------- Reporter: mrkkrp | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by thomie): * failure: Compile-time crash => Compile-time performance bug Comment: Some notes: * There are a lot of `INLINE` pragmas in `Text.Mustache.Parser`, maybe too many? For example, removing the `INLINE` on `symbol` fixes the panic. * A `simpl-tick-factor` of `110` fixes the panic, so the simplifier is going only very slightly over the limit. This is probably nothing to worry about. * The regression in compile time is the real problem. Fixing it will fix the panic as well. I reduced it to the following testcase: https://github.com/thomie/megaslow (no external dependencies). Instructions: {{{ $ ghc -O Char.hs $ ghc -O -c -Rghc-timing Test.hs }}} ||= GHC =||= Bytes allocated for `Test.hs` =|| || 7.8.4 || 117MB || || 7.10.3 || 750MB || || HEAD (ffe4660510a7ba4adce846f316db455ccd91142a) || 724MB || -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12274#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12274: GHC panic: simplifier ticks exhausted -------------------------------------+------------------------------------- Reporter: mrkkrp | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Interesting. Thanks for reducing the test case. No time to look at it now, but can you characterise what is happening more. E.g. what happens with `-dshow-passes`? Does the program get really big at some point? What's the difference between 7.8 and 7.10. Is it non-linear somehow? etc. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12274#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12274: GHC panic: simplifier ticks exhausted -------------------------------------+------------------------------------- Reporter: mrkkrp | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by thomie): The problems start in the `Specialise` phase: {{{ # 7.8.4: # Result size of Simplifier = {terms: 62, types: 158, coercions: 1} # Result size of Specialise = {terms: 62, types: 158, coercions: 1} # # 7.10.3: # Result size of Simplifier = {terms: 66, types: 158, coercions: 1} # Result size of Specialise = {terms: 751, types: 2,319, coercions: 169} }}} * The output of `-ddump-spec` for `7.10` contains a list of `Local rules for imported ids`, but none for `7.8`. * The output of `-ddump-rule-firings` contains 326 rules for `7.10`, but only `20` for `7.8`. Some of the rule firings with `7.10`: {{{ Rule fired: Class op eof Rule fired: Class op fmap Rule fired: Class op fmap Rule fired: Class op $p1Stream Rule fired: Class op uncons Rule fired: Class op updatePos Rule fired: Class op updatePos Rule fired: Class op uncons Rule fired: Class op updatePos Rule fired: Class op updatePos Rule fired: Class op uncons Rule fired: Class op updatePos Rule fired: Class op updatePos Rule fired: Class op uncons Rule fired: Class op updatePos Rule fired: Class op updatePos Rule fired: SPEC/Test $fApplicativeParsecT @ Dec @ [Char] @ Identity Rule fired: SPEC/Test $fAlternativeParsecT @ Dec @ [Char] @ Identity Rule fired: Class op pure Rule fired: Class op pure ... ... ... }}} Here is a simplified example: Test.hs: {{{#!hs module Test where import A xs = mymap (+1) [1,2,3] }}} A.hs: {{{#!hs module A where mymap :: Functor f => (a -> b) -> f a -> f b mymap = fmap }}} ghc-7.8.4: {{{ $ ghc-7.8.4 Test.hs -ddump-rule-firings -O -fforce-recomp [1 of 2] Compiling A ( A.hs, A.o ) [2 of 2] Compiling Test ( Test.hs, Test.o ) Rule fired: Class op + Rule fired: Class op fmap Rule fired: map Rule fired: mapList }}} ghc-7.10.3: {{{ $ ghc-7.10.3 Test.hs -ddump-rule-firings -O -fforce-recomp [1 of 2] Compiling A ( A.hs, A.o ) [2 of 2] Compiling Test ( Test.hs, Test.o ) Rule fired: Class op + Rule fired: Class op fmap Rule fired: Class op fmap Rule fired: Class op fmap Rule fired: map Rule fired: mapList }}} Why does the `Class op fmap` fire three times with 7.10.3? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12274#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12274: GHC panic: simplifier ticks exhausted -------------------------------------+------------------------------------- Reporter: mrkkrp | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): GHC 7.10 makes specialised versions of imported overloaded functions, at least if it can see its inlining. In the example * `mymap` is overloaded, and is small, so its inlining is visible to module `Test` * `mymap` is called at type `Integer` in `Test` so GHC makes specialised copy, and adds a local RULE to rewrite `mymap Integer` to `$smymap`. * The `fmap` rule fires twice, once in the RHS of `$smymap` and once in its (small) unfolding. * But when GHC encounters the call to `mymap` is just inlines it anyway, before thinking about rules. That exposes another call to `fmap` so the rule fires again. Because `mymap` inlines, all the specalisation is in vain. How to avoid that? Maybe one round of simplification so that outright inlining precedes any attempt to specialise. Whether this is the original problem, I'm not sure. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12274#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12274: GHC panic: simplifier ticks exhausted -------------------------------------+------------------------------------- Reporter: mrkkrp | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Inlining Operating System: Linux | Architecture: x86_64 Type of failure: Compile-time | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by mpickering): * keywords: => Inlining -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12274#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC