@@ -527,53 +527,17 @@ function any_stmt_may_throw(ir::IRCode, bb::Int)
527527 return false
528528end
529529
530- mutable struct LazyAugmentedDomtrees
531- const ir:: IRCode
532- cfg:: CFG
533- domtree:: DomTree
534- postdomtree:: PostDomTree
535- LazyAugmentedDomtrees (ir:: IRCode ) = new (ir)
536- end
537-
538- function get! (lazyagdomtrees:: LazyAugmentedDomtrees , sym:: Symbol )
539- isdefined (lazyagdomtrees, sym) && return getfield (lazyagdomtrees, sym)
540- if sym === :cfg
541- return lazyagdomtrees. cfg = construct_augmented_cfg (lazyagdomtrees. ir)
542- elseif sym === :domtree
543- return lazyagdomtrees. domtree = construct_domtree (get! (lazyagdomtrees, :cfg ))
544- elseif sym === :postdomtree
545- return lazyagdomtrees. postdomtree = construct_postdomtree (get! (lazyagdomtrees, :cfg ))
546- else
547- error (" invalid field access" )
548- end
549- end
550-
551- function construct_augmented_cfg (ir:: IRCode )
552- cfg = copy (ir. cfg)
553- # Add a virtual basic block to represent the single exit
554- push! (cfg. blocks, BasicBlock (StmtRange (0 : - 1 )))
555- for bb = 1 : (length (cfg. blocks)- 1 )
556- terminator = ir[SSAValue (last (cfg. blocks[bb]. stmts))][:stmt ]
557- if terminator isa ReturnNode
558- cfg_insert_edge! (cfg, bb, length (cfg. blocks))
559- end
560- end
561- return cfg
562- end
563-
564- visit_conditional_successors (callback, ir:: IRCode , bb:: Int ) =
565- visit_conditional_successors (callback, construct_postdomtree (construct_augmented_cfg (ir)), ir, bb)
566- visit_conditional_successors (callback, lazyagdomtrees:: LazyAugmentedDomtrees , ir:: IRCode , bb:: Int ) =
567- visit_conditional_successors (callback, get! (lazyagdomtrees, :postdomtree ), ir, bb)
568- function visit_conditional_successors (callback, postdomtree:: PostDomTree , ir:: IRCode , bb:: Int )
530+ visit_conditional_successors (callback, ir:: IRCode , bb:: Int ) = # used for test
531+ visit_conditional_successors (callback, LazyPostDomtree (ir), ir, bb)
532+ function visit_conditional_successors (callback, lazypostdomtree:: LazyPostDomtree , ir:: IRCode , bb:: Int )
569533 visited = BitSet ((bb,))
570534 worklist = Int[bb]
571535 while ! isempty (worklist)
572536 thisbb = popfirst! (worklist)
573537 for succ in ir. cfg. blocks[thisbb]. succs
574538 succ in visited && continue
575539 push! (visited, succ)
576- if postdominates (postdomtree , succ, bb)
540+ if postdominates (get! (lazypostdomtree) , succ, bb)
577541 # this successor is not conditional, so no need to visit it further
578542 continue
579543 elseif callback (succ)
@@ -586,12 +550,40 @@ function visit_conditional_successors(callback, postdomtree::PostDomTree, ir::IR
586550 return false
587551end
588552
553+ struct AugmentedDomtree
554+ cfg:: CFG
555+ domtree:: DomTree
556+ end
557+
558+ mutable struct LazyAugmentedDomtree
559+ const ir:: IRCode
560+ agdomtree:: AugmentedDomtree
561+ LazyAugmentedDomtree (ir:: IRCode ) = new (ir)
562+ end
563+
564+ function get! (lazyagdomtree:: LazyAugmentedDomtree )
565+ isdefined (lazyagdomtree, :agdomtree ) && return lazyagdomtree. agdomtree
566+ ir = lazyagdomtree. ir
567+ cfg = copy (ir. cfg)
568+ # Add a virtual basic block to represent the exit
569+ push! (cfg. blocks, BasicBlock (StmtRange (0 : - 1 )))
570+ for bb = 1 : (length (cfg. blocks)- 1 )
571+ terminator = ir[SSAValue (last (cfg. blocks[bb]. stmts))][:stmt ]
572+ if isa (terminator, ReturnNode) && isdefined (terminator, :val )
573+ cfg_insert_edge! (cfg, bb, length (cfg. blocks))
574+ end
575+ end
576+ domtree = construct_domtree (cfg)
577+ return lazyagdomtree. agdomtree = AugmentedDomtree (cfg, domtree)
578+ end
579+
589580mutable struct PostOptAnalysisState
590581 const result:: InferenceResult
591582 const ir:: IRCode
592583 const inconsistent:: BitSetBoundedMinPrioritySet
593584 const tpdum:: TwoPhaseDefUseMap
594- const lazyagdomtrees:: LazyAugmentedDomtrees
585+ const lazypostdomtree:: LazyPostDomtree
586+ const lazyagdomtree:: LazyAugmentedDomtree
595587 const ea_analysis_pending:: Vector{Int}
596588 all_retpaths_consistent:: Bool
597589 all_effect_free:: Bool
@@ -602,8 +594,9 @@ mutable struct PostOptAnalysisState
602594 function PostOptAnalysisState (result:: InferenceResult , ir:: IRCode )
603595 inconsistent = BitSetBoundedMinPrioritySet (length (ir. stmts))
604596 tpdum = TwoPhaseDefUseMap (length (ir. stmts))
605- lazyagdomtrees = LazyAugmentedDomtrees (ir)
606- return new (result, ir, inconsistent, tpdum, lazyagdomtrees, Int[],
597+ lazypostdomtree = LazyPostDomtree (ir)
598+ lazyagdomtree = LazyAugmentedDomtree (ir)
599+ return new (result, ir, inconsistent, tpdum, lazypostdomtree, lazyagdomtree, Int[],
607600 true , true , nothing , true , true , false )
608601 end
609602end
@@ -843,13 +836,13 @@ function ((; sv)::ScanStmt)(inst::Instruction, lstmt::Int, bb::Int)
843836 # inconsistent region.
844837 if ! sv. result. ipo_effects. terminates
845838 sv. all_retpaths_consistent = false
846- elseif visit_conditional_successors (sv. lazyagdomtrees , sv. ir, bb) do succ:: Int
839+ elseif visit_conditional_successors (sv. lazypostdomtree , sv. ir, bb) do succ:: Int
847840 return any_stmt_may_throw (sv. ir, succ)
848841 end
849842 # check if this `GotoIfNot` leads to conditional throws, which taints consistency
850843 sv. all_retpaths_consistent = false
851844 else
852- cfg, domtree = get! (sv. lazyagdomtrees, :cfg ), get! (sv . lazyagdomtrees, :domtree )
845+ (; cfg, domtree) = get! (sv. lazyagdomtree )
853846 for succ in iterated_dominance_frontier (cfg, BlockLiveness (sv. ir. cfg. blocks[bb]. succs, nothing ), domtree)
854847 if succ == length (cfg. blocks)
855848 # Phi node in the virtual exit -> We have a conditional
0 commit comments