Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,868
    • Issues 4,868
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 456
    • Merge requests 456
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #21257
Closed
Open
Created Mar 18, 2022 by Sebastian Graf@sgraf812Developer

DmdAnal: `dmdAnalStar` could yield better usage for trivial args and bindings

Consider

f :: (Bool, Bool) -> (Bool, Bool)
f pr = (pr `seq` True, case pr of (a,b) -> a && b)
{-# NOINLINE f #-}
-- idDmdSig f = LP(1L,1L)

g :: (Bool, Bool) -> ()
g pr = f pr `seq` ()
-- idDmdSig g = L

g simply calls f, yet g puts a worse demand on pr than f; it loses the information that pr's components are only evaluated once.

That is due to dmdAnalStar e (n :* sd), which is used when analysing the argument pr in the call f pr in demand LP(1L,1L). That will

  1. Call dmdAnal "pr" "P(1L,1L)", as if pr was evaluated exactly once in sub-demand P(1L,1L). We get back [pr |-> 1P(1L,1L)] (which of course is too optimistic).
  2. Then it worsens the resulting demand type to account for n=L, by multiplying it with L via multDmdType. That ultimately calls multDmd "L" on the demand of x: multDmd L 1P(1L,1L) === LP(LL,LL) === L.

It's alright to turn the outer 1P(..) into LP(..), but we don't actually need to worsen the inner P(1L,1L), because it is the exact demand that is put on the argument already.

NB: This ticket is specifically concerned with upper bounds. The multDmd "L" situation (with a used more than once upper boudn) only occurs when an arg pr is trivial (or if the RHS of a bindings is trivial). Otherwise, dmdTransformThunkDmd anticipates the memoisation of complex expressions and call oneifyDmd instead. So if we had a call like f (x, True) instead, then we'd get dmdAnalStar "(x, True)" "1P(1L,1L)", e.g., with the oneified demand 1P(..) and all will be well, as we ultimately get a demand of 1L on x.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking