Skip to content

Commit

Permalink
Merge branch 'master' into oc-const
Browse files Browse the repository at this point in the history
  • Loading branch information
tkf committed Oct 21, 2021
2 parents 07f06d5 + 76c2431 commit e38184c
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .buildkite/pipelines/main/platforms/tester_linux.arches
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# linux _armv7l false _armv7l armv7l none 60 no no no v3.2 fb359370b052a47ce5c84cc6b4a7a03ed7053b25
linux 32 false 32 i686 none 60 no no no v3.2 209c4db679a515befd7fb50ecc6bfbecf7ec3d32
# linux _ppc64le false _ppc64le powerpc64le none 60 no no no v3.2 c03a0158b19d48ac84b426834fce0d3584cdd0c7
linux 64_rr false 64 x86_64 none 60 yes no no v3.2 474bf61a926b2d7fcf202284d59d4b11a04601d7
linux 64_rr false 64 x86_64 none 180 yes no no v3.2 474bf61a926b2d7fcf202284d59d4b11a04601d7
linux 64_st false 64 x86_64 none 60 no yes no v3.2 474bf61a926b2d7fcf202284d59d4b11a04601d7
linux 64_mt false 64 x86_64 none 60 no no yes v3.2 474bf61a926b2d7fcf202284d59d4b11a04601d7
musl 64 true 64 x86_64 none 60 no no no v3.19 e6a2730e37c386c46915b2650d6aaaa398195152
25 changes: 10 additions & 15 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -317,31 +317,26 @@ function optimize(interp::AbstractInterpreter, opt::OptimizationState, params::O
end

function run_passes(ci::CodeInfo, sv::OptimizationState)
preserve_coverage = coverage_enabled(sv.mod)
ir = convert_to_ircode(ci, copy_exprargs(ci.code), preserve_coverage, sv)
ir = slot2reg(ir, ci, sv)
#@Base.show ("after_construct", ir)
@timeit "convert" ir = convert_to_ircode(ci, sv)
@timeit "slot2reg" ir = slot2reg(ir, ci, sv)
# TODO: Domsorting can produce an updated domtree - no need to recompute here
@timeit "compact 1" ir = compact!(ir)
@timeit "Inlining" ir = ssa_inlining_pass!(ir, ir.linetable, sv.inlining, ci.propagate_inbounds)
#@timeit "verify 2" verify_ir(ir)
ir = compact!(ir)
#@Base.show ("before_sroa", ir)
@timeit "SROA" ir = getfield_elim_pass!(ir)
#@Base.show ir.new_nodes
#@Base.show ("after_sroa", ir)
ir = adce_pass!(ir)
#@Base.show ("after_adce", ir)
@timeit "Inlining" ir = ssa_inlining_pass!(ir, ir.linetable, sv.inlining, ci.propagate_inbounds)
# @timeit "verify 2" verify_ir(ir)
@timeit "compact 2" ir = compact!(ir)
@timeit "SROA" ir = getfield_elim_pass!(ir)
@timeit "ADCE" ir = adce_pass!(ir)
@timeit "type lift" ir = type_lift_pass!(ir)
@timeit "compact 3" ir = compact!(ir)
#@Base.show ir
if JLOptions().debug_level == 2
@timeit "verify 3" (verify_ir(ir); verify_linetable(ir.linetable))
end
return ir
end

function convert_to_ircode(ci::CodeInfo, code::Vector{Any}, coverage::Bool, sv::OptimizationState)
function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)
code = copy_exprargs(ci.code)
coverage = coverage_enabled(sv.mod)
# Go through and add an unreachable node after every
# Union{} call. Then reindex labels.
idx = 1
Expand Down
5 changes: 5 additions & 0 deletions base/compiler/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1467,3 +1467,8 @@ function iterate(x::BBIdxIter, (idx, bb)::Tuple{Int, Int}=(1, 1))
end
return (bb, idx), (idx + 1, next_bb)
end

is_known_call(e::Expr, @nospecialize(func), ir::IRCode) =
is_known_call(e, func, ir, ir.sptypes, ir.argtypes)

