Skip to content

Commit 1805791

Browse files
authored
Merge branch 'master' into new-heuristics
2 parents 78cbc8d + 879f6d4 commit 1805791

File tree

97 files changed

+1863
-1637
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+1863
-1637
lines changed

Make.inc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,6 +1500,12 @@ endef
15001500
# Overridable in Make.user
15011501
WINE ?= wine
15021502

1503+
ifeq ($(BINARY),32)
1504+
HEAPLIM := --heap-size-hint=500M
1505+
else
1506+
HEAPLIM :=
1507+
endif
1508+
15031509
# many of the following targets must be = not := because the expansion of the makefile functions (and $1) shouldn't happen until later
15041510
ifeq ($(BUILD_OS), WINNT) # MSYS
15051511
spawn = $(1)

base/compiler/abstractlattice.jl

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,19 +95,6 @@ end
9595
widenlattice(𝕃::InferenceLattice) = 𝕃.parent
9696
is_valid_lattice_norec(::InferenceLattice, @nospecialize(elem)) = isa(elem, LimitedAccuracy)
9797

98-
"""
99-
struct OptimizerLattice{𝕃<:AbstractLattice} <: AbstractLattice
100-
101-
The lattice used by the optimizer.
102-
Extends a base lattice `𝕃` and adjoins `MaybeUndef`.
103-
"""
104-
struct OptimizerLattice{𝕃<:AbstractLattice} <: AbstractLattice
105-
parent::𝕃
106-
end
107-
OptimizerLattice() = OptimizerLattice(SimpleInferenceLattice.instance)
108-
widenlattice(𝕃::OptimizerLattice) = 𝕃.parent
109-
is_valid_lattice_norec(::OptimizerLattice, @nospecialize(elem)) = isa(elem, MaybeUndef)
110-
11198
"""
11299
tmeet(𝕃::AbstractLattice, a, b::Type)
113100

base/compiler/inferencestate.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,9 @@ function kill_def_use!(tpdum::TwoPhaseDefUseMap, def::Int, use::Int)
148148
ndata = tpdum.data[idx+1]
149149
ndata == 0 && break
150150
tpdum.data[idx] = ndata
151+
idx += 1
151152
end
152-
tpdum.data[idx + 1] = 0
153+
tpdum.data[idx] = 0
153154
end
154155
end
155156
kill_def_use!(tpdum::TwoPhaseDefUseMap, def::SSAValue, use::Int) =

base/compiler/optimize.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,6 @@ function run_passes(
512512
@pass "compact 2" ir = compact!(ir)
513513
@pass "SROA" ir = sroa_pass!(ir, sv.inlining)
514514
@pass "ADCE" ir = adce_pass!(ir, sv.inlining)
515-
@pass "type lift" ir = type_lift_pass!(ir)
516515
@pass "compact 3" ir = compact!(ir)
517516
if JLOptions().debug_level == 2
518517
@timeit "verify 3" (verify_ir(ir); verify_linetable(ir.linetable))

base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import ._TOP_MOD: # Base definitions
2727
pop!, push!, pushfirst!, empty!, delete!, max, min, enumerate, unwrap_unionall,
2828
ismutabletype
2929
import Core.Compiler: # Core.Compiler specific definitions
30-
Bottom, OptimizerLattice, InferenceResult, IRCode, IR_FLAG_NOTHROW,
30+
Bottom, InferenceResult, IRCode, IR_FLAG_NOTHROW, SimpleInferenceLattice,
3131
isbitstype, isexpr, is_meta_expr_head, println, widenconst, argextype, singleton_type,
3232
fieldcount_noerror, try_compute_field, try_compute_fieldidx, hasintersect, ,
3333
intrinsic_nothrow, array_builtin_common_typecheck, arrayset_typecheck,
@@ -42,7 +42,7 @@ end
4242

4343
const AInfo = IdSet{Any}
4444
const LivenessSet = BitSet
45-
const 𝕃ₒ = OptimizerLattice()
45+
const 𝕃ₒ = SimpleInferenceLattice.instance
4646

4747
"""
4848
x::EscapeInfo
@@ -707,7 +707,6 @@ function analyze_escapes(ir::IRCode, nargs::Int, call_resolved::Bool, get_escape
707707
continue
708708
elseif head === :static_parameter || # this exists statically, not interested in its escape
709709
head === :copyast || # XXX can this account for some escapes?
710-
head === :undefcheck || # XXX can this account for some escapes?
711710
head === :isdefined || # just returns `Bool`, nothing accounts for any escapes
712711
head === :gc_preserve_begin || # `GC.@preserve` expressions themselves won't be used anywhere
713712
head === :gc_preserve_end # `GC.@preserve` expressions themselves won't be used anywhere

base/compiler/ssair/inlining.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ function fix_va_argexprs!(insert_node!::Inserter, inline_target::Union{IRCode, I
488488
push!(tuple_call.args, arg)
489489
push!(tuple_typs, argextype(arg, inline_target))
490490
end
491-
tuple_typ = tuple_tfunc(OptimizerLattice(), tuple_typs)
491+
tuple_typ = tuple_tfunc(SimpleInferenceLattice.instance, tuple_typs)
492492
tuple_inst = NewInstruction(tuple_call, tuple_typ, line_idx)
493493
push!(newargexprs, insert_node!(tuple_inst))
494494
return newargexprs

base/compiler/ssair/ir.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ function is_relevant_expr(e::Expr)
458458
:new, :splatnew, :(=), :(&),
459459
:gc_preserve_begin, :gc_preserve_end,
460460
:foreigncall, :isdefined, :copyast,
461-
:undefcheck, :throw_undef_if_not,
461+
:throw_undef_if_not,
462462
:cfunction, :method, :pop_exception,
463463
:new_opaque_closure)
464464
end

base/compiler/ssair/passes.jl

Lines changed: 31 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -360,10 +360,11 @@ struct LiftedValue
360360
LiftedValue(@nospecialize val) = new(val)
361361
end
362362
const LiftedLeaves = IdDict{Any, Union{Nothing,LiftedValue}}
363+
const LiftedDefs = IdDict{Any, Bool}
363364

364365
# try to compute lifted values that can replace `getfield(x, field)` call
365366
# where `x` is an immutable struct that are defined at any of `leaves`
366-
function lift_leaves(compact::IncrementalCompact, @nospecialize(result_t), field::Int,
367+
function lift_leaves(compact::IncrementalCompact, field::Int,
367368
leaves::Vector{Any}, 𝕃ₒ::AbstractLattice)
368369
# For every leaf, the lifted value
369370
lifted_leaves = LiftedLeaves()
@@ -393,15 +394,6 @@ function lift_leaves(compact::IncrementalCompact, @nospecialize(result_t), field
393394
continue
394395
end
395396
return nothing
396-
# Expand the Expr(:new) to include it's element Expr(:new) nodes up until the one we want
397-
compact[leaf] = nothing
398-
for i = (length(def.args) + 1):(1+field)
399-
ftyp = fieldtype(typ, i - 1)
400-
isbitstype(ftyp) || return nothing
401-
ninst = effect_free(NewInstruction(Expr(:new, ftyp), result_t))
402-
push!(def.args, insert_node!(compact, leaf, ninst))
403-
end
404-
compact[leaf] = def
405397
end
406398
lift_arg!(compact, leaf, cache_key, def, 1+field, lifted_leaves)
407399
continue
@@ -505,8 +497,6 @@ function walk_to_def(compact::IncrementalCompact, @nospecialize(leaf))
505497
return Pair{Any, Any}(def, leaf)
506498
end
507499

508-
make_MaybeUndef(@nospecialize(typ)) = isa(typ, MaybeUndef) ? typ : MaybeUndef(typ)
509-
510500
"""
511501
lift_comparison!(cmp, compact::IncrementalCompact, idx::Int, stmt::Expr, 𝕃ₒ::AbstractLattice)
512502
@@ -620,7 +610,7 @@ end
620610
struct SkipToken end; const SKIP_TOKEN = SkipToken()
621611

622612
function lifted_value(compact::IncrementalCompact, @nospecialize(old_node_ssa#=::AnySSAValue=#), @nospecialize(old_value),
623-
lifted_philikes::Vector{LiftedPhilike}, lifted_leaves::LiftedLeaves, reverse_mapping::IdDict{AnySSAValue, Int})
613+
lifted_philikes::Vector{LiftedPhilike}, lifted_leaves::Union{LiftedLeaves, LiftedDefs}, reverse_mapping::IdDict{AnySSAValue, Int})
624614
val = old_value
625615
if is_old(compact, old_node_ssa) && isa(val, SSAValue)
626616
val = OldSSAValue(val.id)
@@ -630,6 +620,9 @@ function lifted_value(compact::IncrementalCompact, @nospecialize(old_node_ssa#=:
630620
end
631621
if val in keys(lifted_leaves)
632622
lifted_val = lifted_leaves[val]
623+
if isa(lifted_leaves, LiftedDefs)
624+
return lifted_val
625+
end
633626
lifted_val === nothing && return UNDEF_TOKEN
634627
val = lifted_val.val
635628
if isa(val, AnySSAValue)
@@ -653,7 +646,7 @@ end
653646
function perform_lifting!(compact::IncrementalCompact,
654647
visited_philikes::Vector{AnySSAValue}, @nospecialize(cache_key),
655648
lifting_cache::IdDict{Pair{AnySSAValue, Any}, AnySSAValue},
656-
@nospecialize(result_t), lifted_leaves::LiftedLeaves, @nospecialize(stmt_val),
649+
@nospecialize(result_t), lifted_leaves::Union{LiftedLeaves, LiftedDefs}, @nospecialize(stmt_val),
657650
lazydomtree::Union{LazyDomtree,Nothing})
658651
reverse_mapping = IdDict{AnySSAValue, Int}()
659652
for id in 1:length(visited_philikes)
@@ -912,10 +905,11 @@ In a case when all usages are fully eliminated, `struct` allocation may also be
912905
a result of succeeding dead code elimination.
913906
"""
914907
function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
915-
𝕃ₒ = inlining === nothing ? OptimizerLattice() : optimizer_lattice(inlining.interp)
908+
𝕃ₒ = inlining === nothing ? SimpleInferenceLattice.instance : optimizer_lattice(inlining.interp)
916909
compact = IncrementalCompact(ir)
917910
defuses = nothing # will be initialized once we encounter mutability in order to reduce dynamic allocations
918911
lifting_cache = IdDict{Pair{AnySSAValue, Any}, AnySSAValue}()
912+
def_lifting_cache = IdDict{Pair{AnySSAValue, Any}, AnySSAValue}()
919913
# initialization of domtree is delayed to avoid the expensive computation in many cases
920914
lazydomtree = LazyDomtree(ir)
921915
for ((_, idx), stmt) in compact
@@ -1077,28 +1071,40 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
10771071
leaves, visited_philikes = collect_leaves(compact, val, struct_typ, 𝕃ₒ)
10781072
isempty(leaves) && continue
10791073

1080-
result_t = argextype(SSAValue(idx), compact)
1081-
lifted_result = lift_leaves(compact, result_t, field, leaves, 𝕃ₒ)
1074+
lifted_result = lift_leaves(compact, field, leaves, 𝕃ₒ)
10821075
lifted_result === nothing && continue
10831076
lifted_leaves, any_undef = lifted_result
10841077

1085-
if any_undef
1086-
result_t = make_MaybeUndef(result_t)
1078+
result_t = Union{}
1079+
for v in values(lifted_leaves)
1080+
v === nothing && continue
1081+
result_t = tmerge(𝕃ₒ, result_t, argextype(v.val, compact))
10871082
end
10881083

1089-
val = perform_lifting!(compact,
1084+
lifted_val = perform_lifting!(compact,
10901085
visited_philikes, field, lifting_cache, result_t, lifted_leaves, val, lazydomtree)
10911086

10921087
# Insert the undef check if necessary
1093-
if any_undef && val === nothing
1088+
if any_undef
1089+
if lifted_val === nothing
1090+
def_val = false
1091+
else
1092+
lifted_leaves_def = LiftedDefs()
1093+
for (k, v) in pairs(lifted_leaves)
1094+
lifted_leaves_def[k] = v === nothing ? false : true
1095+
end
1096+
def_val = perform_lifting!(compact,
1097+
visited_philikes, field, def_lifting_cache, Bool, lifted_leaves_def, val, lazydomtree).val
1098+
end
10941099
insert_node!(compact, SSAValue(idx), non_effect_free(NewInstruction(
1095-
Expr(:throw_undef_if_not, Symbol("##getfield##"), false), Nothing)))
1100+
Expr(:throw_undef_if_not, Symbol("##getfield##"), def_val), Nothing)))
1101+
10961102
else
10971103
# val must be defined
1098-
@assert val !== nothing
1104+
@assert lifted_val !== nothing
10991105
end
11001106

1101-
compact[idx] = val === nothing ? nothing : val.val
1107+
compact[idx] = lifted_val === nothing ? nothing : lifted_val.val
11021108
compact[SSAValue(idx)][:flag] |= IR_FLAG_REFINED
11031109
end
11041110

@@ -1572,7 +1578,6 @@ function mark_phi_cycles!(compact::IncrementalCompact, safe_phis::SPCSet, phi::I
15721578
end
15731579

15741580
function is_some_union(@nospecialize(t))
1575-
isa(t, MaybeUndef) && (t = t.typ)
15761581
return isa(t, Union)
15771582
end
15781583

@@ -1626,7 +1631,7 @@ the `typeassert` elimination depends on the transformation by `canonicalize_type
16261631
within `sroa_pass!` which redirects references of `typeassert`ed value to the corresponding `PiNode`.
16271632
"""
16281633
function adce_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
1629-
𝕃ₒ = inlining === nothing ? OptimizerLattice() : optimizer_lattice(inlining.interp)
1634+
𝕃ₒ = inlining === nothing ? SimpleInferenceLattice.instance : optimizer_lattice(inlining.interp)
16301635
phi_uses = fill(0, length(ir.stmts) + length(ir.new_nodes))
16311636
all_phis = Int[]
16321637
unionphis = Pair{Int,Any}[] # sorted
@@ -1751,153 +1756,6 @@ function adce_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
17511756
return complete(compact)
17521757
end
17531758

1754-
function type_lift_pass!(ir::IRCode)
1755-
lifted_undef = IdDict{Int, Any}()
1756-
insts = ir.stmts
1757-
for idx in 1:length(insts)
1758-
stmt = insts[idx][:inst]
1759-
stmt isa Expr || continue
1760-
if (stmt.head === :isdefined || stmt.head === :undefcheck)
1761-
# after optimization, undef can only show up by being introduced in
1762-
# a phi node (or an UpsilonNode() argument to a PhiC node), so lift
1763-
# all these nodes that have maybe undef values
1764-
val = stmt.args[(stmt.head === :isdefined) ? 1 : 2]
1765-
if stmt.head === :isdefined && (val isa GlobalRef || isexpr(val, :static_parameter) ||
1766-
val isa Argument || val isa Symbol)
1767-
# this is a legal node, so assume it was not introduced by
1768-
# slot2ssa (at worst, we might leave in a runtime check that
1769-
# shouldn't have been there)
1770-
continue
1771-
end
1772-
# otherwise, we definitely have a corrupt node from slot2ssa, and
1773-
# must fix or delete that now
1774-
processed = IdDict{Int, Union{SSAValue, Bool}}()
1775-
def = val
1776-
while true
1777-
# peek through PiNodes
1778-
isa(val, SSAValue) || break
1779-
def = insts[val.id][:inst]
1780-
isa(def, PiNode) || break
1781-
val = def.val
1782-
end
1783-
if !isa(val, SSAValue) || (!isa(def, PhiNode) && !isa(def, PhiCNode))
1784-
# in most cases, reaching this statement implies we had a value
1785-
if stmt.head === :undefcheck
1786-
insts[idx][:inst] = nothing
1787-
else
1788-
insts[idx][:inst] = true
1789-
end
1790-
continue
1791-
end
1792-
stmt_id = val.id
1793-
worklist = Tuple{Int, Int, SSAValue, Int}[(stmt_id, 0, SSAValue(0), 0)]
1794-
if !haskey(lifted_undef, stmt_id)
1795-
first = true
1796-
while !isempty(worklist)
1797-
item, w_up_id, which, use = pop!(worklist)
1798-
def = insts[item][:inst]
1799-
if isa(def, PhiNode)
1800-
edges = copy(def.edges)
1801-
values = Vector{Any}(undef, length(edges))
1802-
new_phi = if length(values) == 0
1803-
false
1804-
else
1805-
insert_node!(ir, item, NewInstruction(PhiNode(edges, values), Bool))
1806-
end
1807-
else
1808-
def = def::PhiCNode
1809-
values = Vector{Any}(undef, length(def.values))
1810-
new_phi = if length(values) == 0
1811-
false
1812-
else
1813-
insert_node!(ir, item, NewInstruction(PhiCNode(values), Bool))
1814-
end
1815-
end
1816-
processed[item] = new_phi
1817-
if first
1818-
lifted_undef[stmt_id] = new_phi
1819-
first = false
1820-
end
1821-
local id::Int = 0
1822-
all_same = true
1823-
local last_val
1824-
for i = 1:length(values)
1825-
if !isassigned(def.values, i)
1826-
val = false
1827-
elseif !isa(def.values[i], SSAValue)
1828-
val = true
1829-
else
1830-
up_id = id = (def.values[i]::SSAValue).id
1831-
@label restart
1832-
if !isa(ir.stmts[id][:type], MaybeUndef)
1833-
val = true
1834-
else
1835-
node = insts[id][:inst]
1836-
if isa(node, UpsilonNode)
1837-
if !isdefined(node, :val)
1838-
val = false
1839-
elseif !isa(node.val, SSAValue)
1840-
val = true
1841-
else
1842-
id = (node.val::SSAValue).id
1843-
@goto restart
1844-
end
1845-
else
1846-
while isa(node, PiNode)
1847-
id = (node.val::SSAValue).id
1848-
node = insts[id][:inst]
1849-
end
1850-
if isa(node, Union{PhiNode, PhiCNode})
1851-
if haskey(processed, id)
1852-
val = processed[id]
1853-
else
1854-
# TODO: Re-check after convergence whether all the values are the same
1855-
all_same = false
1856-
push!(worklist, (id, up_id, new_phi::SSAValue, i))
1857-
continue
1858-
end
1859-
else
1860-
val = true
1861-
end
1862-
end
1863-
end
1864-
end
1865-
if isa(def, PhiNode)
1866-
if !@isdefined(last_val)
1867-
last_val = val
1868-
elseif all_same
1869-
all_same &= last_val === val
1870-
end
1871-
values[i] = val
1872-
else
1873-
values[i] = insert_node!(ir, up_id, NewInstruction(UpsilonNode(val), Bool))
1874-
end
1875-
end
1876-
if all_same && @isdefined(last_val)
1877-
# Decay the PhiNode back to the single value
1878-
ir[new_phi][:inst] = last_val
1879-
isa(last_val, Bool) && (processed[item] = last_val)
1880-
end
1881-
if which !== SSAValue(0)
1882-
phi = ir[which][:inst]
1883-
if isa(phi, PhiNode)
1884-
phi.values[use] = new_phi
1885-
elseif isa(phi, PhiCNode)
1886-
phi.values[use] = insert_node!(ir, w_up_id, NewInstruction(UpsilonNode(new_phi), Bool))
1887-
end
1888-
end
1889-
end
1890-
end
1891-
inst = lifted_undef[stmt_id]
1892-
if stmt.head === :undefcheck
1893-
inst = Expr(:throw_undef_if_not, stmt.args[1], inst)
1894-
end
1895-
insts[idx][:inst] = inst
1896-
end
1897-
end
1898-
ir
1899-
end
1900-
19011759
function is_bb_empty(ir::IRCode, bb::BasicBlock)
19021760
isempty(bb.stmts) && return true
19031761
if length(bb.stmts) == 1

0 commit comments

Comments
 (0)