Skip to content

Instantly share code, notes, and snippets.

@timholy
Last active April 15, 2025 07:58
Show Gist options
  • Save timholy/9a64b27c1932bb414e69b8fe48284b5e to your computer and use it in GitHub Desktop.
Save timholy/9a64b27c1932bb414e69b8fe48284b5e to your computer and use it in GitHub Desktop.
Illustration of constprop in SnoopCompile
julia> tinf.children
2-element Vector{SnoopCompileCore.InferenceTimingNode}:
InferenceTimingNode: 0.000141/0.000324 on Main.anonymous.g() with 1 direct children
InferenceTimingNode: 0.000068/0.001370 on Main.anonymous.f() with 4 direct children
julia> tinf.children[1].children
1-element Vector{SnoopCompileCore.InferenceTimingNode}:
InferenceTimingNode: 0.000069/0.000182 on Main.anonymous.hlcp(::Int64) with 1 direct children
julia> tinf.children[1].children[1].children
1-element Vector{SnoopCompileCore.InferenceTimingNode}:
InferenceTimingNode: 0.000114/0.000114 on Main.anonymous.likescp(::Int64) with 0 direct children
julia> tinf.children[2].children
4-element Vector{SnoopCompileCore.InferenceTimingNode}:
InferenceTimingNode: 0.000107/0.000107 on Main.anonymous.llcp(::Int64) with 0 direct children
InferenceTimingNode: 0.000017/0.000046 on Main.anonymous.llcp(1::Int64) with 1 direct children
InferenceTimingNode: 0.000013/0.000030 on Main.anonymous.llcp(2::Int64) with 1 direct children
InferenceTimingNode: 0.000023/0.001120 on Main.anonymous.llcp(5::Int64) with 1 direct children
# `newly_inferred` CodeInstances:
5-element Vector{Core.CodeInstance}:
CodeInstance for MethodInstance for Main.anonymous.likescp(::Int64)
CodeInstance for MethodInstance for Main.anonymous.hlcp(::Int64)
CodeInstance for MethodInstance for Main.anonymous.g()
CodeInstance for MethodInstance for Main.anonymous.llcp(::Int64)
CodeInstance for MethodInstance for Main.anonymous.f()
# I plan to use the forward-edges of the CodeInstances to link these together,
# assuming that once a function is inferred it doesn't need to be re-inferred.
# Interestingly, if this list is stored as `cis`, then
julia> ci = cis[4]
CodeInstance for MethodInstance for Main.anonymous.llcp(::Int64)
julia> e = cis[5].edges[1]
CodeInstance for MethodInstance for Main.anonymous.llcp(::Int64)
julia> ci == e
false
# which makes it possible to tell that something "interesting" is happening.
# But I'm not sure of what the rules are. `e` is not linked from
# `ci.def.cache`, which I'm guessing is a clear indicator of constprop, but
# I'm unsure whether there are more efficient ways to deduce the same thing.
# (`e.inferred` is `nothing`, maybe?)
# Precise constprop
M = Module()
@eval M begin
using Random
function likescp(x::Int)
x == 1 && return "a"
x == 2 && return "b"
return randstring(x)
end
llcp(x) = length(likescp(x))
Base.@constprop :none hlcp(x) = length(likescp(x))
f() = llcp(1) + llcp(2) + llcp(5)
g() = hlcp(1) + hlcp(2) + hlcp(5)
end
tinf = @snoop_inference begin
M.g() # call the version with no constprop first
M.f()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment