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

inference: concretize invoke callsite correctly #46743

Merged
merged 1 commit into from
Sep 14, 2022
Merged

Conversation

aviatesk
Copy link
Sponsor Member

It turns out that previously we didn't concretize invoke callsite correctly, as we didn't take into account whether or not the call being concretized is invoke-d or not, e.g.:

julia> invoke_concretized2(a::Int) = a > 0 ? :int : nothing
invoke_concretized2 (generic function with 1 method)

julia> invoke_concretized2(a::Integer) = a > 0 ? :integer : nothing
invoke_concretized2 (generic function with 2 methods)

julia> let
           Base.Experimental.@force_compile
           Base.@invoke invoke_concretized2(42::Integer)
       end
:int # this should return `:integer` instead

This commit fixes that up by propagating information invoke-d callsite to concrete_eval_call. Now we should pass the following test cases:

invoke_concretized1(a::Int) = a > 0 ? :int : nothing
invoke_concretized1(a::Integer) = a > 0 ? "integer" : nothing
@test Base.infer_effects((Int,)) do a
    @invoke invoke_concretized1(a::Integer)
end |> Core.Compiler.is_foldable
@test Base.return_types() do
    @invoke invoke_concretized1(42::Integer)
end |> only === String

invoke_concretized2(a::Int) = a > 0 ? :int : nothing
invoke_concretized2(a::Integer) = a > 0 ? :integer : nothing
@test Base.infer_effects((Int,)) do a
    @invoke invoke_concretized2(a::Integer)
end |> Core.Compiler.is_foldable
@test let
    Base.Experimental.@force_compile
    @invoke invoke_concretized2(42::Integer)
end === :integer

@aviatesk aviatesk added compiler:inference Type inference backport 1.8 Change should be backported to release-1.8 labels Sep 13, 2022
@aviatesk aviatesk requested a review from Keno September 13, 2022 16:42
@@ -885,6 +885,7 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter, resul
add_backedge!(res.const_result.mi, sv, invoketypes)
return res
end
f isa InvokeCall && (f = f.f) # unwrap `invoke`-ed function (the call will be virtualized)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't usually like wrapper objects in non-escaped contexts. E.g. one could probably end up with an InvokeCall here, by doing something like const foo = CC.InvokeCall(...) and then calling foo, but I suppose that wouldn't actually be a problem here, since that would still give the right answer, so I suppose it's not a problem.

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I stopped passing the wrapper object through the f argument, but rather pass the invoke information as an additional argument.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, I like that better

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that better too

It turns out that previously we didn't concretize `invoke` callsite
correctly, as we didn't take into account whether or not the call being
concretized is `invoke`-d or not, e.g.:
```
julia> invoke_concretized2(a::Int) = a > 0 ? :int : nothing
invoke_concretized2 (generic function with 1 method)

julia> invoke_concretized2(a::Integer) = a > 0 ? :integer : nothing
invoke_concretized2 (generic function with 2 methods)

julia> let
           Base.Experimental.@force_compile
           Base.@invoke invoke_concretized2(42::Integer)
       end
:int # this should return `:integer` instead
```

This commit fixes that up by propagating information `invoke`-d callsite
to `concrete_eval_call`. Now we should pass the following test cases:
```julia
invoke_concretized1(a::Int) = a > 0 ? :int : nothing
invoke_concretized1(a::Integer) = a > 0 ? "integer" : nothing
@test Base.infer_effects((Int,)) do a
    @invoke invoke_concretized1(a::Integer)
end |> Core.Compiler.is_foldable
@test Base.return_types() do
    @invoke invoke_concretized1(42::Integer)
end |> only === String

invoke_concretized2(a::Int) = a > 0 ? :int : nothing
invoke_concretized2(a::Integer) = a > 0 ? :integer : nothing
@test Base.infer_effects((Int,)) do a
    @invoke invoke_concretized2(a::Integer)
end |> Core.Compiler.is_foldable
@test let
    Base.Experimental.@force_compile
    @invoke invoke_concretized2(42::Integer)
end === :integer
```
@aviatesk
Copy link
Sponsor Member Author

The whitespace failure is fixed on master.

@aviatesk aviatesk merged commit 8455c8f into master Sep 14, 2022
@aviatesk aviatesk deleted the avi/concretize-invoke branch September 14, 2022 05:17
aviatesk added a commit that referenced this pull request Sep 14, 2022
It turns out that previously we didn't concretize `invoke` callsite
correctly, as we didn't take into account whether the call being
concretized is `invoke`-d or not, e.g.:
```
julia> invoke_concretized2(a::Int) = a > 0 ? :int : nothing
invoke_concretized2 (generic function with 1 method)

julia> invoke_concretized2(a::Integer) = a > 0 ? :integer : nothing
invoke_concretized2 (generic function with 2 methods)

julia> let
           Base.Experimental.@force_compile
           Base.@invoke invoke_concretized2(42::Integer)
       end
:int # this should return `:integer` instead
```

This commit fixes that up by propagating information `invoke`-d callsite
to `concrete_eval_call`. Now we should be able to pass the following test cases:
```julia
invoke_concretized1(a::Int) = a > 0 ? :int : nothing
invoke_concretized1(a::Integer) = a > 0 ? "integer" : nothing
@test Base.infer_effects((Int,)) do a
    @invoke invoke_concretized1(a::Integer)
end |> Core.Compiler.is_foldable
@test Base.return_types() do
    @invoke invoke_concretized1(42::Integer)
end |> only === String

invoke_concretized2(a::Int) = a > 0 ? :int : nothing
invoke_concretized2(a::Integer) = a > 0 ? :integer : nothing
@test Base.infer_effects((Int,)) do a
    @invoke invoke_concretized2(a::Integer)
end |> Core.Compiler.is_foldable
@test let
    Base.Experimental.@force_compile
    @invoke invoke_concretized2(42::Integer)
end === :integer
```
@aviatesk aviatesk mentioned this pull request Sep 14, 2022
28 tasks
@aviatesk aviatesk removed the backport 1.8 Change should be backported to release-1.8 label Sep 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:inference Type inference
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants