Skip to content

Commit

Permalink
EA: some noncritical updates on EA (#51292)
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk authored and NHDaly committed Sep 20, 2023
1 parent 386876f commit 35791e2
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 188 deletions.
2 changes: 1 addition & 1 deletion base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ export CodeInfo, MethodInstance, CodeInstance, GotoNode, GotoIfNot, ReturnNode,
PiNode, PhiNode, PhiCNode, UpsilonNode, LineInfoNode,
Const, PartialStruct, InterConditional

import Core: CodeInfo, MethodInstance, CodeInstance, GotoNode, GotoIfNot, ReturnNode,
using Core: CodeInfo, MethodInstance, CodeInstance, GotoNode, GotoIfNot, ReturnNode,
NewvarNode, SSAValue, SlotNumber, Argument,
PiNode, PhiNode, PhiCNode, UpsilonNode, LineInfoNode,
Const, PartialStruct, InterConditional
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/bootstrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ time() = ccall(:jl_clock_now, Float64, ())

let interp = NativeInterpreter()

analyze_escapes_tt = Tuple{typeof(analyze_escapes), IRCode, Int, Bool, typeof(null_escape_cache)}
# analyze_escapes_tt = Tuple{typeof(analyze_escapes), IRCode, Int, Bool, typeof(null_escape_cache)}
fs = Any[
# we first create caches for the optimizer, because they contain many loop constructions
# and they're better to not run in interpreter even during bootstrapping
Expand Down
101 changes: 38 additions & 63 deletions base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,22 @@ const _TOP_MOD = ccall(:jl_base_relative_to, Any, (Any,), EscapeAnalysis)::Modul
# imports
import ._TOP_MOD: ==, getindex, setindex!
# usings
import Core:
MethodInstance, Const, Argument, SSAValue, PiNode, PhiNode, UpsilonNode, PhiCNode,
ReturnNode, GotoNode, GotoIfNot, SimpleVector, MethodMatch, CodeInstance,
sizeof, ifelse, arrayset, arrayref, arraysize
import ._TOP_MOD: # Base definitions
@__MODULE__, @eval, @assert, @specialize, @nospecialize, @inbounds, @inline, @noinline,
@label, @goto, !, !==, !=, , +, -, *, , <, , >, &, |, <<, error, missing, copy,
Vector, BitSet, IdDict, IdSet, UnitRange, Csize_t, Callable, , , , :, , , =>,
in, length, get, first, last, haskey, keys, get!, isempty, isassigned,
pop!, push!, pushfirst!, empty!, delete!, max, min, enumerate, unwrap_unionall,
ismutabletype
import Core.Compiler: # Core.Compiler specific definitions
Bottom, InferenceResult, IRCode, IR_FLAG_NOTHROW, SimpleInferenceLattice,
isbitstype, isexpr, is_meta_expr_head, println, widenconst, argextype, singleton_type,
fieldcount_noerror, try_compute_field, try_compute_fieldidx, hasintersect, ,
intrinsic_nothrow, array_builtin_common_typecheck, arrayset_typecheck,
setfield!_nothrow, alloc_array_ndims, check_effect_free!
using Core:
MethodMatch, SimpleVector,
arrayref, arrayset, arraysize, ifelse, sizeof
using Core.IR
using ._TOP_MOD: # Base definitions
@__MODULE__, @assert, @eval, @goto, @inbounds, @inline, @label, @noinline,
@nospecialize, @specialize, BitSet, Callable, Csize_t, IdDict, IdSet, UnitRange, Vector,
copy, delete!, empty!, enumerate, error, first, get, get!, haskey, in, isassigned,
isempty, ismutabletype, keys, last, length, max, min, missing, pop!, push!, pushfirst!,
unwrap_unionall, !, !=, !==, &, *, +, -, :, <, <<, =>, >, |, , , , , , , ,
using Core.Compiler: # Core.Compiler specific definitions
Bottom, IRCode, IR_FLAG_NOTHROW, InferenceResult, SimpleInferenceLattice,
alloc_array_ndims, argextype, array_builtin_common_typecheck, arrayset_typecheck,
check_effect_free!, fieldcount_noerror, hasintersect, intrinsic_nothrow,
is_meta_expr_head, isbitstype, isexpr, println, setfield!_nothrow, singleton_type,
try_compute_field, try_compute_fieldidx, widenconst,

include(x) = _TOP_MOD.include(@__MODULE__, x)
if _TOP_MOD === Core.Compiler
Expand Down Expand Up @@ -97,16 +96,14 @@ struct EscapeInfo
ReturnEscape::Bool,
ThrownEscape::LivenessSet,
AliasInfo#=::Union{IndexableFields,IndexableElements,Unindexable,Bool}=#,
Liveness::LivenessSet,
)
Liveness::LivenessSet)
@nospecialize AliasInfo
return new(
Analyzed,
ReturnEscape,
ThrownEscape,
AliasInfo,
Liveness,
)
Liveness)
end
function EscapeInfo(
x::EscapeInfo,
Expand All @@ -116,16 +113,14 @@ struct EscapeInfo
Analyzed::Bool = x.Analyzed,
ReturnEscape::Bool = x.ReturnEscape,
ThrownEscape::LivenessSet = x.ThrownEscape,
Liveness::LivenessSet = x.Liveness,
)
Liveness::LivenessSet = x.Liveness)
@nospecialize AliasInfo
return new(
Analyzed,
ReturnEscape,
ThrownEscape,
AliasInfo,
Liveness,
)
Liveness)
end
end

