Skip to content

Commit 10cdbda

Browse files
committed
added a section on implementation of the profiler using IRTools
1 parent a61f9f9 commit 10cdbda

File tree

4 files changed

+148
-239
lines changed

4 files changed

+148
-239
lines changed

docs/src/lecture_09/calls.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
struct Calls
32
stamps::Vector{Float64} # contains the time stamps
43
event::Vector{Symbol} # name of the function that is being recorded
@@ -59,3 +58,10 @@ end
5958

6059
reset!(calls::Calls) = calls.i[] = 0
6160

61+
function Base.resize!(calls::Calls, n::Integer)
62+
resize!(calls.stamps, n)
63+
resize!(calls.event, n)
64+
resize!(calls.startstop, n)
65+
end
66+
67+

docs/src/lecture_09/codeinfo.jl

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,13 @@ function retrieve_code_info(sigtypes, world = Base.get_world_counter())
1616
ci
1717
end
1818

19-
# # We migth consider this from IRTools. Importantly, it has partially_inline to get
20-
# # rid of static parameters
21-
# function meta(T; types = T, world = worldcounter())
22-
# F = T.parameters[1]
23-
# F == typeof(invoke) && return invoke_meta(T; world = world)
24-
# F isa DataType && (F.name.module === Core.Compiler ||
25-
# F <: Core.Builtin ||
26-
# F <: Core.Builtin) && return nothing
27-
# _methods = Base._methods_by_ftype(T, -1, world)
28-
# length(_methods) == 0 && return nothing
29-
# type_signature, sps, method = last(_methods)
30-
# sps = svec(map(untvar, sps)...)
31-
# @static if VERSION >= v"1.2-"
32-
# mi = Core.Compiler.specialize_method(method, types, sps)
33-
# ci = Base.isgenerated(mi) ? Core.Compiler.get_staged(mi) : Base.uncompressed_ast(method)
34-
# else
35-
# mi = Core.Compiler.code_for_method(method, types, sps, world, false)
36-
# ci = Base.isgenerated(mi) ? Core.Compiler.get_staged(mi) : Base.uncompressed_ast(mi)
37-
# end
38-
# Base.Meta.partially_inline!(ci.code, [], method.sig, Any[sps...], 0, 0, :propagate)
39-
# Meta(method, mi, ci, method.nargs, sps)
40-
# end
41-
42-
4319
function overdubbable(ex::Expr)
4420
ex.head != :call && return(false)
4521
length(ex.args) < 2 && return(false)
4622
return(overdubbable(ex.args[1]))
4723
end
4824
overdubbable(gr::Core.GlobalRef) = gr.name [:overdub, :record_start, :record_end, :promote, :convert, :tuple]
49-
overdubbable(gr::Symbol) =
25+
# overdubbable(gr::Symbol) =
5026
overdubbable(ex) = false
5127
timable(ex) = overdubbable(ex)
5228

@@ -80,6 +56,7 @@ end
8056

8157

8258
overdub(f::Core.IntrinsicFunction, args...) = f(args...)
59+
overdub(f::Core.Builtin, args...) = f(args...)
8360

8461
@generated function overdub(f::F, args...) where {F}
8562
ci = retrieve_code_info((F, args...))
@@ -121,9 +98,9 @@ overdub(f::Core.IntrinsicFunction, args...) = f(args...)
12198
push!(new_ci.codelocs, ci.codelocs[ci_no])
12299
newci_no += 1
123100
maps.goto[ci_no] = newci_no
124-
if overdubbable(ex)
125-
ex = Expr(:call, GlobalRef(Main, :overdub), ex.args...)
126-
end
101+
# if overdubbable(ex)
102+
# ex = Expr(:call, GlobalRef(Main, :overdub), ex.args...)
103+
# end
127104
push!(new_ci.code, ex)
128105
push!(new_ci.codelocs, ci.codelocs[ci_no])
129106
newci_no += 1

docs/src/lecture_09/irtools.jl

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Generated functions
2-
using Dictionaries, IRTools
2+
using IRTools
3+
using IRTools: var, xcall, insert!, insertafter!, func, recurse!, @dynamo
34
include("calls.jl")
4-
using IRTools: var, xcall, insert!, insertafter!, func
5+
resize!(to, 10000)
56

67
function timable(ex::Expr)
78
ex.head != :call && return(false)
@@ -12,34 +13,20 @@ function timable(ex::Expr)
1213
end
1314
timable(ex) = false
1415

16+
recursable(gr::GlobalRef) = gr.name [:profile_fun, :record_start, :record_end]
17+
recursable(ex::Expr) = ex.head == :call && recursable(ex.args[1])
18+
recursable(ex) = false
19+
1520
exportname(ex::GlobalRef) = QuoteNode(ex.name)
1621
exportname(ex::Symbol) = QuoteNode(ex)
1722
exportname(ex::Expr) = exportname(ex.args[1])
1823
exportname(i::Int) = QuoteNode(Symbol("Int(",i,")"))
1924

20-
function foo(x, y)
21-
z = x * y
22-
z + sin(y)
23-
end
24-
25-
# ir = @code_ir foo(1.0, 1.0)
26-
ir = @code_ir sin(1.0)
25+
profile_fun(f::Core.IntrinsicFunction, args...) = f(args...)
26+
profile_fun(f::Core.Builtin, args...) = f(args...)
2727

28-
# writing our profiler would be relatively
29-
# we will iterate over the ir code and inserts appropriate logs
30-
for b in IRTools.blocks(ir)
31-
for (v, ex) in b
32-
if timable(ex.expr)
33-
fname = exportname(ex.expr)
34-
insert!(b, v, xcall(Main, :record_start, fname))
35-
insertafter!(b, v, xcall(Main, :record_end, fname))
36-
end
37-
end
38-
end
39-
40-
@generated function profile_fun(f, args...)
41-
m = IRTools.Inner.meta(Tuple{f,args...})
42-
ir = IRTools.Inner.IR(m)
28+
@dynamo function profile_fun(f, args...)
29+
ir = IRTools.Inner.IR(f, args...)
4330
for b in IRTools.blocks(ir)
4431
for (v, ex) in b
4532
if timable(ex.expr)
@@ -49,19 +36,14 @@ end
4936
end
5037
end
5138
end
52-
53-
# we need to deal with the problem that ir has different set so f arguments than profile_fun(f, args...)
54-
# THis is what a dynamo does for us
55-
return(IRTools.Inner.build_codeinfo(ir))
39+
for (x, st) in ir
40+
recursable(st.expr) || continue
41+
ir[x] = xcall(profile_fun, st.expr.args...)
42+
end
43+
# recurse!(ir)
44+
return ir
5645
end
5746

58-
f = func(ir)
59-
# f(nothing, 1.0, 1.0)
60-
# f = func(ir)
61-
f(nothing, 1.0)
62-
63-
function func(m::Module, ir::IR)
64-
@eval @generated function $(gensym())($([Symbol(:arg, i) for i = 1:length(arguments(ir))]...))
65-
return build_codeinfo($ir)
66-
end
67-
end
47+
reset!(to)
48+
profile_fun(foo, 1.0, 1.0)
49+
to

0 commit comments

Comments
 (0)