[GHC] #14687: Investigate differences in Int-In/Outlining

GHC ghc-devs at haskell.org
Wed Jan 31 23:20:35 UTC 2018


#14687: Investigate differences in Int-In/Outlining
-------------------------------------+-------------------------------------
        Reporter:  AndreasK          |                Owner:  mpickering
            Type:  task              |               Status:  new
        Priority:  lowest            |            Milestone:
       Component:  Compiler          |              Version:  8.2.2
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by mpickering):

 Here is what is happening. I don't know if there are any bugs here or not.

 The core for `func` looks like

 {{{
 -- RHS size: {terms: 17, types: 4, coercions: 0, joins: 0/0}
 func :: Int# -> Int# -> Int
 [LclIdX,
  Arity=2,
  Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
          WorkFree=True, Expandable=True, Guidance=IF_ARGS [50 40] 90 0}]
 func
   = \ (ds_dWL :: Int#) (ds_dWM :: Int#) ->
       case ds_dWL of {
         __DEFAULT -> fail_sXf void#;
         1# ->
           case ds_dWM of {
             __DEFAULT -> fail_sXf void#;
             1# -> lvl_sXg;
             2# -> lvl_sXh
           }
       }
 }}}

 whilst the core for `foo` looks like

 {{{
 -- RHS size: {terms: 23, types: 5, coercions: 0, joins: 0/0}
 foo :: Int# -> Int# -> Int
 [LclIdX,
  Arity=2,
  Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
          WorkFree=True, Expandable=True, Guidance=IF_ARGS [100 60] 130 0}]
 foo
   = \ (ds_dWG :: Int#) (ds_dWH :: Int#) ->
       case ds_dWG of {
         __DEFAULT -> fail_sXk void#;
         1# ->
           case ds_dWH of {
             __DEFAULT -> fail_sXk void#;
             1# -> lvl_sXl
           };
         2# ->
           case ds_dWH of {
             __DEFAULT -> fail_sXk void#;
             1# -> lvl_sXm
           }
       }
 }}}

 It is key to note at this stage that the size of `func` is 90 whilst the
 size of `foo` is 130.

 GHC has already dutifully floated out the integers at this stage so how do
 they reappear?

 `foo` is then W/W but `func` is not. The reason for this is that GHC
 decides that `func` will certainly get inlined due to the following line
 in `CoreUnfold`

 {{{
 , size - (10 * (arity + 1)) <= ufUseThreshold dflags
 }}}

 As the size of `func` is 90, this condition returns `True` (90-30 = 60,
 ufUseThreshold=60).

 So then what happens to `foo`? Well it is W/Wed and then the constants
 appear in the worker immediately in `post-worker-wrapper` simplifier run.
 It looks likely because the worker has a case-of-case opportunity which
 then leaves the variable in a case position. However I didn't verify
 exactly why the variable is inlined as it didn't appear in `-ddump-
 inlinings`.

 The worker is then inlined back into the wrapper and thus they reappear in
 the definition.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14687#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list