Skip to content

Commit

Permalink
Merge pull request #15261 from JuliaLang/jn/grabbag
Browse files Browse the repository at this point in the history
grab-bag of inference and codegen related improvements
  • Loading branch information
JeffBezanson committed Feb 29, 2016
2 parents 542137a + b4fff7f commit 9cda4ab
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 43 deletions.
1 change: 1 addition & 0 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ macro generated(f)
end


tuple_type_head(::Type{Union{}}) = throw(MethodError(tuple_type_head, (Type{Union{}},)))
function tuple_type_head{T<:Tuple}(::Type{T})
@_pure_meta
T.parameters[1]
Expand Down
89 changes: 50 additions & 39 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -857,16 +857,17 @@ function abstract_apply(af::ANY, fargs, aargtypes::Vector{Any}, vtypes, sv, e)
end

function isconstantargs(args, argtypes::Vector{Any}, sv::VarInfo)
if isempty(argtypes)
if length(argtypes) == 1 # just the function
return true
end
if is(args,()) || isvarargtype(argtypes[end])
if isvarargtype(argtypes[end])
return false
end
for i = 2:length(args)
arg = args[i]
for i = 2:length(argtypes)
t = argtypes[i]
if !isType(t) || has_typevars(t.parameters[1])
args === () && return false
arg = args[i]
if isconstantref(arg, sv) === false
return false
end
Expand All @@ -876,13 +877,13 @@ function isconstantargs(args, argtypes::Vector{Any}, sv::VarInfo)
end

function _ieval_args(args, argtypes::Vector{Any}, sv::VarInfo)
c = cell(length(args)-1)
c = cell(length(argtypes) - 1)
for i = 2:length(argtypes)
t = argtypes[i]
if isType(t) && !has_typevars(t.parameters[1])
c[i-1] = t.parameters[1]
c[i - 1] = t.parameters[1]
else
c[i-1] = _ieval(isconstantref(args[i], sv), sv)
c[i - 1] = _ieval(isconstantref(args[i], sv), sv)
end
end
return c
Expand All @@ -901,7 +902,6 @@ function pure_eval_call(f::ANY, fargs, argtypes::ANY, sv, e)
end

args = _ieval_args(fargs, argtypes, sv)
tm = _topmod(sv)
atype = Tuple{type_typeof(f), Any[type_typeof(a) for a in args]...}
meth = _methods_by_ftype(atype, 1)
if meth === false || length(meth) != 1
Expand All @@ -923,29 +923,12 @@ function pure_eval_call(f::ANY, fargs, argtypes::ANY, sv, e)
end
end

local v
try
v = f(args...)
return type_typeof(v)
catch
return false
end
if isa(e, Expr) # replace Expr with a constant
stmts = Any[] # check if any arguments aren't effect_free and need to be kept around
for i = 1:length(fargs)
arg = fargs[i]
if !effect_free(arg, sv, false)
push!(stmts, arg)
end
end
if isempty(stmts)
e.head = :inert # eval_annotate will turn this into a QuoteNode
e.args = Any[v]
else
e.head = :call # should get cleaned up by tuple elimination
e.args = Any[top_getfield, Expr(:call, top_tuple, stmts..., v), length(stmts) + 1]
end
end
return type_typeof(v)
end


Expand Down Expand Up @@ -1929,8 +1912,6 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::VarInfo, decls, undefs)
return e
#elseif is(head,:gotoifnot) || is(head,:return)
# e.typ = Any
elseif is(head,:inert)
return QuoteNode(e.args[1])
elseif is(head,:(=))
# e.typ = Any
s = e.args[1]
Expand Down Expand Up @@ -2244,11 +2225,10 @@ end
# static parameters are ok if all the static parameter values are leaf types,
# meaning they are fully known.
# `ft` is the type of the function. `f` is the exact function if known, or else `nothing`.
function inlineable(f::ANY, ft::ANY, e::Expr, atype::ANY, sv::VarInfo, enclosing_ast::Expr)
function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::VarInfo, enclosing_ast::Expr)
local linfo,
metharg::Type,
atypes = atype.parameters,
argexprs = copy(e.args),
argexprs = e.args,
incompletematch = false

if (is(f, typeassert) || is(ft, typeof(typeassert))) && length(atypes)==3
Expand Down Expand Up @@ -2281,6 +2261,10 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atype::ANY, sv::VarInfo, enclosing
end

local methfunc
atype = Tuple{atypes...}
if length(atype.parameters)-1 > MAX_TUPLETYPE_LEN
atype = limit_tuple_type(atype)
end
meth = _methods_by_ftype(atype, 1)
if meth === false || length(meth) != 1
return NF
Expand All @@ -2296,6 +2280,31 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atype::ANY, sv::VarInfo, enclosing
if linfo === NF
return NF
end
if linfo.pure && isconstantargs(argexprs, atypes, sv)
# check if any arguments aren't effect_free and need to be kept around
stmts = Any[]
for i = 1:length(argexprs)
arg = argexprs[i]
if !effect_free(arg, sv, false)
push!(stmts, arg)
end
end