Expand Down Expand Up @@ -638,15 +633,6 @@ struct AnalysisState{T<:Callable}
get_escape_cache::T
end

function getinst(ir::IRCode, idx::Int)
nstmts = length(ir.stmts)
if idx nstmts
return ir.stmts[idx]
else
return ir.new_nodes.stmts[idx - nstmts]
end
end

"""
analyze_escapes(ir::IRCode, nargs::Int, call_resolved::Bool, get_escape_cache::Callable)
-> estate::EscapeState
Expand All @@ -671,7 +657,7 @@ function analyze_escapes(ir::IRCode, nargs::Int, call_resolved::Bool, get_escape
local anyupdate = false

for pc in nstmts:-1:1
stmt = getinst(ir, pc)[:stmt]
stmt = ir[SSAValue(pc)][:stmt]

# collect escape information
if isa(stmt, Expr)
Expand Down Expand Up @@ -783,7 +769,7 @@ function compute_frameinfo(ir::IRCode, call_resolved::Bool)
callinfo = nothing
end
for idx in 1:nstmts+nnewnodes
inst = getinst(ir, idx)
inst = ir[SSAValue(idx)]
stmt = inst[:stmt]
if !call_resolved
# TODO don't call `check_effect_free!` in the inlinear
Expand Down Expand Up @@ -1079,7 +1065,7 @@ end
error("unexpected assignment found: inspect `Main.pc` and `Main.pc`")
end

is_nothrow(ir::IRCode, pc::Int) = getinst(ir, pc)[:flag] & IR_FLAG_NOTHROW 0
is_nothrow(ir::IRCode, pc::Int) = ir[SSAValue(pc)][:flag] & IR_FLAG_NOTHROW 0

# NOTE if we don't maintain the alias set that is separated from the lattice state, we can do
# something like below: it essentially incorporates forward escape propagation in our default
Expand Down Expand Up @@ -1882,7 +1868,7 @@ function array_isassigned_nothrow(args::Vector{Any}, src::IRCode)
end

# # COMBAK do we want to enable this (and also backport this to Base for array allocations?)
# import Core.Compiler: Cint, svec
# using Core.Compiler: Cint, svec
# function validate_foreigncall_args(args::Vector{Any},
# name::Symbol, @nospecialize(rt), argtypes::SimpleVector, nreq::Int, convention::Symbol)
# length(args) ≥ 5 || return false
Expand All @@ -1893,30 +1879,19 @@ end
# normalize(args[5]) === convention || return false
# return true
# end

if isdefined(Core, :ImmutableArray)

import Core: ImmutableArray, arrayfreeze, mutating_arrayfreeze, arraythaw

escape_builtin!(::typeof(arrayfreeze), astate::AnalysisState, pc::Int, args::Vector{Any}) =
is_safe_immutable_array_op(Array, astate, args)
escape_builtin!(::typeof(mutating_arrayfreeze), astate::AnalysisState, pc::Int, args::Vector{Any}) =
is_safe_immutable_array_op(Array, astate, args)
escape_builtin!(::typeof(arraythaw), astate::AnalysisState, pc::Int, args::Vector{Any}) =
is_safe_immutable_array_op(ImmutableArray, astate, args)
function is_safe_immutable_array_op(@nospecialize(arytype), astate::AnalysisState, args::Vector{Any})
length(args) == 2 || return false
argextype(args[2], astate.ir) arytype || return false
return true
end

end # if isdefined(Core, :ImmutableArray)

if _TOP_MOD !== Core.Compiler
# NOTE define fancy package utilities when developing EA as an external package
include("EAUtils.jl")
using .EAUtils
export code_escapes, @code_escapes, __clear_cache!
end
#
# using Core: ImmutableArray, arrayfreeze, mutating_arrayfreeze, arraythaw
#
# escape_builtin!(::typeof(arrayfreeze), astate::AnalysisState, pc::Int, args::Vector{Any}) =
# is_safe_immutable_array_op(Array, astate, args)
# escape_builtin!(::typeof(mutating_arrayfreeze), astate::AnalysisState, pc::Int, args::Vector{Any}) =
# is_safe_immutable_array_op(Array, astate, args)
# escape_builtin!(::typeof(arraythaw), astate::AnalysisState, pc::Int, args::Vector{Any}) =
# is_safe_immutable_array_op(ImmutableArray, astate, args)
# function is_safe_immutable_array_op(@nospecialize(arytype), astate::AnalysisState, args::Vector{Any})
# length(args) == 2 || return false
# argextype(args[2], astate.ir) ⊑ arytype || return false
# return true
# end

end # baremodule EscapeAnalysis
9 changes: 5 additions & 4 deletions base/compiler/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -390,11 +390,12 @@ function block_for_inst(ir::IRCode, inst::Int)
block_for_inst(ir.cfg, inst)
end

function getindex(x::IRCode, s::SSAValue)
if s.id <= length(x.stmts)
return x.stmts[s.id]
function getindex(ir::IRCode, s::SSAValue)
nstmts = length(ir.stmts)
if s.id <= nstmts
return ir.stmts[s.id]
else
return x.new_nodes.stmts[s.id - length(x.stmts)]
return ir.new_nodes.stmts[s.id - nstmts]
end
end

Expand Down
5 changes: 1 addition & 4 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,7 @@ end

function maybe_compress_codeinfo(interp::AbstractInterpreter, linfo::MethodInstance, ci::CodeInfo)
def = linfo.def
toplevel = !isa(def, Method)
if toplevel
return ci
end
isa(def, Method) || return ci # don't compress toplevel code
if may_discard_trees(interp)
cache_the_tree = ci.inferred && (is_inlineable(ci) || isa_compileable_sig(linfo.specTypes, linfo.sparam_vals, def))
else
Expand Down
9 changes: 8 additions & 1 deletion doc/src/devdocs/EscapeAnalysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@ This escape analysis aims to:
You can give a try to the escape analysis by loading the `EAUtils.jl` utility script that
define the convenience entries `code_escapes` and `@code_escapes` for testing and debugging purposes:
```@repl EAUtils
include(normpath(Sys.BINDIR, "..", "share", "julia", "test", "compiler", "EscapeAnalysis", "EAUtils.jl")); using .EAUtils
let JULIA_DIR = normpath(Sys.BINDIR, "..", "share", "julia")
# load `EscapeAnalysis` module to define the core analysis code
include(normpath(JULIA_DIR, "base", "compiler", "ssair", "EscapeAnalysis", "EscapeAnalysis.jl"))
using .EscapeAnalysis
# load `EAUtils` module to define the utilities
include(normpath(JULIA_DIR, "test", "compiler", "EscapeAnalysis", "EAUtils.jl"))
using .EAUtils
end
mutable struct SafeRef{T}
x::T
Expand Down
Loading

0 comments on commit 35791e2

Please sign in to comment.