[GHC] #14170: 8.2.1 regression: GHC fails to simplify `natVal`

GHC ghc-devs at haskell.org
Thu Aug 31 10:03:29 UTC 2017


#14170: 8.2.1 regression: GHC fails to simplify `natVal`
-------------------------------------+-------------------------------------
        Reporter:  vagarenko         |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  high              |            Milestone:  8.2.2
       Component:  Compiler          |              Version:  8.2.1
      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 simonpj):

 OK here's the deal.

 * In the olden days we represented in `Integer` literal, say 3, in Core by
 `S# 3#`; that is, we exposed its reprsentation.  That made constant
 folding of `plusInteger 3 5` hard, becuase it meant inlining `plusInteger`
 which is remarkably big.  Result: tons of useless clutter.

 * Nowadays an `Integer` literal, say 3, is represented in GHC by `Lit
 (LitInteger 3)`, and ''not'' by an application of the data constructor
 `S#`.   This latter expansion is done right at the end, by `CorePrep`.

 * That makes constant-folding, like `3+4` rewriting to `7` much, much
 easier.

 * We refrain from inlining things like `plusInteger`, `negateInteger` etc
 until a later stage, and instead add constant-folding rwerite rules for
 each of these functions.  By delaying inlining, the constant-folding
 rewrite rules (all in `compiler/prelude/PrelRules`) have a decent chance
 to fire first.

 * However, in introducing `Natural` we failed to do any of this.  The code
 {{{
 foo :: Natural
 foo = 0
 }}}
   turns into `foo = naturalFromInteger (0::Integer)`, and
 `naturalFromInteger` has an INLINE pragma.

 The right thing is presumably to treat `Natural` just like we treat
 `Integer`:
 * Keep it as a `LitInteger`. Conveniently `LitInteger` already stores its
 type, so we can distinguish literal integers from naturals.
 * Expand the literal in `CorePrep`.
 * Delay the inlining of `Natural` operations.
 * Add constant-folding rewrite rules to `PrelRules`

 I suppose we could also consider making `exprIsConApp_maybe` on an
 `Integer` literal return `S# n` or whatnot; just possibly that'd be useful
 anyway, but only for funcions that lack a constant-fold rewrite rule.

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


More information about the ghc-tickets mailing list