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

backport #42766 into backports-release-1.7 #42805

Merged
merged 3 commits into from
Oct 27, 2021

Commits on Oct 26, 2021

  1. manually-cherry-picked: optimizer: eliminate excessive specialization…

    … in inlining code
    
    This commit includes several code quality improvements in inlining code:
    - eliminate excessive specializations around:
      * `item::Pair{Any, Any}` constructions
      * iterations on `Vector{Pair{Any, Any}}`
    - replace `Pair{Any, Any}` with new, more explicit data type `InliningCase`
    - remove dead code
    aviatesk committed Oct 26, 2021
    Configuration menu
    Copy the full SHA
    e0f980e View commit details
    Browse the repository at this point in the history
  2. manually-cherry-picked: optimizer: fix #42754, inline union-split con…

    …st-prop'ed sources
    
    This commit complements #39754 and #39305: implements a logic to use
    constant-prop'ed results for inlining at union-split callsite.
    Currently it works only for cases when constant-prop' succeeded for all
    (union-split) signatures.
    
    > example
    ```julia
    julia> mutable struct X
               # NOTE in order to confuse `fieldtype_tfunc`, we need to have at least two fields with different types
               a::Union{Nothing, Int}
               b::Symbol
           end;
    
    julia> code_typed((X, Union{Nothing,Int})) do x, a
               # this `setproperty` call would be union-split and constant-prop will happen for
               # each signature: inlining would fail if we don't use constant-prop'ed source
               # since the approximated inlining cost of `convert(fieldtype(X, sym), a)` would
               # end up very high if we don't propagate `sym::Const(:a)`
               x.a = a
               x
           end |> only |> first
    ```
    
    > before this commit
    ```julia
    CodeInfo(
    1 ─ %1 = Base.setproperty!::typeof(setproperty!)
    │   %2 = (isa)(a, Nothing)::Bool
    └──      goto #3 if not %2
    2 ─ %4 = π (a, Nothing)
    │        invoke %1(_2::X, 🅰️:Symbol, %4::Nothing)::Any
    └──      goto #6
    3 ─ %7 = (isa)(a, Int64)::Bool
    └──      goto #5 if not %7
    4 ─ %9 = π (a, Int64)
    │        invoke %1(_2::X, 🅰️:Symbol, %9::Int64)::Any
    └──      goto #6
    5 ─      Core.throw(ErrorException("fatal error in type inference (type bound)"))::Union{}
    └──      unreachable
    6 ┄      return x
    )
    ```
    
    > after this commit
    ```julia
    CodeInfo(
    1 ─ %1 = (isa)(a, Nothing)::Bool
    └──      goto #3 if not %1
    2 ─      Base.setfield!(x, :a, nothing)::Nothing
    └──      goto #6
    3 ─ %5 = (isa)(a, Int64)::Bool
    └──      goto #5 if not %5
    4 ─ %7 = π (a, Int64)
    │        Base.setfield!(x, :a, %7)::Int64
    └──      goto #6
    5 ─      Core.throw(ErrorException("fatal error in type inference (type bound)"))::Union{}
    └──      unreachable
    6 ┄      return x
    )
    ```
    aviatesk committed Oct 26, 2021
    Configuration menu
    Copy the full SHA
    da71d29 View commit details
    Browse the repository at this point in the history
  3. manually-cherry-picked: inference: prioritize force_constant_prop o…

    …ver `const_prop_entry_heuristic` (#41882)
    
    Currently our constant-prop' heuristics work in the following way:
    1. `const_prop_entry_heuristic`
    2. `const_prop_argument_heuristic` & `const_prop_rettype_heuristic`
    3. `force_const_prop` custom heuristic & `!const_prop_function_heuristic`
    4. `MethodInstance` specialization and `const_prop_methodinstance_heuristic`
    
    This PR changes it so that the step 1. now works like:
    
    1. `force_const_prop` custom heuristic & `const_prop_entry_heuristic`
    
    and the steps 2., 3. and 4. don't change
    
    This change particularly allows us to more forcibly constant-propagate
    for `getproperty` and `setproperty!`, and inline them more, e.g.:
    ```julia
    mutable struct Foo
        val
        _::Int
    end
    
    function setter(xs)
        for x in xs
            x.val = nothing # `setproperty!` can be inlined with this PR
        end
    end
    ```
    
    It might be useful because now we can intervene into the constant-prop'
    heuristic in a more reliable way with the `aggressive_constprop` interface.
    
    I did the simple benchmark below, and it looks like this change doesn't
    cause the latency problem for this particular example:
    ```zsh
    ~/julia master aviatesk@amdci2 6s
    ❯ ./usr/bin/julia -e '@time using Plots; @time plot(rand(10,3))'
      3.708500 seconds (7.28 M allocations: 506.128 MiB, 3.45% gc time, 1.13% compilation time)
      2.817794 seconds (3.45 M allocations: 195.127 MiB, 7.84% gc time, 53.76% compilation time)
    
    ~/julia avi/forceconstantprop aviatesk@amdci2 6s
    ❯ ./usr/bin/julia -e '@time using Plots; @time plot(rand(10,3))'
      3.622109 seconds (7.02 M allocations: 481.710 MiB, 4.19% gc time, 1.17% compilation time)
      2.863419 seconds (3.44 M allocations: 194.210 MiB, 8.02% gc time, 53.53% compilation time)
    ```
    aviatesk committed Oct 26, 2021
    Configuration menu
    Copy the full SHA
    c22889e View commit details
    Browse the repository at this point in the history