Skip to content

Commit 12df875

Browse files
yhlsvchuravy
authored andcommitted
Fix bug in dynamic domtree implementation
1 parent 4ef7a4e commit 12df875

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

base/compiler/ssair/domtree.jl

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,28 @@ function SNCA!(domtree::DomTree, blocks::Vector{BasicBlock}, max_pre::PreNumber)
263263
# we wanted to.
264264
resize!(state, n_nodes)
265265
for w in 1:max_pre
266+
# Only reset semidominators for nodes we want to recompute
266267
state[w] = SNCAData(typemax(PreNumber), w)
267268
end
268269

270+
# If we are only recomputing some of the semidominators, the remaining
271+
# labels should be reset, because they may have become inapplicable to the
272+
# node/semidominator we are currently processing/recomputing. They can
273+
# become inapplicable because of path compressions that were triggered by
274+
# nodes that should only be processed after the current one (but were
275+
# processed the last time `SNCA!` was run).
276+
#
277+
# So, for every node that is not being reprocessed, we reset its label to
278+
# its semidominator, which is the value that its label assumes once its
279+
# semidominator is computed. If this was too conservative, i.e. if the
280+
# label would have been updated before we process the current node in a
281+
# situation where all semidominators were recomputed, then path compression
282+
# will produce the correct label.
283+
for w in max_pre+1:n_nodes
284+
semi = state[w].semi
285+
state[w] = SNCAData(semi, semi)
286+
end
287+
269288
# Calculate semidominators, but only for blocks with preorder number up to
270289
# max_pre
271290
ancestors = copy(D.to_parent_pre)
@@ -376,6 +395,11 @@ end
376395
"Given updated blocks, update the given dominator tree with an inserted edge."
377396
function domtree_insert_edge!(domtree::DomTree, blocks::Vector{BasicBlock},
378397
from::BBNumber, to::BBNumber)
398+
# `from` is unreachable, so `from` and `to` aren't in domtree
399+
if bb_unreachable(domtree, from)
400+
return domtree
401+
end
402+
379403
# Implements Section 3.1 of [GI16]
380404
dt = domtree.dfs_tree
381405
from_pre = dt.to_pre[from]
@@ -397,6 +421,11 @@ end
397421
"Given updated blocks, update the given dominator tree with a deleted edge."
398422
function domtree_delete_edge!(domtree::DomTree, blocks::Vector{BasicBlock},
399423
from::BBNumber, to::BBNumber)
424+
# `from` is unreachable, so `from` and `to` aren't in domtree
425+
if bb_unreachable(domtree, from)
426+
return domtree
427+
end
428+
400429
# Implements Section 3.1 of [GI16]
401430
if is_parent(domtree.dfs_tree, from, to)
402431
# The `from` block is the parent of the `to` block in the DFS tree, so
@@ -449,6 +478,68 @@ function on_semidominator_path(domtree::DomTree, x::BBNumber, y::BBNumber)
449478
return false
450479
end
451480

481+
"""
482+
Rename basic block numbers in a dominator tree, removing the block if it is
483+
renamed to -1.
484+
"""
485+
function rename_nodes!(domtree::DomTree, rename_bb::Vector{BBNumber})
486+
# Rename DFS tree
487+
rename_nodes!(domtree.dfs_tree, rename_bb)
488+
489+
# `snca_state` is indexed by preorder number, so should be unchanged
490+
491+
# Rename `idoms_bb` and `nodes`
492+
old_idoms_bb = copy(domtree.idoms_bb)
493+
old_nodes = copy(domtree.nodes)
494+
for (old_bb, new_bb) in enumerate(rename_bb)
495+
if new_bb != -1
496+
domtree.idoms_bb[new_bb] = (new_bb == 1) ?
497+
0 : rename_bb[old_idoms_bb[old_bb]]
498+
domtree.nodes[new_bb] = old_nodes[old_bb]
499+
map!(i -> rename_bb[i],
500+
domtree.nodes[new_bb].children,
501+
domtree.nodes[new_bb].children)
502+
end
503+
end
504+
505+
# length of `to_pre` after renaming DFS tree is new number of basic blocks
506+
resize!(domtree.idoms_bb, length(domtree.dfs_tree.to_pre))
507+
resize!(domtree.nodes, length(domtree.dfs_tree.to_pre))
508+
return domtree
509+
end
510+
511+
"""
512+
Rename basic block numbers in a DFS tree, removing the block if it is renamed
513+
to -1.
514+
"""
515+
function rename_nodes!(D::DFSTree, rename_bb::Vector{BBNumber})
516+
n_blocks = length(D.to_pre)
517+
n_reachable_blocks = length(D.from_pre)
518+
519+
old_to_pre = copy(D.to_pre)
520+
old_from_pre = copy(D.from_pre)
521+
old_to_post = copy(D.to_post)
522+
old_from_post = copy(D.from_post)
523+
max_new_bb = 0
524+
for (old_bb, new_bb) in enumerate(rename_bb)
525+
if new_bb != -1
526+
D.to_pre[new_bb] = old_to_pre[old_bb]
527+
D.from_pre[old_to_pre[old_bb]] = new_bb
528+
D.to_post[new_bb] = old_to_post[old_bb]
529+
D.from_post[old_to_post[old_bb]] = new_bb
530+
531+
# Keep track of highest BB number to resize arrays with
532+
if new_bb > max_new_bb
533+
max_new_bb = new_bb
534+
end
535+
end
536+
end
537+
resize!(D.to_pre, max_new_bb)
538+
resize!(D.to_post, max_new_bb)
539+
# `to_parent_pre` should be unchanged
540+
return D
541+
end
542+
452543
"""
453544
Checks if bb1 dominates bb2.
454545
bb1 and bb2 are indexes into the CFG blocks.

0 commit comments

Comments
 (0)