Skip to content

Commit

Permalink
Merge pull request #45491 from JuliaLang/backports-release-1.8
Browse files Browse the repository at this point in the history
Backports for 1.8-rc2/1.8.0
  • Loading branch information
KristofferC committed Jul 6, 2022
2 parents 6368fdc + 7a23871 commit 381eac3
Show file tree
Hide file tree
Showing 65 changed files with 1,065 additions and 946 deletions.
4 changes: 0 additions & 4 deletions Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -900,10 +900,6 @@ OPENBLAS_DYNAMIC_ARCH:=0
OPENBLAS_TARGET_ARCH:=ARMV8
USE_BLAS64:=1
BINARY:=64
ifeq ($(OS),Darwin)
# Apple Chips are all at least A12Z
MCPU:=apple-a12
endif
endif

# Set MARCH-specific flags
Expand Down
12 changes: 8 additions & 4 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ New language features
e.g. `[;;;]` creates a 0×0×0 `Array` ([#41618]).
* `try`-blocks can now optionally have an `else`-block which is executed right after the main body only if
no errors were thrown ([#42211]).
* `@inline` and `@noinline` annotations can now be placed within a function body ([#41312]).
* `@inline` and `@noinline` annotations can now be applied to a function call site or block
* `@inline` and `@noinline` can now be placed within a function body, allowing one to annotate anonymous function ([#41312]).
* `@inline` and `@noinline` can now be applied to a function at callsite or block
to enforce the involved function calls to be (or not to be) inlined ([#41328]).
* ``, ``, and `` are now allowed as identifier characters ([#42314]).
* Support for Unicode 14.0.0 ([#43443]).
Expand Down Expand Up @@ -43,7 +43,9 @@ Compiler/Runtime improvements
`libjulia-codegen`. It is loaded by default, so normal usage should see no changes.
In deployments that do not need the compiler (e.g. system images where all needed code
is precompiled), this library (and its LLVM dependency) can simply be excluded ([#41936]).
* Conditional type constraints can now be forwarded interprocedurally (i.e. propagated from caller to callee) ([#42529]).
* Conditional type constraints are now be forwarded interprocedurally (i.e. propagated from caller to callee).
This allows inference to understand e.g. `Base.ifelse(isa(x, Int), x, 0)` returns `::Int`-value
even if the type of `x` is not known ([#42529]).
* Julia-level SROA (Scalar Replacement of Aggregates) has been improved: allowing elimination of
`getfield` calls with constant global fields ([#42355]), enabling elimination of mutable structs with
uninitialized fields ([#43208]), improving performance ([#43232]), and handling more nested `getfield`
Expand All @@ -53,7 +55,7 @@ Compiler/Runtime improvements
* Inference now tracks various effects such as side-effectful-ness and nothrow-ness on a per-specialization basis.
Code heavily dependent on constant propagation should see significant compile-time performance improvements and
certain cases (e.g. calls to uninlinable functions that are nevertheless effect free) should see runtime performance
improvements. Effects may be overwritten manually with the `@Base.assume_effects` macro ([#43852]).
improvements. Effects may be overwritten manually with the `Base.@assume_effects` macro ([#43852]).
* Precompilation (with explicit `precompile` directives or representative workloads) now saves more type-inferred code,
resulting in reduced time-to-first task for packages that use precompilation. This change also eliminates the
runtime performance degradation occasionally triggered by precompilation on older Julia versions. More specifically,
Expand Down Expand Up @@ -108,6 +110,8 @@ New library features
* TCP socket objects now expose `closewrite` functionality and support half-open mode usage ([#40783]).
* `extrema` now accepts an `init` keyword argument ([#36265], [#43604]).
* `Iterators.countfrom` now accepts any type that defines `+` ([#37747]).
* `@time` now separates out % time spent recompiling invalidated methods ([#45015]).
* `@time_imports` now shows any compilation and recompilation time percentages per import ([#45064]).

Standard library changes
------------------------
Expand Down
4 changes: 2 additions & 2 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2478,7 +2478,7 @@ function _typed_hvncat_shape(::Type{T}, shape::NTuple{N, Tuple}, row_first, as::
shapelength == lengthas || throw(ArgumentError("number of elements does not match shape; expected $(shapelength), got $lengthas)"))
# discover dimensions
nd = max(N, cat_ndims(as[1]))
outdims = zeros(Int, nd)
outdims = fill(-1, nd)
currentdims = zeros(Int, nd)
blockcounts = zeros(Int, nd)
shapepos = ones(Int, nd)
Expand All @@ -2503,7 +2503,7 @@ function _typed_hvncat_shape(::Type{T}, shape::NTuple{N, Tuple}, row_first, as::

isendblock = blockcounts[d] == shapev[d][shapepos[d]]
if isendblock
if outdims[d] == 0
if outdims[d] == -1
outdims[d] = currentdims[d]
elseif outdims[d] != currentdims[d]
throw(ArgumentError("argument $i has a mismatched number of elements along axis $ad; \
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ function concrete_eval_eligible(interp::AbstractInterpreter,
isoverlayed(method_table(interp)) && !is_nonoverlayed(result.edge_effects) && return false
return f !== nothing &&
result.edge !== nothing &&
is_concrete_eval_eligible(result.edge_effects) &&
is_foldable(result.edge_effects) &&
is_all_const_arg(arginfo)
end

Expand Down
10 changes: 4 additions & 6 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1257,11 +1257,7 @@ function handle_const_call!(
result = results[j]
if isa(result, ConstResult)
case = const_result_item(result, state)
if case === nothing
fully_covered = false
else
push!(cases, InliningCase(result.mi.specTypes, case))
end
push!(cases, InliningCase(result.mi.specTypes, case))
elseif isa(result, InferenceResult)
fully_covered &= handle_inf_result!(result, argtypes, flag, state, cases)
else
Expand Down Expand Up @@ -1314,7 +1310,9 @@ end

function const_result_item(result::ConstResult, state::InliningState)
if !isdefined(result, :result) || !is_inlineable_constant(result.result)
return compileable_specialization(state.et, result.mi, result.effects)
case = compileable_specialization(state.et, result.mi, result.effects)
@assert case !== nothing "concrete evaluation should never happen for uncompileable callsite"
return case
end
@assert result.effects === EFFECTS_TOTAL
return ConstantCase(quoted(result.result))
Expand Down
8 changes: 8 additions & 0 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1515,6 +1515,10 @@ function tuple_tfunc(argtypes::Vector{Any})
params[i] = typeof(x.val)
else
x = isvarargtype(x) ? x : widenconst(x)
# since there don't exist any values whose runtime type are `Tuple{Type{...}}`,
# here we should turn such `Type{...}`-parameters to valid parameters, e.g.
# (::Type{Int},) -> Tuple{DataType} (or PartialStruct for more accuracy)
# (::Union{Type{Int32},Type{Int64}}) -> Tuple{Type}
if isType(x)
anyinfo = true
xparam = x.parameters[1]
Expand All @@ -1523,6 +1527,10 @@ function tuple_tfunc(argtypes::Vector{Any})
else
params[i] = Type
end
elseif iskindtype(x)
params[i] = x
elseif !isvarargtype(x) && hasintersect(x, Type)
params[i] = Union{x, Type}
else
params[i] = x
end
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,13 @@ is_nothrow(effects::Effects) = effects.nothrow === ALWAYS_TRUE
is_terminates(effects::Effects) = effects.terminates === ALWAYS_TRUE
is_nonoverlayed(effects::Effects) = effects.nonoverlayed

is_concrete_eval_eligible(effects::Effects) =
is_foldable(effects::Effects) =
is_consistent(effects) &&
is_effect_free(effects) &&
is_terminates(effects)

is_total(effects::Effects) =
is_concrete_eval_eligible(effects) &&
is_foldable(effects) &&
is_nothrow(effects)

is_removable_if_unused(effects::Effects) =
Expand Down
2 changes: 1 addition & 1 deletion base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ function invoke_in_world(world::UInt, @nospecialize(f), @nospecialize args...; k
end

# TODO: possibly make this an intrinsic
inferencebarrier(@nospecialize(x)) = Ref{Any}(x)[]
inferencebarrier(@nospecialize(x)) = RefValue{Any}(x).x

"""
isempty(collection) -> Bool
Expand Down
112 changes: 74 additions & 38 deletions base/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,9 @@ end
`@assume_effects` overrides the compiler's effect modeling for the given method.
`ex` must be a method definition or `@ccall` expression.
!!! compat "Julia 1.8"
Using `Base.@assume_effects` requires Julia version 1.8.
```jldoctest
julia> Base.@assume_effects :terminates_locally function pow(x)
# this :terminates_locally allows `pow` to be constant-folded
Expand All @@ -402,7 +405,7 @@ julia> code_typed() do
1 ─ return 479001600
) => Int64
julia> Base.@assume_effects :total_may_throw @ccall jl_type_intersection(Vector{Int}::Any, Vector{<:Integer}::Any)::Any
julia> Base.@assume_effects :total !:nothrow @ccall jl_type_intersection(Vector{Int}::Any, Vector{<:Integer}::Any)::Any
Vector{Int64} (alias for Array{Int64, 1})
```
Expand All @@ -423,12 +426,15 @@ The following `setting`s are supported.
- `:nothrow`
- `:terminates_globally`
- `:terminates_locally`
- `:foldable`
- `:total`
# Extended help
---
# `:consistent`
## `:consistent`
The `:consistent` setting asserts that for egal inputs:
The `:consistent` setting asserts that for egal (`===`) inputs:
- The manner of termination (return value, exception, non-termination) will always be the same.
- If the method returns, the results will always be egal.
Expand Down Expand Up @@ -461,7 +467,7 @@ The `:consistent` setting asserts that for egal inputs:
itself is not required to meet the egality requirement specified above.
---
# `:effect_free`
## `:effect_free`
The `:effect_free` setting asserts that the method is free of externally semantically
visible side effects. The following is an incomplete list of externally semantically
Expand Down Expand Up @@ -491,7 +497,7 @@ were not executed.
valid for all world ages and limit use of this assertion accordingly.
---
# `:nothrow`
## `:nothrow`
The `:nothrow` settings asserts that this method does not terminate abnormally
(i.e. will either always return a value or never return).
Expand All @@ -505,7 +511,7 @@ The `:nothrow` settings asserts that this method does not terminate abnormally
`MethodErrors` and similar exceptions count as abnormal termination.
---
# `:terminates_globally`
## `:terminates_globally`
The `:terminates_globally` settings asserts that this method will eventually terminate
(either normally or abnormally), i.e. does not loop indefinitely.
Expand All @@ -520,7 +526,7 @@ The `:terminates_globally` settings asserts that this method will eventually ter
on a method that *technically*, but not *practically*, terminates.
---
# `:terminates_locally`
## `:terminates_locally`
The `:terminates_locally` setting is like `:terminates_globally`, except that it only
applies to syntactic control flow *within* the annotated method. It is thus
Expand All @@ -531,59 +537,79 @@ non-termination if the method calls some other method that does not terminate.
`:terminates_globally` implies `:terminates_locally`.
---
# `:total`
## `:foldable`
This setting is a convenient shortcut for the set of effects that the compiler
requires to be guaranteed to constant fold a call at compile time. It is
currently equivalent to the following `setting`s:
This `setting` combines the following other assertions:
- `:consistent`
- `:effect_free`
- `:nothrow`
- `:terminates_globally`
and is a convenient shortcut.
!!! note
This list in particular does not include `:nothrow`. The compiler will still
attempt constant propagation and note any thrown error at compile time. Note
however, that by the `:consistent`-cy requirements, any such annotated call
must consistently throw given the same argument values.
---
# `:total_may_throw`
## `:total`
This `setting` combines the following other assertions:
This `setting` is the maximum possible set of effects. It currently implies
the following other `setting`s:
- `:consistent`
- `:effect_free`
- `:nothrow`
- `:terminates_globally`
and is a convenient shortcut.
!!! note
This setting is particularly useful since it allows the compiler to evaluate a call of
the applied method when all the call arguments are fully known to be constant, no matter
if the call results in an error or not.
`@assume_effects :total_may_throw` is similar to [`@pure`](@ref) with the primary
distinction that the `:consistent`-cy requirement applies world-age wise rather
than globally as described above. However, in particular, a method annotated
`@pure` should always be `:total` or `:total_may_throw`.
Another advantage is that effects introduced by `@assume_effects` are propagated to
callers interprocedurally while a purity defined by `@pure` is not.
!!! warning
`:total` is a very strong assertion and will likely gain additional semantics
in future versions of Julia (e.g. if additional effects are added and included
in the definition of `:total`). As a result, it should be used with care.
Whenever possible, prefer to use the minimum possible set of specific effect
assertions required for a particular application. In cases where a large
number of effect overrides apply to a set of functions, a custom macro is
recommended over the use of `:total`.
---
## Negated effects
Effect names may be prefixed by `!` to indicate that the effect should be removed
from an earlier meta effect. For example, `:total !:nothrow` indicates that while
the call is generally total, it may however throw.
---
## Comparison to `@pure`
`@assume_effects :foldable` is similar to [`@pure`](@ref) with the primary
distinction that the `:consistent`-cy requirement applies world-age wise rather
than globally as described above. However, in particular, a method annotated
`@pure` should always be at least `:foldable`.
Another advantage is that effects introduced by `@assume_effects` are propagated to
callers interprocedurally while a purity defined by `@pure` is not.
"""
macro assume_effects(args...)
(consistent, effect_free, nothrow, terminates_globally, terminates_locally) =
(false, false, false, false, false, false)
for setting in args[1:end-1]
if isa(setting, QuoteNode)
setting = setting.value
end
for org_setting in args[1:end-1]
(setting, val) = compute_assumed_setting(org_setting)
if setting === :consistent
consistent = true
consistent = val
elseif setting === :effect_free
effect_free = true
effect_free = val
elseif setting === :nothrow
nothrow = true
nothrow = val
elseif setting === :terminates_globally
terminates_globally = true
terminates_globally = val
elseif setting === :terminates_locally
terminates_locally = true
terminates_locally = val
elseif setting === :foldable
consistent = effect_free = terminates_globally = val
elseif setting === :total
consistent = effect_free = nothrow = terminates_globally = true
elseif setting === :total_may_throw
consistent = effect_free = terminates_globally = true
consistent = effect_free = nothrow = terminates_globally = val
else
throw(ArgumentError("@assume_effects $setting not supported"))
throw(ArgumentError("@assume_effects $org_setting not supported"))
end
end
ex = args[end]
Expand All @@ -598,6 +624,16 @@ macro assume_effects(args...)
return esc(pushmeta!(ex, :purity, consistent, effect_free, nothrow, terminates_globally, terminates_locally))
end

function compute_assumed_setting(@nospecialize(setting), val::Bool=true)
if isexpr(setting, :call) && setting.args[1] === :(!)
return compute_assumed_setting(setting.args[2], !val)
elseif isa(setting, QuoteNode)
return compute_assumed_setting(setting.value, val)
else
return (setting, val)
end
end

"""
@propagate_inbounds
Expand Down
4 changes: 2 additions & 2 deletions base/fastmath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,8 @@ exp10_fast(x::Union{Float32,Float64}) = Base.Math.exp10_fast(x)

# builtins

pow_fast(x::Float32, y::Integer) = ccall("llvm.powi.f32", llvmcall, Float32, (Float32, Int32), x, y)
pow_fast(x::Float64, y::Integer) = ccall("llvm.powi.f64", llvmcall, Float64, (Float64, Int32), x, y)
pow_fast(x::Float32, y::Integer) = ccall("llvm.powi.f32.i32", llvmcall, Float32, (Float32, Int32), x, y)
pow_fast(x::Float64, y::Integer) = ccall("llvm.powi.f64.i32", llvmcall, Float64, (Float64, Int32), x, y)
pow_fast(x::FloatTypes, ::Val{p}) where {p} = pow_fast(x, p) # inlines already via llvm.powi
@inline pow_fast(x, v::Val) = Base.literal_pow(^, x, v)

Expand Down
Loading

0 comments on commit 381eac3

Please sign in to comment.