Admin message

Due to a large amount of spam we do not allow new users to create repositories, they are "external" users. If you are a new user and want to create a repository, for example for forking GHC, open a new issue on ghc/ghc using the "get-verified" issue template

Improve inlining for local functions
See also * #19643 * #3755 * #20516 * #21938 * #22317 * !8778 Andreas's MR addressing this issue * [Problem with the binary library](https://gitlab.haskell.org/ghc/ghc/-/issues/21457#note_445884), and [the binary-library ticket](https://github.com/kolmodin/binary/issues/200) I found that `boyer2/Rewritefuns.onewayunify1` has a join point that really should be inlined. It should get a big discount from scrutinizing free variables. But the inlining mechanism only take account of arguments, not free variables. There's a small optimisation opportunity here, which this ticket records. See also: #4960 Here's the code: ``` Rewritefns.onewayunify1 = \ (t1_acm :: Lisplikefns.Lisplist) (t2_acn :: Lisplikefns.Lisplist) (u_aco :: Lisplikefns.Lisplist) -> case t2_acn of wild_ao1 { __DEFAULT -> case t1_acm of wild_Xok { __DEFAULT -> let { $j_spS :: GHC.Prim.State# GHC.Prim.RealWorld -> (GHC.Bool.Bool, Lisplikefns.Lisplist) [LclId, Arity=1, Unf=Unf{Src=<vanilla>, TopLvl=False, Arity=1, Value=True, ConLike=True, Cheap=True, Expandable=True, Guidance=IF_ARGS [0] 10 0}] $j_spS = \ _ -> Rewritefns.onewayunify1lst (case wild_Xok of _ { Lisplikefns.Nil -> Lisplikefns.Nil; Lisplikefns.Cons ds1_anT -> case ds1_anT of _ { (_, y_anY) -> y_anY } }) (case wild_ao1 of _ { Lisplikefns.Nil -> Lisplikefns.Nil; Lisplikefns.Cons ds1_anT -> case ds1_anT of _ { (_, y_anY) -> y_anY } }) u_aco } in case wild_Xok of _ { Lisplikefns.Nil -> case wild_ao1 of _ { Lisplikefns.Nil -> case Lisplikefns.$fEqLisplist_$c== Lisplikefns.Nil Lisplikefns.Nil of _ { GHC.Bool.False -> (GHC.Bool.False, u_aco); GHC.Bool.True -> $j_spS GHC.Prim.realWorld# }; Lisplikefns.Cons ds1_anJ -> case ds1_anJ of _ { (x_anN, _) -> case Lisplikefns.$fEqLisplist_$c== Lisplikefns.Nil x_anN of _ { GHC.Bool.False -> (GHC.Bool.False, u_aco); GHC.Bool.True -> $j_spS GHC.Prim.realWorld# } } }; Lisplikefns.Cons ds1_anJ -> case ds1_anJ of _ { (x_anN, _) -> case wild_ao1 of _ { Lisplikefns.Nil -> case Lisplikefns.$fEqLisplist_$c== x_anN Lisplikefns.Nil of _ { GHC.Bool.False -> (GHC.Bool.False, u_aco); GHC.Bool.True -> $j_spS GHC.Prim.realWorld# }; Lisplikefns.Cons ds1_Xof -> case ds1_Xof of _ { (x_Xom, _) -> case Lisplikefns.$fEqLisplist_$c== x_anN x_Xom of _ { GHC.Bool.False -> (GHC.Bool.False, u_aco); GHC.Bool.True -> $j_spS GHC.Prim.realWorld# } } } } }; Lisplikefns.Atom x_ao3 -> (GHC.Bool.False, u_aco) }; ``` You can see that `$j_sps` scrutinises `wild_Xok` and `wild_ao1`, but it currently gets no discount for doing so. <details><summary>Trac metadata</summary> | Trac field | Value | | ---------------------- | ------------ | | Version | 6.12.1 | | Type | Bug | | TypeOfFailure | OtherFailure | | Priority | normal | | Resolution | Unresolved | | Component | Compiler | | Test case | | | Differential revisions | | | BlockedBy | | | Related | | | Blocking | | | CC | | | Operating system | | | Architecture | | </details> <!-- {"blocked_by":[],"summary":"Improve inlining for local functions","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.12.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"I found that `boyer2/Rewritefuns.onewayunify1` has a join point that really should be inlined. It should get a big discount from scrutinizing free variables. But the inlining mechanism only take account of arguments, not free variables. There's a small optimisation opportunity here, which this ticket records. \r\n\r\nHere's the code:\r\n{{{\r\nRewritefns.onewayunify1 =\r\n \\ (t1_acm :: Lisplikefns.Lisplist)\r\n (t2_acn :: Lisplikefns.Lisplist)\r\n (u_aco :: Lisplikefns.Lisplist) ->\r\n case t2_acn of wild_ao1 {\r\n __DEFAULT ->\r\n case t1_acm of wild_Xok {\r\n __DEFAULT ->\r\n let {\r\n $j_spS\r\n :: GHC.Prim.State# GHC.Prim.RealWorld\r\n -> (GHC.Bool.Bool, Lisplikefns.Lisplist)\r\n [LclId,\r\n Arity=1,\r\n Unf=Unf{Src=<vanilla>, TopLvl=False, Arity=1, Value=True,\r\n ConLike=True, Cheap=True, Expandable=True,\r\n Guidance=IF_ARGS [0] 10 0}]\r\n $j_spS =\r\n \\ _ ->\r\n Rewritefns.onewayunify1lst\r\n (case wild_Xok of _ {\r\n Lisplikefns.Nil -> Lisplikefns.Nil;\r\n Lisplikefns.Cons ds1_anT ->\r\n case ds1_anT of _ { (_, y_anY) -> y_anY }\r\n })\r\n (case wild_ao1 of _ {\r\n Lisplikefns.Nil -> Lisplikefns.Nil;\r\n Lisplikefns.Cons ds1_anT ->\r\n case ds1_anT of _ { (_, y_anY) -> y_anY }\r\n })\r\n u_aco } in\r\n case wild_Xok of _ {\r\n Lisplikefns.Nil ->\r\n case wild_ao1 of _ {\r\n Lisplikefns.Nil ->\r\n case Lisplikefns.$fEqLisplist_$c== Lisplikefns.Nil Lisplikefns.Nil\r\n of _ {\r\n GHC.Bool.False -> (GHC.Bool.False, u_aco);\r\n GHC.Bool.True -> $j_spS GHC.Prim.realWorld#\r\n };\r\n Lisplikefns.Cons ds1_anJ ->\r\n case ds1_anJ of _ { (x_anN, _) ->\r\n case Lisplikefns.$fEqLisplist_$c== Lisplikefns.Nil x_anN of _ {\r\n GHC.Bool.False -> (GHC.Bool.False, u_aco);\r\n GHC.Bool.True -> $j_spS GHC.Prim.realWorld#\r\n }\r\n }\r\n };\r\n Lisplikefns.Cons ds1_anJ ->\r\n case ds1_anJ of _ { (x_anN, _) ->\r\n case wild_ao1 of _ {\r\n Lisplikefns.Nil ->\r\n case Lisplikefns.$fEqLisplist_$c== x_anN Lisplikefns.Nil of _ {\r\n GHC.Bool.False -> (GHC.Bool.False, u_aco);\r\n GHC.Bool.True -> $j_spS GHC.Prim.realWorld#\r\n };\r\n Lisplikefns.Cons ds1_Xof ->\r\n case ds1_Xof of _ { (x_Xom, _) ->\r\n case Lisplikefns.$fEqLisplist_$c== x_anN x_Xom of _ {\r\n GHC.Bool.False -> (GHC.Bool.False, u_aco);\r\n GHC.Bool.True -> $j_spS GHC.Prim.realWorld#\r\n }\r\n }\r\n }\r\n }\r\n };\r\n Lisplikefns.Atom x_ao3 -> (GHC.Bool.False, u_aco)\r\n };\r\n}}}\r\nYou can see that `$j_sps` scrutinises `wild_Xok` and `wild_ao1`, but it currently gets no discount for doing so.\r\n","type_of_failure":"OtherFailure","blocking":[]} -->
issue