Add a statement-cost printer for analyzing inlining decisions#37275
Add a statement-cost printer for analyzing inlining decisions#37275
Conversation
| Print type-inferred and optimized code for `f` given argument types `types`, | ||
| prepending each line with its cost as estimated by the compiler's inlining engine. | ||
| """ | ||
| function print_statement_costs(io::IO, @nospecialize(f), @nospecialize(t); kwargs...) |
There was a problem hiding this comment.
Maybe it makes sense to add a @code_ version of this to InteractiveUtils. Could always be done later of course.
There was a problem hiding this comment.
No way, is that @code_costs?:joy:
There was a problem hiding this comment.
Or an argument to one of the others (cost = true)
There was a problem hiding this comment.
FYI, I'm providing @code_costs and it's exactly @timholy who gave me the motivation to do so. 😄
I have some objections about the display style, but I agree that Julia supports that feature.
There was a problem hiding this comment.
I like your printing quite a lot better. But if you do it as separate code-display (print(io, src); lines = readlines(io)) then one risks having the two get misaligned, whereas this version ensures that the two will always stay aligned.
Demo:
julia> function buildexpr()
items = [7, 3]
ex = quote
X = $items
for x in X
println(x)
end
end
return ex
end
buildexpr (generic function with 1 method)
julia> @code_typed buildexpr()
CodeInfo(
1 ─ %1 = Core.tuple(7, 3)::Core.Const((7, 3), false)
│ %2 = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Vector{Int64}, svec(Any, Int64), 0, :(:ccall), Vector{Int64}, 2, 2))::Vector{Int64}
│ Base.arraysize(%2, 1)::Int64
└── goto #7 if not true
2 ┄ %5 = φ (#1 => 1, #6 => %10)::Int64
│ %6 = φ (#1 => 1, #6 => %16)::Int64
│ %7 = φ (#1 => 1, #6 => %17)::Int64
│ %8 = Base.getfield(%1, %6, true)::Int64
│ Base.arrayset(false, %2, %8, %5)::Vector{Int64}
│ %10 = Base.add_int(%5, 1)::Int64
│ %11 = (%7 === 2)::Bool
└── goto #4 if not %11
3 ─ goto #5
4 ─ %14 = Base.add_int(%7, 1)::Int64
└── goto #5
5 ┄ %16 = φ (#4 => %14)::Int64
│ %17 = φ (#4 => %14)::Int64
│ %18 = φ (#3 => true, #4 => false)::Bool
│ %19 = Base.not_int(%18)::Bool
└── goto #7 if not %19
6 ─ goto #2
7 ┄ goto #8
8 ─ %23 = Core._expr(:(=), :X, %2)::Expr
│ %24 = $(Expr(:copyast, :($(QuoteNode(:(for x = X
#= REPL[4]:6 =#
println(x)
end))))))::Expr
│ %25 = Core._expr(:block, $(QuoteNode(:(#= REPL[4]:4 =#))), %23, $(QuoteNode(:(#= REPL[4]:5 =#))), %24)::Expr
└── return %25
) => ExprYou can see statement %24 took more than one line to print.
There was a problem hiding this comment.
I just made a change that will make it easier to fix that problem. Perhaps that will be fixed in a few hours. 😃
Edit: Done. CodeCosts.jl v0.2.0 is available.
There was a problem hiding this comment.
I switched the order of the printing so the cost comes first...I just needed to look a little harder at how these functions were working. I edited the top post to show the current output.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
BTW, is this some kind of magic? |
|
What I'm suggesting is the cost "zero". 😅 Edit: |
|
I'm not sure I understand your point, but the zero for the julia/base/compiler/optimize.jl Lines 329 to 331 in 3285ee0 The old demo at https://docs.julialang.org/en/v1.6-dev/devdocs/inference/ set |
27408cb to
d2ed45a
Compare
d2ed45a to
9f33c69
Compare
While it now has a doctest, https://docs.julialang.org/en/latest/devdocs/inference/#The-inlining-algorithm-(inline_worthy)-1 has bitrotted more than once. And it's sufficiently laborious that it discourages rapid investigation. This makes printing the costs easy.
Here's a demo:
The numbers in the first column are the inliner's assigned cost.
If folks like this, I can add a test to make sure this stays working.(done)