From 9758917c8f9b439c680f7a8e2c287f26a77040aa Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 3 Dec 2024 18:47:05 +0000 Subject: [PATCH] Fully outline all GlobalRefs This is an alternative to #56714 that goes in the opposite direction - just outline all GlobalRefs during lowering. It is a lot simpler that #56714 at the cost of some size increase. Numbers: sys.so .ldata size: This PR: 159.8 MB Master: 158.9 MB I don't have numbers of #56714, because it's not fully complete. Additionally, it's possible that restricting GlobalRefs from arguments position would let us use a more efficient encoding in the future. --- Compiler/test/inference.jl | 9 +++--- src/ast.c | 37 ----------------------- src/jlfrontend.scm | 1 - src/julia-syntax.scm | 1 - test/core.jl | 61 ++++++++++++++++++++++++-------------- test/staged.jl | 12 ++++---- 6 files changed, 48 insertions(+), 73 deletions(-) diff --git a/Compiler/test/inference.jl b/Compiler/test/inference.jl index b3099897faf51..c8b599adb1323 100644 --- a/Compiler/test/inference.jl +++ b/Compiler/test/inference.jl @@ -3031,14 +3031,13 @@ end # issue #28279 # ensure that lowering doesn't move these into statement position, which would require renumbering -using Base: +, - -function f28279(b::Bool) +@eval function f28279(b::Bool) let i = 1 - while i > b - i -= 1 + while $(>)(i, b) + i = $(-)(i, 1) end if b end - return i + 1 + return $(+)(i, 1) end end code28279 = code_lowered(f28279, (Bool,))[1].code diff --git a/src/ast.c b/src/ast.c index 474c0661f5230..959bac26c2c15 100644 --- a/src/ast.c +++ b/src/ast.c @@ -181,42 +181,6 @@ static value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint return (bpart != NULL && decode_restriction_kind(jl_atomic_load_relaxed(&bpart->restriction)) == BINDING_KIND_GLOBAL) ? fl_ctx->T : fl_ctx->F; } -static value_t fl_nothrow_julia_global(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) -{ - // tells whether a var is defined, in the sense that accessing it is nothrow - // can take either a symbol or a module and a symbol - jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); - jl_module_t *mod = ctx->module; - jl_sym_t *var = NULL; - if (nargs == 1) { - (void)tosymbol(fl_ctx, args[0], "nothrow-julia-global"); - var = scmsym_to_julia(fl_ctx, args[0]); - } - else { - argcount(fl_ctx, "nothrow-julia-global", nargs, 2); - value_t argmod = args[0]; - if (iscvalue(argmod) && cv_class((cvalue_t*)ptr(argmod)) == jl_ast_ctx(fl_ctx)->jvtype) { - mod = *(jl_module_t**)cv_data((cvalue_t*)ptr(argmod)); - JL_GC_PROMISE_ROOTED(mod); - } else { - if (!iscons(argmod) || !issymbol(car_(argmod)) || scmsym_to_julia(fl_ctx, car_(argmod)) != jl_thismodule_sym) { - lerrorf(fl_ctx, fl_ctx->ArgError, "nothrow-julia-global: Unknown globalref module kind"); - } - } - (void)tosymbol(fl_ctx, args[1], "nothrow-julia-global"); - var = scmsym_to_julia(fl_ctx, args[1]); - } - jl_binding_t *b = jl_get_module_binding(mod, var, 0); - jl_binding_partition_t *bpart = jl_get_binding_partition(b, jl_current_task->world_age); - jl_ptr_kind_union_t pku = jl_walk_binding_inplace(&b, &bpart, jl_current_task->world_age); - if (!bpart) - return fl_ctx->F; - if (jl_bkind_is_some_guard(decode_restriction_kind(pku))) - return fl_ctx->F; - return (jl_bkind_is_some_constant(decode_restriction_kind(pku)) ? - decode_restriction_value(pku) : jl_atomic_load_relaxed(&b->value)) != NULL ? fl_ctx->T : fl_ctx->F; -} - // Used to generate a unique suffix for a given symbol (e.g. variable or type name) // first argument contains a stack of method definitions seen so far by `closure-convert` in flisp. // if the top of the stack is non-NIL, we use it to augment the suffix so that it becomes @@ -288,7 +252,6 @@ static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, jl_module_t *m static const builtinspec_t julia_flisp_ast_ext[] = { { "defined-julia-global", fl_defined_julia_global }, // TODO: can we kill this safepoint - { "nothrow-julia-global", fl_nothrow_julia_global }, { "current-julia-module-counter", fl_module_unique_name }, { "julia-scalar?", fl_julia_scalar }, { NULL, NULL } diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm index 3d46940d6fcbb..9c69da199c0cd 100644 --- a/src/jlfrontend.scm +++ b/src/jlfrontend.scm @@ -31,7 +31,6 @@ ;; this is overwritten when we run in actual julia (define (defined-julia-global v) #f) -(define (nothrow-julia-global v) #f) ;; parser entry points diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index c7ca5d553bb31..c522a565f462a 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -4356,7 +4356,6 @@ f(x) = yt(x) (define (valid-ir-argument? e) (or (simple-atom? e) - (and (globalref? e) (nothrow-julia-global (cadr e) (caddr e))) (and (pair? e) (memq (car e) '(quote inert top core slot static_parameter))))) diff --git a/test/core.jl b/test/core.jl index 63952e8728e1e..c84509c635747 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7434,6 +7434,7 @@ end @test isa(Core.eval(@__MODULE__, :(Bar31062(()))), Bar31062) @test precompile(identity, (Foo31062,)) +using Core: SSAValue ftype_eval = Ref(0) FieldTypeA = String FieldTypeE = UInt32 @@ -7457,27 +7458,41 @@ let fc = FieldConvert(1.0, [2.0], 0x3, 0x4, 0x5) end @test ftype_eval[] == 1 let code = code_lowered(FieldConvert)[1].code - local fc_global_ssa, sp1_ssa, apply_type_ssa, field_type_ssa, - field_type2_ssa, field_type4_ssa, field_type5_ssa, - slot_read_1, slot_read_2, slot_read_3, slot_read_4, - new_ssa - @test code[(fc_global_ssa = 1;)] == GlobalRef(@__MODULE__, :FieldConvert) - @test code[(sp1_ssa = 2;)] == Expr(:static_parameter, 1) - @test code[(apply_type_ssa = 3;)] == Expr(:call, GlobalRef(Core, :apply_type), Core.SSAValue(fc_global_ssa), GlobalRef(@__MODULE__, :FieldTypeA), Core.SSAValue(sp1_ssa)) - @test code[(field_type_ssa = 4;)] == Expr(:call, GlobalRef(Core, :fieldtype), Core.SSAValue(apply_type_ssa), 1) - @test code[10] == Expr(:(=), Core.SlotNumber(10), Expr(:call, GlobalRef(Base, :convert), Core.SSAValue(field_type_ssa), Core.SlotNumber(10))) - @test code[(slot_read_1 = 11;)] == Core.SlotNumber(10) - @test code[(field_type2_ssa = 12;)] == Expr(:call, GlobalRef(Core, :fieldtype), Core.SSAValue(apply_type_ssa), 2) - @test code[18] == Expr(:(=), Core.SlotNumber(9), Expr(:call, GlobalRef(Base, :convert), Core.SSAValue(field_type2_ssa), Core.SlotNumber(9))) - @test code[(slot_read_2 = 19;)] == Core.SlotNumber(9) - @test code[(field_type4_ssa = 20;)] == Expr(:call, GlobalRef(Core, :fieldtype), Core.SSAValue(apply_type_ssa), 4) - @test code[26] == Expr(:(=), Core.SlotNumber(8), Expr(:call, GlobalRef(Base, :convert), Core.SSAValue(field_type4_ssa), Core.SlotNumber(8))) - @test code[(slot_read_3 = 27;)] == Core.SlotNumber(8) - @test code[(field_type5_ssa = 28;)] == Expr(:call, GlobalRef(Core, :fieldtype), Core.SSAValue(apply_type_ssa), 5) - @test code[34] == Expr(:(=), Core.SlotNumber(7), Expr(:call, GlobalRef(Base, :convert), Core.SSAValue(field_type5_ssa), Core.SlotNumber(7))) - @test code[(slot_read_4 = 35;)] == Core.SlotNumber(7) - @test code[(new_ssa = 36;)] == Expr(:new, Core.SSAValue(apply_type_ssa), Core.SSAValue(slot_read_1), Core.SSAValue(slot_read_2), Core.SlotNumber(4), Core.SSAValue(slot_read_3), Core.SSAValue(slot_read_4)) - @test code[37] == Core.ReturnNode(Core.SSAValue(new_ssa)) + calls = Vector{Pair{SSAValue, Expr}}(undef, 0) + for i = 1:length(code) + expr = code[i] + if Meta.isexpr(expr, :call) || (Meta.isexpr(expr, :(=)) && Meta.isexpr(expr.args[2], :call)) + push!(calls, SSAValue(i)=>expr) + end + end + + function is_globalref(arg, gr) + while isa(arg, SSAValue) + arg = code[arg.id] + end + arg == gr + end + + # calls[1] + @test all(is_globalref.(calls[1][2].args[1:3], (GlobalRef(Core, :apply_type), GlobalRef(@__MODULE__, :FieldConvert), GlobalRef(@__MODULE__, :FieldTypeA)))) + + # calls[2] + @test all(is_globalref.(calls[2][2].args[1:1], (GlobalRef(Core, :fieldtype),))) + @test all(calls[2][2].args[2:3] .== (calls[1][1], 1)) + + # calls[3] - isa + + # calls[4] + let calle = calls[4][2] + @test Meta.isexpr(calle, :(=)) + call = calle.args[2] + @test is_globalref(call.args[1], GlobalRef(Base, :convert)) + @test call.args[2] == calls[2][1] + end + + # calls[5] + @test all(is_globalref.(calls[5][2].args[1:1], (GlobalRef(Core, :fieldtype),))) + @test all(calls[5][2].args[2:3] .== (calls[1][1], 2)) end # Issue #32820 @@ -8155,7 +8170,7 @@ end @test Core.Compiler.is_foldable(Base.infer_effects(length, (Core.SimpleVector,))) @test Core.Compiler.is_foldable(Base.infer_effects(getindex, (Core.SimpleVector,Int))) -# Test that a nothrow-globalref doesn't get outlined during lowering +# Test that a the lowering of nothrow globalref module WellKnownGlobal global well_known = 1 end @@ -8164,7 +8179,7 @@ macro insert_global() end check_globalref_lowering() = @insert_global let src = code_lowered(check_globalref_lowering)[1] - @test length(src.code) == 2 + @test length(src.code) == 4 end # Test correctness of widen_diagonal diff --git a/test/staged.jl b/test/staged.jl index 1b28144639f97..6cb99950a7bb2 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -270,12 +270,12 @@ end # PR #23168 -function f23168(a, x) +@eval function f23168(a, x) push!(a, 1) if @generated - :(y = x + x) + :(y = $(+)(x, x)) else - y = 2x + y = $(*)(2, x) end push!(a, y) if @generated @@ -290,9 +290,9 @@ end let a = Any[] @test f23168(a, 3) == (6, Int) @test a == [1, 6, 3] - @test occursin(" + ", string(code_lowered(f23168, (Vector{Any},Int)))) - @test occursin("2 * ", string(Base.uncompressed_ir(first(methods(f23168))))) - @test occursin("2 * ", string(code_lowered(f23168, (Vector{Any},Int), generated=false))) + @test occursin("(+)(", string(code_lowered(f23168, (Vector{Any},Int)))) + @test occursin("(*)(2", string(Base.uncompressed_ir(first(methods(f23168))))) + @test occursin("(*)(2", string(code_lowered(f23168, (Vector{Any},Int), generated=false))) @test occursin("Base.add_int", string(code_typed(f23168, (Vector{Any},Int)))) end