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,260
    • Issues 4,260
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 402
    • Merge Requests 402
  • 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
  • #9291

Closed
Open
Opened Jul 10, 2014 by schyler@trac-schyler

Don't reconstruct sum types if the type subtly changes

Consider this test case:

module Main (main) where

fun :: Either Int String -> Either String String
fun x = case x of
    Left int -> Left (show int)
    Right str -> Right str
{-# NOINLINE fun #-}

main :: IO ()
main = do
    l <- getLine
    print $ fun (Right l)

The core we get for fun looks like:

Main.fun [InlPrag=NOINLINE]
  :: Data.Either.Either GHC.Types.Int GHC.Base.String
     -> Data.Either.Either GHC.Base.String GHC.Base.String
[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType <S,1*U>]
Main.fun =
  \ (x_aur :: Data.Either.Either GHC.Types.Int GHC.Base.String) ->
    case x_aur of _ [Occ=Dead] {
      Data.Either.Left int_aus ->
        Data.Either.Left
          @ GHC.Base.String
          @ GHC.Base.String
          (GHC.Show.$fShowInt_$cshow int_aus);
      Data.Either.Right str_aCG ->
        Data.Either.Right @ GHC.Base.String @ GHC.Base.String str_aCG
    }

There would be less allocations and probably perform better if we just coerced x into the new type. Because the coercion is common code, this also means that if hypothetically some other sum type which had 15 constructors, and only 3 had subtle type changes, 12 of the case branches could be CSE'd into the single coerce greatly reducing code generated and also hinting the inliner better.

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