Skip to content

Commit

Permalink
Eliminating allocation of ccall root in simple cases
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyichao committed Jul 10, 2017
1 parent eca9fe5 commit 15c92f1
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
42 changes: 38 additions & 4 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5217,6 +5217,23 @@ function occurs_outside_getfield(e::ANY, sym::ANY,
if head === :(=)
return occurs_outside_getfield(e.args[2], sym, sv,
field_count, field_names)
elseif head === :foreigncall
args = e.args
nccallargs = args[5]::Int
# Only arguments escape, GC root arguments do not escape.
for i in 1:length(args)
a = args[i]
if i > 5 + nccallargs && symequal(a, sym)
ty = widenconst(exprtype(a, sv.src, sv.mod))
if isleaftype(ty) && nfields(ty) <= field_count
continue
end
return true
end
if occurs_outside_getfield(a, sym, sv, field_count, field_names)
return true
end
end
else
if (head === :block && isa(sym, Slot) &&
sv.src.slotflags[slot_id(sym)] & Slot_UsedUndef == 0)
Expand Down Expand Up @@ -5800,8 +5817,11 @@ end
function replace_getfield!(e::Expr, tupname, vals, field_names, sv::InferenceState)
for i = 1:length(e.args)
a = e.args[i]
if isa(a,Expr) && is_known_call(a, getfield, sv.src, sv.mod) &&
symequal(a.args[2],tupname)
if !isa(a, Expr)
continue
end
a = a::Expr
if is_known_call(a, getfield, sv.src, sv.mod) && symequal(a.args[2], tupname)
idx = if isa(a.args[3], Int)
a.args[3]
else
Expand Down Expand Up @@ -5830,8 +5850,22 @@ function replace_getfield!(e::Expr, tupname, vals, field_names, sv::InferenceSta
end
end
e.args[i] = val
elseif isa(a, Expr)
replace_getfield!(a::Expr, tupname, vals, field_names, sv)
else
if a.head === :foreigncall
args = a.args
nccallargs = args[5]::Int
le = length(args)
next_i = 6 + nccallargs
while next_i <= le
i = next_i
next_i += 1

symequal(args[i], tupname) || continue
splice!(args, i, vals)
next_i += length(vals) - 1
end
end
replace_getfield!(a, tupname, vals, field_names, sv)
end
end
end
Expand Down
11 changes: 11 additions & 0 deletions test/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,21 @@ function compare_large_struct(a)
end
end

mutable struct MutableStruct
a::Int
MutableStruct() = new()
end

breakpoint_mutable(a::MutableStruct) = ccall(:jl_breakpoint, Void, (Ref{MutableStruct},), a)

if opt_level > 0
@test !contains(get_llvm(isequal, Tuple{Nullable{BigFloat}, Nullable{BigFloat}}), "%gcframe")
@test !contains(get_llvm(pointer_not_safepoint, Tuple{}), "%gcframe")
compare_large_struct_ir = get_llvm(compare_large_struct, Tuple{typeof(create_ref_struct())})
@test contains(compare_large_struct_ir, "call i32 @memcmp")
@test !contains(compare_large_struct_ir, "%gcframe")
breakpoint_mutable_ir = get_llvm(breakpoint_mutable, Tuple{MutableStruct})
@test !contains(breakpoint_mutable_ir, "%gcframe")
@test !contains(breakpoint_mutable_ir, "jl_gc_pool_alloc")
@test contains(get_llvm(MutableStruct, Tuple{}), "jl_gc_pool_alloc")
end

0 comments on commit 15c92f1

Please sign in to comment.