argextype(@nospecialize(x), ir::IRCode) = argextype(x, ir, ir.sptypes, ir.argtypes)
50 changes: 31 additions & 19 deletions base/compiler/ssair/passes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,10 @@ function lift_comparison!(compact::IncrementalCompact, idx::Int,
lifted_val = perform_lifting!(compact, visited_phinodes, cmp, lifting_cache, Bool, lifted_leaves, val)
@assert lifted_val !== nothing

#global assertion_counter
#assertion_counter::Int += 1
#insert_node_here!(compact, Expr(:assert_egal, Symbol(string("assert_egal_", assertion_counter)), SSAValue(idx), lifted_val), nothing, 0, true)
#return
# global assertion_counter
# assertion_counter::Int += 1
# insert_node_here!(compact, Expr(:assert_egal, Symbol(string("assert_egal_", assertion_counter)), SSAValue(idx), lifted_val), nothing, 0, true)
# return
compact[idx] = lifted_val.x
end

Expand Down Expand Up @@ -734,17 +734,6 @@ function getfield_elim_pass!(ir::IRCode)
result_t = make_MaybeUndef(result_t)
end

# @Base.show result_t
# @Base.show stmt
# for (k,v) in lifted_leaves
# @Base.show (k, v)
# if isa(k, AnySSAValue)
# @Base.show compact[k]
# end
# if isa(v, RefValue) && isa(v.x, AnySSAValue)
# @Base.show compact[v.x]
# end
# end
val = perform_lifting!(compact, visited_phinodes, field, lifting_cache, result_t, lifted_leaves, stmt.args[2])

# Insert the undef check if necessary
Expand All @@ -761,8 +750,8 @@ function getfield_elim_pass!(ir::IRCode)

# global assertion_counter
# assertion_counter::Int += 1
#insert_node_here!(compact, Expr(:assert_egal, Symbol(string("assert_egal_", assertion_counter)), SSAValue(idx), val), nothing, 0, true)
#continue
# insert_node_here!(compact, Expr(:assert_egal, Symbol(string("assert_egal_", assertion_counter)), SSAValue(idx), val), nothing, 0, true)
# continue
compact[idx] = val === nothing ? nothing : val.x
end

Expand Down Expand Up @@ -894,7 +883,8 @@ function getfield_elim_pass!(ir::IRCode)
ir[SSAValue(use)] = new_expr
end
end
ir

return ir
end
# assertion_counter = 0

Expand Down Expand Up @@ -935,7 +925,21 @@ end
"""
adce_pass!(ir::IRCode) -> newir::IRCode
Aggressive Dead Code Elimination pass to eliminate code.
Aggressive Dead Code Elimination pass.
In addition to a simple DCE for unused values and allocations,
this pass also nullifies `typeassert` calls that can be proved to be no-op,
in order to allow LLVM to emit simpler code down the road.
Note that this pass is more effective after SROA optimization (i.e. `getfield_elim_pass!`),
since SROA often allows this pass to:
- eliminate allocation of object whose field references are all replaced with scalar values, and
- nullify `typeassert` call whose first operand has been replaced with a scalar value
(, which may have introduced new type information that inference did not understand)
Also note that currently this pass _needs_ to run after `getfield_elim_pass!`, because
the `typeassert` elimination depends on the transformation within `getfield_elim_pass!`
which redirects references of `typeassert`ed value to the corresponding `PiNode`.
"""
function adce_pass!(ir::IRCode)
phi_uses = fill(0, length(ir.stmts) + length(ir.new_nodes))
Expand All @@ -944,6 +948,14 @@ function adce_pass!(ir::IRCode)
for ((_, idx), stmt) in compact
if isa(stmt, PhiNode)
push!(all_phis, idx)
elseif isexpr(stmt, :call)
# nullify safe `typeassert` calls
if is_known_call(stmt, typeassert, compact) && length(stmt.args) == 3
ty, isexact = instanceof_tfunc(compact_exprtype(compact, stmt.args[3]))
if isexact && compact_exprtype(compact, stmt.args[2]) ty
compact[idx] = nothing
end
end
end
end
non_dce_finish!(compact)
Expand Down
3 changes: 2 additions & 1 deletion base/namedtuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ function show(io::IO, t::NamedTuple)
typeinfo = get(io, :typeinfo, Any)
print(io, "(")
for i = 1:n
print(io, fieldname(typeof(t),i), " = ")
show_sym(io, fieldname(typeof(t), i))
print(io, " = ")
show(IOContext(io, :typeinfo =>
t isa typeinfo <: NamedTuple ? fieldtype(typeinfo, i) : Any),
getfield(t, i))
Expand Down
17 changes: 16 additions & 1 deletion src/dlload.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
uv_stat_t stbuf;
void *handle;
int abspath;
int is_atpath;
// number of extensions to try — if modname already ends with the
// standard extension, then we don't try adding additional extensions
int n_extensions = endswith_extension(modname) ? 1 : N_EXTENSIONS;
Expand All @@ -181,16 +182,30 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
}

