@@ -6,56 +6,6 @@ const CC = Core.Compiler
6
6
using .. EscapeAnalysis
7
7
const EA = EscapeAnalysis
8
8
9
- # entries
10
- # -------
11
-
12
- using Base: IdSet, unwrap_unionall, rewrap_unionall
13
- using InteractiveUtils: gen_call_with_extracted_types_and_kwargs
14
-
15
- """
16
- @code_escapes [options...] f(args...)
17
-
18
- Evaluates the arguments to the function call, determines its types, and then calls
19
- [`code_escapes`](@ref) on the resulting expression.
20
- As with `@code_typed` and its family, any of `code_escapes` keyword arguments can be given
21
- as the optional arguments like `@code_escapes optimize=false myfunc(myargs...)`.
22
- """
23
- macro code_escapes (ex0... )
24
- return gen_call_with_extracted_types_and_kwargs (__module__, :code_escapes , ex0)
25
- end
26
-
27
- """
28
- code_escapes(f, argtypes=Tuple{}; [debuginfo::Symbol = :none], [optimize::Bool = true]) -> result::EscapeResult
29
-
30
- Runs the escape analysis on optimized IR of a generic function call with the given type signature.
31
-
32
- # Keyword Arguments
33
-
34
- - `optimize::Bool = true`:
35
- if `true` returns escape information of post-inlining IR (used for local optimization),
36
- otherwise returns escape information of pre-inlining IR (used for interprocedural escape information generation)
37
- - `debuginfo::Symbol = :none`:
38
- controls the amount of code metadata present in the output, possible options are `:none` or `:source`.
39
- """
40
- function code_escapes (@nospecialize (f), @nospecialize (types= Base. default_tt (f));
41
- world:: UInt = get_world_counter (),
42
- debuginfo:: Symbol = :none )
43
- tt = Base. signature_type (f, types)
44
- match = Base. _which (tt; world, raise= true )
45
- mi = Core. Compiler. specialize_method (match):: MethodInstance
46
- interp = EscapeAnalyzer (world, mi)
47
- frame = Core. Compiler. typeinf_frame (interp, mi, #= run_optimizer=# true )
48
- isdefined (interp, :result ) || error (" optimization didn't happen: maybe everything has been constant folded?" )
49
- slotnames = let src = frame. src
50
- src isa CodeInfo ? src. slotnames : nothing
51
- end
52
- return EscapeResult (interp. result. ir, interp. result. estate, interp. result. mi,
53
- slotnames, debuginfo === :source , interp)
54
- end
55
-
56
- # in order to run a whole analysis from ground zero (e.g. for benchmarking, etc.)
57
- __clear_cache! () = empty! (GLOBAL_EA_CODE_CACHE)
58
-
59
9
# AbstractInterpreter
60
10
# -------------------
61
11
@@ -99,10 +49,10 @@ mutable struct EscapeAnalyzer <: AbstractInterpreter
99
49
const opt_params:: OptimizationParams
100
50
const inf_cache:: Vector{InferenceResult}
101
51
const escape_cache:: EscapeCache
102
- const entry_mi:: MethodInstance
52
+ const entry_mi:: Union{Nothing, MethodInstance}
103
53
result:: EscapeResultForEntry
104
- function EscapeAnalyzer (world:: UInt , entry_mi :: MethodInstance ,
105
- escape_cache :: EscapeCache = GLOBAL_ESCAPE_CACHE )
54
+ function EscapeAnalyzer (world:: UInt , escape_cache :: EscapeCache ;
55
+ entry_mi :: Union{Nothing,MethodInstance} = nothing )
106
56
inf_params = InferenceParams ()
107
57
opt_params = OptimizationParams ()
108
58
inf_cache = InferenceResult[]
@@ -299,4 +249,83 @@ function print_with_info(preprint, postprint, io::IO, ir::IRCode, source::Bool)
299
249
return nothing
300
250
end
301
251
252
+ # entries
253
+ # -------
254
+
255
+ using InteractiveUtils: gen_call_with_extracted_types_and_kwargs
256
+
257
+ """
258
+ @code_escapes [options...] f(args...)
259
+
260
+ Evaluates the arguments to the function call, determines its types, and then calls
261
+ [`code_escapes`](@ref) on the resulting expression.
262
+ As with `@code_typed` and its family, any of `code_escapes` keyword arguments can be given
263
+ as the optional arguments like `@code_escapes optimize=false myfunc(myargs...)`.
264
+ """
265
+ macro code_escapes (ex0... )
266
+ return gen_call_with_extracted_types_and_kwargs (__module__, :code_escapes , ex0)
267
+ end
268
+
269
+ """
270
+ code_escapes(f, argtypes=Tuple{}; [world::UInt], [debuginfo::Symbol]) -> result::EscapeResult
271
+ code_escapes(mi::MethodInstance; [world::UInt], [interp::EscapeAnalyzer], [debuginfo::Symbol]) -> result::EscapeResult
272
+
273
+ Runs the escape analysis on optimized IR of a generic function call with the given type signature,
274
+ while caching the analysis results.
275
+
276
+ # Keyword Arguments
277
+
278
+ - `world::UInt = Base.get_world_counter()`:
279
+ controls the world age to use when looking up methods, use current world age if not specified.
280
+ - `interp::EscapeAnalyzer = EscapeAnalyzer(world)`:
281
+ specifies the escape analyzer to use, by default a new analyzer with the global cache is created.
282
+ - `debuginfo::Symbol = :none`:
283
+ controls the amount of code metadata present in the output, possible options are `:none` or `:source`.
284
+ """
285
+ function code_escapes (@nospecialize (f), @nospecialize (types= Base. default_tt (f));
286
+ world:: UInt = get_world_counter (),
287
+ debuginfo:: Symbol = :none )
288
+ tt = Base. signature_type (f, types)
289
+ match = Base. _which (tt; world, raise= true )
290
+ mi = Core. Compiler. specialize_method (match)
291
+ return code_escapes (mi; world, debuginfo)
292
+ end
293
+
294
+ function code_escapes (mi:: MethodInstance ;
295
+ world:: UInt = get_world_counter (),
296
+ interp:: EscapeAnalyzer = EscapeAnalyzer (world, GLOBAL_ESCAPE_CACHE; entry_mi= mi),
297
+ debuginfo:: Symbol = :none )
298
+ frame = Core. Compiler. typeinf_frame (interp, mi, #= run_optimizer=# true )
299
+ isdefined (interp, :result ) || error (" optimization didn't happen: maybe everything has been constant folded?" )
300
+ slotnames = let src = frame. src
301
+ src isa CodeInfo ? src. slotnames : nothing
302
+ end
303
+ return EscapeResult (interp. result. ir, interp. result. estate, interp. result. mi,
304
+ slotnames, debuginfo === :source , interp)
305
+ end
306
+
307
+ """
308
+ code_escapes(ir::IRCode, nargs::Int; [world::UInt], [interp::AbstractInterpreter]) -> result::EscapeResult
309
+
310
+ Runs the escape analysis on `ir::IRCode`.
311
+ `ir` is supposed to be optimized already, specifically after inlining has been applied.
312
+ Note that this version does not cache the analysis results.
313
+
314
+ # Keyword Arguments
315
+
316
+ - `world::UInt = Base.get_world_counter()`:
317
+ controls the world age to use when looking up methods, use current world age if not specified.
318
+ - `interp::AbstractInterpreter = EscapeAnalyzer(world, EscapeCache())`:
319
+ specifies the abstract interpreter to use, by default a new `EscapeAnalyzer` with an empty cache is created.
320
+ """
321
+ function code_escapes (ir:: IRCode , nargs:: Int ;
322
+ world:: UInt = get_world_counter (),
323
+ interp:: AbstractInterpreter = EscapeAnalyzer (world, EscapeCache ()))
324
+ estate = analyze_escapes (ir, nargs, CC. optimizer_lattice (interp), CC. get_escape_cache (interp))
325
+ return EscapeResult (ir, estate) # return back the result
326
+ end
327
+
328
+ # in order to run a whole analysis from ground zero (e.g. for benchmarking, etc.)
329
+ __clear_cache! () = empty! (GLOBAL_EA_CODE_CACHE)
330
+
302
331
end # module EAUtils
0 commit comments