From a5d54c2413248c5cb9854b724711297c6fef53a7 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 22 Apr 2014 21:02:51 -0400 Subject: [PATCH 1/3] fix #6599 --- base/inference.jl | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index 3bf4893b17227..648aaa78a3ffc 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1864,7 +1864,12 @@ function effect_free(e::ANY, sv, allow_volatile::Bool) if is_known_call_p(e, is_pure_builtin, sv) if !allow_volatile && is_known_call_p(e, (f)->contains_is(_pure_builtins_volatile, f), sv) # arguments must be immutable to ensure e is affect_free + first = true for a in ea + if first # first "arg" is the function name + first = false + continue + end if isa(a,Symbol) return false end @@ -1890,7 +1895,21 @@ function effect_free(e::ANY, sv, allow_volatile::Bool) end return true end - elseif e.head === :new || e.head == :return + elseif e.head == :new + first = !allow_volatile + for a in ea + if first + first = false + isa(a,SymbolNode) || return false + typ = (a::SymbolNode).typ + isa(typ,DataType) || return false + !(typ::DataType).mutable || return false + elseif !effect_free(a,sv,allow_volatile) + return false + end + end + return true + elseif e.head == :return for a in ea if !effect_free(a,sv,allow_volatile) return false From 6905d1ebb596573b40aaca4a8e3a7467f32902b9 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 22 Apr 2014 22:09:09 -0400 Subject: [PATCH 2/3] better fix for #6566. also increase inlining this inlining threshold seems to translates to approximately 8 expressions of low complexity, and about the same number of llvm instructions --- base/inference.jl | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 648aaa78a3ffc..02f3de1413dc4 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2155,16 +2155,19 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) for j = length(body.args):-1:1 b = body.args[j] if occ < 1 - occ += occurs_more(b, x->is(x,a), 1) + occ += occurs_more(b, x->is(x,a), 5) end - if occ > 0 && (!affect_free || !effect_free(b, sv, true)) #TODO: we could short-circuit this test better by memoizing effect_free(b) in the for loop over i + if occ > 0 && affect_free && !effect_free(b, sv, true) #TODO: we could short-circuit this test better by memoizing effect_free(b) in the for loop over i affect_free = false + end + if occ > 5 + occ = 6 break end end free = effect_free(aei,sv,true) - affect_unfree = (islocal || (affect_free && !free) || (!affect_free && !effect_free(aei,sv,false))) - if affect_unfree || (occ==0 && is(aeitype,None)) + if ((occ==0 && is(aeitype,None)) || islocal || !inline_worthy(aei, occ) || + (affect_free && !free) || (!affect_free && !effect_free(aei,sv,false))) if occ != 0 # islocal=true is implied # introduce variable for this argument vnew = unique_name(enclosing_ast, ast) @@ -2257,13 +2260,19 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) return (expr, stmts) end -function inline_worthy(body::Expr) +inline_worthy(body, occurences::Int) = true +function inline_worthy(body::Expr, occurences::Int=1) # 0 <= occurrences <= 6 + occurences == 0 && return true # if isa(body.args[1],QuoteNode) && (body.args[1]::QuoteNode).value === :inline # shift!(body.args) # return true # end - if length(body.args) < 6 && occurs_more(body, e->true, 40) < 40 - return true + symlim = div(8,occurences) + if length(body.args) < symlim + symlim *= 12 + if occurs_more(body, e->true, symlim) < symlim + return true + end end return false end From 7033cc5dcffcb452d530c62e8607178934133ae7 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 24 Apr 2014 21:26:21 -0400 Subject: [PATCH 3/3] incorporate Jeff's comments for inlining patch --- base/inference.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 02f3de1413dc4..c960a56db8efb 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1900,11 +1900,12 @@ function effect_free(e::ANY, sv, allow_volatile::Bool) for a in ea if first first = false - isa(a,SymbolNode) || return false - typ = (a::SymbolNode).typ - isa(typ,DataType) || return false - !(typ::DataType).mutable || return false - elseif !effect_free(a,sv,allow_volatile) + typ = exprtype(a) + if !isType(typ) || !isa((typ::Type).parameters[1],DataType) || ((typ::Type).parameters[1]::DataType).mutable + return false + end + end + if !effect_free(a,sv,allow_volatile) return false end end @@ -2166,7 +2167,7 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) end end free = effect_free(aei,sv,true) - if ((occ==0 && is(aeitype,None)) || islocal || !inline_worthy(aei, occ) || + if ((occ==0 && is(aeitype,None)) || islocal || (occ > 1 && !inline_worthy(aei, occ)) || (affect_free && !free) || (!affect_free && !effect_free(aei,sv,false))) if occ != 0 # islocal=true is implied # introduce variable for this argument @@ -2261,15 +2262,14 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) end inline_worthy(body, occurences::Int) = true -function inline_worthy(body::Expr, occurences::Int=1) # 0 <= occurrences <= 6 - occurences == 0 && return true +function inline_worthy(body::Expr, occurences::Int=1) # 0 < occurrences <= 6 # if isa(body.args[1],QuoteNode) && (body.args[1]::QuoteNode).value === :inline # shift!(body.args) # return true # end - symlim = div(8,occurences) + symlim = div(6,occurences) if length(body.args) < symlim - symlim *= 12 + symlim *= 6 if occurs_more(body, e->true, symlim) < symlim return true end