From dc46b0c9d2170c079d81306fc29b675a00700eaa Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 5 Apr 2016 00:25:44 -0400 Subject: [PATCH 1/4] GenSym is slightly cheaper than gensym in terms of the code generated this might make tests a wee bit faster ref #15346 --- base/test.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/test.jl b/base/test.jl index 0b1fad045c21e..a7dba03d76ac0 100644 --- a/base/test.jl +++ b/base/test.jl @@ -160,7 +160,7 @@ macro test(ex) if isa(ex, Expr) && ex.head == :comparison # Generate a temporary for every term in the expression n = length(ex.args) - terms = [gensym() for i in 1:n] + terms = [GenSym(i) for i in 1:n] # Create a new block that evaluates each term in the # comparison indivudally comp_block = Expr(:block) From e529058e386595f464e0eb85b34d1ffa75d2dbe8 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 4 Apr 2016 20:45:24 -0400 Subject: [PATCH 2/4] make == type comparisions much cheaper and faster ref #11425 --- base/operators.jl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/base/operators.jl b/base/operators.jl index 67b7a90fd9107..b2672ce4fc30b 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -19,8 +19,14 @@ isless(x::AbstractFloat, y::AbstractFloat) = (!isnan(x) & isnan(y)) | (signbit(x isless(x::Real, y::AbstractFloat) = (!isnan(x) & isnan(y)) | (signbit(x) & !signbit(y)) | (x < y) isless(x::AbstractFloat, y::Real ) = (!isnan(x) & isnan(y)) | (signbit(x) & !signbit(y)) | (x < y) -=={T}(::Type{T}, ::Type{T}) = true # encourage more specialization on types (see #11425) -==(T::Type, S::Type) = typeseq(T, S) +function ==(T::Type, S::Type) + @_pure_meta + typeseq(T, S) +end +function !=(T::Type, S::Type) + @_pure_meta + !(T == S) +end ## comparison fallbacks ## From c60a734cb06fa0eb4cbc911ab407f03fc979413d Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 5 Apr 2016 00:22:43 -0400 Subject: [PATCH 3/4] fix critical latent bug in inlining @pure --- base/inference.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index e7d524bb694ac..24da6d6c07a00 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2361,7 +2361,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference if linfo === NF return NF end - if linfo.pure && isconstantargs(argexprs, atypes, sv) + if isa(f, ft) && 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) From cb5e2fa59410ede34897acc2a78f193bd92d1244 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 8 Mar 2016 18:45:38 -0500 Subject: [PATCH 4/4] stupdate can be expensive: refactor to avoid needing to call it twice --- base/coreimg.jl | 5 ++++- base/inference.jl | 52 +++++++++++++++++++++-------------------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/base/coreimg.jl b/base/coreimg.jl index f79ffc286543e..96a9658910358 100644 --- a/base/coreimg.jl +++ b/base/coreimg.jl @@ -42,7 +42,10 @@ include("operators.jl") include("pointer.jl") const checked_add = + const checked_sub = - -(::Type{T}){T}(arg) = convert(T, arg)::T +if !isdefined(Main, :Base) + # conditional to allow redefining Core.Inference after base exists + (::Type{T}){T}(arg) = convert(T, arg)::T +end # core array operations include("abstractarray.jl") diff --git a/base/inference.jl b/base/inference.jl index 24da6d6c07a00..fe8e10cffcfc5 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -124,7 +124,7 @@ type InferenceState # exception handlers cur_hand = () - handler_at = Any[ 0 for i=1:n ] + handler_at = Any[ () for i=1:n ] n_handlers = 0 W = IntSet() @@ -1401,31 +1401,24 @@ function stupdate!(state::VarTable, change::StateUpdate) return state end -stupdate!(state::Tuple{}, changes::VarTable) = copy(changes) - function stupdate!(state::VarTable, changes::VarTable) + newstate = false for i = 1:length(state) newtype = changes[i] oldtype = state[i] if schanged(newtype, oldtype) + newstate = state state[i] = smerge(oldtype, newtype) end end - return state + return newstate end -stchanged(new::Tuple{}, old::Tuple{}) = false -stchanged(new, old::Tuple{}) = true +stupdate!(state::Tuple{}, changes::VarTable) = copy(changes) -function stchanged(new::VarTable, old::VarTable) - is(old,()) && return true - for i = 1:length(new) - newtype = new[i] - oldtype = old[i] - schanged(newtype, oldtype) && return true - end - return false -end +stupdate!(state::Tuple{}, changes::Tuple{}) = false + +#### helper functions for typeinf initialization and looping #### function stchanged(new::StateUpdate, old::VarTable) is(old,()) && return true @@ -1744,11 +1737,7 @@ function typeinf_frame(frame) delete!(W, pc) frame.currpc = pc frame.static_typeof = false - if frame.handler_at[pc] === 0 - frame.handler_at[pc] = frame.cur_hand - else - frame.cur_hand = frame.handler_at[pc] - end + frame.cur_hand = frame.handler_at[pc] stmt = frame.linfo.code[pc] changes = abstract_interpret(stmt, s[pc]::Array{Any,1}, frame) if changes === () @@ -1761,9 +1750,10 @@ function typeinf_frame(frame) if frame.cur_hand !== () # propagate type info to exception handler l = frame.cur_hand[1] - if stchanged(changes, s[l]) + newstate = stupdate!(s[l], changes) + if newstate !== false push!(W, l) - s[l] = stupdate!(s[l], changes) + s[l] = newstate end end pc´ = pc+1 @@ -1796,10 +1786,11 @@ function typeinf_frame(frame) else # general case frame.handler_at[l] = frame.cur_hand - if stchanged(changes, s[l]) + newstate = stupdate!(s[l], changes) + if newstate !== false # add else branch to active IP list push!(W, l) - s[l] = stupdate!(s[l], changes) + s[l] = newstate end end elseif is(hd, :type_goto) @@ -1845,9 +1836,10 @@ function typeinf_frame(frame) l = frame.cur_hand[1] old = s[l] new = s[pc]::Array{Any,1} - if old === () || stchanged(new, old::Array{Any,1}) + newstate = stupdate!(old, new) + if newstate !== false push!(W, l) - s[l] = stupdate!(old, new) + s[l] = newstate end # if frame.handler_at[l] === 0 # frame.n_handlers += 1 @@ -1866,9 +1858,11 @@ function typeinf_frame(frame) end end end - if pc´<=n && (frame.handler_at[pc´] = frame.cur_hand; true) && - stchanged(changes, s[pc´]) - s[pc´] = stupdate!(s[pc´], changes) + pc´ > n && break # can't proceed with the fast-path fall-through + frame.handler_at[pc´] = frame.cur_hand + newstate = stupdate!(s[pc´], changes) + if newstate !== false + s[pc´] = newstate pc = pc´ elseif pc´ in W pc = pc´