@@ -28,29 +28,57 @@ struct InliningState{S <: Union{EdgeTracker, Nothing}, T, I<:AbstractInterpreter
28
28
interp:: I
29
29
end
30
30
31
- function inlining_policy (interp:: AbstractInterpreter , @nospecialize (src), stmt_flag:: UInt8 , match:: Union{MethodMatch,InferenceResult} )
31
+ include (" compiler/ssair/driver.jl" )
32
+
33
+ function inlining_policy (interp:: AbstractInterpreter , @nospecialize (src),
34
+ stmt_flag:: UInt8 , todo:: Union{Nothing,InliningTodo} )
32
35
if isa (src, CodeInfo) || isa (src, Vector{UInt8})
33
36
src_inferred = ccall (:jl_ir_flag_inferred , Bool, (Any,), src)
34
37
src_inlineable = is_stmt_inline (stmt_flag) || ccall (:jl_ir_flag_inlineable , Bool, (Any,), src)
35
38
return src_inferred && src_inlineable ? src : nothing
36
39
elseif isa (src, OptimizationState) && isdefined (src, :ir )
37
40
return (is_stmt_inline (stmt_flag) || src. src. inlineable) ? src. ir : nothing
38
- elseif src === nothing && is_stmt_inline (stmt_flag) && isa (match, MethodMatch)
39
- # when the source isn't available at this moment, try to re-infer and inline it
40
- # NOTE we can make inference try to keep the source if the call is going to be inlined,
41
- # but then inlining will depend on local state of inference and so the first entry
42
- # and the succeeding ones may generate different code; rather we always re-infer
43
- # the source to avoid the problem while it's obviously not most efficient
44
- # HACK disable inlining for the re-inference to avoid cycles by making sure the following inference never comes here again
45
- interp = NativeInterpreter (get_world_counter (interp); opt_params = OptimizationParams (; inlining = false ))
46
- src, rt = typeinf_code (interp, match. method, match. spec_types, match. sparams, true )
47
- return src
41
+ elseif src === nothing && todo != = nothing && is_stmt_inline (stmt_flag)
42
+ # if this statement is forced to be inlined, try additional effort to find the source
43
+ # in the local cache, and if found optimize and inline it
44
+ mi = todo. mi
45
+ (; match, atypes, stmttype) = todo. spec:: DelayedInliningSpec
46
+ if isa (match, MethodMatch)
47
+ cache = cache_lookup (mi, atypes, get_inference_cache (interp))
48
+ cache === nothing && return nothing
49
+ inf_result, stmt_info = cache
50
+ else
51
+ local cache = nothing
52
+ for (inf_result, stmt_info) in get_inference_cache (interp)
53
+ if inf_result === match
54
+ cache = inf_result, stmt_info
55
+ break
56
+ end
57
+ end
58
+ cache === nothing && return nothing
59
+ inf_result, stmt_info = cache
60
+ end
61
+ src = inf_result. src
62
+ if isa (src, CodeInfo)
63
+ elseif isa (src, OptimizationState)
64
+ src = src. src
65
+ else
66
+ return nothing
67
+ end
68
+ # HACK disable inlining for this optimization, otherwise we're likely to come back to here again
69
+ params = OptimizationParams (interp)
70
+ newparams = OptimizationParams (; inlining = false ,
71
+ max_methods = params. MAX_METHODS,
72
+ tuple_splat = params. MAX_TUPLE_SPLAT,
73
+ union_splitting = params. MAX_UNION_SPLITTING,
74
+ unoptimize_throw_blocks = params. unoptimize_throw_blocks)
75
+ opt = OptimizationState (mi, copy (src), newparams, interp; stmt_info)
76
+ optimize (interp, opt, newparams, stmttype)
77
+ return opt. ir
48
78
end
49
79
return nothing
50
80
end
51
81
52
- include (" compiler/ssair/driver.jl" )
53
-
54
82
mutable struct OptimizationState
55
83
linfo:: MethodInstance
56
84
src:: CodeInfo
@@ -72,7 +100,8 @@ mutable struct OptimizationState
72
100
frame. sptypes, frame. slottypes, false ,
73
101
inlining)
74
102
end
75
- function OptimizationState (linfo:: MethodInstance , src:: CodeInfo , params:: OptimizationParams , interp:: AbstractInterpreter )
103
+ function OptimizationState (linfo:: MethodInstance , src:: CodeInfo , params:: OptimizationParams , interp:: AbstractInterpreter ;
104
+ stmt_info:: Union{Nothing,Vector{Any}} = nothing )
76
105
# prepare src for running optimization passes
77
106
# if it isn't already
78
107
nssavalues = src. ssavaluetypes
@@ -86,7 +115,9 @@ mutable struct OptimizationState
86
115
if slottypes === nothing
87
116
slottypes = Any[ Any for i = 1 : nslots ]
88
117
end
89
- stmt_info = Any[nothing for i = 1 : nssavalues]
118
+ if stmt_info === nothing
119
+ stmt_info = Any[nothing for i = 1 : nssavalues]
120
+ end
90
121
# cache some useful state computations
91
122
def = linfo. def
92
123
mod = isa (def, Method) ? def. module : def
@@ -103,10 +134,11 @@ mutable struct OptimizationState
103
134
end
104
135
end
105
136
106
- function OptimizationState (linfo:: MethodInstance , params:: OptimizationParams , interp:: AbstractInterpreter )
137
+ function OptimizationState (linfo:: MethodInstance , params:: OptimizationParams , interp:: AbstractInterpreter ;
138
+ stmt_info:: Union{Nothing,Vector{Any}} = nothing )
107
139
src = retrieve_code_info (linfo)
108
140
src === nothing && return nothing
109
- return OptimizationState (linfo, src, params, interp)
141
+ return OptimizationState (linfo, src, params, interp; stmt_info )
110
142
end
111
143
112
144
function ir_to_codeinf! (opt:: OptimizationState )
0 commit comments