104
104
function finish! (interp:: AbstractInterpreter , caller:: InferenceState , validation_world:: UInt , time_before:: UInt64 )
105
105
result = caller. result
106
106
# @assert last(result.valid_worlds) <= get_world_counter() || isempty(caller.edges)
107
- if caller. cache_mode === CACHE_MODE_LOCAL
108
- @assert ! isdefined (result, :ci )
109
- result. src = transform_result_for_local_cache (interp, result)
110
- elseif isdefined (result, :ci )
107
+ if isdefined (result, :ci )
111
108
edges = result_edges (interp, caller)
112
109
ci = result. ci
113
110
# if we aren't cached, we don't need this edge
@@ -118,47 +115,40 @@ function finish!(interp::AbstractInterpreter, caller::InferenceState, validation
118
115
store_backedges (ci, edges)
119
116
end
120
117
inferred_result = nothing
121
- uncompressed = result . src
118
+ uncompressed = inferred_result
122
119
const_flag = is_result_constabi_eligible (result)
123
- debuginfo = get_debuginfo (result. src)
124
120
discard_src = caller. cache_mode === CACHE_MODE_NULL || const_flag
125
121
if ! discard_src
126
122
inferred_result = transform_result_for_cache (interp, result, edges)
127
- if inferred_result != = nothing
128
- uncompressed = inferred_result
129
- debuginfo = get_debuginfo (inferred_result)
130
- # Inlining may fast-path the global cache via `VolatileInferenceResult`, so store it back here
131
- result. src = inferred_result
132
- end
133
123
# TODO : do we want to augment edges here with any :invoke targets that we got from inlining (such that we didn't have a direct edge to it already)?
134
124
if inferred_result isa CodeInfo
125
+ result. src = inferred_result
135
126
if may_compress (interp)
136
127
nslots = length (inferred_result. slotflags)
137
128
resize! (inferred_result. slottypes:: Vector{Any} , nslots)
138
129
resize! (inferred_result. slotnames, nslots)
139
130
end
131
+ di = inferred_result. debuginfo
132
+ uncompressed = inferred_result
140
133
inferred_result = maybe_compress_codeinfo (interp, result. linfo, inferred_result)
141
134
result. is_src_volatile = false
142
135
elseif ci. owner === nothing
143
136
# The global cache can only handle objects that codegen understands
144
137
inferred_result = nothing
145
138
end
146
139
end
147
- if debuginfo === nothing
148
- debuginfo = DebugInfo (result. linfo)
140
+ if ! @isdefined di
141
+ di = DebugInfo (result. linfo)
149
142
end
150
143
time_now = _time_ns ()
151
144
time_self_ns = caller. time_self_ns + (time_now - time_before)
152
145
time_total = (time_now - caller. time_start - caller. time_paused) * 1e-9
153
146
ccall (:jl_update_codeinst , Cvoid, (Any, Any, Int32, UInt, UInt, UInt32, Any, Float64, Float64, Float64, Any, Any),
154
147
ci, inferred_result, const_flag, first (result. valid_worlds), last (result. valid_worlds), encode_effects (result. ipo_effects),
155
- result. analysis_results, time_total, caller. time_caches, time_self_ns * 1e-9 , debuginfo , edges)
148
+ result. analysis_results, time_total, caller. time_caches, time_self_ns * 1e-9 , di , edges)
156
149
engine_reject (interp, ci)
157
150
codegen = codegen_cache (interp)
158
- if ! discard_src && codegen != = nothing && (isa (uncompressed, CodeInfo) || isa (uncompressed, OptimizationState))
159
- if isa (uncompressed, OptimizationState)
160
- uncompressed = ir_to_codeinf! (uncompressed, edges)
161
- end
151
+ if ! discard_src && codegen != = nothing && uncompressed isa CodeInfo
162
152
# record that the caller could use this result to generate code when required, if desired, to avoid repeating n^2 work
163
153
codegen[ci] = uncompressed
164
154
if bootstrapping_compiler && inferred_result == nothing
@@ -309,116 +299,36 @@ function adjust_cycle_frame!(sv::InferenceState, cycle_valid_worlds::WorldRange,
309
299
return nothing
310
300
end
311
301
312
- function get_debuginfo (src)
313
- isa (src, CodeInfo) && return src. debuginfo
314
- isa (src, OptimizationState) && return src. src. debuginfo
315
- return nothing
316
- end
317
-
318
302
function is_result_constabi_eligible (result:: InferenceResult )
319
303
result_type = result. result
320
304
return isa (result_type, Const) && is_foldable_nothrow (result. ipo_effects) && is_inlineable_constant (result_type. val)
321
305
end
322
306
323
- function compute_inlining_cost (interp:: AbstractInterpreter , result:: InferenceResult )
324
- src = result. src
325
- isa (src, OptimizationState) || return MAX_INLINE_COST
326
- compute_inlining_cost (interp, result, src. optresult)
327
- end
328
-
329
- function compute_inlining_cost (interp:: AbstractInterpreter , result:: InferenceResult , optresult#= ::OptimizationResult=# )
330
- return inline_cost_model (interp, result, optresult. inline_flag, optresult. ir)
331
- end
332
-
333
- function inline_cost_model (interp:: AbstractInterpreter , result:: InferenceResult ,
334
- inline_flag:: UInt8 , ir:: IRCode )
335
-
336
- inline_flag === SRC_FLAG_DECLARED_NOINLINE && return MAX_INLINE_COST
337
-
338
- mi = result. linfo
339
- (; def, specTypes) = mi
340
- if ! isa (def, Method)
341
- return MAX_INLINE_COST
342
- end
343
-
344
- declared_inline = inline_flag === SRC_FLAG_DECLARED_INLINE
345
-
346
- rt = result. result
347
- @assert ! (rt isa LimitedAccuracy)
348
- rt = widenslotwrapper (rt)
349
-
350
- sig = unwrap_unionall (specTypes)
351
- if ! (isa (sig, DataType) && sig. name === Tuple. name)
352
- return MAX_INLINE_COST
353
- end
354
- if ! declared_inline && rt === Bottom
355
- return MAX_INLINE_COST
356
- end
357
-
358
- if declared_inline && isdispatchtuple (specTypes)
359
- # obey @inline declaration if a dispatch barrier would not help
360
- return MIN_INLINE_COST
361
- else
362
- # compute the cost (size) of inlining this code
363
- params = OptimizationParams (interp)
364
- cost_threshold = default = params. inline_cost_threshold
365
- if ⊑ (optimizer_lattice (interp), rt, Tuple) && ! isconcretetype (widenconst (rt))
366
- cost_threshold += params. inline_tupleret_bonus
367
- end
368
- # if the method is declared as `@inline`, increase the cost threshold 20x
369
- if declared_inline
370
- cost_threshold += 19 * default
371
- end
372
- # a few functions get special treatment
373
- if def. module === _topmod (def. module)
374
- name = def. name
375
- if name === :iterate || name === :unsafe_convert || name === :cconvert
376
- cost_threshold += 4 * default
377
- end
378
- end
379
- return inline_cost_model (ir, params, cost_threshold)
380
- end
381
- end
382
-
383
- function transform_result_for_local_cache (interp:: AbstractInterpreter , result:: InferenceResult )
384
- if is_result_constabi_eligible (result)
385
- return nothing
386
- end
307
+ function transform_result_for_cache (:: AbstractInterpreter , result:: InferenceResult , edges:: SimpleVector )
387
308
src = result. src
388
309
if isa (src, OptimizationState)
389
- # Compute and store any information required to determine the inlineability of the callee.
390
- opt = src
391
- opt. src. inlining_cost = compute_inlining_cost (interp, result)
392
- end
393
- return src
394
- end
395
-
396
- function transform_result_for_cache (interp:: AbstractInterpreter , result:: InferenceResult , edges:: SimpleVector )
397
- inlining_cost = nothing
398
- src = result. src
399
- if isa (src, OptimizationState)
400
- opt = src
401
- inlining_cost = compute_inlining_cost (interp, result, opt. optresult)
402
- discard_optimized_result (interp, opt, inlining_cost) && return nothing
403
- src = ir_to_codeinf! (opt)
310
+ src = ir_to_codeinf! (src)
404
311
end
405
312
if isa (src, CodeInfo)
406
313
src. edges = edges
407
- src. inlining_cost = inlining_cost != = nothing ? inlining_cost : compute_inlining_cost (interp, result)
408
314
end
409
315
return src
410
316
end
411
317
412
- function discard_optimized_result (interp:: AbstractInterpreter , opt#= ::OptimizationState=# , inlining_cost#= ::InlineCostType=# )
413
- may_discard_trees (interp) || return false
414
- return inlining_cost == MAX_INLINE_COST
415
- end
416
-
417
318
function maybe_compress_codeinfo (interp:: AbstractInterpreter , mi:: MethodInstance , ci:: CodeInfo )
418
319
def = mi. def
419
320
isa (def, Method) || return ci # don't compress toplevel code
420
- may_compress (interp) && return ccall (:jl_compress_ir , String, (Any, Any), def, ci)
421
- return ci
321
+ can_discard_trees = may_discard_trees (interp)
322
+ cache_the_tree = ! can_discard_trees || is_inlineable (ci)
323
+ if cache_the_tree
324
+ if may_compress (interp)
325
+ return ccall (:jl_compress_ir , String, (Any, Any), def, ci)
326
+ else
327
+ return ci
328
+ end
329
+ else
330
+ return nothing
331
+ end
422
332
end
423
333
424
334
function cache_result! (interp:: AbstractInterpreter , result:: InferenceResult , ci:: CodeInstance )
@@ -1193,7 +1103,8 @@ function typeinf_frame(interp::AbstractInterpreter, mi::MethodInstance, run_opti
1193
1103
else
1194
1104
opt = OptimizationState (frame, interp)
1195
1105
optimize (interp, opt, frame. result)
1196
- src = ir_to_codeinf! (opt, frame, Core. svec (opt. inlining. edges... ))
1106
+ src = ir_to_codeinf! (opt)
1107
+ src. edges = Core. svec (opt. inlining. edges... )
1197
1108
end
1198
1109
result. src = frame. src = src
1199
1110
end
0 commit comments