Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,262
    • Issues 4,262
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 419
    • Merge Requests 419
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Security & Compliance
    • Security & Compliance
    • Dependency List
    • License Compliance
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #16029

Closed
Open
Opened Dec 10, 2018 by Simon Peyton Jones@simonpjDeveloper

Inadequate absence analysis

Consider

data S = MkS Int Int
g1 :: S -> Int -> Int
g1 (MkS x y) 0 = 0
g1 (MkS x y) n = g1 (MkS y x) (n-1)

With GHC 8.6 we get

$wg1 :: S -> GHC.Prim.Int# -> GHC.Prim.Int#
[Str=<S,1*H><S,1*U>]
$wg1 = \ (w_s2oH :: S)
         (ww_s2oL :: GHC.Prim.Int#) ->
         case w_s2oH of { MkS x_s2pz y_s2pA ->
         case ww_s2oL of ds_X2nb {
           __DEFAULT ->
             Foo.$wg1 (Foo.MkS y_s2pA x_s2pz) (GHC.Prim.-# ds_X2nb 1#);
           0# -> 0# }}

g1 :: S -> Int -> Int
[Str=<S,1*H><S(S),1*U(1*U)>m]
g1 = \ (w_s2oH :: S) (w1_s2oI :: Int) ->
       case w_s2oH  of w2_X2pG { MkS ipv_s2p2 ipv1_s2p3 ->
       case w1_s2oI of { GHC.Types.I# ww1_s2oL ->
       case Foo.$wg1 w2_X2pG ww1_s2oL of ww2_s2oP { __DEFAULT ->
       GHC.Types.I# ww2_s2oP }}}

What terrible code! We evaluate the S argument in the wrapper, and box and unbox it every time around the loop, even though it is never ultimately used.

Here's what happens if the arguments are banged:

data T = MkT !Int !Int
g2 :: T -> Int -> Int
g2 (MkT x y) 0 = 0
g2 (MkT x y) n = g2 (MkT y x) (n-1)

We get

$wg2 GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Prim.Int#
[Str=<L,1*U><L,1*U><S,1*U>]
Foo.$wg2 = \ (ww_s2ow :: GHC.Prim.Int#)
             (ww1_s2ox :: GHC.Prim.Int#)
             (ww2_s2oB :: GHC.Prim.Int#) ->
             case ww2_s2oB of ds_X2n0 {
               __DEFAULT -> Foo.$wg2 ww1_s2ox ww_s2ow (GHC.Prim.-# ds_X2n0 1#);
               0# -> 0# }

g2 :: T -> Int -> Int
[Str=<S(SS),1*U(1*U,1*U)><S(S),1*U(1*U)>m ]
g2 = \ (w_s2os :: T) (w1_s2ot :: Int) ->
       case w_s2os  of { MkT ww1_s2ow ww2_s2ox ->
       case w1_s2ot of { GHC.Types.I# ww4_s2oB ->
       case Foo.$wg2 ww1_s2ow ww2_s2ox ww4_s2oB of ww5_s2oF {
         __DEFAULT -> GHC.Types.I# ww5_s2oF }}}

Still terrible. We pass the two components around the loop before discarding them at the end.

Trac metadata
Trac field Value
Version 8.6.2
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
Assignee
Assign to
8.6.3
Milestone
8.6.3
Assign milestone
Time tracking
None
Due date
None
Reference: ghc/ghc#16029