Skip to content

Exponential inlining with strict constructors and -O1

Summary

A module that had compiled normally using 8.8.4, took very long to compile with 9.2. It looks like the simplifier phase causes an exponential increase in code size. I managed to reduce it to the following reproducer.

It looks like this behaviour is also present in 8.10.4 and 9.0.1, but doesn't happen in 8.8.4

In 8.8.4, f gets inlined into g, producing a linear chain of join points. Whereas in later versions of GHC, code is duplicated instead.

Steps to reproduce

Try to compile this module:

{-# OPTIONS_GHC -O1 #-}
module Repro where

data A = A
  { a1 :: (Maybe ())
  , a2 :: (Maybe ())
  , a3 :: (Maybe ())
  , a4 :: (Maybe ())
  , a5 :: (Maybe ())
  , a6 :: (Maybe ())
  , a7 :: (Maybe ())
  , a8 :: (Maybe ())
  , a9 :: (Maybe ())
  , a10 :: (Maybe ())
  , a11 :: (Maybe ())
  , a12 :: (Maybe ())
  }

data B = B
  { b1 :: !Bool
  , b2 :: !Bool
  , b3 :: !Bool
  , b4 :: !Bool
  , b5 :: !Bool
  , b6 :: !Bool
  , b7 :: !Bool
  , b8 :: !Bool
  , b9 :: !Bool
  , b10 :: !Bool
  , b11 :: !Bool
  , b12 :: !Bool
  }

f :: Maybe () -> Bool
f (Just ()) = True
f Nothing = False

g :: A -> B
g (A a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12) = 
  B { 
      b1 = f a1
    , b2 = f a2
    , b3 = f a3
    , b4 = f a4
    , b5 = f a5
    , b6 = f a6
    , b7 = f a7
    , b8 = f a8
    , b9 = f a9
    , b10 = f a10
    , b11 = f a11
    , b12 = f a12 
  }

Expected behaviour

The module should compile quickly and not lead to an explosion in code size.

Environment

  • GHC version used:
> ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.2.0.20210619

Optional:

  • Operating System: NixOS 21.05
  • System Architecture: X86_64
Edited by Teo Camarasu
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information