Skip to content

Commit

Permalink
Merge pull request #48733 from JuliaLang/backports-release-1.9
Browse files Browse the repository at this point in the history
Backports for 1.9.0-rc1
  • Loading branch information
KristofferC authored Mar 6, 2023
2 parents 3850e88 + 9ced070 commit 94603a7
Show file tree
Hide file tree
Showing 86 changed files with 2,007 additions and 1,315 deletions.
10 changes: 8 additions & 2 deletions Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,10 @@ SANITIZE_LDFLAGS :=
ifeq ($(SANITIZE_MEMORY),1)
SANITIZE_OPTS += -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer
SANITIZE_LDFLAGS += $(SANITIZE_OPTS)
endif
ifneq ($(findstring $(OS),Linux FreeBSD),)
SANITIZE_LDFLAGS += -Wl,--warn-unresolved-symbols
endif # OS Linux or FreeBSD
endif # SANITIZE_MEMORY=1
ifeq ($(SANITIZE_ADDRESS),1)
SANITIZE_OPTS += -fsanitize=address
SANITIZE_LDFLAGS += -fsanitize=address
Expand Down Expand Up @@ -848,7 +851,6 @@ endif
# If we are running on powerpc64le or ppc64le, set certain options automatically
ifneq (,$(filter $(ARCH), powerpc64le ppc64le))
JCFLAGS += -fsigned-char
OPENBLAS_DYNAMIC_ARCH:=0
OPENBLAS_TARGET_ARCH:=POWER8
BINARY:=64
# GCC doesn't do -march= on ppc64le
Expand Down Expand Up @@ -1036,6 +1038,10 @@ PATCHELF := patchelf
else
PATCHELF := $(build_depsbindir)/patchelf
endif
# In the standard build system we want to patch files with `--set-rpath`, but downstream
# packagers like Spack may want to use `--add-rpath` instead, leave them the possibility to
# choose the command.
PATCHELF_SET_RPATH_ARG := --set-rpath

ifeq ($(USE_SYSTEM_LIBWHICH), 1)
LIBWHICH := libwhich
Expand Down
17 changes: 10 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ endif
# Install `lld` into libexec/
$(INSTALL_M) $(build_depsbindir)/lld$(EXE) $(DESTDIR)$(libexecdir)/

# Install `dsymutil` into libexec/
$(INSTALL_M) $(build_depsbindir)/dsymutil$(EXE) $(DESTDIR)$(libexecdir)/

# Copy public headers
cp -R -L $(build_includedir)/julia/* $(DESTDIR)$(includedir)/julia
# Copy system image
Expand Down Expand Up @@ -365,7 +368,7 @@ ifneq ($(DARWIN_FRAMEWORK),1)
endif
else ifneq (,$(findstring $(OS),Linux FreeBSD))
for j in $(JL_TARGETS) ; do \
$(PATCHELF) --set-rpath '$$ORIGIN/$(private_libdir_rel):$$ORIGIN/$(libdir_rel)' $(DESTDIR)$(bindir)/$$j; \
$(PATCHELF) $(PATCHELF_SET_RPATH_ARG) '$$ORIGIN/$(private_libdir_rel):$$ORIGIN/$(libdir_rel)' $(DESTDIR)$(bindir)/$$j; \
done
endif

Expand Down Expand Up @@ -397,17 +400,17 @@ endif
endif
else ifneq (,$(findstring $(OS),Linux FreeBSD))
ifeq ($(JULIA_BUILD_MODE),release)
$(PATCHELF) --set-rpath '$$ORIGIN:$$ORIGIN/$(reverse_private_libdir_rel)' $(DESTDIR)$(private_libdir)/libjulia-internal.$(SHLIB_EXT)
$(PATCHELF) --set-rpath '$$ORIGIN:$$ORIGIN/$(reverse_private_libdir_rel)' $(DESTDIR)$(private_libdir)/libjulia-codegen.$(SHLIB_EXT)
$(PATCHELF) $(PATCHELF_SET_RPATH_ARG) '$$ORIGIN:$$ORIGIN/$(reverse_private_libdir_rel)' $(DESTDIR)$(private_libdir)/libjulia-internal.$(SHLIB_EXT)
$(PATCHELF) $(PATCHELF_SET_RPATH_ARG) '$$ORIGIN:$$ORIGIN/$(reverse_private_libdir_rel)' $(DESTDIR)$(private_libdir)/libjulia-codegen.$(SHLIB_EXT)
else ifeq ($(JULIA_BUILD_MODE),debug)
$(PATCHELF) --set-rpath '$$ORIGIN:$$ORIGIN/$(reverse_private_libdir_rel)' $(DESTDIR)$(private_libdir)/libjulia-internal-debug.$(SHLIB_EXT)
$(PATCHELF) --set-rpath '$$ORIGIN:$$ORIGIN/$(reverse_private_libdir_rel)' $(DESTDIR)$(private_libdir)/libjulia-codegen-debug.$(SHLIB_EXT)
$(PATCHELF) $(PATCHELF_SET_RPATH_ARG) '$$ORIGIN:$$ORIGIN/$(reverse_private_libdir_rel)' $(DESTDIR)$(private_libdir)/libjulia-internal-debug.$(SHLIB_EXT)
$(PATCHELF) $(PATCHELF_SET_RPATH_ARG) '$$ORIGIN:$$ORIGIN/$(reverse_private_libdir_rel)' $(DESTDIR)$(private_libdir)/libjulia-codegen-debug.$(SHLIB_EXT)
endif
endif

# Fix rpaths for dependencies. This should be fixed in BinaryBuilder later.
ifeq ($(OS), Linux)
-$(PATCHELF) --set-rpath '$$ORIGIN' $(DESTDIR)$(private_shlibdir)/libLLVM.$(SHLIB_EXT)
-$(PATCHELF) $(PATCHELF_SET_RPATH_ARG) '$$ORIGIN' $(DESTDIR)$(private_shlibdir)/libLLVM.$(SHLIB_EXT)
endif

ifneq ($(LOADER_BUILD_DEP_LIBS),$(LOADER_INSTALL_DEP_LIBS))
Expand Down Expand Up @@ -437,7 +440,7 @@ ifeq ($(OS),FreeBSD)
# don't set libgfortran's RPATH, it won't be able to find its friends on systems
# that don't have the exact GCC port installed used for the build.
for lib in $(DESTDIR)$(private_libdir)/libgfortran*$(SHLIB_EXT)*; do \
$(PATCHELF) --set-rpath '$$ORIGIN' $$lib; \
$(PATCHELF) $(PATCHELF_SET_RPATH_ARG) '$$ORIGIN' $$lib; \
done
endif

Expand Down
267 changes: 183 additions & 84 deletions base/compiler/abstractinterpretation.jl

Large diffs are not rendered by default.

138 changes: 117 additions & 21 deletions base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,23 @@ is_effect_overridden(override::EffectsOverride, effect::Symbol) = getfield(overr

add_remark!(::AbstractInterpreter, sv::Union{InferenceState, IRCode}, remark) = return

function bail_out_toplevel_call(::AbstractInterpreter, @nospecialize(callsig), sv::Union{InferenceState, IRCode})
return isa(sv, InferenceState) && sv.restrict_abstract_call_sites && !isdispatchtuple(callsig)
struct InferenceLoopState
sig
rt
effects::Effects
function InferenceLoopState(@nospecialize(sig), @nospecialize(rt), effects::Effects)
new(sig, rt, effects)
end
end

function bail_out_toplevel_call(::AbstractInterpreter, state::InferenceLoopState, sv::Union{InferenceState, IRCode})
return isa(sv, InferenceState) && sv.restrict_abstract_call_sites && !isdispatchtuple(state.sig)
end
function bail_out_call(::AbstractInterpreter, @nospecialize(rt), sv::Union{InferenceState, IRCode})
return rt === Any
function bail_out_call(::AbstractInterpreter, state::InferenceLoopState, sv::Union{InferenceState, IRCode})
return state.rt === Any
end
function bail_out_apply(::AbstractInterpreter, @nospecialize(rt), sv::Union{InferenceState, IRCode})
return rt === Any
function bail_out_apply(::AbstractInterpreter, state::InferenceLoopState, sv::Union{InferenceState, IRCode})
return state.rt === Any
end

was_reached(sv::InferenceState, pc::Int) = sv.ssavaluetypes[pc] !== NOT_FOUND
Expand Down Expand Up @@ -348,15 +357,100 @@ function InferenceState(result::InferenceResult, cache::Symbol, interp::Abstract
return InferenceState(result, src, cache, interp)
end

"""
constrains_param(var::TypeVar, sig, covariant::Bool, type_constrains::Bool)
Check if `var` will be constrained to have a definite value
in any concrete leaftype subtype of `sig`.
It is used as a helper to determine whether type intersection is guaranteed to be able to
find a value for a particular type parameter.
A necessary condition for type intersection to not assign a parameter is that it only
appears in a `Union[All]` and during subtyping some other union component (that does not
constrain the type parameter) is selected.
The `type_constrains` flag determines whether Type{T} is considered to be constraining
`T`. This is not true in general, because of the existence of types with free type
parameters, however, some callers would like to ignore this corner case.
"""
function constrains_param(var::TypeVar, @nospecialize(typ), covariant::Bool, type_constrains::Bool=false)
typ === var && return true
while typ isa UnionAll
covariant && constrains_param(var, typ.var.ub, covariant, type_constrains) && return true
# typ.var.lb doesn't constrain var
typ = typ.body
end
if typ isa Union
# for unions, verify that both options would constrain var
ba = constrains_param(var, typ.a, covariant, type_constrains)
bb = constrains_param(var, typ.b, covariant, type_constrains)
(ba && bb) && return true
elseif typ isa DataType
# return true if any param constrains var
fc = length(typ.parameters)
if fc > 0
if typ.name === Tuple.name
# vararg tuple needs special handling
for i in 1:(fc - 1)
p = typ.parameters[i]
constrains_param(var, p, covariant, type_constrains) && return true
end
lastp = typ.parameters[fc]
vararg = unwrap_unionall(lastp)
if vararg isa Core.TypeofVararg && isdefined(vararg, :N)
constrains_param(var, vararg.N, covariant, type_constrains) && return true
# T = vararg.parameters[1] doesn't constrain var
else
constrains_param(var, lastp, covariant, type_constrains) && return true
end
else
if typ.name === typename(Type) && typ.parameters[1] === var && var.ub === Any
# Types with free type parameters are <: Type cause the typevar
# to be unconstrained because Type{T} with free typevars is illegal
return type_constrains
end
for i in 1:fc
p = typ.parameters[i]
constrains_param(var, p, false, type_constrains) && return true
end
end
end
end
return false
end

"""
MaybeUndefSP(typ)
is_maybeundefsp(typ) -> Bool
unwrap_maybeundefsp(typ) -> Any
A special wrapper that represents a static parameter that could be undefined at runtime.
This does not participate in the native type system nor the inference lattice,
and it thus should be always unwrapped when performing any type or lattice operations on it.
"""
struct MaybeUndefSP
typ
MaybeUndefSP(@nospecialize typ) = new(typ)
end
is_maybeundefsp(@nospecialize typ) = isa(typ, MaybeUndefSP)
unwrap_maybeundefsp(@nospecialize typ) = isa(typ, MaybeUndefSP) ? typ.typ : typ
is_maybeundefsp(sptypes::Vector{Any}, idx::Int) = is_maybeundefsp(sptypes[idx])
unwrap_maybeundefsp(sptypes::Vector{Any}, idx::Int) = unwrap_maybeundefsp(sptypes[idx])

const EMPTY_SPTYPES = Any[]

function sptypes_from_meth_instance(linfo::MethodInstance)
toplevel = !isa(linfo.def, Method)
if !toplevel && isempty(linfo.sparam_vals) && isa(linfo.def.sig, UnionAll)
def = linfo.def
isa(def, Method) || return EMPTY_SPTYPES # toplevel
sig = def.sig
if isempty(linfo.sparam_vals)
isa(sig, UnionAll) || return EMPTY_SPTYPES
# linfo is unspecialized
sp = Any[]
sig = linfo.def.sig
while isa(sig, UnionAll)
push!(sp, sig.var)
sig = sig.body
sig = sig
while isa(sig, UnionAll)
push!(sp, sig.var)
sig = sig.body
end
else
sp = collect(Any, linfo.sparam_vals)
Expand All @@ -365,9 +459,7 @@ function sptypes_from_meth_instance(linfo::MethodInstance)
v = sp[i]
if v isa TypeVar
fromArg = 0
# if this parameter came from arg::Type{T}, then `arg` is more precise than
# Type{T} where lb<:T<:ub
sig = linfo.def.sig
maybe_undef = !constrains_param(v, linfo.specTypes, #=covariant=#true)
temp = sig
for j = 1:i-1
temp = temp.body
Expand Down Expand Up @@ -408,6 +500,8 @@ function sptypes_from_meth_instance(linfo::MethodInstance)
ty = UnionAll(tv, Type{tv})
end
end
@label ty_computed
maybe_undef && (ty = MaybeUndefSP(ty))
elseif isvarargtype(v)
ty = Int
else
Expand All @@ -429,14 +523,14 @@ end

update_valid_age!(edge::InferenceState, sv::InferenceState) = update_valid_age!(sv, edge.valid_worlds)

function record_ssa_assign!(ssa_id::Int, @nospecialize(new), frame::InferenceState)
function record_ssa_assign!(𝕃ᵢ::AbstractLattice, ssa_id::Int, @nospecialize(new), frame::InferenceState)
ssavaluetypes = frame.ssavaluetypes
old = ssavaluetypes[ssa_id]
if old === NOT_FOUND || !(new old)
if old === NOT_FOUND || !(𝕃ᵢ, new, old)
# typically, we expect that old ⊑ new (that output information only
# gets less precise with worse input information), but to actually
# guarantee convergence we need to use tmerge here to ensure that is true
ssavaluetypes[ssa_id] = old === NOT_FOUND ? new : tmerge(old, new)
ssavaluetypes[ssa_id] = old === NOT_FOUND ? new : tmerge(𝕃ᵢ, old, new)
W = frame.ip
for r in frame.ssavalue_uses[ssa_id]
if was_reached(frame, r)
Expand Down Expand Up @@ -519,9 +613,11 @@ end

get_curr_ssaflag(sv::InferenceState) = sv.src.ssaflags[sv.currpc]

function narguments(sv::InferenceState)
function narguments(sv::InferenceState, include_va::Bool=true)
def = sv.linfo.def
isva = isa(def, Method) && def.isva
nargs = length(sv.result.argtypes) - isva
nargs = length(sv.result.argtypes)
if !include_va
nargs -= isa(def, Method) && def.isva
end
return nargs
end
6 changes: 3 additions & 3 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,9 @@ function stmt_effect_flags(lattice::AbstractLattice, @nospecialize(stmt), @nospe
if isa(stmt, Expr)
(; head, args) = stmt
if head === :static_parameter
etyp = (isa(src, IRCode) ? src.sptypes : src.ir.sptypes)[args[1]::Int]
# if we aren't certain enough about the type, it might be an UndefVarError at runtime
nothrow = isa(etyp, Const)
sptypes = isa(src, IRCode) ? src.sptypes : src.ir.sptypes
nothrow = !is_maybeundefsp(sptypes, args[1]::Int)
return (true, nothrow, nothrow)
end
if head === :call
Expand Down Expand Up @@ -343,7 +343,7 @@ function argextype(
sptypes::Vector{Any}, slottypes::Vector{Any})
if isa(x, Expr)
if x.head === :static_parameter
return sptypes[x.args[1]::Int]
return unwrap_maybeundefsp(sptypes, x.args[1]::Int)
elseif x.head === :boundscheck
return Bool
elseif x.head === :copyast
Expand Down
4 changes: 3 additions & 1 deletion base/compiler/ssair/irinterp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,9 @@ function reprocess_instruction!(interp::AbstractInterpreter,
# Handled at the very end
return false
elseif isa(inst, PiNode)
rt = tmeet(typeinf_lattice(interp), argextype(inst.val, ir), inst.typ)
rt = tmeet(typeinf_lattice(interp), argextype(inst.val, ir), widenconst(inst.typ))
elseif inst === nothing
return false
else
ccall(:jl_, Cvoid, (Any,), inst)
error()
Expand Down
10 changes: 6 additions & 4 deletions base/compiler/ssair/slot2ssa.jl
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ end
function typ_for_val(@nospecialize(x), ci::CodeInfo, sptypes::Vector{Any}, idx::Int, slottypes::Vector{Any})
if isa(x, Expr)
if x.head === :static_parameter
return sptypes[x.args[1]::Int]
return unwrap_maybeundefsp(sptypes, x.args[1]::Int)
elseif x.head === :boundscheck
return Bool
elseif x.head === :copyast
Expand Down Expand Up @@ -337,7 +337,9 @@ function iterated_dominance_frontier(cfg::CFG, liveness::BlockLiveness, domtree:
end

function rename_incoming_edge(old_edge::Int, old_to::Int, result_order::Vector{Int}, bb_rename::Vector{Int})
old_edge == 0 && return 0
new_edge_from = bb_rename[old_edge]
new_edge_from < 0 && return new_edge_from
if old_edge == old_to - 1
# Could have been a crit edge break
if new_edge_from < length(result_order) && result_order[new_edge_from + 1] == 0
Expand All @@ -363,7 +365,7 @@ function rename_phinode_edges(node::PhiNode, bb::Int, result_order::Vector{Int},
new_edges = Int32[]
for (idx, edge) in pairs(node.edges)
edge = Int(edge)
(edge == 0 || bb_rename[edge] != 0) || continue
(edge == 0 || bb_rename[edge] != -1) || continue
new_edge_from = edge == 0 ? 0 : rename_incoming_edge(edge, bb, result_order, bb_rename)
push!(new_edges, new_edge_from)
if isassigned(node.values, idx)
Expand All @@ -386,7 +388,7 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree)
# First compute the new order of basic blocks
result_order = Int[]
stack = Int[]
bb_rename = zeros(Int, length(ir.cfg.blocks))
bb_rename = fill(-1, length(ir.cfg.blocks))
node = 1
ncritbreaks = 0
nnewfallthroughs = 0
Expand Down Expand Up @@ -497,7 +499,7 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree)
bb_start_off += length(inst_range)
local new_preds, new_succs
let bb = bb, bb_rename = bb_rename, result_order = result_order
new_preds = Int[i == 0 ? 0 : rename_incoming_edge(i, bb, result_order, bb_rename) for i in ir.cfg.blocks[bb].preds]
new_preds = Int[bb for bb in (rename_incoming_edge(i, bb, result_order, bb_rename) for i in ir.cfg.blocks[bb].preds) if bb != -1]
new_succs = Int[ rename_outgoing_edge(i, bb, result_order, bb_rename) for i in ir.cfg.blocks[bb].succs]
end
new_bbs[new_bb] = BasicBlock(inst_range, new_preds, new_succs)
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/ssair/verify.jl
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ function verify_ir(ir::IRCode, print::Bool=true, allow_frontend_forms::Bool=fals
elseif stmt.head === :foreigncall
isforeigncall = true
elseif stmt.head === :isdefined && length(stmt.args) == 1 &&
(stmt.args[1] isa GlobalRef || (stmt.args[1] isa Expr && stmt.args[1].head === :static_parameter))
(stmt.args[1] isa GlobalRef || isexpr(stmt.args[1], :static_parameter))
# a GlobalRef or static_parameter isdefined check does not evaluate its argument
continue
elseif stmt.head === :call
Expand Down
Loading

0 comments on commit 94603a7

Please sign in to comment.