-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a new macro @outline
, and use it in @assert
.
#57122
base: master
Are you sure you want to change the base?
Conversation
Compiler/test/inline.jl
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this file was the right place to put the @outline
tests. It seems decent, but a bit oxymoronic. :D Please let me know if you have any better suggestions!
Macro usage: ```julia @BoundsCheck i > 1 && i <= len || @outline throw(BoundsError(x, i)) ``` This commit applies the above to Assertions, e.g.: ```julia julia> @macroexpand @Assert x != x "x == x: $x" :(if x != x nothing else #= REPL[3]:36 =# var"#17#outline"(x) = begin $(Expr(:meta, :noinline)) #= REPL[3]:36 =# (throw)((AssertionError)(((Main).Base.inferencebarrier((Main).Base.string))("x == x: $(x)"))) end #= REPL[3]:38 =# var"#17#outline"(x) end) ``` This can improve performance for fast code that uses assertions, e.g.: Before: ```julia julia> @Btime Base.Sort.WithoutMissingVector($(Any[1]))[$1] 3.041 ns (0 allocations: 0 bytes) 1 ``` After: ```julia julia> @Btime Base.Sort.WithoutMissingVector($(Any[1]))[$1] 2.250 ns (0 allocations: 0 bytes) 1 ``` The number of instructions in that function according to `@code_native` (on an aarch64 M2 MacBook) reduced from ~90 to ~40.
Co-authored-by: adienes <[email protected]>
2fb251c
to
91876ea
Compare
end | ||
_free_vars(s::Symbol) = [s] | ||
_free_vars(_) = [] | ||
_free_vars(e::Expr) = isempty(e.args) ? [] : unique!(mapreduce(_free_vars, vcat, e.args)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think unique!
is not defined yet so this fails to compile for me
although, what happens if you use outline
as a zero-arg closure and don't pass the vars in explicitly at all? like
macro outline2(expr)
local fname = gensym(:outlined_expr)
quote
@noinline $(fname)() = $(esc(expr))
$(fname)()
end
end
comparing the @code_native
of
foo1() = @outline rand() > 0.5 || throw(AssertionError("abc"))
foo2() = @outline2 rand() > 0.5 || throw(AssertionError("abc"))
it seems a lot simpler, but I'm not an expert at these things so maybe I'm missing something
Adds a new macro
@outline
, and uses it in@assert
.This implements the simplest suggestion in #29688.
It would still be excellent if the compiler would automatically perform this optimization for any
throw()
statement, but it sounds like introducing automatic outlining for such cases would be a difficult implementation task in the Compiler.And in either case, even if we had such an optimization, there may be cases where a human will want to perform this optimization themselves for a number of reasons, including code-size reduction, improving type stability, outlining rare branches, etc, and having this in a macro is a nice way to automate it, and make this optimization more accessible. 😊
Example macro usage:
This commit applies this new macro
@outline
to@assert
, producing essentially:or in a more complete example:
This can improve performance for fast code that uses assertions. For example, take this definition of
getindex
forWithoutMissingVector
:julia/base/sort.jl
Lines 597 to 601 in 5058dba
Before:
After:
The number of instructions in that function according to
@code_native
(on an aarch64 M2 MacBook) reduced from ~90 to ~40.