@@ -742,7 +742,7 @@ its argument).
742742In a case when all usages are fully eliminated, `struct` allocation may also be erased as
743743a result of succeeding dead code elimination.
744744"""
745- function sroa_pass! (ir:: IRCode , inlining :: Union{Nothing, InliningState} = nothing )
745+ function sroa_pass! (ir:: IRCode )
746746 compact = IncrementalCompact (ir)
747747 defuses = nothing # will be initialized once we encounter mutability in order to reduce dynamic allocations
748748 lifting_cache = IdDict {Pair{AnySSAValue, Any}, AnySSAValue} ()
@@ -775,11 +775,11 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing, InliningState} = nothin
775775 widenconst (field_ordering) === Bool && (field_ordering = :unspecified )
776776 end
777777 elseif is_known_call (stmt, Core. finalizer, compact)
778- 3 <= length (stmt. args) <= 5 || continue
778+ 3 <= length (stmt. args) <= 4 || continue
779779 # Inlining performs legality checks on the finalizer to determine
780780 # whether or not we may inline it. If so, it appends extra arguments
781781 # at the end of the intrinsic. Detect that here.
782- length (stmt. args) == 5 || continue
782+ length (stmt. args) == 4 || continue
783783 is_finalizer = true
784784 elseif isexpr (stmt, :foreigncall )
785785 nccallargs = length (stmt. args[3 ]:: SimpleVector )
@@ -940,44 +940,40 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing, InliningState} = nothin
940940 used_ssas = copy (compact. used_ssas)
941941 simple_dce! (compact, (x:: SSAValue ) -> used_ssas[x. id] -= 1 )
942942 ir = complete (compact)
943- sroa_mutables! (ir, defuses, used_ssas, lazydomtree, inlining )
943+ sroa_mutables! (ir, defuses, used_ssas, lazydomtree)
944944 return ir
945945 else
946946 simple_dce! (compact)
947947 return complete (compact)
948948 end
949949end
950950
951- function try_inline_finalizer! (ir:: IRCode , argexprs:: Vector{Any} , idx:: Int , mi:: MethodInstance , inlining:: InliningState )
952- code = get (inlining. mi_cache, mi, nothing )
953- if code isa CodeInstance
954- if use_const_api (code)
955- # No code in the function - Nothing to do
956- inlining. et != = nothing && push! (inlining. et, mi)
957- return true
958- end
959- src = code. inferred
960- else
961- src = code
951+ function inline_finalizer! (ir:: IRCode , argexprs:: Vector{Any} , idx:: Int , @nospecialize (case))
952+ if isa (case, ConstantCase)
953+ # No code in the function - Nothing to do
954+ return true
955+ elseif isa (case, InvokeCase)
956+ insert_node! (ir, idx, NewInstruction (Expr (:invoke , case. invoke, argexprs... ), Nothing), true )
957+ return true
958+ elseif case === nothing
959+ @assert false " this case should never happen"
962960 end
963961
964- src = inlining_policy (inlining . interp, src, IR_FLAG_NULL, mi, Any[])
965- src === nothing && return false
966- src = retrieve_ir_for_inlining (mi, src)
962+ # now try to inline the finalizer body
963+ (; mi, spec) = case :: InliningTodo
964+ src = (spec :: ResolvedInliningSpec ) . ir
967965
968966 # For now: Require finalizer to only have one basic block
969967 length (src. cfg. blocks) == 1 || return false
970968
971969 # Ok, we're committed to inlining the finalizer
972- inlining. et != = nothing && push! (inlining. et, mi)
973970
974971 linetable_offset, extra_coverage_line = ir_inline_linetable! (ir. linetable, src, mi. def, ir[SSAValue (idx)][:line ])
975972 if extra_coverage_line != 0
976973 insert_node! (ir, idx, NewInstruction (Expr (:code_coverage_effect ), Nothing, extra_coverage_line))
977974 end
978975
979- # TODO : Use the actual inliner here rather than open coding this special
980- # purpose inliner.
976+ # TODO : Use the actual inliner here rather than open coding this special purpose inliner.
981977 spvals = mi. sparam_vals
982978 ssa_rename = Vector {Any} (undef, length (src. stmts))
983979 for idx′ = 1 : length (src. stmts)
1002998
1003999is_nothrow (ir:: IRCode , pc:: Int ) = ir. stmts[pc][:flag ] & (IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW) ≠ 0
10041000
1005- function try_inline_finalizer! (ir:: IRCode , idx:: Int , finalizer_idx:: Int , defuse:: SSADefUse , inlining :: InliningState )
1001+ function try_inline_finalizer! (ir:: IRCode , idx:: Int , finalizer_idx:: Int , defuse:: SSADefUse )
10061002 # For now: Require that all uses and defs are in the same basic block,
10071003 # so that live range calculations are easy.
10081004 bb = ir. cfg. blocks[block_for_inst (ir. cfg, first (defuse. uses). idx)]
@@ -1025,40 +1021,30 @@ function try_inline_finalizer!(ir::IRCode, idx::Int, finalizer_idx::Int, defuse:
10251021 return true
10261022 end
10271023
1028- check_in_range (idx) || return
1029- _all (check_in_range, defuse. uses) || return
1030- _all (check_in_range, defuse. defs) || return
1024+ check_in_range (idx) || return nothing
1025+ _all (check_in_range, defuse. uses) || return nothing
1026+ _all (check_in_range, defuse. defs) || return nothing
10311027
10321028 # For now: Require all statements in the basic block range to be nothrow.
10331029 _all (minval: maxval) do idx:: Int
10341030 return is_nothrow (ir, idx) || idx == finalizer_idx
1035- end || return
1031+ end || return nothing
10361032
10371033 # Ok, finalizer rewrite is legal.
10381034 finalizer_stmt = ir[SSAValue (finalizer_idx)][:inst ]
10391035 argexprs = Any[finalizer_stmt. args[2 ], finalizer_stmt. args[3 ]]
1040- mi = finalizer_stmt. args[5 ]:: MethodInstance
1041- if finalizer_stmt. args[4 ]:: Bool # may inline
1042- if try_inline_finalizer! (ir, argexprs, maxval, mi, inlining)
1043- @goto done_finalizer
1044- end
1045- mi = compileable_specialization (inlining. et, mi, Effects ()). invoke
1046- end
1047- if mi != = nothing
1048- insert_node! (ir, maxval,
1049- NewInstruction (Expr (:invoke , mi, argexprs... ), Nothing),
1050- true )
1036+ case = finalizer_stmt. args[4 ]
1037+ if inline_finalizer! (ir, argexprs, maxval, case)
1038+ # Erase call to finalizer
1039+ ir[SSAValue (finalizer_idx)][:inst ] = nothing
10511040 else
1052- insert_node! (ir, maxval,
1053- NewInstruction (Expr (:call , argexprs... ), Nothing),
1054- true )
1041+ pop! (finalizer_stmt. args)
1042+ @assert length (finalizer_stmt. args) == 3
10551043 end
1056- @label done_finalizer
1057- # Erase call to finalizer
1058- ir[SSAValue (finalizer_idx)][:inst ] = nothing
1044+ return nothing
10591045end
10601046
1061- function sroa_mutables! (ir:: IRCode , defuses:: IdDict{Int, Tuple{SPCSet, SSADefUse}} , used_ssas:: Vector{Int} , lazydomtree:: LazyDomtree , inlining :: Union{Nothing, InliningState} )
1047+ function sroa_mutables! (ir:: IRCode , defuses:: IdDict{Int, Tuple{SPCSet, SSADefUse}} , used_ssas:: Vector{Int} , lazydomtree:: LazyDomtree )
10621048 for (idx, (intermediaries, defuse)) in defuses
10631049 intermediaries = collect (intermediaries)
10641050 # Check if there are any uses we did not account for. If so, the variable
@@ -1090,8 +1076,8 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse
10901076 finalizer_idx = use. idx
10911077 end
10921078 end
1093- if finalizer_idx != = nothing && inlining != = nothing
1094- try_inline_finalizer! (ir, idx, finalizer_idx, defuse, inlining )
1079+ if finalizer_idx != = nothing
1080+ try_inline_finalizer! (ir, idx, finalizer_idx, defuse)
10951081 continue
10961082 end
10971083 # Partition defuses by field
0 commit comments