Skip to content

Add `joinState# :: State# s -> State# s -> State# s` primop

The state threading in GHC.Prim requires the user to impose a total order on memory reads and writes within a state thread. In some cases, this total order constrains the compiler more than necessary. For example, if the programmer knows that addr1 and addr2 don't alias, then they might like to express that the two writes in the following can be reordered relative to each other:

doTwoWrites :: Addr# -> Addr# -> State# s -> State# s
doTwoWrites addr1 addr2 s =
  writeWord8OffAddr# addr2 0# 123## (
  writeWord8OffAddr# addr1 0# 234## s)

If we had the following primop, then we could express that flexibility in reordering:

-- | Produces a state that has a data dependency on the two input 
-- states. Generates no machine code.
joinState# :: State# s -> State# s -> State# s

That is, we'd write the above function as:

doTwoWrites :: Addr# -> Addr# -> State# s -> State# s
doTwoWrites addr1 addr2 s =
  joinState#
    (writeWord8OffAddr# addr2 0# 123## s)
    (writeWord8OffAddr# addr1 0# 234## s)

This would give us fine-grained fork/join of State# threads, with fork provided by copying of State# s objects and join provided by joinState#. This lets the programmer express arbitrary DAGs of dependencies between memory operations, rather than just linear chains of dependencies.

Low priority; I don't have a specific use case with a missed optimization.

Trac metadata
Trac field Value
Version 8.2.2
Type FeatureRequest
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information