@@ -626,47 +626,51 @@ end
626626GetNativeEscapeCache (interp:: AbstractInterpreter ) = GetNativeEscapeCache (code_cache (interp))
627627function ((; code_cache):: GetNativeEscapeCache )(mi:: MethodInstance )
628628 codeinst = get (code_cache, mi, nothing )
629- codeinst isa CodeInstance || return false
630- argescapes = traverse_analysis_results (codeinst) do @nospecialize result
629+ codeinst isa CodeInstance || return nothing
630+ return traverse_analysis_results (codeinst) do @nospecialize result
631631 return result isa EscapeAnalysis. ArgEscapeCache ? result : nothing
632632 end
633- if argescapes != = nothing
634- return argescapes
635- end
636- effects = decode_effects (codeinst . ipo_purity_bits )
637- if is_effect_free (effects) && is_inaccessiblememonly (effects)
638- # We might not have run EA on simple frames without any escapes (e.g. when optimization
639- # is skipped when result is constant-folded by abstract interpretation). If those
640- # frames aren't inlined, the accuracy of EA for caller context takes a big hit.
641- # This is a HACK to avoid that, but obviously, a more comprehensive fix would be ideal.
642- return true
643- end
644- return false
633+ end
634+
635+ analyze_and_cache_escapes! (interp :: AbstractInterpreter , opt :: OptimizationState , sv :: PostOptAnalysisState ) =
636+ analyze_and_cache_escapes! (interp, opt, sv . ir, sv . result )
637+
638+ function analyze_and_cache_escapes! (interp :: AbstractInterpreter , opt :: OptimizationState ,
639+ ir :: IRCode , result :: InferenceResult )
640+ nargs = Int (opt . src . nargs)
641+ estate = EscapeAnalysis . analyze_escapes (ir, nargs, optimizer_lattice (interp), get_escape_cache (interp))
642+ argescapes = EscapeAnalysis . ArgEscapeCache (estate)
643+ stack_analysis_result! (result, argescapes)
644+ return estate
645645end
646646
647647function refine_effects! (interp:: AbstractInterpreter , opt:: OptimizationState , sv:: PostOptAnalysisState )
648+ EA_cached = false
648649 if ! is_effect_free (sv. result. ipo_effects) && sv. all_effect_free && ! isempty (sv. ea_analysis_pending)
649- ir = sv. ir
650- nargs = Int (opt. src. nargs)
651- estate = EscapeAnalysis. analyze_escapes (ir, nargs, optimizer_lattice (interp), get_escape_cache (interp))
652- argescapes = EscapeAnalysis. ArgEscapeCache (estate)
653- stack_analysis_result! (sv. result, argescapes)
650+ estate = analyze_and_cache_escapes! (interp, opt, sv)
654651 validate_mutable_arg_escapes! (estate, sv)
652+ EA_cached = true
655653 end
656654
657- any_refinable (sv) || return false
658655 effects = sv. result. ipo_effects
659- sv. result. ipo_effects = Effects (effects;
656+ any_refinable (sv) || @goto run_EA_on_simple_frame
657+ effects = sv. result. ipo_effects = Effects (effects;
660658 consistent = sv. all_retpaths_consistent ? ALWAYS_TRUE : effects. consistent,
661659 effect_free = sv. all_effect_free ? ALWAYS_TRUE :
662- sv. effect_free_if_argmem_only === true ? EFFECT_FREE_IF_INACCESSIBLEMEMONLY : effects. effect_free,
660+ sv. effect_free_if_argmem_only === true ? EFFECT_FREE_IF_INACCESSIBLEMEMONLY : effects. effect_free,
663661 nothrow = sv. all_nothrow ? true : effects. nothrow,
664662 noub = sv. all_noub ? (sv. any_conditional_ub ? NOUB_IF_NOINBOUNDS : ALWAYS_TRUE) : effects. noub,
665663 nortcall = sv. nortcall ? true : effects. nortcall)
666- return true
664+
665+ @label run_EA_on_simple_frame
666+ if ! EA_cached && is_effect_free (effects) && is_inaccessiblememonly (effects)
667+ analyze_and_cache_escapes! (interp, opt, sv)
668+ end
669+
670+ nothing
667671end
668672
669- function is_ipo_dataflow_analysis_profitable (effects:: Effects )
673+ function is_ipo_effects_refinable (effects:: Effects )
670674 return ! (is_consistent (effects) && is_effect_free (effects) &&
671675 is_nothrow (effects) && is_noub (effects))
672676end
941945
942946function ipo_dataflow_analysis! (interp:: AbstractInterpreter , opt:: OptimizationState ,
943947 ir:: IRCode , result:: InferenceResult )
944- if ! is_ipo_dataflow_analysis_profitable (result. ipo_effects)
945- return false
948+ if ! is_ipo_effects_refinable (result. ipo_effects)
949+ analyze_and_cache_escapes! (interp, opt, ir, result)
950+ return nothing
946951 end
947952
948953 @assert isempty (ir. new_nodes) " IRCode should be compacted before post-opt analysis"
@@ -968,7 +973,8 @@ function ipo_dataflow_analysis!(interp::AbstractInterpreter, opt::OptimizationSt
968973 end
969974 end
970975
971- return refine_effects! (interp, opt, sv)
976+ refine_effects! (interp, opt, sv)
977+ nothing
972978end
973979
974980# run the optimization work
0 commit comments