From 9edac22a6676c31361d068483c677f1217645d2d Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 12 Jul 2022 23:30:33 -0400 Subject: [PATCH] propagate method metadata to keyword sorter methods (#45041) Co-authored-by: Shuhei Kadowaki --- base/compiler/abstractinterpretation.jl | 5 ++- base/compiler/utilities.jl | 14 ++++++++ src/ast.scm | 15 ++++++++ src/julia-syntax.scm | 3 ++ test/compiler/inline.jl | 46 +++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 3 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index e2802768d98ad..9ca234e56e394 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -827,8 +827,7 @@ function const_prop_enabled(interp::AbstractInterpreter, sv::InferenceState, mat add_remark!(interp, sv, "[constprop] Disabled by parameter") return false end - method = match.method - if method.constprop == 0x02 + if is_no_constprop(match.method) add_remark!(interp, sv, "[constprop] Disabled by method parameter") return false end @@ -1028,7 +1027,7 @@ function is_all_overridden((; fargs, argtypes)::ArgInfo, sv::InferenceState) end function force_const_prop(interp::AbstractInterpreter, @nospecialize(f), method::Method) - return method.constprop == 0x01 || + return is_aggressive_constprop(method) || InferenceParams(interp).aggressive_constant_propagation || istopfunction(f, :getproperty) || istopfunction(f, :setproperty!) diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index 7ef006f244aa6..82748669e4387 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -209,6 +209,20 @@ function specialize_method(match::MethodMatch; kwargs...) return specialize_method(match.method, match.spec_types, match.sparams; kwargs...) end +""" + is_aggressive_constprop(method::Union{Method,CodeInfo}) -> Bool + +Check if `method` is declared as `Base.@constprop :aggressive`. +""" +is_aggressive_constprop(method::Union{Method,CodeInfo}) = method.constprop == 0x01 + +""" + is_no_constprop(method::Union{Method,CodeInfo}) -> Bool + +Check if `method` is declared as `Base.@constprop :none`. +""" +is_no_constprop(method::Union{Method,CodeInfo}) = method.constprop == 0x02 + ######### # types # ######### diff --git a/src/ast.scm b/src/ast.scm index 0f69638fdb52e..bbb2180a8a92f 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -523,6 +523,21 @@ (and (if one (length= e 3) (length> e 2)) (eq? (car e) 'meta) (memq (cadr e) '(nospecialize specialize)))) +(define (meta? e) + (and (length> e 1) (eq? (car e) 'meta))) + +(define (method-meta-sym? x) + (memq x '(inline noinline aggressive_constprop no_constprop propagate_inbounds))) + +(define (propagate-method-meta e) + `(meta ,@(filter (lambda (x) + (or (method-meta-sym? x) + (and (pair? x) (eq? (car x) 'purity)))) + (cdr e)))) + +(define (argwide-nospecialize-meta? e) + (and (length= e 2) (eq? (car e) 'meta) (memq (cadr e) '(nospecialize specialize)))) + (define (if-generated? e) (and (length= e 4) (eq? (car e) 'if) (equal? (cadr e) '(generated)))) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 4024d25c2e9ec..8af1bc8b80d23 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -562,6 +562,9 @@ ,(if (any kwarg? pargl) (gensy) UNUSED) (call (core kwftype) ,ftype)) ,kw ,@pargl ,@vararg) `(block + ;; propagate method metadata to keyword sorter + ,@(map propagate-method-meta (filter meta? prologue)) + ,@(filter argwide-nospecialize-meta? prologue) ,@(let ((lnns (filter linenum? prologue))) (if (pair? lnns) (list (car lnns)) diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 94331da6a7d03..a11fdbd2b6203 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -1402,3 +1402,49 @@ end end end end + +# https://github.com/JuliaLang/julia/issues/45050 +@testset "propagate :meta annotations to keyword sorter methods" begin + # @inline, @noinline, @constprop + let @inline f(::Any; x::Int=1) = 2x + @test ccall(:jl_ir_flag_inlineable, Bool, (Any,), only(methods(f)).source) + @test ccall(:jl_ir_flag_inlineable, Bool, (Any,), only(methods(Core.kwfunc(f))).source) + end + let @noinline f(::Any; x::Int=1) = 2x + @test !ccall(:jl_ir_flag_inlineable, Bool, (Any,), only(methods(f)).source) + @test !ccall(:jl_ir_flag_inlineable, Bool, (Any,), only(methods(Core.kwfunc(f))).source) + end + let Base.@constprop :aggressive f(::Any; x::Int=1) = 2x + @test Core.Compiler.is_aggressive_constprop(only(methods(f))) + @test Core.Compiler.is_aggressive_constprop(only(methods(Core.kwfunc(f)))) + end + let Base.@constprop :none f(::Any; x::Int=1) = 2x + @test Core.Compiler.is_no_constprop(only(methods(f))) + @test Core.Compiler.is_no_constprop(only(methods(Core.kwfunc(f)))) + end + # @nospecialize + let f(@nospecialize(A::Any); x::Int=1) = 2x + @test only(methods(f)).nospecialize == 1 + @test only(methods(Core.kwfunc(f))).nospecialize == 4 + end + let f(::Any; x::Int=1) = (@nospecialize; 2x) + @test only(methods(f)).nospecialize == -1 + @test only(methods(Core.kwfunc(f))).nospecialize == -1 + end + # Base.@assume_effects + let Base.@assume_effects :notaskstate f(::Any; x::Int=1) = 2x + @test Core.Compiler.decode_effects_override(only(methods(f)).purity).notaskstate + @test Core.Compiler.decode_effects_override(only(methods(Core.kwfunc(f))).purity).notaskstate + end + # propagate multiple metadata also + let @inline Base.@assume_effects :notaskstate Base.@constprop :aggressive f(::Any; x::Int=1) = (@nospecialize; 2x) + @test ccall(:jl_ir_flag_inlineable, Bool, (Any,), only(methods(f)).source) + @test Core.Compiler.is_aggressive_constprop(only(methods(f))) + @test ccall(:jl_ir_flag_inlineable, Bool, (Any,), only(methods(Core.kwfunc(f))).source) + @test Core.Compiler.is_aggressive_constprop(only(methods(Core.kwfunc(f)))) + @test only(methods(f)).nospecialize == -1 + @test only(methods(Core.kwfunc(f))).nospecialize == -1 + @test Core.Compiler.decode_effects_override(only(methods(f)).purity).notaskstate + @test Core.Compiler.decode_effects_override(only(methods(Core.kwfunc(f))).purity).notaskstate + end +end