Skip to content

Instantly share code, notes, and snippets.

@JeffBezanson
Last active January 14, 2016 22:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JeffBezanson/3c6b029ca4a2cda8a62d to your computer and use it in GitHub Desktop.
Save JeffBezanson/3c6b029ca4a2cda8a62d to your computer and use it in GitHub Desktop.
how to invoke julia inlining passes

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.

inlining_pass

Runs inlining in-place on an expression.

Arguments:

  • expression (usually function body)
  • StaticVarInfo
  • pointer to full AST (:lambda expression)

inlineable

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

inline_worthy

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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment