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 |