diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 5aa7669c3a3a92..581f8226a3829a 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -799,8 +799,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 @@ -1003,7 +1002,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 7ef006f244aa6b..82748669e43875 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 0f69638fdb52e0..9d2e5e71b42301 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -523,6 +523,22 @@ (and (if one (length= e 3) (length> e 2)) (eq? (car e) 'meta) (memq (cadr e) '(nospecialize specialize)))) +(define (nospecialize-meta-noarg? e) + (and (length= e 2) + (eq? (car e) 'meta) (memq (cadr e) '(nospecialize specialize)))) + +(define (inline-meta? e) + (and (length> e 1) + (eq? (car e) 'meta) (any (lambda (x) (memq x '(inline noinline))) (cdr e)))) + +(define (propagate_inbounds-meta? e) + (and (length> e 1) + (eq? (car e) 'meta) (any (lambda (x) (equal? x '(propagate_inbounds))) (cdr e)))) + +(define (constprop-meta? e) + (and (length> e 1) + (eq? (car e) 'meta) (any (lambda (x) (memq x '(aggressive_constprop no_constprop))) (cdr e)))) + (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 4024d25c2e9ec0..3dfcaba509ee15 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -562,6 +562,10 @@ ,(if (any kwarg? pargl) (gensy) UNUSED) (call (core kwftype) ,ftype)) ,kw ,@pargl ,@vararg) `(block + ,@(filter nospecialize-meta-noarg? prologue) + ,@(filter inline-meta? prologue) + ,@(filter propagate_inbounds-meta? prologue) + ,@(filter constprop-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 044ba03bacf32d..395870255fbfdd 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -1402,3 +1402,51 @@ 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 + + # propagate multiple metadata also + let @inline 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 + end + let @noinline 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 + end +end