Skip to content

Infinite simplifier iteration

Consider this little program:

module Foo(woo) where


foo :: String -> Int -> a
{-# NOINLINE foo #-}
foo s _ = error s

f :: (Int->Int) -> Int
{-# NOINLINE f #-}
f g = g 3

x :: Int -> a
x = foo "urk"

woo = f x

When compiling with HEAD we get

bash$ ~/code/HEAD/$s1 -c -O  -fmax-simplifier-iterations=10 Foo.hs
WARNING:
  Simplifier bailing out
  Foo, after 10 iterations [12, 2, 2, 2, 2, 2, 2, 2, 2, 2]
    Size = {terms: 85, types: 55, coercions: 4, joins: 0/0}
  Call stack:
      CallStack (from HasCallStack):
        warnPprTrace, called at compiler/GHC/Core/Opt/Simplify.hs:191:9 in ghc:GHC.Core.Opt.Simplify
WARNING:
  Simplifier bailing out
  Foo, after 10 iterations [46, 3, 3, 3, 3, 3, 3, 3, 3, 3]
    Size = {terms: 85, types: 45, coercions: 4, joins: 0/0}
  Call stack:
      CallStack (from HasCallStack):
        warnPprTrace, called at compiler/GHC/Core/Opt/Simplify.hs:191:9 in ghc:GHC.Core.Opt.Simplify
WARNING:
  Simplifier bailing out
  Foo, after 10 iterations [3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
    Size = {terms: 85, types: 45, coercions: 4, joins: 0/0}
  Call stack:
      CallStack (from HasCallStack):
        warnPprTrace, called at compiler/GHC/Core/Opt/Simplify.hs:191:9 in ghc:GHC.Core.Opt.Simplify

Clearly the Simplifier is not reaching a fixed point.

This is true in HEAD, and goes back to at least GHC 9.6 probably earlier.

Diagnosis

We end up with

  s1 = "urk#"
  s2 = unpackSString# s1
  x = foo s2   -- A partial application, since foo has arity 2
               -- but x is bottoming so we don't inline it

The Simplifier is

  • doing preInlineUnconditionally to inline s1 into s2, and s2 into x
  • and then ANF-ising the RHS foo (unpackCString# "urk"#) to get back what we started with.

The (long-standing) bug is that the certainly_inline predicate in GHC.Core.Opt.OccurAnal.mkNonRecRhsCtxt is not tracking preInlineUnconditionally correctly; see Note [Cascading inlines] in that module. (In this case it is not accounting for the fact that x a top-level is bottoming binding.

Solution

Update certainly_inline. It's not very satisfactory that this out-of-sync-ness can happen but I don't see an easy solution.

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