Line | Exclusive | Inclusive | Code |
---|---|---|---|
1 | # This file is a part of Julia. License is MIT: https://julialang.org/license | ||
2 | |||
3 | using Core: LineInfoNode | ||
4 | const NullLineInfo = LineInfoNode(@__MODULE__, Symbol(""), Symbol(""), 0, 0) | ||
5 | |||
6 | if false | ||
7 | import Base: Base, @show | ||
8 | else | ||
9 | macro show(s) | ||
10 | return :(println(stdout, $(QuoteNode(s)), " = ", $(esc(s)))) | ||
11 | end | ||
12 | end | ||
13 | |||
14 | include("compiler/ssair/ir.jl") | ||
15 | include("compiler/ssair/domtree.jl") | ||
16 | include("compiler/ssair/slot2ssa.jl") | ||
17 | include("compiler/ssair/queries.jl") | ||
18 | include("compiler/ssair/passes.jl") | ||
19 | include("compiler/ssair/inlining.jl") | ||
20 | include("compiler/ssair/verify.jl") | ||
21 | include("compiler/ssair/legacy.jl") | ||
22 | #@isdefined(Base) && include("compiler/ssair/show.jl") | ||
23 | |||
24 | function normalize_expr(stmt::Expr) | ||
25 | if stmt.head === :gotoifnot | ||
26 | return GotoIfNot(stmt.args[1], stmt.args[2]::Int) | ||
27 | elseif stmt.head === :return | ||
28 | return (length(stmt.args) == 0) ? ReturnNode(nothing) : ReturnNode(stmt.args[1]) | ||
29 | elseif stmt.head === :unreachable | ||
30 | return ReturnNode() | ||
31 | else | ||
32 | return stmt | ||
33 | end | ||
34 | end | ||
35 | |||
36 | function normalize(@nospecialize(stmt), meta::Vector{Any}) | ||
37 | if isa(stmt, Expr) | ||
38 | if stmt.head == :meta | ||
39 | args = stmt.args | ||
40 | if length(args) > 0 | ||
41 | push!(meta, stmt) | ||
42 | end | ||
43 | return nothing | ||
44 | elseif stmt.head === :line | ||
45 | return nothing # deprecated - we shouldn't encounter this | ||
46 | else | ||
47 | return normalize_expr(stmt) | ||
48 | end | ||
49 | end | ||
50 | return stmt | ||
51 | end | ||
52 | |||
53 | function just_construct_ssa(ci::CodeInfo, code::Vector{Any}, nargs::Int, sv::OptimizationState) | ||
54 | # Go through and add an unreachable node after every | ||
55 | # Union{} call. Then reindex labels. | ||
56 | idx = 1 | ||
57 | oldidx = 1 | ||
58 | changemap = fill(0, length(code)) | ||
59 | while idx <= length(code) | ||
60 | if code[idx] isa Expr && ci.ssavaluetypes[idx] === Union{} | ||
61 | if !(idx < length(code) && isexpr(code[idx+1], :unreachable)) | ||
62 | insert!(code, idx + 1, ReturnNode()) | ||
63 | insert!(ci.codelocs, idx + 1, ci.codelocs[idx]) | ||
64 | insert!(ci.ssavaluetypes, idx + 1, Union{}) | ||
65 | if oldidx < length(changemap) | ||
66 | changemap[oldidx + 1] = 1 | ||
67 | end | ||
68 | idx += 1 | ||
69 | end | ||
70 | end | ||
71 | idx += 1 | ||
72 | oldidx += 1 | ||
73 | end | ||
74 | renumber_ir_elements!(code, changemap) | ||
75 | |||
76 | inbounds_depth = 0 # Number of stacked inbounds | ||
77 | meta = Any[] | ||
78 | flags = fill(0x00, length(code)) | ||
79 | for i = 1:length(code) | ||
80 | stmt = code[i] | ||
81 | if isexpr(stmt, :inbounds) | ||
82 | arg1 = stmt.args[1] | ||
83 | if arg1 === true # push | ||
84 | inbounds_depth += 1 | ||
85 | elseif arg1 === false # clear | ||
86 | inbounds_depth = 0 | ||
87 | elseif inbounds_depth > 0 # pop | ||
88 | inbounds_depth -= 1 | ||
89 | end | ||
90 | stmt = nothing | ||
91 | else | ||
92 | stmt = normalize(stmt, meta) | ||
93 | end | ||
94 | code[i] = stmt | ||
95 | if !(stmt === nothing) | ||
96 | if inbounds_depth > 0 | ||
97 | flags[i] |= IR_FLAG_INBOUNDS | ||
98 | end | ||
99 | end | ||
100 | end | ||
101 | strip_trailing_junk!(ci, code, flags) | ||
102 | cfg = compute_basic_blocks(code) | ||
103 | defuse_insts = scan_slot_def_use(nargs, ci, code) | ||
104 | @timeit "domtree 1" domtree = construct_domtree(cfg) | ||
105 | ir = let code = Any[nothing for _ = 1:length(code)] | ||
106 | argtypes = sv.slottypes[1:(nargs+1)] | ||
107 | IRCode(code, Any[], ci.codelocs, flags, cfg, collect(LineInfoNode, ci.linetable), argtypes, meta, sv.sp) | ||
108 | end | ||
109 | @timeit "construct_ssa" ir = construct_ssa!(ci, code, ir, domtree, defuse_insts, nargs, sv.sp, sv.slottypes) | ||
110 | return ir | ||
111 | end | ||
112 | |||
113 |
1 (2.70%) samples spent in run_passes
function run_passes(ci::CodeInfo, nargs::Int, sv::OptimizationState)
0 (ex.), 1 (100.00%) (incl.) when called from optimize line 166 |
||
114 | ir = just_construct_ssa(ci, copy_exprargs(ci.code), nargs, sv) | ||
115 | #@Base.show ("after_construct", ir) | ||
116 | # TODO: Domsorting can produce an updated domtree - no need to recompute here | ||
117 | @timeit "compact 1" ir = compact!(ir) | ||
118 | @timeit "Inlining" ir = ssa_inlining_pass!(ir, ir.linetable, sv) | ||
119 | #@timeit "verify 2" verify_ir(ir) | ||
120 | @timeit "domtree 2" domtree = construct_domtree(ir.cfg) | ||
121 | 1 (2.70%) |
1 (100.00%)
samples spent calling
compact!
ir = compact!(ir)
|
|
122 | #@Base.show ("before_sroa", ir) | ||
123 | @timeit "SROA" ir = getfield_elim_pass!(ir, domtree) | ||
124 | #@Base.show ir.new_nodes | ||
125 | #@Base.show ("after_sroa", ir) | ||
126 | ir = adce_pass!(ir) | ||
127 | #@Base.show ("after_adce", ir) | ||
128 | @timeit "type lift" ir = type_lift_pass!(ir) | ||
129 | @timeit "compact 3" ir = compact!(ir) | ||
130 | #@Base.show ir | ||
131 | if JLOptions().debug_level == 2 | ||
132 | @timeit "verify 3" (verify_ir(ir); verify_linetable(ir.linetable)) | ||
133 | end | ||
134 | return ir | ||
135 | end |