Conversation
|
This looks very useful. Your ShowCode.jl package has been very nice for working at the IRCode level |
Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com>
|
A very exciting showcase of this PR!: https://nbviewer.org/gist/tkf/d4734be24d2694a3afd669f8f50e6b0f/00_notebook.ipynb |
|
Also, FYI, I'll probably tweak the API a little bit. So, the exact API may be a bit different by the time we merge #45305. But it'll have a similar flavor. |
To match `typeinf_ircode` with how typeinf lock is used ATM (i.e., optimizer is run inside the lock), we can manually lock it because the lock is re-entrant.
|
Yup, looks good! |
base/compiler/optimize.jl
Outdated
| """ | ||
| function run_minimal_passes(ci::CodeInfo, sv::OptimizationState, caller::InferenceResult) | ||
| @timeit "convert" ir = convert_to_ircode(ci, sv) | ||
| @timeit "slot2reg" ir = slot2reg(ir, ci, sv) |
There was a problem hiding this comment.
I would not consider this to be a minimal pass, since it is quite a significant optimization and change to the IR
| @timeit "slot2reg" ir = slot2reg(ir, ci, sv) |
There was a problem hiding this comment.
I think it would be very rare to deal with IRCode without slog2reg (unless you are changing slog2reg itself). For one thing, verify_ir considers IRCode with slots invalid:
julia/base/compiler/ssair/verify.jl
Lines 47 to 48 in 2159bfb
So, I think running slot2reg with optimize = false makes sense, if we treat it as "least optimized typical IRCode that compiler passes deal with." But running slot2reg manually is not super hard. So I don't have super strong opinion about it.
There was a problem hiding this comment.
I guess we can also pass numeric optimize_level
function run_passes(ci::CodeInfo, sv::OptimizationState, caller::InferenceResult, optimize_level = typeinf(Int))
stage = 1
isdone() = optimize_level < (stage += 1)
@timeit "convert" ir = convert_to_ircode(ci, sv)
isdone() && return ir
@timeit "slot2reg" ir = slot2reg(ir, ci, sv)
isdone() && return ir
# TODO: Domsorting can produce an updated domtree - no need to recompute here
@timeit "compact 1" ir = compact!(ir)
isdone() && return ir
@timeit "Inlining" ir = ssa_inlining_pass!(ir, ir.linetable, sv.inlining, ci.propagate_inbounds)
isdone() && return ir
...There was a problem hiding this comment.
I prefer running slot2reg as we often work on post-slot2reg IRCode when developing Julia-level optimizer. I also think the other "pre-inlining optimizations (mostly DCE)" happening within convert_to_ircode and type_annotate! is also significant anyway.
And the optimize_level idea sounds very useful!
There was a problem hiding this comment.
I added optimize_level 04797d5
julia> function demo(f)
y = f()
y isa Any ? nothing : f()
end;
julia> Base.code_ircode(demo; optimize_level = 1) |> only |> first
2 1 ─ (_3 = (_2)())::#UNDEF │
3 │ %2 = (_3 isa Main.Any)::#UNDEF │
└── goto #5 if not %2::#UNDEF │
2 ─ return Main.nothing::#UNDEF │
3 ─ Core.Const(:((_2)()))::#UNDEF │
│ Core.Const(:(return %5))::#UNDEF │
└── unreachable::#UNDEF │
julia> Base.code_ircode(demo; optimize_level = 2) |> only |> first
2 1 ─ %1 = (_2)()::Any │
3 │ %2 = (%1 isa Main.Any)::Core.Const(true) │
└── goto #3 if not %2 │
2 ─ return Main.nothing │
3 ─ Core.Const(:((_2)()))::Union{} │
│ Core.Const(:(return %5))::Union{} │
└── unreachable │
julia> Base.code_ircode(demo) |> only |> first
2 1 ─ (_2)()::Any │
3 └── goto #3 if not true │
2 ─ return Main.nothing │
3 ─ unreachable │
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
Just in case: @nanosoldier |
|
Your benchmark job has completed - no performance regressions were detected. A full report can be found here. |
|
Good to go? @vtjnash Do you want to review this? |
When working on code like #45305, it would be helpful if we can easily get "real"
IRCodeexamples. It's also useful for writing tests. So, I wonder if we can have acode_typed-like API forIRCode?