Skip to content
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 supports for new @inline and @noinline features #753

Merged
merged 1 commit into from
Sep 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "Compat"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.36.0"
version = "3.37.0"

[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ changes in `julia`.

## Supported features

* `Compat.@inline` and `Compat.@noinline` can be used at function callsites to encourage the compiler to (not) inline the function calls on Julia versions that support these features, and otherwise do not have any effects ([#41312]) (since Compat 3.37)

* `Compat.@inline` and `Compat.@noinline` can be used within function body to hint to the compiler the inlineability of the defined function ([#41312]) (since Compat 3.37)

* `Compat.@constprop :aggressive ex` and `Compat.@constprop :none ex` allow control over constant-propagation during inference on Julia versions that support this feature, and otherwise just pass back `ex`. ([#42125]) (since Compat 3.36)

* `Returns(value)` returns `value` for any arguments ([#39794]) (since Compat 3.35)
Expand Down Expand Up @@ -276,3 +280,5 @@ Note that you should specify the correct minimum version for `Compat` in the
[#34331]: https://github.com/JuliaLang/julia/pull/34331
[#39794]: https://github.com/JuliaLang/julia/pull/39794
[#42125]: https://github.com/JuliaLang/julia/pull/42125
[#41312]: https://github.com/JuliaLang/julia/pull/41312
[#41328]: https://github.com/JuliaLang/julia/pull/41328
44 changes: 44 additions & 0 deletions src/Compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,50 @@ using LinearAlgebra: Adjoint, Diagonal, Transpose, UniformScaling, RealHermSymCo

include("compatmacro.jl")

# NOTE these `@inline` and `@noinline` definitions overwrite the definitions implicitly
# imported from Base and so should happen before any usages of them within this module

# https://github.com/JuliaLang/julia/pull/41312: `@inline`/`@noinline` annotations within a function body
@static if !hasmethod(getfield(Base, Symbol("@inline")), (LineNumberNode,Module))
macro inline() Expr(:meta, :inline) end
macro noinline() Expr(:meta, :noinline) end
end

# https://github.com/JuliaLang/julia/pull/41328: callsite annotations of inlining
@static if !isdefined(Base, :annotate_meta_def_or_block)
macro inline(ex) annotate_meta_def_or_nothing(ex, :inline) end
macro noinline(ex) annotate_meta_def_or_nothing(ex, :noinline) end
function annotate_meta_def_or_nothing(@nospecialize(ex), meta::Symbol)
inner = unwrap_macrocalls(ex)
if is_function_def(inner)
# annotation on a definition
return esc(Base.pushmeta!(ex, meta))
else
# do nothing
return esc(ex)
end
end
unwrap_macrocalls(@nospecialize(x)) = x
function unwrap_macrocalls(ex::Expr)
inner = ex
while inner.head === :macrocall
inner = inner.args[end]::Expr
end
return inner
end
is_function_def(@nospecialize(ex)) =
return Meta.isexpr(ex, :function) || is_short_function_def(ex) || Meta.isexpr(ex, :->)
function is_short_function_def(@nospecialize(ex))
Meta.isexpr(ex, :(=)) || return false
while length(ex.args) >= 1 && isa(ex.args[1], Expr)
(ex.args[1].head === :call) && return true
(ex.args[1].head === :where || ex.args[1].head === :(::)) || return false
ex = ex.args[1]
end
return false
end
end

# https://github.com/JuliaLang/julia/pull/29440
if VERSION < v"1.1.0-DEV.389"
Base.:(:)(I::CartesianIndex{N}, J::CartesianIndex{N}) where N =
Expand Down
41 changes: 41 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1171,3 +1171,44 @@ end
)
@test aggf("hi") == nonef("hi") == :hi
end

# https://github.com/JuliaLang/julia/pull/41312
@testset "`@inline`/`@noinline` annotations within a function body" begin
callf(f, args...) = f(args...)
function foo1(a)
Compat.@inline
sum(sincos(a))
end
foo2(a) = (Compat.@inline; sum(sincos(a)))
foo3(a) = callf(a) do a
Compat.@inline
sum(sincos(a))
end
function foo4(a)
Compat.@noinline
sum(sincos(a))
end
foo5(a) = (Compat.@noinline; sum(sincos(a)))
foo6(a) = callf(a) do a
Compat.@noinline
sum(sincos(a))
end

@test foo1(42) == foo2(42) == foo3(42) == foo4(42) == foo5(42) == foo6(42)
end

# https://github.com/JuliaLang/julia/pull/41328
@testset "callsite annotations of inlining" begin
function foo1(a)
Compat.@inline begin
return sum(sincos(a))
end
end
function foo2(a)
Compat.@noinline begin
return sum(sincos(a))
end
end

@test foo1(42) == foo2(42)
end