Skip to content

Commit

Permalink
Merge branch 'JuliaLang:master' into bk
Browse files Browse the repository at this point in the history
  • Loading branch information
aravindh-krishnamoorthy authored Jul 8, 2023
2 parents 5600677 + d60f9b3 commit 9205b6c
Show file tree
Hide file tree
Showing 75 changed files with 1,104 additions and 426 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Build system changes

New library functions
---------------------
* `copyuntil(out, io, delim)` and `copyline(out, io)` copy data into an `out::IO` stream ([#48273]).

New library features
--------------------
Expand Down
5 changes: 2 additions & 3 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1757,7 +1757,7 @@ function splice!(a::Vector, i::Integer, ins=_default_splice)
if m == 0
_deleteat!(a, i, 1)
elseif m == 1
a[i] = ins[1]
a[i] = only(ins)
else
_growat!(a, i, m-1)
k = 1
Expand Down Expand Up @@ -2445,9 +2445,8 @@ julia> findall(x -> x >= 0, d)
```
"""
function findall(testf::Function, A)
T = eltype(keys(A))
gen = (first(p) for p in pairs(A) if testf(last(p)))
isconcretetype(T) ? collect(T, gen) : collect(gen)
@default_eltype(gen) === Union{} ? collect(@default_eltype(keys(A)), gen) : collect(gen)
end

# Broadcasting is much faster for small testf, and computing
Expand Down
4 changes: 2 additions & 2 deletions base/asyncevent.jl
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,8 @@ julia> begin
3
```
"""
function Timer(cb::Function, timeout::Real; interval::Real=0.0)
timer = Timer(timeout, interval=interval)
function Timer(cb::Function, timeout; kwargs...)
timer = Timer(timeout; kwargs...)
t = @task begin
unpreserve_handle(timer)
while _trywait(timer)
Expand Down
102 changes: 46 additions & 56 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,41 @@ is_stmt_inline(stmt_flag::UInt8) = stmt_flag & IR_FLAG_INLINE ≠ 0
is_stmt_noinline(stmt_flag::UInt8) = stmt_flag & IR_FLAG_NOINLINE 0
is_stmt_throw_block(stmt_flag::UInt8) = stmt_flag & IR_FLAG_THROW_BLOCK 0

function new_expr_effect_flags(𝕃ₒ::AbstractLattice, args::Vector{Any}, src::Union{IRCode,IncrementalCompact}, pattern_match=nothing)
Targ = args[1]
atyp = argextype(Targ, src)
# `Expr(:new)` of unknown type could raise arbitrary TypeError.
typ, isexact = instanceof_tfunc(atyp)
if !isexact
atyp = unwrap_unionall(widenconst(atyp))
if isType(atyp) && isTypeDataType(atyp.parameters[1])
typ = atyp.parameters[1]
else
return (false, false, false)
end
isabstracttype(typ) && return (false, false, false)
else
isconcretedispatch(typ) || return (false, false, false)
end
typ = typ::DataType
fcount = datatype_fieldcount(typ)
fcount === nothing && return (false, false, false)
fcount >= length(args) - 1 || return (false, false, false)
for fidx in 1:(length(args) - 1)
farg = args[fidx + 1]
eT = argextype(farg, src)
fT = fieldtype(typ, fidx)
if !isexact && has_free_typevars(fT)
if pattern_match !== nothing && pattern_match(src, typ, fidx, Targ, farg)
continue
end
return (false, false, false)
end
(𝕃ₒ, eT, fT) || return (false, false, false)
end
return (false, true, true)
end

"""
stmt_effect_flags(stmt, rt, src::Union{IRCode,IncrementalCompact}) ->
(consistent::Bool, effect_free_and_nothrow::Bool, nothrow::Bool)
Expand Down Expand Up @@ -264,36 +299,7 @@ function stmt_effect_flags(𝕃ₒ::AbstractLattice, @nospecialize(stmt), @nospe
nothrow = is_nothrow(effects)
return (consistent, effect_free & nothrow, nothrow)
elseif head === :new
atyp = argextype(args[1], src)
# `Expr(:new)` of unknown type could raise arbitrary TypeError.
typ, isexact = instanceof_tfunc(atyp)
if !isexact
atyp = unwrap_unionall(widenconst(atyp))
if isType(atyp) && isTypeDataType(atyp.parameters[1])
typ = atyp.parameters[1]
else
return (false, false, false)
end
isabstracttype(typ) && return (false, false, false)
else
isconcretedispatch(typ) || return (false, false, false)
end
typ = typ::DataType
fcount = datatype_fieldcount(typ)
fcount === nothing && return (false, false, false)
fcount >= length(args) - 1 || return (false, false, false)
for fld_idx in 1:(length(args) - 1)
eT = argextype(args[fld_idx + 1], src)
fT = fieldtype(typ, fld_idx)
# Currently, we cannot represent any type equality constraints
# in the lattice, so if we see any type of type parameter,
# there is very little we can say about it
if !isexact && has_free_typevars(fT)
return (false, false, false)
end
(𝕃ₒ, eT, fT) || return (false, false, false)
end
return (false, true, true)
return new_expr_effect_flags(𝕃ₒ, args, src)
elseif head === :foreigncall
effects = foreigncall_effects(stmt) do @nospecialize x
argextype(x, src)
Expand Down Expand Up @@ -400,18 +406,9 @@ function finish(interp::AbstractInterpreter, opt::OptimizationState,
opt.ir = ir

# determine and cache inlineability
union_penalties = false
if !force_noinline
sig = unwrap_unionall(specTypes)
if isa(sig, DataType) && sig.name === Tuple.name
for P in sig.parameters
P = unwrap_unionall(P)
if isa(P, Union)
union_penalties = true
break
end
end
else
if !(isa(sig, DataType) && sig.name === Tuple.name)
force_noinline = true
end
if !is_declared_inline(src) && result === Bottom
Expand Down Expand Up @@ -442,7 +439,7 @@ function finish(interp::AbstractInterpreter, opt::OptimizationState,
cost_threshold += 4*default
end
end
src.inlining_cost = inline_cost(ir, params, union_penalties, cost_threshold)
src.inlining_cost = inline_cost(ir, params, cost_threshold)
end
end
return nothing
Expand Down Expand Up @@ -639,7 +636,7 @@ plus_saturate(x::Int, y::Int) = max(x, y, x+y)
isknowntype(@nospecialize T) = (T === Union{}) || isa(T, Const) || isconcretetype(widenconst(T))

function statement_cost(ex::Expr, line::Int, src::Union{CodeInfo, IRCode}, sptypes::Vector{VarState},
union_penalties::Bool, params::OptimizationParams, error_path::Bool = false)
params::OptimizationParams, error_path::Bool = false)
head = ex.head
if is_meta_expr_head(head)
return 0
Expand Down Expand Up @@ -677,13 +674,6 @@ function statement_cost(ex::Expr, line::Int, src::Union{CodeInfo, IRCode}, sptyp
return isknowntype(atyp) ? 4 : error_path ? params.inline_error_path_cost : params.inline_nonleaf_penalty
elseif f === typeassert && isconstType(widenconst(argextype(ex.args[3], src, sptypes)))
return 1
elseif f === Core.isa
# If we're in a union context, we penalize type computations
# on union types. In such cases, it is usually better to perform
# union splitting on the outside.
if union_penalties && isa(argextype(ex.args[2], src, sptypes), Union)
return params.inline_nonleaf_penalty
end
end
fidx = find_tfunc(f)
if fidx === nothing
Expand Down Expand Up @@ -714,7 +704,7 @@ function statement_cost(ex::Expr, line::Int, src::Union{CodeInfo, IRCode}, sptyp
end
a = ex.args[2]
if a isa Expr
cost = plus_saturate(cost, statement_cost(a, -1, src, sptypes, union_penalties, params, error_path))
cost = plus_saturate(cost, statement_cost(a, -1, src, sptypes, params, error_path))
end
return cost
elseif head === :copyast
Expand All @@ -730,11 +720,11 @@ function statement_cost(ex::Expr, line::Int, src::Union{CodeInfo, IRCode}, sptyp
end

function statement_or_branch_cost(@nospecialize(stmt), line::Int, src::Union{CodeInfo, IRCode}, sptypes::Vector{VarState},
union_penalties::Bool, params::OptimizationParams)
params::OptimizationParams)
thiscost = 0
dst(tgt) = isa(src, IRCode) ? first(src.cfg.blocks[tgt].stmts) : tgt
if stmt isa Expr
thiscost = statement_cost(stmt, line, src, sptypes, union_penalties, params,
thiscost = statement_cost(stmt, line, src, sptypes, params,
is_stmt_throw_block(isa(src, IRCode) ? src.stmts.flag[line] : src.ssaflags[line]))::Int
elseif stmt isa GotoNode
# loops are generally always expensive
Expand All @@ -747,24 +737,24 @@ function statement_or_branch_cost(@nospecialize(stmt), line::Int, src::Union{Cod
return thiscost
end

function inline_cost(ir::IRCode, params::OptimizationParams, union_penalties::Bool=false,
function inline_cost(ir::IRCode, params::OptimizationParams,
cost_threshold::Integer=params.inline_cost_threshold)::InlineCostType
bodycost::Int = 0
for line = 1:length(ir.stmts)
stmt = ir.stmts[line][:inst]
thiscost = statement_or_branch_cost(stmt, line, ir, ir.sptypes, union_penalties, params)
thiscost = statement_or_branch_cost(stmt, line, ir, ir.sptypes, params)
bodycost = plus_saturate(bodycost, thiscost)
bodycost > cost_threshold && return MAX_INLINE_COST
end
return inline_cost_clamp(bodycost)
end

function statement_costs!(cost::Vector{Int}, body::Vector{Any}, src::Union{CodeInfo, IRCode}, sptypes::Vector{VarState}, unionpenalties::Bool, params::OptimizationParams)
function statement_costs!(cost::Vector{Int}, body::Vector{Any}, src::Union{CodeInfo, IRCode}, sptypes::Vector{VarState}, params::OptimizationParams)
maxcost = 0
for line = 1:length(body)
stmt = body[line]
thiscost = statement_or_branch_cost(stmt, line, src, sptypes,
unionpenalties, params)
params)
cost[line] = thiscost
if thiscost > maxcost
maxcost = thiscost
Expand Down
15 changes: 3 additions & 12 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ function cfg_inline_unionsplit!(ir::IRCode, idx::Int,
push!(from_bbs, length(state.new_cfg_blocks))
# TODO: Right now we unconditionally generate a fallback block
# in case of subtyping errors - This is probably unnecessary.
if i != length(cases) || (!fully_covered || (!params.trust_inference))
if i != length(cases) || (!fully_covered)
# This block will have the next condition or the final else case
push!(state.new_cfg_blocks, BasicBlock(StmtRange(idx, idx)))
push!(state.new_cfg_blocks[cond_bb].succs, length(state.new_cfg_blocks))
Expand Down Expand Up @@ -494,8 +494,6 @@ function fix_va_argexprs!(insert_node!::Inserter, inline_target::Union{IRCode, I
return newargexprs
end

const FATAL_TYPE_BOUND_ERROR = ErrorException("fatal error in type inference (type bound)")

"""
ir_inline_unionsplit!
Expand Down Expand Up @@ -575,7 +573,7 @@ function ir_inline_unionsplit!(compact::IncrementalCompact, idx::Int,
cond = true
nparams = fieldcount(atype)
@assert nparams == fieldcount(mtype)
if i != ncases || !fully_covered || !params.trust_inference
if i != ncases || !fully_covered
for i = 1:nparams
a, m = fieldtype(atype, i), fieldtype(mtype, i)
# If this is always true, we don't need to check for it
Expand Down Expand Up @@ -630,14 +628,7 @@ function ir_inline_unionsplit!(compact::IncrementalCompact, idx::Int,
end
bb += 1
# We're now in the fall through block, decide what to do
if fully_covered
if !params.trust_inference
e = Expr(:call, GlobalRef(Core, :throw), FATAL_TYPE_BOUND_ERROR)
insert_node_here!(compact, NewInstruction(e, Union{}, line))
insert_node_here!(compact, NewInstruction(ReturnNode(), Union{}, line))
finish_current_bb!(compact, 0)
end
else
if !fully_covered
ssa = insert_node_here!(compact, NewInstruction(stmt, typ, line))
push!(pn.edges, bb)
push!(pn.values, ssa)
Expand Down
58 changes: 58 additions & 0 deletions base/compiler/ssair/passes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,62 @@ end
return nothing
end

struct IsEgal <: Function
x::Any
IsEgal(@nospecialize(x)) = new(x)
end
(x::IsEgal)(@nospecialize(y)) = x.x === y

# This tries to match patterns of the form
# %ft = typeof(%farg)
# %Targ = apply_type(Foo, ft)
# %x = new(%Targ, %farg)
#
# and if possible refines the nothrowness of the new expr based on it.
function pattern_match_typeof(compact::IncrementalCompact, typ::DataType, fidx::Int,
@nospecialize(Targ), @nospecialize(farg))
isa(Targ, SSAValue) || return false

Tdef = compact[Targ][:inst]
is_known_call(Tdef, Core.apply_type, compact) || return false
length(Tdef.args) 2 || return false

applyT = argextype(Tdef.args[2], compact)
isa(applyT, Const) || return false

applyT = applyT.val
tvars = Any[]
while isa(applyT, UnionAll)
applyTvar = applyT.var
applyT = applyT.body
push!(tvars, applyTvar)
end

applyT.name === typ.name || return false
fT = fieldtype(applyT, fidx)
idx = findfirst(IsEgal(fT), tvars)
idx === nothing && return false
checkbounds(Bool, Tdef.args, 2+idx) || return false
valarg = Tdef.args[2+idx]
isa(valarg, SSAValue) || return false
valdef = compact[valarg][:inst]
is_known_call(valdef, typeof, compact) || return false

return valdef.args[2] === farg
end

function refine_new_effects!(𝕃ₒ::AbstractLattice, compact::IncrementalCompact, idx::Int, stmt::Expr)
(consistent, effect_free_and_nothrow, nothrow) = new_expr_effect_flags(𝕃ₒ, stmt.args, compact, pattern_match_typeof)
if consistent
compact[SSAValue(idx)][:flag] |= IR_FLAG_CONSISTENT
end
if effect_free_and_nothrow
compact[SSAValue(idx)][:flag] |= IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW
elseif nothrow
compact[SSAValue(idx)][:flag] |= IR_FLAG_NOTHROW
end
end

# NOTE we use `IdSet{Int}` instead of `BitSet` for in these passes since they work on IR after inlining,
# which can be very large sometimes, and program counters in question are often very sparse
const SPCSet = IdSet{Int}
Expand Down Expand Up @@ -1037,6 +1093,8 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
lift_comparison!(===, compact, idx, stmt, lifting_cache, 𝕃ₒ)
elseif is_known_call(stmt, isa, compact)
lift_comparison!(isa, compact, idx, stmt, lifting_cache, 𝕃ₒ)
elseif isexpr(stmt, :new) && (compact[SSAValue(idx)][:flag] & IR_FLAG_NOTHROW) == 0x00
refine_new_effects!(𝕃ₒ, compact, idx, stmt)
end
continue
end
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ add_tfunc(neg_float, 1, 1, math_tfunc, 1)
add_tfunc(add_float, 2, 2, math_tfunc, 1)
add_tfunc(sub_float, 2, 2, math_tfunc, 1)
add_tfunc(mul_float, 2, 2, math_tfunc, 4)
add_tfunc(div_float, 2, 2, math_tfunc, 20)
add_tfunc(div_float, 2, 2, math_tfunc, 4)
add_tfunc(fma_float, 3, 3, math_tfunc, 5)
add_tfunc(muladd_float, 3, 3, math_tfunc, 5)

Expand All @@ -193,7 +193,7 @@ add_tfunc(neg_float_fast, 1, 1, math_tfunc, 1)
add_tfunc(add_float_fast, 2, 2, math_tfunc, 1)
add_tfunc(sub_float_fast, 2, 2, math_tfunc, 1)
add_tfunc(mul_float_fast, 2, 2, math_tfunc, 2)
add_tfunc(div_float_fast, 2, 2, math_tfunc, 10)
add_tfunc(div_float_fast, 2, 2, math_tfunc, 2)

# bitwise operators
# -----------------
Expand Down
Loading

0 comments on commit 9205b6c

Please sign in to comment.