@@ -263,9 +263,28 @@ function SNCA!(domtree::DomTree, blocks::Vector{BasicBlock}, max_pre::PreNumber)
263
263
# we wanted to.
264
264
resize! (state, n_nodes)
265
265
for w in 1 : max_pre
266
+ # Only reset semidominators for nodes we want to recompute
266
267
state[w] = SNCAData (typemax (PreNumber), w)
267
268
end
268
269
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
+
269
288
# Calculate semidominators, but only for blocks with preorder number up to
270
289
# max_pre
271
290
ancestors = copy (D. to_parent_pre)
376
395
" Given updated blocks, update the given dominator tree with an inserted edge."
377
396
function domtree_insert_edge! (domtree:: DomTree , blocks:: Vector{BasicBlock} ,
378
397
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
+
379
403
# Implements Section 3.1 of [GI16]
380
404
dt = domtree. dfs_tree
381
405
from_pre = dt. to_pre[from]
397
421
" Given updated blocks, update the given dominator tree with a deleted edge."
398
422
function domtree_delete_edge! (domtree:: DomTree , blocks:: Vector{BasicBlock} ,
399
423
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
+
400
429
# Implements Section 3.1 of [GI16]
401
430
if is_parent (domtree. dfs_tree, from, to)
402
431
# 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)
449
478
return false
450
479
end
451
480
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
+
452
543
"""
453
544
Checks if bb1 dominates bb2.
454
545
bb1 and bb2 are indexes into the CFG blocks.
0 commit comments