@@ -49,28 +49,45 @@ function normalize(@nospecialize(stmt), meta::Vector{Any})
4949 return stmt
5050end
5151
52- function just_construct_ssa (ci:: CodeInfo , code:: Vector{Any} , nargs:: Int , sv:: OptimizationState )
52+ function convert_to_ircode (ci:: CodeInfo , code:: Vector{Any} , coverage :: Bool , nargs:: Int , sv:: OptimizationState )
5353 # Go through and add an unreachable node after every
5454 # Union{} call. Then reindex labels.
5555 idx = 1
5656 oldidx = 1
5757 changemap = fill (0 , length (code))
58+ labelmap = coverage ? fill (0 , length (code)) : changemap
59+ prevloc = zero (eltype (ci. codelocs))
5860 while idx <= length (code)
61+ codeloc = ci. codelocs[idx]
62+ if coverage && codeloc != prevloc && codeloc != 0
63+ # insert a side-effect instruction before the current instruction in the same basic block
64+ insert! (code, idx, Expr (:code_coverage_marker ))
65+ insert! (ci. codelocs, idx, codeloc)
66+ insert! (ci. ssavaluetypes, idx, Nothing)
67+ changemap[oldidx] += 1
68+ if oldidx < length (labelmap)
69+ labelmap[oldidx + 1 ] += 1
70+ end
71+ idx += 1
72+ prevloc = codeloc
73+ end
5974 if code[idx] isa Expr && ci. ssavaluetypes[idx] === Union{}
60- if ! (idx < length (code) && isexpr (code[idx+ 1 ], :unreachable ))
75+ if ! (idx < length (code) && isexpr (code[idx + 1 ], :unreachable ))
76+ # insert unreachable in the same basic block after the current instruction (splitting it)
6177 insert! (code, idx + 1 , ReturnNode ())
6278 insert! (ci. codelocs, idx + 1 , ci. codelocs[idx])
6379 insert! (ci. ssavaluetypes, idx + 1 , Union{})
6480 if oldidx < length (changemap)
65- changemap[oldidx + 1 ] = 1
81+ changemap[oldidx + 1 ] += 1
82+ coverage && (labelmap[oldidx + 1 ] += 1 )
6683 end
6784 idx += 1
6885 end
6986 end
7087 idx += 1
7188 oldidx += 1
7289 end
73- renumber_ir_elements! (code, changemap)
90+ renumber_ir_elements! (code, changemap, labelmap )
7491
7592 inbounds_depth = 0 # Number of stacked inbounds
7693 meta = Any[]
@@ -99,17 +116,22 @@ function just_construct_ssa(ci::CodeInfo, code::Vector{Any}, nargs::Int, sv::Opt
99116 end
100117 strip_trailing_junk! (ci, code, flags)
101118 cfg = compute_basic_blocks (code)
102- defuse_insts = scan_slot_def_use (nargs, ci, code)
103- @timeit " domtree 1" domtree = construct_domtree (cfg)
104- ir = let code = Any[nothing for _ = 1 : length (code)]
105- IRCode (code, Any[], ci. codelocs, flags, cfg, collect (LineInfoNode, ci. linetable), sv. slottypes, meta, sv. sptypes)
106- end
107- @timeit " construct_ssa" ir = construct_ssa! (ci, code, ir, domtree, defuse_insts, nargs, sv. sptypes, sv. slottypes)
119+ ir = IRCode (code, Any[], ci. codelocs, flags, cfg, collect (LineInfoNode, ci. linetable), sv. slottypes, meta, sv. sptypes)
120+ return ir
121+ end
122+
123+ function slot2reg (ir:: IRCode , ci:: CodeInfo , nargs:: Int , sv:: OptimizationState )
124+ # need `ci` for the slot metadata, IR for the code
125+ @timeit " domtree 1" domtree = construct_domtree (ir. cfg)
126+ defuse_insts = scan_slot_def_use (nargs, ci, ir. stmts)
127+ @timeit " construct_ssa" ir = construct_ssa! (ci, ir, domtree, defuse_insts, nargs, sv. sptypes, sv. slottypes) # consumes `ir`
108128 return ir
109129end
110130
111131function run_passes (ci:: CodeInfo , nargs:: Int , sv:: OptimizationState )
112- ir = just_construct_ssa (ci, copy_exprargs (ci. code), nargs, sv)
132+ preserve_coverage = coverage_enabled (sv. mod)
133+ ir = convert_to_ircode (ci, copy_exprargs (ci. code), preserve_coverage, nargs, sv)
134+ ir = slot2reg (ir, ci, nargs, sv)
113135 # @Base.show ("after_construct", ir)
114136 # TODO : Domsorting can produce an updated domtree - no need to recompute here
115137 @timeit " compact 1" ir = compact! (ir)
0 commit comments