abspath = jl_isabspath(modname);
is_atpath = 0;

// Detect if our `modname` is something like `@rpath/libfoo.dylib`
#ifdef _OS_DARWIN_
size_t nameLen = strlen(modname);
const char *const atPaths[] = {"@executable_path/", "@loader_path/", "@rpath/"};
for (i = 0; i < sizeof(atPaths)/sizeof(char*); ++i) {
size_t atLen = strlen(atPaths[i]);
if (nameLen >= atLen && 0 == strncmp(modname, atPaths[i], atLen)) {
is_atpath = 1;
}
}
#endif

/*
this branch permutes all base paths in DL_LOAD_PATH with all extensions
note: skip when !jl_base_module to avoid UndefVarError(:DL_LOAD_PATH),
and also skip for absolute paths
and also skip for `@`-paths on macOS
We also do simple string replacement here for elements starting with `@executable_path/`.
While these exist as OS concepts on Darwin, we want to use them on other platforms
such as Windows, so we emulate them here.
*/
if (!abspath && jl_base_module != NULL) {
if (!abspath && !is_atpath && jl_base_module != NULL) {
jl_binding_t *b = jl_get_module_binding(jl_base_module, jl_symbol("DL_LOAD_PATH"));
jl_array_t *DL_LOAD_PATH = (jl_array_t*)(b ? jl_atomic_load_relaxed(&b->value) : NULL);
if (DL_LOAD_PATH != NULL) {
Expand Down
3 changes: 1 addition & 2 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3422,8 +3422,7 @@ let
ci.ssavaluetypes = Any[Any for i = 1:ci.ssavaluetypes]
sv = Core.Compiler.OptimizationState(mi, Core.Compiler.OptimizationParams(),
Core.Compiler.NativeInterpreter())
ir = Core.Compiler.convert_to_ircode(ci, Core.Compiler.copy_exprargs(ci.code),
false, sv)
ir = Core.Compiler.convert_to_ircode(ci, sv)
ir = Core.Compiler.slot2reg(ir, ci, sv)
ir = Core.Compiler.compact!(ir)
Core.Compiler.replace_code_newstyle!(ci, ir, 4)
Expand Down
29 changes: 29 additions & 0 deletions test/compiler/irpasses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -425,3 +425,32 @@ let # `getfield_elim_pass!` should work with constant globals
return Meta.isexpr(stmt, :new)
end
end

let # `typeassert_elim_pass!`
src = @eval Module() begin
struct Foo; x; end

code_typed((Int,)) do a
x1 = Foo(a)
x2 = Foo(x1)
x3 = Foo(x2)

r1 = (x2.x::Foo).x
r2 = (x2.x::Foo).x::Int
r3 = (x2.x::Foo).x::Integer
r4 = ((x3.x::Foo).x::Foo).x

return r1, r2, r3, r4
end |> only |> first
end
# eliminate `typeassert(f2.a, Foo)`
@test all(src.code) do @nospecialize(stmt)
Meta.isexpr(stmt, :call) || return true
ft = Core.Compiler.argextype(stmt.args[1], src, Any[], src.slottypes)
return Core.Compiler.widenconst(ft) !== typeof(typeassert)
end
# succeeding simple DCE will eliminate `Foo(a)`
@test all(src.code) do @nospecialize(stmt)
return !Meta.isexpr(stmt, :new)
end
end
6 changes: 6 additions & 0 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1843,6 +1843,12 @@ end
# issue #34343
@test showstr([[1], Int[]]) == "[[1], $Int[]]"
@test showstr([Dict(1=>1), Dict{Int,Int}()]) == "[Dict(1 => 1), Dict{$Int, $Int}()]"

# issue #42719, NamedTuple with @var_str
@test replstr((; var"a b"=1)) == """(var"a b" = 1,)"""
@test replstr((; var"#var#"=1)) == """(var"#var#" = 1,)"""
@test replstr((; var"a"=1, b=2)) == "(a = 1, b = 2)"
@test replstr((; a=1, b=2)) == "(a = 1, b = 2)"
end

@testset "#14684: `display` should print associative types in full" begin
Expand Down

0 comments on commit e38184c

Please sign in to comment.