Skip to content

Instantly share code, notes, and snippets.

@oxinabox
Created April 20, 2019 21:27
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 oxinabox/77ebc945e4135a5438b51f7334a99153 to your computer and use it in GitHub Desktop.
Save oxinabox/77ebc945e4135a5438b51f7334a99153 to your computer and use it in GitHub Desktop.
Cassette and I, killing the optimizer
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 127,
"metadata": {},
"outputs": [
{
"ename": "LoadError",
"evalue": "syntax: unexpected \"]\"",
"output_type": "error",
"traceback": [
"syntax: unexpected \"]\"",
""
]
}
],
"source": [
"] activate .."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"using Cassette\n",
"using BenchmarkTools"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"demo (generic function with 2 methods)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function demo(x)\n",
" local never_assigned\n",
" xx = 2*x\n",
" if x > 5\n",
" y = 2\n",
" xx += y\n",
" end\n",
" return xx\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Cassette.Context{nametype(Ctx),M,T,P,B,H} where H<:Union{DisableHooks, Nothing} where B<:Union{Nothing, IdDict{Module,Dict{Symbol,BindingMeta}}} where P<:Cassette.AbstractPass where T<:Union{Nothing, Tag} where M"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Cassette.@context Ctx"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"print_vars (generic function with 1 method)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function print_vars(names, values)\n",
" for (name,val) in zip(names, values)\n",
" println(name, \" = \", val)\n",
" end\n",
" println(\"-\"^32)\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 129,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"storevars_transform (generic function with 1 method)"
]
},
"execution_count": 129,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function enter_debug_statements(slotnames, i)\n",
" statements = [\n",
" # Declare Vector to hold the names\n",
" Expr(:call, Expr(:nooverdub, GlobalRef(Base, :getindex)), GlobalRef(Core, :Symbol)), # stmt i, SSA %i\n",
" # Declare Vector to hold the values\n",
" Expr(:call, Expr(:nooverdub, GlobalRef(Base, :getindex)), GlobalRef(Core, :Any)), # stmt i+1, SSA %i+1\n",
" ]\n",
"\n",
" names_ssa = Core.SSAValue(i)\n",
" values_ssa = Core.SSAValue(i+1)\n",
" cur_ind = i + 2\n",
" # Now we store all of the slots that have values assigned to them\n",
" for (slotind, slotname) in enumerate(slotnames)\n",
" slot = Core.SlotNumber(slotind)\n",
" append!(statements, (\n",
" Expr(:isdefined, slot), # cur_ind\n",
" Expr(:gotoifnot, Core.SSAValue(cur_ind), cur_ind + 4), # cur_ind + 1\n",
" Expr(:call, Expr(:nooverdub, GlobalRef(Base, :push!)), names_ssa, QuoteNode(slotname)), # cur_ind + 2\n",
" Expr(:call, Expr(:nooverdub, GlobalRef(Base, :push!)), values_ssa, slot) # cur_ind + 3 \n",
" ))\n",
"\n",
" cur_ind += 4\n",
" end\n",
"\n",
" push!(statements, Expr(:call, Expr(:nooverdub, GlobalRef(Main, :print_vars)), names_ssa, values_ssa))\n",
" return statements\n",
"end\n",
"\n",
"function storevars_transform(::Type{<:Ctx}, reflection::Cassette.Reflection)\n",
" ir = reflection.code_info\n",
" n_statments = length(enter_debug_statements(ir.slotnames, 0)) + 1\n",
"\n",
" Cassette.insert_statements!(\n",
" ir.code, ir.codelocs,\n",
" (stmt, i) -> n_statments,\n",
" (stmt, i) -> [enter_debug_statements(ir.slotnames, i); stmt]\n",
" )\n",
" return ir\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 180,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"succeed_demo (generic function with 1 method)"
]
},
"execution_count": 180,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function fail_demo()\n",
" if true\n",
" z=true \n",
" end\n",
" 1\n",
"end\n",
"\n",
"function succeed_demo()\n",
" z=false\n",
" if true\n",
" z=true \n",
" end\n",
" 1\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 181,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"#self# = succeed_demo\n",
"--------------------------------\n",
"#self# = succeed_demo\n",
"z = false\n",
"--------------------------------\n",
"#self# = succeed_demo\n",
"z = false\n",
"--------------------------------\n",
"#self# = succeed_demo\n",
"z = true\n",
"--------------------------------\n"
]
},
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 181,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ctx = Ctx(pass=(Cassette.@pass storevars_transform));\n",
"Cassette.recurse(ctx, succeed_demo)"
]
},
{
"cell_type": "code",
"execution_count": 182,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"#self# = fail_demo\n",
"--------------------------------\n",
"#self# = fail_demo\n",
"--------------------------------\n",
"#self# = fail_demo\n",
"--------------------------------\n",
"#self# = fail_demo\n",
"z = true\n",
"--------------------------------\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Internal error: encountered unexpected error in runtime:\n",
"BoundsError(a=Array{Any, (44,)}[SSAValue(1), SSAValue(2), SSAValue(3), SSAValue(4), SSAValue(18446744073709551615), SSAValue(6), SSAValue(7), SSAValue(8), SSAValue(18446744073709551615), SSAValue(10), SSAValue(11), SSAValue(12), SSAValue(13), SSAValue(14), SSAValue(18446744073709551615), SSAValue(16), SSAValue(17), SSAValue(18), SSAValue(18446744073709551615), SSAValue(20), SSAValue(18446744073709551615), SSAValue(22), SSAValue(23), SSAValue(24), SSAValue(18446744073709551615), SSAValue(26), SSAValue(27), SSAValue(28), SSAValue(18446744073709551615), SSAValue(30), SSAValue(31), SSAValue(32), SSAValue(33), SSAValue(34), SSAValue(18446744073709551615), SSAValue(36), SSAValue(37), SSAValue(38), SSAValue(18446744073709551615), SSAValue(40), SSAValue(41), SSAValue(42), SSAValue(43), SSAValue(18446744073709551615)], i=(-1,))\n",
"rec_backtrace at /Users/osx/buildbot/slave/package_osx64/build/src/stackwalk.c:94\n",
"record_backtrace at /Users/osx/buildbot/slave/package_osx64/build/src/task.c:217 [inlined]\n",
"jl_throw at /Users/osx/buildbot/slave/package_osx64/build/src/task.c:417\n",
"jl_bounds_error_ints at /Users/osx/buildbot/slave/package_osx64/build/src/rtutils.c:183\n",
"getindex at ./array.jl:729 [inlined]\n",
"renumber_ssa at ./compiler/ssair/slot2ssa.jl:65 [inlined]\n",
"#241 at ./compiler/ssair/slot2ssa.jl:74 [inlined]\n",
"ssamap at ./compiler/ssair/ir.jl:429\n",
"renumber_ssa! at ./compiler/ssair/slot2ssa.jl:74 [inlined]\n",
"renumber_ssa! at ./compiler/ssair/slot2ssa.jl:73\n",
"construct_ssa! at ./compiler/ssair/slot2ssa.jl:859\n",
"just_construct_ssa at ./compiler/ssair/driver.jl:109\n",
"run_passes at ./compiler/ssair/driver.jl:114\n",
"optimize at ./compiler/optimize.jl:164\n",
"typeinf at ./compiler/typeinfer.jl:35\n",
"typeinf_ext at ./compiler/typeinfer.jl:576\n",
"typeinf_ext at ./compiler/typeinfer.jl:613\n",
"jfptr_typeinf_ext_1.clone_1 at /Applications/Julia-1.1.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)\n",
"jl_apply_generic at /Users/osx/buildbot/slave/package_osx64/build/src/gf.c:2219 [inlined]\n",
"jl_apply at /Users/osx/buildbot/slave/package_osx64/build/src/./julia.h:1571 [inlined]\n",
"jl_type_infer at /Users/osx/buildbot/slave/package_osx64/build/src/gf.c:277\n",
"jl_compile_method_internal at /Users/osx/buildbot/slave/package_osx64/build/src/gf.c:1819\n",
"jl_fptr_trampoline at /Users/osx/buildbot/slave/package_osx64/build/src/gf.c:1863\n",
"do_call at /Users/osx/buildbot/slave/package_osx64/build/src/interpreter.c:323\n",
"eval_stmt_value at /Users/osx/buildbot/slave/package_osx64/build/src/interpreter.c:362 [inlined]\n",
"eval_body at /Users/osx/buildbot/slave/package_osx64/build/src/interpreter.c:759\n",
"jl_interpret_toplevel_thunk_callback at /Users/osx/buildbot/slave/package_osx64/build/src/interpreter.c:885\n",
"Interpreter frame (ip: 1)\n",
"Core.CodeInfo(code=Array{Any, (3,)}[\n",
" Expr(:call, Base.getproperty, :Cassette, :(:recurse)),\n",
" Expr(:call, SSAValue(1), :ctx, :fail_demo),\n",
" Expr(:return, SSAValue(2))], codelocs=Array{Int32, (3,)}[1, 1, 1], method_for_inference_limit_heuristics=nothing, ssavaluetypes=3, linetable=Array{Any, (1,)}[Core.LineInfoNode(mod=Main, method=Symbol(\"top-level scope\"), file=Symbol(\"In[182]\"), line=2, inlined_at=0)], ssaflags=Array{UInt8, (0,)}[], slotflags=Array{UInt8, (0,)}[], slotnames=Array{Any, (0,)}[], inferred=false, inlineable=false, propagate_inbounds=false, pure=false)jl_interpret_toplevel_thunk at /Users/osx/buildbot/slave/package_osx64/build/src/interpreter.c:894\n",
"jl_toplevel_eval_flex at /Users/osx/buildbot/slave/package_osx64/build/src/toplevel.c:764\n",
"jl_toplevel_eval at /Users/osx/buildbot/slave/package_osx64/build/src/toplevel.c:773 [inlined]\n",
"jl_toplevel_eval_in at /Users/osx/buildbot/slave/package_osx64/build/src/toplevel.c:793\n",
"eval at ./boot.jl:328 [inlined]\n",
"softscope_include_string at /Users/oxinabox/.julia/packages/SoftGlobalScope/cSbw5/src/SoftGlobalScope.jl:218\n",
"execute_request at /Users/oxinabox/.julia/packages/IJulia/gI2uA/src/execute_request.jl:67\n",
"jl_apply at /Users/osx/buildbot/slave/package_osx64/build/src/./julia.h:1571 [inlined]\n",
"jl_f__apply at /Users/osx/buildbot/slave/package_osx64/build/src/builtins.c:556\n",
"jl_f__apply_latest at /Users/osx/buildbot/slave/package_osx64/build/src/builtins.c:594\n",
"#invokelatest#1 at ./essentials.jl:742 [inlined]\n",
"invokelatest at ./essentials.jl:741 [inlined]\n",
"eventloop at /Users/oxinabox/.julia/packages/IJulia/gI2uA/src/eventloop.jl:8\n",
"#15 at ./task.jl:259\n",
"jl_fptr_trampoline at /Users/osx/buildbot/slave/package_osx64/build/src/gf.c:1864\n",
"jl_apply at /Users/osx/buildbot/slave/package_osx64/build/src/./julia.h:1571 [inlined]\n",
"start_task at /Users/osx/buildbot/slave/package_osx64/build/src/task.c:572\n"
]
},
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 182,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ctx = Ctx(pass=(Cassette.@pass storevars_transform));\n",
"Cassette.recurse(ctx, fail_demo)"
]
},
{
"cell_type": "code",
"execution_count": 183,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"CodeInfo(\n",
"\u001b[90m1 ──\u001b[39m (#self# = (Core.getfield)(##overdub_arguments#364, 1))\u001b[90m::Const(fail_demo, false)\u001b[39m\n",
"\u001b[90m│ \u001b[39m %2 = (Base.getindex)(Core.Symbol)\u001b[36m::Array{Symbol,1}\u001b[39m\n",
"\u001b[90m│ \u001b[39m %3 = (Base.getindex)(Core.Any)\u001b[36m::Array{Any,1}\u001b[39m\n",
"\u001b[90m│ \u001b[39m %4 = $(Expr(:isdefined, :(#self#)))\u001b[36m::Const(true, false)\u001b[39m\n",
"\u001b[90m└───\u001b[39m goto #3 if not %4\n",
"\u001b[90m2 ──\u001b[39m (Base.push!)(%2, Symbol(\"#self#\"))\u001b[90m::Any\u001b[39m\n",
"\u001b[90m└───\u001b[39m (Base.push!)(%3, #self#)\u001b[90m::Any\u001b[39m\n",
"\u001b[90m3 ┄─\u001b[39m %8 = $(Expr(:isdefined, :(z::Union{})))\u001b[36m::Const(false, false)\u001b[39m\n",
"\u001b[90m└───\u001b[39m goto #5 if not %8\n",
"\u001b[90m4 ──\u001b[39m Const(:((Base.push!)(%2, :z)), false)\u001b[90m::Union{}\u001b[39m\n",
"\u001b[90m└───\u001b[39m Const(:((Base.push!)(%3, z)), false)\u001b[90m::Union{}\u001b[39m\n",
"\u001b[90m5 ┄─\u001b[39m (Main.print_vars)(%2, %3)\u001b[90m::Any\u001b[39m\n",
"\u001b[90m│ \u001b[39m NewvarNode(:(z))\u001b[90m::Any\u001b[39m\n",
"\u001b[90m│ \u001b[39m %14 = (Base.getindex)(Core.Symbol)\u001b[36m::Array{Symbol,1}\u001b[39m\n",
"\u001b[90m│ \u001b[39m %15 = (Base.getindex)(Core.Any)\u001b[36m::Array{Any,1}\u001b[39m\n",
"\u001b[90m│ \u001b[39m %16 = $(Expr(:isdefined, :(#self#)))\u001b[36m::Const(true, false)\u001b[39m\n",
"\u001b[90m└───\u001b[39m goto #7 if not %16\n",
"\u001b[90m6 ──\u001b[39m (Base.push!)(%14, Symbol(\"#self#\"))\u001b[90m::Any\u001b[39m\n",
"\u001b[90m└───\u001b[39m (Base.push!)(%15, #self#)\u001b[90m::Any\u001b[39m\n",
"\u001b[90m7 ┄─\u001b[39m %20 = $(Expr(:isdefined, :(z::Union{})))\u001b[36m::Const(false, false)\u001b[39m\n",
"\u001b[90m└───\u001b[39m goto #9 if not %20\n",
"\u001b[90m8 ──\u001b[39m Const(:((Base.push!)(%14, :z)), false)\u001b[90m::Union{}\u001b[39m\n",
"\u001b[90m└───\u001b[39m Const(:((Base.push!)(%15, z)), false)\u001b[90m::Union{}\u001b[39m\n",
"\u001b[90m9 ┄─\u001b[39m (Main.print_vars)(%14, %15)\u001b[90m::Any\u001b[39m\n",
"\u001b[90m└───\u001b[39m goto #15 if not true\n",
"\u001b[90m10 ─\u001b[39m %26 = (Base.getindex)(Core.Symbol)\u001b[36m::Array{Symbol,1}\u001b[39m\n",
"\u001b[90m│ \u001b[39m %27 = (Base.getindex)(Core.Any)\u001b[36m::Array{Any,1}\u001b[39m\n",
"\u001b[90m│ \u001b[39m %28 = $(Expr(:isdefined, :(#self#)))\u001b[36m::Const(true, false)\u001b[39m\n",
"\u001b[90m└───\u001b[39m goto #12 if not %28\n",
"\u001b[90m11 ─\u001b[39m (Base.push!)(%26, Symbol(\"#self#\"))\u001b[90m::Any\u001b[39m\n",
"\u001b[90m└───\u001b[39m (Base.push!)(%27, #self#)\u001b[90m::Any\u001b[39m\n",
"\u001b[90m12 ┄\u001b[39m %32 = $(Expr(:isdefined, :(z::Union{})))\u001b[36m::Const(false, false)\u001b[39m\n",
"\u001b[90m└───\u001b[39m goto #14 if not %32\n",
"\u001b[90m13 ─\u001b[39m Const(:((Base.push!)(%26, :z)), false)\u001b[90m::Union{}\u001b[39m\n",
"\u001b[90m└───\u001b[39m Const(:((Base.push!)(%27, z)), false)\u001b[90m::Union{}\u001b[39m\n",
"\u001b[90m14 ┄\u001b[39m (Main.print_vars)(%26, %27)\u001b[90m::Any\u001b[39m\n",
"\u001b[90m└───\u001b[39m (z = true)\u001b[90m::Const(true, false)\u001b[39m\n",
"\u001b[90m15 ┄\u001b[39m %38 = (Base.getindex)(Core.Symbol)\u001b[36m::Array{Symbol,1}\u001b[39m\n",
"\u001b[90m│ \u001b[39m %39 = (Base.getindex)(Core.Any)\u001b[36m::Array{Any,1}\u001b[39m\n",
"\u001b[90m│ \u001b[39m %40 = $(Expr(:isdefined, :(#self#)))\u001b[36m::Const(true, false)\u001b[39m\n",
"\u001b[90m└───\u001b[39m goto #17 if not %40\n",
"\u001b[90m16 ─\u001b[39m (Base.push!)(%38, Symbol(\"#self#\"))\u001b[90m::Any\u001b[39m\n",
"\u001b[90m└───\u001b[39m (Base.push!)(%39, #self#)\u001b[90m::Any\u001b[39m\n",
"\u001b[90m17 ┄\u001b[39m %44 = $(Expr(:isdefined, :(z::Const(true, false))))\u001b[36m::Const(true, false)\u001b[39m\n",
"\u001b[90m└───\u001b[39m goto #19 if not %44\n",
"\u001b[90m18 ─\u001b[39m (Base.push!)(%38, :z)\u001b[90m::Any\u001b[39m\n",
"\u001b[90m└───\u001b[39m (Base.push!)(%39, z::Const(true, false))\u001b[90m::Any\u001b[39m\n",
"\u001b[90m19 ┄\u001b[39m (Main.print_vars)(%38, %39)\u001b[90m::Any\u001b[39m\n",
"\u001b[90m└───\u001b[39m return 1\n",
") => Int64"
]
},
"execution_count": 183,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@code_typed optimize=false Cassette.recurse(ctx, fail_demo)"
]
},
{
"cell_type": "code",
"execution_count": 184,
"metadata": {},
"outputs": [
{
"ename": "BoundsError",
"evalue": "BoundsError: attempt to access 50-element Array{Any,1} at index [-1]",
"output_type": "error",
"traceback": [
"BoundsError: attempt to access 50-element Array{Any,1} at index [-1]",
"",
"Stacktrace:",
" [1] getindex at ./array.jl:729 [inlined]",
" [2] renumber_ssa at ./compiler/ssair/slot2ssa.jl:65 [inlined]",
" [3] #241 at ./compiler/ssair/slot2ssa.jl:74 [inlined]",
" [4] ssamap(::getfield(Core.Compiler, Symbol(\"##241#242\")){Array{Any,1},Bool,Nothing}, ::Any) at ./compiler/ssair/ir.jl:429",
" [5] renumber_ssa! at ./compiler/ssair/slot2ssa.jl:74 [inlined]",
" [6] renumber_ssa!(::Any, ::Array{Any,1}) at ./compiler/ssair/slot2ssa.jl:73",
" [7] construct_ssa!(::Core.CodeInfo, ::Array{Any,1}, ::Core.Compiler.IRCode, ::Core.Compiler.DomTree, ::Array{Core.Compiler.SlotInfo,1}, ::Int64, ::Core.SimpleVector, ::Array{Any,1}) at ./compiler/ssair/slot2ssa.jl:859",
" [8] just_construct_ssa(::Core.CodeInfo, ::Array{Any,1}, ::Int64, ::Core.Compiler.OptimizationState) at ./compiler/ssair/driver.jl:109",
" [9] run_passes(::Core.CodeInfo, ::Int64, ::Core.Compiler.OptimizationState) at ./compiler/ssair/driver.jl:114",
" [10] optimize(::Core.Compiler.OptimizationState, ::Any) at ./compiler/optimize.jl:164",
" [11] typeinf_code(::Method, ::Any, ::Core.SimpleVector, ::Bool, ::Core.Compiler.Params) at ./compiler/typeinfer.jl:524",
" [12] #code_typed#20(::Bool, ::Symbol, ::Function, ::Any, ::Any) at ./reflection.jl:961",
" [13] (::getfield(Base, Symbol(\"#kw##code_typed\")))(::NamedTuple{(:optimize,),Tuple{Bool}}, ::typeof(code_typed), ::Function, ::Type) at ./none:0",
" [14] top-level scope at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/InteractiveUtils/src/macros.jl:143",
" [15] top-level scope at In[184]:1"
]
}
],
"source": [
"@code_typed optimize=true Cassette.recurse(ctx, fail_demo)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 1.1.0",
"language": "julia",
"name": "julia-1.1"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.1.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment