Make bindings with multiple occurrences a join point instead of duplicating code during inlining.
I have some intermediate core of the form:
-- RHS size: {terms: 9, types: 2, coercions: 0, joins: 0/0}
cseAlts_s1dD [Occ=Once!T[1]] :: T -> Int#
[LclId, CallArity=1, Str=<S,1*U>]
cseAlts_s1dD
= \ (lamVar_s1dw [Occ=Once!, Dmd=<S,1*U>, OS=OneShot] :: T) ->
case lamVar_s1dw of wild_Xc [Dmd=<L,A>] {
__DEFAULT -> 1#;
B -> 2#;
C -> 3#
}
-- RHS size: {terms: 14, types: 3, coercions: 0, joins: 0/0}
$wfmerge_s1cZ [InlPrag=NOUSERINLINE[0]] :: T -> T -> Int#
[LclId, Arity=2, CallArity=2, Str=<S,1*U><L,1*U>]
$wfmerge_s1cZ
= \ (w_s1cU [Occ=Once!, Dmd=<S,1*U>] :: T)
(w_s1cV [Occ=Once*, Dmd=<L,1*U>] :: T) ->
case w_s1cU of wild_XA [Dmd=<L,A>] {
__DEFAULT -> -1#;
A -> 2#;
B -> cseAlts_s1dD w_s1cV;
C -> cseAlts_s1dD w_s1cV
}
Which after the simplifier ran got inlined into the branches to give us:
fmerge
= \ (w_s1cU :: T) (w_s1cV :: T) ->
case w_s1cU of {
__DEFAULT -> GHC.Types.I# -1#;
A -> GHC.Types.I# 2#;
B ->
case w_s1cV of {
__DEFAULT -> GHC.Types.I# 1#;
B -> GHC.Types.I# 2#;
C -> GHC.Types.I# 3#
};
C ->
case w_s1cV of {
__DEFAULT -> GHC.Types.I# 1#;
B -> GHC.Types.I# 2#;
C -> GHC.Types.I# 3#
}
}
What I would really like GHC to do instead though is to make cseAlts_s1dD
a join point when possible.
This would eliminate both the call overhead AND the call duplication.
The current behavior seems fine when we can't make it a join point. But when we can we should try to take advantage of that opportunity.
Trac metadata
Trac field | Value |
---|---|
Version | 8.4.3 |
Type | Task |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |