Skip to content

Commit 38ae975

Browse files
authored
Merge branch 'master' into kf/unusederror
2 parents eb37e92 + d215d91 commit 38ae975

File tree

16 files changed

+184
-115
lines changed

16 files changed

+184
-115
lines changed

base/abstractarray.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ julia> axes(A)
9595
"""
9696
function axes(A)
9797
@inline
98-
map(oneto, size(A))
98+
map(unchecked_oneto, size(A))
9999
end
100100

101101
"""

base/broadcast.jl

Lines changed: 43 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -341,20 +341,16 @@ function flatten(bc::Broadcasted)
341341
isflat(bc) && return bc
342342
# concatenate the nested arguments into {a, b, c, d}
343343
args = cat_nested(bc)
344-
# build a function `makeargs` that takes a "flat" argument list and
345-
# and creates the appropriate input arguments for `f`, e.g.,
346-
# makeargs = (w, x, y, z) -> (w, g(x, y), z)
347-
#
348-
# `makeargs` is built recursively and looks a bit like this:
349-
# makeargs(w, x, y, z) = (w, makeargs1(x, y, z)...)
350-
# = (w, g(x, y), makeargs2(z)...)
351-
# = (w, g(x, y), z)
352-
let makeargs = make_makeargs(()->(), bc.args), f = bc.f
353-
newf = @inline function(args::Vararg{Any,N}) where N
354-
f(makeargs(args...)...)
355-
end
356-
return Broadcasted(bc.style, newf, args, bc.axes)
357-
end
344+
# build a tuple of functions `makeargs`. Its elements take
345+
# the whole "flat" argument list and and generate the appropriate
346+
# input arguments for the broadcasted function `f`, e.g.,
347+
# makeargs[1] = ((w, x, y, z)) -> w
348+
# makeargs[2] = ((w, x, y, z)) -> g(x, y)
349+
# makeargs[3] = ((w, x, y, z)) -> z
350+
makeargs = make_makeargs(bc.args)
351+
f = Base.maybeconstructor(bc.f)
352+
newf = (args...) -> (@inline; f(prepare_args(makeargs, args)...))
353+
return Broadcasted(bc.style, newf, args, bc.axes)
358354
end
359355

360356
const NestedTuple = Tuple{<:Broadcasted,Vararg{Any}}
@@ -363,78 +359,47 @@ _isflat(args::NestedTuple) = false
363359
_isflat(args::Tuple) = _isflat(tail(args))
364360
_isflat(args::Tuple{}) = true
365361

366-
cat_nested(t::Broadcasted, rest...) = (cat_nested(t.args...)..., cat_nested(rest...)...)
367-
cat_nested(t::Any, rest...) = (t, cat_nested(rest...)...)
368-
cat_nested() = ()
362+
cat_nested(bc::Broadcasted) = cat_nested_args(bc.args)
363+
cat_nested_args(::Tuple{}) = ()
364+
cat_nested_args(t::Tuple{Any}) = cat_nested(t[1])
365+
cat_nested_args(t::Tuple) = (cat_nested(t[1])..., cat_nested_args(tail(t))...)
366+
cat_nested(a) = (a,)
369367

370368
"""
371-
make_makeargs(makeargs_tail::Function, t::Tuple) -> Function
369+
make_makeargs(t::Tuple) -> Tuple{Vararg{Function}}
372370
373371
Each element of `t` is one (consecutive) node in a broadcast tree.
374-
Ignoring `makeargs_tail` for the moment, the job of `make_makeargs` is
375-
to return a function that takes in flattened argument list and returns a
376-
tuple (each entry corresponding to an entry in `t`, having evaluated
377-
the corresponding element in the broadcast tree). As an additional
378-
complication, the passed in tuple may be longer than the number of leaves
379-
in the subtree described by `t`. The `makeargs_tail` function should
380-
be called on such additional arguments (but not the arguments consumed
381-
by `t`).
372+
The returned `Tuple` are functions which take in the (whole) flattened
373+
list and generate the inputs for the corresponding broadcasted function.
382374
"""
383-
@inline make_makeargs(makeargs_tail, t::Tuple{}) = makeargs_tail
384-
@inline function make_makeargs(makeargs_tail, t::Tuple)
385-
makeargs = make_makeargs(makeargs_tail, tail(t))
386-
(head, tail...)->(head, makeargs(tail...)...)
375+
make_makeargs(args::Tuple) = _make_makeargs(args, 1)[1]
376+
377+
# We build `makeargs` by traversing the broadcast nodes recursively.
378+
# note: `n` indicates the flattened index of the next unused argument.
379+
@inline function _make_makeargs(args::Tuple, n::Int)
380+
head, n = _make_makeargs1(args[1], n)
381+
rest, n = _make_makeargs(tail(args), n)
382+
(head, rest...), n
387383
end
388-
function make_makeargs(makeargs_tail, t::Tuple{<:Broadcasted, Vararg{Any}})
389-
bc = t[1]
390-
# c.f. the same expression in the function on leaf nodes above. Here
391-
# we recurse into siblings in the broadcast tree.
392-
let makeargs_tail = make_makeargs(makeargs_tail, tail(t)),
393-
# Here we recurse into children. It would be valid to pass in makeargs_tail
394-
# here, and not use it below. However, in that case, our recursion is no
395-
# longer purely structural because we're building up one argument (the closure)
396-
# while destructuing another.
397-
makeargs_head = make_makeargs((args...)->args, bc.args),
398-
f = bc.f
399-
# Create two functions, one that splits of the first length(bc.args)
400-
# elements from the tuple and one that yields the remaining arguments.
401-
# N.B. We can't call headargs on `args...` directly because
402-
# args is flattened (i.e. our children have not been evaluated
403-
# yet).
404-
headargs, tailargs = make_headargs(bc.args), make_tailargs(bc.args)
405-
return @inline function(args::Vararg{Any,N}) where N
406-
args1 = makeargs_head(args...)
407-
a, b = headargs(args1...), makeargs_tail(tailargs(args1...)...)
408-
(f(a...), b...)
409-
end
410-
end
384+
_make_makeargs(::Tuple{}, n::Int) = (), n
385+
386+
# A help struct to store the flattened index staticly
387+
struct Pick{N} <: Function end
388+
(::Pick{N})(@nospecialize(args::Tuple)) where {N} = args[N]
389+
390+
# For flat nodes, we just consume one argument (n += 1), and return the "Pick" function
391+
@inline _make_makeargs1(_, n::Int) = Pick{n}(), n + 1
392+
# For nested nodes, we form the `makeargs1` based on the child `makeargs` (n += length(cat_nested(bc)))
393+
@inline function _make_makeargs1(bc::Broadcasted, n::Int)
394+
makeargs, n = _make_makeargs(bc.args, n)
395+
f = Base.maybeconstructor(bc.f)
396+
makeargs1 = (args::Tuple) -> (@inline; f(prepare_args(makeargs, args)...))
397+
makeargs1, n
411398
end
412399

413-
@inline function make_headargs(t::Tuple)
414-
let headargs = make_headargs(tail(t))
415-
return @inline function(head, tail::Vararg{Any,N}) where N
416-
(head, headargs(tail...)...)
417-
end
418-
end
419-
end
420-
@inline function make_headargs(::Tuple{})
421-
return @inline function(tail::Vararg{Any,N}) where N
422-
()
423-
end
424-
end
425-
426-
@inline function make_tailargs(t::Tuple)
427-
let tailargs = make_tailargs(tail(t))
428-
return @inline function(head, tail::Vararg{Any,N}) where N
429-
tailargs(tail...)
430-
end
431-
end
432-
end
433-
@inline function make_tailargs(::Tuple{})
434-
return @inline function(tail::Vararg{Any,N}) where N
435-
tail
436-
end
437-
end
400+
@inline prepare_args(makeargs::Tuple, @nospecialize(x::Tuple)) = (makeargs[1](x), prepare_args(tail(makeargs), x)...)
401+
@inline prepare_args(makeargs::Tuple{Any}, @nospecialize(x::Tuple)) = (makeargs[1](x),)
402+
prepare_args(::Tuple{}, ::Tuple) = ()
438403

439404
## Broadcasting utilities ##
440405

base/compiler/ssair/passes.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1107,7 +1107,7 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
11071107
struct_typ = widenconst(argextype(val, compact))
11081108
struct_argtyp = argument_datatype(struct_typ)
11091109
if struct_argtyp === nothing
1110-
if isa(struct_typ, Union)
1110+
if isa(struct_typ, Union) && is_isdefined
11111111
lift_comparison!(isdefined, compact, idx, stmt, lifting_cache, 𝕃ₒ)
11121112
end
11131113
continue

base/range.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ distinction that the lower limit is guaranteed (by the type system) to
447447
be 1.
448448
"""
449449
struct OneTo{T<:Integer} <: AbstractUnitRange{T}
450-
stop::T
450+
stop::T # invariant: stop >= zero(stop)
451451
function OneTo{T}(stop) where {T<:Integer}
452452
throwbool(r) = (@noinline; throw(ArgumentError("invalid index: $r of type Bool")))
453453
T === Bool && throwbool(stop)
@@ -463,6 +463,8 @@ struct OneTo{T<:Integer} <: AbstractUnitRange{T}
463463
T === Bool && throwbool(r)
464464
return new(max(zero(T), last(r)))
465465
end
466+
467+
global unchecked_oneto(stop::Integer) = new{typeof(stop)}(stop)
466468
end
467469
OneTo(stop::T) where {T<:Integer} = OneTo{T}(stop)
468470
OneTo(r::AbstractRange{T}) where {T<:Integer} = OneTo{T}(r)
@@ -703,8 +705,6 @@ step(r::LinRange) = (last(r)-first(r))/r.lendiv
703705
step_hp(r::StepRangeLen) = r.step
704706
step_hp(r::AbstractRange) = step(r)
705707

706-
axes(r::AbstractRange) = (oneto(length(r)),)
707-
708708
# Needed to ensure `has_offset_axes` can constant-fold.
709709
has_offset_axes(::StepRange) = false
710710

doc/man/julia.1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Print uncommon options not shown by `-h`
6767

6868
.TP
6969
--project[=<dir>/@.]
70-
Set <dir> as the home project/environment. The default @. option will search
70+
Set <dir> as the active project/environment. The default @. option will search
7171
through parent directories until a Project.toml or JuliaProject.toml file is
7272
found.
7373

doc/src/manual/command-line-interface.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ The following is a complete list of command-line switches available when launchi
9595
|`-v`, `--version` |Display version information|
9696
|`-h`, `--help` |Print command-line options (this message).|
9797
|`--help-hidden` |Uncommon options not shown by `-h`|
98-
|`--project[={<dir>\|@.}]` |Set `<dir>` as the home project/environment. The default `@.` option will search through parent directories until a `Project.toml` or `JuliaProject.toml` file is found.|
98+
|`--project[={<dir>\|@.}]` |Set `<dir>` as the active project/environment. The default `@.` option will search through parent directories until a `Project.toml` or `JuliaProject.toml` file is found.|
9999
|`-J`, `--sysimage <file>` |Start up with the given system image file|
100100
|`-H`, `--home <dir>` |Set location of `julia` executable|
101101
|`--startup-file={yes*\|no}` |Load `JULIA_DEPOT_PATH/config/startup.jl`; if `JULIA_DEPOT_PATH` environment variable is unset, load `~/.julia/config/startup.jl`|

src/aotcompile.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,10 +2093,10 @@ void jl_get_llvmf_defn_impl(jl_llvmf_dump_t* dump, jl_method_instance_t *mi, siz
20932093
// // Force imaging mode for names of pointers
20942094
// output.imaging = true;
20952095
// This would also be nice, but it seems to cause OOMs on the windows32 builder
2096-
// // Force at least medium debug info for introspection
2096+
// Force at least medium debug info for introspection
20972097
// No debug info = no variable names,
20982098
// max debug info = llvm.dbg.declare/value intrinsics which clutter IR output
2099-
output.debug_level = jl_options.debug_level;
2099+
output.debug_level = std::max(1, static_cast<int>(jl_options.debug_level));
21002100
auto decls = jl_emit_code(m, mi, src, jlrettype, output);
21012101
JL_UNLOCK(&jl_codegen_lock); // Might GC
21022102

src/codegen.cpp

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,7 @@ jl_aliasinfo_t jl_aliasinfo_t::fromTBAA(jl_codectx_t &ctx, MDNode *tbaa) {
17361736
}
17371737

17381738
static Type *julia_type_to_llvm(jl_codectx_t &ctx, jl_value_t *jt, bool *isboxed = NULL);
1739-
static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value *fval, StringRef name, jl_value_t *sig, jl_value_t *jlrettype, bool is_opaque_closure, bool gcstack_arg);
1739+
static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value *fval, StringRef name, jl_value_t *sig, jl_value_t *jlrettype, bool is_opaque_closure, bool gcstack_arg, BitVector *used_arguments=nullptr, size_t *args_begin=nullptr);
17401740
static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval = -1);
17411741
static Value *global_binding_pointer(jl_codectx_t &ctx, jl_module_t *m, jl_sym_t *s,
17421742
jl_binding_t **pbnd, bool assign);
@@ -2363,17 +2363,17 @@ std::unique_ptr<Module> jl_create_llvm_module(StringRef name, LLVMContext &conte
23632363

23642364
static void jl_name_jlfunc_args(jl_codegen_params_t &params, Function *F) {
23652365
assert(F->arg_size() == 3);
2366-
F->getArg(0)->setName("function");
2367-
F->getArg(1)->setName("args");
2368-
F->getArg(2)->setName("nargs");
2366+
F->getArg(0)->setName("function::Core.Function");
2367+
F->getArg(1)->setName("args::Any[]");
2368+
F->getArg(2)->setName("nargs::UInt32");
23692369
}
23702370

23712371
static void jl_name_jlfuncparams_args(jl_codegen_params_t &params, Function *F) {
23722372
assert(F->arg_size() == 4);
2373-
F->getArg(0)->setName("function");
2374-
F->getArg(1)->setName("args");
2375-
F->getArg(2)->setName("nargs");
2376-
F->getArg(3)->setName("sparams");
2373+
F->getArg(0)->setName("function::Core.Function");
2374+
F->getArg(1)->setName("args::Any[]");
2375+
F->getArg(2)->setName("nargs::UInt32");
2376+
F->getArg(3)->setName("sparams::Any");
23772377
}
23782378

23792379
static void jl_init_function(Function *F, const Triple &TT)
@@ -4359,7 +4359,7 @@ static jl_cgval_t emit_call_specfun_boxed(jl_codectx_t &ctx, jl_value_t *jlretty
43594359
}
43604360
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const);
43614361
theFptr = ai.decorateInst(ctx.builder.CreateAlignedLoad(pfunc, GV, Align(sizeof(void*))));
4362-
setName(ctx.emission_context, theFptr, namep);
4362+
setName(ctx.emission_context, theFptr, specFunctionObject);
43634363
}
43644364
else {
43654365
theFptr = jl_Module->getOrInsertFunction(specFunctionObject, ctx.types().T_jlfunc).getCallee();
@@ -6941,10 +6941,11 @@ static Function *gen_invoke_wrapper(jl_method_instance_t *lam, jl_value_t *jlret
69416941
return w;
69426942
}
69436943

6944-
static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value *fval, StringRef name, jl_value_t *sig, jl_value_t *jlrettype, bool is_opaque_closure, bool gcstack_arg)
6944+
static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value *fval, StringRef name, jl_value_t *sig, jl_value_t *jlrettype, bool is_opaque_closure, bool gcstack_arg, BitVector *used_arguments, size_t *arg_offset)
69456945
{
69466946
jl_returninfo_t props = {};
69476947
SmallVector<Type*, 8> fsig;
6948+
SmallVector<std::string, 4> argnames;
69486949
Type *rt = NULL;
69496950
Type *srt = NULL;
69506951
if (jlrettype == (jl_value_t*)jl_bottom_type) {
@@ -6962,6 +6963,7 @@ static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value
69626963
props.cc = jl_returninfo_t::Union;
69636964
Type *AT = ArrayType::get(getInt8Ty(ctx.builder.getContext()), props.union_bytes);
69646965
fsig.push_back(AT->getPointerTo());
6966+
argnames.push_back("union_bytes_return");
69656967
Type *pair[] = { ctx.types().T_prjlvalue, getInt8Ty(ctx.builder.getContext()) };
69666968
rt = StructType::get(ctx.builder.getContext(), makeArrayRef(pair));
69676969
}
@@ -6986,6 +6988,7 @@ static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value
69866988
// sret is always passed from alloca
69876989
assert(M);
69886990
fsig.push_back(rt->getPointerTo(M->getDataLayout().getAllocaAddrSpace()));
6991+
argnames.push_back("sret_return");
69896992
srt = rt;
69906993
rt = getVoidTy(ctx.builder.getContext());
69916994
}
@@ -7024,6 +7027,7 @@ static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value
70247027
param.addAttribute(Attribute::NoUndef);
70257028
attrs.push_back(AttributeSet::get(ctx.builder.getContext(), param));
70267029
fsig.push_back(get_returnroots_type(ctx, props.return_roots)->getPointerTo(0));
7030+
argnames.push_back("return_roots");
70277031
}
70287032

70297033
if (gcstack_arg){
@@ -7032,9 +7036,16 @@ static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value
70327036
param.addAttribute(Attribute::NonNull);
70337037
attrs.push_back(AttributeSet::get(ctx.builder.getContext(), param));
70347038
fsig.push_back(PointerType::get(JuliaType::get_ppjlvalue_ty(ctx.builder.getContext()), 0));
7039+
argnames.push_back("pgcstack_arg");
70357040
}
70367041

7037-
for (size_t i = 0; i < jl_nparams(sig); i++) {
7042+
if (arg_offset)
7043+
*arg_offset = fsig.size();
7044+
size_t nparams = jl_nparams(sig);
7045+
if (used_arguments)
7046+
used_arguments->resize(nparams);
7047+
7048+
for (size_t i = 0; i < nparams; i++) {
70387049
jl_value_t *jt = jl_tparam(sig, i);
70397050
bool isboxed = false;
70407051
Type *ty = NULL;
@@ -7066,6 +7077,8 @@ static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value
70667077
}
70677078
attrs.push_back(AttributeSet::get(ctx.builder.getContext(), param));
70687079
fsig.push_back(ty);
7080+
if (used_arguments)
7081+
used_arguments->set(i);
70697082
}
70707083

70717084
AttributeSet FnAttrs;
@@ -7095,8 +7108,14 @@ static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, Value
70957108
else
70967109
fval = emit_bitcast(ctx, fval, ftype->getPointerTo());
70977110
}
7098-
if (gcstack_arg && isa<Function>(fval))
7099-
cast<Function>(fval)->setCallingConv(CallingConv::Swift);
7111+
if (auto F = dyn_cast<Function>(fval)) {
7112+
if (gcstack_arg)
7113+
F->setCallingConv(CallingConv::Swift);
7114+
assert(F->arg_size() >= argnames.size());
7115+
for (size_t i = 0; i < argnames.size(); i++) {
7116+
F->getArg(i)->setName(argnames[i]);
7117+
}
7118+
}
71007119
props.decl = FunctionCallee(ftype, fval);
71017120
props.attrs = attributes;
71027121
return props;
@@ -7322,11 +7341,49 @@ static jl_llvm_functions_t
73227341
Function *f = NULL;
73237342
bool has_sret = false;
73247343
if (specsig) { // assumes !va and !needsparams
7344+
BitVector used_args;
7345+
size_t args_begin;
73257346
returninfo = get_specsig_function(ctx, M, NULL, declarations.specFunctionObject, lam->specTypes,
7326-
jlrettype, ctx.is_opaque_closure, JL_FEAT_TEST(ctx,gcstack_arg));
7347+
jlrettype, ctx.is_opaque_closure, JL_FEAT_TEST(ctx,gcstack_arg), &used_args, &args_begin);
73277348
f = cast<Function>(returninfo.decl.getCallee());
73287349
has_sret = (returninfo.cc == jl_returninfo_t::SRet || returninfo.cc == jl_returninfo_t::Union);
73297350
jl_init_function(f, ctx.emission_context.TargetTriple);
7351+
if (ctx.emission_context.debug_level > 0) {
7352+
auto arg_typename = [&](size_t i) JL_NOTSAFEPOINT {
7353+
auto tp = jl_tparam(lam->specTypes, i);
7354+
return jl_is_datatype(tp) ? jl_symbol_name(((jl_datatype_t*)tp)->name->name) : "<unknown type>";
7355+
};
7356+
size_t nreal = 0;
7357+
for (size_t i = 0; i < std::min(nreq, static_cast<size_t>(used_args.size())); i++) {
7358+
jl_sym_t *argname = slot_symbol(ctx, i);
7359+
if (argname == jl_unused_sym)
7360+
continue;
7361+
if (used_args.test(i)) {
7362+
auto &arg = *f->getArg(args_begin++);
7363+
nreal++;
7364+
auto name = jl_symbol_name(argname);
7365+
if (!name[0]) {
7366+
arg.setName(StringRef("#") + Twine(nreal) + StringRef("::") + arg_typename(i));
7367+
} else {
7368+
arg.setName(name + StringRef("::") + arg_typename(i));
7369+
}
7370+
}
7371+
}
7372+
if (va && ctx.vaSlot != -1) {
7373+
size_t vidx = 0;
7374+
for (size_t i = nreq; i < used_args.size(); i++) {
7375+
if (used_args.test(i)) {
7376+
auto &arg = *f->getArg(args_begin++);
7377+
auto type = arg_typename(i);
7378+
const char *name = jl_symbol_name(slot_symbol(ctx, ctx.vaSlot));
7379+
if (!name[0])
7380+
name = "...";
7381+
vidx++;
7382+
arg.setName(name + StringRef("[") + Twine(vidx) + StringRef("]::") + type);
7383+
}
7384+
}
7385+
}
7386+
}
73307387

73317388
// common pattern: see if all return statements are an argument in that
73327389
// case the apply-generic call can re-use the original box for the return

0 commit comments

Comments
 (0)