@@ -742,7 +742,7 @@ its argument).
742
742
In a case when all usages are fully eliminated, `struct` allocation may also be erased as
743
743
a result of succeeding dead code elimination.
744
744
"""
745
- function sroa_pass! (ir:: IRCode , inlining :: Union{Nothing, InliningState} = nothing )
745
+ function sroa_pass! (ir:: IRCode )
746
746
compact = IncrementalCompact (ir)
747
747
defuses = nothing # will be initialized once we encounter mutability in order to reduce dynamic allocations
748
748
lifting_cache = IdDict {Pair{AnySSAValue, Any}, AnySSAValue} ()
@@ -775,11 +775,11 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing, InliningState} = nothin
775
775
widenconst (field_ordering) === Bool && (field_ordering = :unspecified )
776
776
end
777
777
elseif is_known_call (stmt, Core. finalizer, compact)
778
- 3 <= length (stmt. args) <= 5 || continue
778
+ 3 <= length (stmt. args) <= 4 || continue
779
779
# Inlining performs legality checks on the finalizer to determine
780
780
# whether or not we may inline it. If so, it appends extra arguments
781
781
# at the end of the intrinsic. Detect that here.
782
- length (stmt. args) == 5 || continue
782
+ length (stmt. args) == 4 || continue
783
783
is_finalizer = true
784
784
elseif isexpr (stmt, :foreigncall )
785
785
nccallargs = length (stmt. args[3 ]:: SimpleVector )
@@ -940,44 +940,40 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing, InliningState} = nothin
940
940
used_ssas = copy (compact. used_ssas)
941
941
simple_dce! (compact, (x:: SSAValue ) -> used_ssas[x. id] -= 1 )
942
942
ir = complete (compact)
943
- sroa_mutables! (ir, defuses, used_ssas, lazydomtree, inlining )
943
+ sroa_mutables! (ir, defuses, used_ssas, lazydomtree)
944
944
return ir
945
945
else
946
946
simple_dce! (compact)
947
947
return complete (compact)
948
948
end
949
949
end
950
950
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"
962
960
end
963
961
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
967
965
968
966
# For now: Require finalizer to only have one basic block
969
967
length (src. cfg. blocks) == 1 || return false
970
968
971
969
# Ok, we're committed to inlining the finalizer
972
- inlining. et != = nothing && push! (inlining. et, mi)
973
970
974
971
linetable_offset, extra_coverage_line = ir_inline_linetable! (ir. linetable, src, mi. def, ir[SSAValue (idx)][:line ])
975
972
if extra_coverage_line != 0
976
973
insert_node! (ir, idx, NewInstruction (Expr (:code_coverage_effect ), Nothing, extra_coverage_line))
977
974
end
978
975
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.
981
977
spvals = mi. sparam_vals
982
978
ssa_rename = Vector {Any} (undef, length (src. stmts))
983
979
for idx′ = 1 : length (src. stmts)
1002
998
1003
999
is_nothrow (ir:: IRCode , pc:: Int ) = ir. stmts[pc][:flag ] & (IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW) ≠ 0
1004
1000
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 )
1006
1002
# For now: Require that all uses and defs are in the same basic block,
1007
1003
# so that live range calculations are easy.
1008
1004
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:
1025
1021
return true
1026
1022
end
1027
1023
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
1031
1027
1032
1028
# For now: Require all statements in the basic block range to be nothrow.
1033
1029
_all (minval: maxval) do idx:: Int
1034
1030
return is_nothrow (ir, idx) || idx == finalizer_idx
1035
- end || return
1031
+ end || return nothing
1036
1032
1037
1033
# Ok, finalizer rewrite is legal.
1038
1034
finalizer_stmt = ir[SSAValue (finalizer_idx)][:inst ]
1039
1035
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
1051
1040
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
1055
1043
end
1056
- @label done_finalizer
1057
- # Erase call to finalizer
1058
- ir[SSAValue (finalizer_idx)][:inst ] = nothing
1044
+ return nothing
1059
1045
end
1060
1046
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 )
1062
1048
for (idx, (intermediaries, defuse)) in defuses
1063
1049
intermediaries = collect (intermediaries)
1064
1050
# 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
1090
1076
finalizer_idx = use. idx
1091
1077
end
1092
1078
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)
1095
1081
continue
1096
1082
end
1097
1083
# Partition defuses by field
0 commit comments