Skip to content

Gratuitous code bloat due to `postInlineUnconditionally`

Consider this small program:

module Foo where

sORTKind_maybe :: TyCon -> String
sORTKind_maybe tc
  -- First, short-cuts for Type and Constraint that do no allocation
  | tc_uniq == 1 = "one"
  | tc_uniq == 2 = "two"
  | tc_uniq == 3 = "three"
  | tc_uniq == 4 = "four"
  where
    tc_uniq = tyConUnique tc
sORTKind_maybe _ = "five"


data TyCon = A Int | B Int | C Int | D Int | E Int | F Int | G Int

tyConUnique (A i) = i
tyConUnique (B i) = i
tyConUnique (C i) = i
tyConUnique (D i) = i
tyConUnique (E i) = i
tyConUnique (F i) = i
tyConUnique (G i) = i

We hope to get code like

sORT_Kind_maybe tc
  = case tyConUnique tc of
       1# -> "one"
       2# -> "two"
       3# -> "three"
       4# -> "four"
       _  -> "five"

But no; we get this giant mess

sORTKind_maybe :: TyCon -> String
[GblId, Arity=1, Str=<SL>, Unf=OtherCon []]
sORTKind_maybe
  = \ (tc_aum :: TyCon) ->
      join {
        $j_sNu [Dmd=1C(1,L)] :: GHC.Prim.Int# -> [Char]
        [LclId[JoinId(1)(Nothing)], Arity=1, Str=<1L>, Unf=OtherCon []]
        $j_sNu (x_aNj [OS=OneShot] :: GHC.Prim.Int#)
          = case x_aNj of {
              __DEFAULT ->
                join {
                  $j1_sNs [Dmd=1C(1,L)] :: GHC.Prim.Int# -> [Char]
                  [LclId[JoinId(1)(Nothing)], Arity=1, Str=<1L>, Unf=OtherCon []]
                  $j1_sNs (x1_X3 [OS=OneShot] :: GHC.Prim.Int#)
                    = case x1_X3 of {
                        __DEFAULT ->
                          join {
                            $j2_sNq [Dmd=1C(1,L)] :: GHC.Prim.Int# -> [Char]
                            [LclId[JoinId(1)(Nothing)], Arity=1, Str=<1L>, Unf=OtherCon []]
                            $j2_sNq (x2_X6 [OS=OneShot] :: GHC.Prim.Int#)
                              = case x2_X6 of {
                                  __DEFAULT ->
                                    case tc_aum of {
                                      A i_aG3 ->
                                        case i_aG3 of { GHC.Types.I# x3_Xa ->
                                        case x3_Xa of {
                                          __DEFAULT -> lvl1_rNL;
                                          4# -> lvl3_rNN
                                        }
                                        };
                                      B i_aG4 ->
                                        case i_aG4 of { GHC.Types.I# x3_Xa ->
                                        case x3_Xa of {
                                          __DEFAULT -> lvl1_rNL;
                                          4# -> lvl3_rNN
                                        }
                                        };
                                      C i_aG5 ->
                                        case i_aG5 of { GHC.Types.I# x3_Xa ->
                                        case x3_Xa of {
                                          __DEFAULT -> lvl1_rNL;
                                          4# -> lvl3_rNN
                                        }
                                        };
                                      D i_aG6 ->
                                        case i_aG6 of { GHC.Types.I# x3_Xa ->
                                        case x3_Xa of {
                                          __DEFAULT -> lvl1_rNL;
                                          4# -> lvl3_rNN
                                        }
                                        };
                                      E i_aG7 ->
                                        case i_aG7 of { GHC.Types.I# x3_Xa ->
                                        case x3_Xa of {
                                          __DEFAULT -> lvl1_rNL;
                                          4# -> lvl3_rNN
                                        }
                                        };
                                      F i_aG8 ->
                                        case i_aG8 of { GHC.Types.I# x3_Xa ->
                                        case x3_Xa of {
                                          __DEFAULT -> lvl1_rNL;
                                          4# -> lvl3_rNN
                                        }
                                        };
                                      G i_aG9 ->
                                        case i_aG9 of { GHC.Types.I# x3_Xa ->
                                        case x3_Xa of {
                                          __DEFAULT -> lvl1_rNL;
                                          4# -> lvl3_rNN
                                        }
                                        }
                                    };
                                  3# -> lvl5_rNP
                                } } in
                          case tc_aum of {
                            A i_aG3 ->
                              case i_aG3 of { GHC.Types.I# x2_X7 -> jump $j2_sNq x2_X7 };
                            B i_aG4 ->
                              case i_aG4 of { GHC.Types.I# x2_X7 -> jump $j2_sNq x2_X7 };
                            C i_aG5 ->
                              case i_aG5 of { GHC.Types.I# x2_X7 -> jump $j2_sNq x2_X7 };
                            D i_aG6 ->
                              case i_aG6 of { GHC.Types.I# x2_X7 -> jump $j2_sNq x2_X7 };
                            E i_aG7 ->
                              case i_aG7 of { GHC.Types.I# x2_X7 -> jump $j2_sNq x2_X7 };
                            F i_aG8 ->
                              case i_aG8 of { GHC.Types.I# x2_X7 -> jump $j2_sNq x2_X7 };
                            G i_aG9 ->
                              case i_aG9 of { GHC.Types.I# x2_X7 -> jump $j2_sNq x2_X7 }
                          };
                        2# -> lvl7_rNR
                      } } in
                case tc_aum of {
                  A i_aG3 ->
                    case i_aG3 of { GHC.Types.I# x1_X4 -> jump $j1_sNs x1_X4 };
                  B i_aG4 ->
                    case i_aG4 of { GHC.Types.I# x1_X4 -> jump $j1_sNs x1_X4 };
                  C i_aG5 ->
                    case i_aG5 of { GHC.Types.I# x1_X4 -> jump $j1_sNs x1_X4 };
                  D i_aG6 ->
                    case i_aG6 of { GHC.Types.I# x1_X4 -> jump $j1_sNs x1_X4 };
                  E i_aG7 ->
                    case i_aG7 of { GHC.Types.I# x1_X4 -> jump $j1_sNs x1_X4 };
                  F i_aG8 ->
                    case i_aG8 of { GHC.Types.I# x1_X4 -> jump $j1_sNs x1_X4 };
                  G i_aG9 ->
                    case i_aG9 of { GHC.Types.I# x1_X4 -> jump $j1_sNs x1_X4 }
                };
              1# -> lvl9_rNT
            } } in
      case tc_aum of {
        A i_aG3 ->
          case i_aG3 of { GHC.Types.I# x_aNj -> jump $j_sNu x_aNj };
        B i_aG4 ->
          case i_aG4 of { GHC.Types.I# x_aNj -> jump $j_sNu x_aNj };
        C i_aG5 ->
          case i_aG5 of { GHC.Types.I# x_aNj -> jump $j_sNu x_aNj };
        D i_aG6 ->
          case i_aG6 of { GHC.Types.I# x_aNj -> jump $j_sNu x_aNj };
        E i_aG7 ->
          case i_aG7 of { GHC.Types.I# x_aNj -> jump $j_sNu x_aNj };
        F i_aG8 ->
          case i_aG8 of { GHC.Types.I# x_aNj -> jump $j_sNu x_aNj };
        G i_aG9 ->
          case i_aG9 of { GHC.Types.I# x_aNj -> jump $j_sNu x_aNj }
      }

This is stupid. I think it's because we are too aggressive about Note [Inline small things to avoid creating a thunk] in postInlineUnconditionally in GHC.Core.Opt.Simplify.Utils.

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