if isType(e.typ) && !has_typevars(e.typ.parameters[1])
return (QuoteNode(e.typ.parameters[1]), stmts)
end

constargs = _ieval_args(argexprs, atypes, sv)
try
v = f(constargs...)
return (QuoteNode(v), stmts)
catch ex
thrw = Expr(:call, TopNode(:throw), QuoteNode(ex))
thrw.typ = Bottom
return (thrw, stmts)
end
end

methfunc = meth[3].func
methsig = meth[3].sig
if !(atype <: metharg)
Expand Down Expand Up @@ -2471,6 +2480,9 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atype::ANY, sv::VarInfo, enclosing

@assert na == length(argexprs)

if argexprs === e.args
argexprs = copy(argexprs)
end
if needcopy
body = astcopy(body)
end
Expand All @@ -2491,7 +2503,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atype::ANY, sv::VarInfo, enclosing
end

# see if each argument occurs only once in the body expression
stmts = []
stmts = Any[]
stmts_free = true # true = all entries of stmts are effect_free

# when 1 method matches the inferred types, there is still a chance
Expand Down Expand Up @@ -2925,15 +2937,14 @@ function inlining_pass(e::Expr, sv, ast)
end

for ninline = 1:100
ata = Any[exprtype(e.args[i],sv) for i in 2:length(e.args)]
for a in ata
ata = cell(length(e.args))
ata[1] = ft
for i = 2:length(e.args)
a = exprtype(e.args[i], sv)
(a === Bottom || isvarargtype(a)) && return (e, stmts)
ata[i] = a
end
atype = Tuple{ft, ata...}
if length(atype.parameters)-1 > MAX_TUPLETYPE_LEN
atype = limit_tuple_type(atype)
end
res = inlineable(f, ft, e, atype, sv, ast)
res = inlineable(f, ft, e, ata, sv, ast)
if isa(res,Tuple)
if isa(res[2],Array) && !isempty(res[2])
append!(stmts,res[2])
Expand Down
3 changes: 3 additions & 0 deletions base/linalg/arpack.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ function aupd_wrapper(T, matvecA::Function, matvecB::Function, solveSI::Function
naupd(ido, bmat, n, which, nev, TOL, resid, ncv, v, n,
iparam, ipntr, workd, workl, lworkl, info)
end
if info[1] != 0
throw(ARPACKException(info[1]))
end

load_idx = ipntr[1]+zernm1
store_idx = ipntr[2]+zernm1
Expand Down
6 changes: 3 additions & 3 deletions base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ function show_trace_entry(io, frame, n)
n > 1 && print(io, " (repeats ", n, " times)")
end

function show_backtrace(io::IO, t, set=1:typemax(Int))
function show_backtrace(io::IO, t::Vector, set=1:typemax(Int))
# we may not declare :eval_user_input
# directly so that we get a compile error
# in case its name changes in the future
Expand All @@ -416,7 +416,7 @@ function show_backtrace(io::IO, t, set=1:typemax(Int))
end, t, set)
end

function show_backtrace(io::IO, top_function::Symbol, t, set)
function show_backtrace(io::IO, top_function::Symbol, t::Vector, set)
process_entry(last_frame, n) =
show_trace_entry(io, last_frame, n)
process_backtrace(process_entry, top_function, t, set)
Expand All @@ -429,7 +429,7 @@ function show_backtrace(io::IO, top_function::Symbol, t::Vector{Any}, set)
end

# process the backtrace, up to (but not including) top_function
function process_backtrace(process_func::Function, top_function::Symbol, t, set; skipC = true)
function process_backtrace(process_func::Function, top_function::Symbol, t::Vector, set; skipC = true)
n = 0
last_frame = StackTraces.UNKNOWN
count = 0
Expand Down
10 changes: 10 additions & 0 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3140,6 +3140,16 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx)
emit_unbox(vtype, slot, slot.typ),
false, slot.typ, ctx);
}
else if (slot.isboxed) {
// see if inference had a better type for the gensym than the expression (after inlining getfield on a Tuple)
jl_value_t *gensym_types = jl_lam_gensyms(ctx->ast);
if (jl_is_array(gensym_types)) {
jl_value_t *declType = jl_cellref(gensym_types, idx);
if (declType != slot.typ) {
slot = remark_julia_type(slot, declType);
}
}
}
ctx->gensym_SAvalues.at(idx) = slot; // now gensym_SAvalues[idx] contains the SAvalue
ctx->gensym_assigned.at(idx) = true;
return;
Expand Down
2 changes: 1 addition & 1 deletion src/llvm-gcroot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ void allocate_frame()
}
}
// delete any StoreInst to a gcframe slot that isn't live
if (StoreInst *storeInst = dyn_cast<StoreInst>(inst)) {
else if (StoreInst *storeInst = dyn_cast<StoreInst>(inst)) {
frame_register def = get_gcroot(storeInst->getPointerOperand());
if (CallInst *gcroot = def.first) {
if (gcroot->getCalledFunction() == jlcall_frame_func) {
Expand Down

0 comments on commit 9cda4ab

Please sign in to comment.