| ... |
... |
@@ -58,10 +58,44 @@ import qualified Data.List.NonEmpty as NE |
|
58
|
58
|
-- hashes, and at most once otherwise. Previously, we were slower, and people
|
|
59
|
59
|
-- rightfully complained: #10397
|
|
60
|
60
|
|
|
|
61
|
+{- Note [Resolving the CBE substitution]
|
|
|
62
|
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
63
|
+The substitution built by `iterate` can contain chains: the winner of a
|
|
|
64
|
+merge may itself lose a later merge, giving k1 :-> k2 and k2 :-> k3.
|
|
|
65
|
+`lookupBid` resolves such chains transitively, but `replaceLabels`
|
|
|
66
|
+looks up each label only once. So before rewriting the graph we
|
|
|
67
|
+resolve the substitution, mapping every eliminated label directly to
|
|
|
68
|
+its final representative.
|
|
|
69
|
+
|
|
|
70
|
+This matters because the losing blocks of the merges stay in the block
|
|
|
71
|
+map, unreachable (removing them here would take an extra reachability
|
|
|
72
|
+pass). With an unresolved
|
|
|
73
|
+substitution, an edge in a losing block could be rewritten to k2 --
|
|
|
74
|
+itself an eliminated label with no live twin. In #27368 such a stranded
|
|
|
75
|
+label was a call continuation: callProcPoints folds over the whole
|
|
|
76
|
+block map, so the label became a proc point, attachContInfoTables gave
|
|
|
77
|
+it an info table, but stack layout (which walks reachable blocks only)
|
|
|
78
|
+produced no stack map for it, and setInfoTableStackMap panicked.
|
|
|
79
|
+
|
|
|
80
|
+With the substitution resolved, every edge -- including those in the
|
|
|
81
|
+unreachable losing copies -- points at a surviving block, and every
|
|
|
82
|
+surviving block is reachable: the input graph contains no unreachable
|
|
|
83
|
+blocks (the control-flow optimiser runs first and drops them), and
|
|
|
84
|
+merging only diverts paths from losers to their body-equal winners.
|
|
|
85
|
+In particular the continuation of a call in a losing copy is also the
|
|
|
86
|
+continuation of its reachable winner, so stack layout has a stack map
|
|
|
87
|
+for it.
|
|
|
88
|
+
|
|
|
89
|
+Resolving also improves copyTicks: each loser's ticks are copied into
|
|
|
90
|
+its final representative instead of into a dead intermediate block.
|
|
|
91
|
+-}
|
|
|
92
|
+
|
|
61
|
93
|
-- TODO: Use optimization fuel
|
|
62
|
94
|
elimCommonBlocks :: CmmGraph -> CmmGraph
|
|
63
|
|
-elimCommonBlocks g = replaceLabels env $ copyTicks env g
|
|
|
95
|
+elimCommonBlocks g = replaceLabels env' $ copyTicks env' g
|
|
64
|
96
|
where
|
|
|
97
|
+ -- See Note [Resolving the CBE substitution]
|
|
|
98
|
+ env' = mapMap (lookupBid env) env
|
|
65
|
99
|
env = iterate mapEmpty blocks_with_key
|
|
66
|
100
|
-- The order of blocks doesn't matter here. While we could use
|
|
67
|
101
|
-- revPostorder which drops unreachable blocks this is done in
|