Here is a description and demo of the relevant functions.
StaticVarInfo
is the state object used to track local variable and other context information
during inference and other passes.
Runs inlining in-place on an expression.
Arguments:
- expression (usually function body)
StaticVarInfo
- pointer to full AST (:lambda expression)
Fiven a specific call site, return an expression to replace it with
if inlining should be done. If we decide against inlining, returns NF
instead. Returns (expr, stmts) where expr is the replacement expression
and stmts is an array of statements that need to be inserted before it.
Arguments:
- the called function we might inline
- the expression calling the function
- a tuple type of argument types
StaticVarInfo
- the ast of the calling function
code-size based inlining heuristic
Argument:
- a candidate function body expression
Demo run:
julia> a = methods(sin,(Complex,))[end].func.code; # a LambdaStaticData
julia> sv = Core.Inference.call(Core.Inference.StaticVarInfo,a)
Core.Inference.StaticVarInfo(svec(),Core.Inference.ObjectIdDict(Any[#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef … #undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef]),Any[:z,:zr,:zi,symbol("#s54"),symbol("#s53"),symbol("#s52"),symbol("#s21"),symbol("#s20"),symbol("#s19")],Any[Core.Inference.NotFound(),Core.Inference.NotFound(),Core.Inference.NotFound()],Any[Any[:z,:Any,0],Any[:zr,:Any,18],Any[:zi,:Any,18],Any[symbol("#s54"),:Any,2],Any[symbol("#s53"),:Any,2],Any[symbol("#s52"),:Any,2],Any[symbol("#s21"),:Any,2],Any[symbol("#s20"),:Any,2],Any[symbol("#s19"),:Any,2]],15,Core.Inference.ObjectIdDict(Any[#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef … #undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef]),Base)
julia> ast = Base.uncompressed_ast(a)
:($(Expr(:lambda, Any[:z], Any[Any[Any[:z,:Any,0],Any[:zr,:Any,18],Any[:zi,:Any,18],Any[symbol("#s54"),:Any,2],Any[symbol("#s53"),:Any,2],Any[symbol("#s52"),:Any,2],Any[symbol("#s21"),:Any,2],Any[symbol("#s20"),:Any,2],Any[symbol("#s19"),:Any,2]],Any[],3,Any[]], :(begin # complex.jl, line 557:
NewvarNode(symbol("#s53"))
NewvarNode(symbol("#s52"))
NewvarNode(symbol("#s21"))
NewvarNode(symbol("#s20"))
NewvarNode(symbol("#s19"))
GenSym(0) = (Base.reim)(z)
#s54 = (top(start))(GenSym(0))
GenSym(1) = (top(indexed_next))(GenSym(0),1,#s54)
zr = (top(getfield))(GenSym(1),1)
#s54 = (top(getfield))(GenSym(1),2)
GenSym(2) = (top(indexed_next))(GenSym(0),2,#s54)
zi = (top(getfield))(GenSym(2),1)
#s54 = (top(getfield))(GenSym(2),2) # complex.jl, line 558:
unless !((Base.isfinite)(zi)) goto 0
#s53 = zr == 0
goto 1
0:
#s53 = false
1:
unless #s53 goto 2 # complex.jl, line 558:
return (Base.Complex)(zr,zi)
2: # complex.jl, line 559:
unless (Base.isnan)(zr) goto 3
#s52 = !((Base.isfinite)(zi))
goto 4
3:
#s52 = false
4:
unless #s52 goto 5 # complex.jl, line 559:
return (Base.Complex)(zr,zi)
5: # complex.jl, line 560:
unless !((Base.isfinite)(zr)) goto 6
#s21 = zi == 0
goto 7
6:
#s21 = false
7:
unless #s21 goto 8 # complex.jl, line 560:
return (Base.Complex)((Base.oftype)(zr,Base.NaN),zi)
8: # complex.jl, line 561:
unless !((Base.isfinite)(zr)) goto 9
#s20 = (Base.isfinite)(zi)
goto 10
9:
#s20 = false
10:
unless #s20 goto 11 # complex.jl, line 561:
return (Base.Complex)((Base.oftype)(zr,Base.NaN),(Base.oftype)(zi,Base.NaN))
11: # complex.jl, line 562:
unless !((Base.isfinite)(zr)) goto 12
#s19 = !((Base.isfinite)(zi))
goto 13
12:
#s19 = false
13:
unless #s19 goto 14 # complex.jl, line 562:
return (Base.Complex)(zr,(Base.oftype)(zi,Base.NaN))
14: # complex.jl, line 563:
return (Base._sin)(z)
end))))
julia> Core.Inference.inlineable(+, :(1+2), Tuple{Int,Int}, sv, ast)
(:((Base.box)(Int64,(Base.add_int)(1,2))),Any[])
julia> Core.Inference.inline_worthy(ast.args[3])
false
julia> Core.Inference.inlining_pass(ast.args[3], sv, ast)