Hello,
Below is a MWE of what I am seeing in an application:
function foo(v)
#uncomment for Box
size(v) == (10,10) && error()
ss=zeros(Float64,Threads.nthreads())
#this does not lead to Box
#size(v) == (10,10) && error()
Threads.@threads for i2 in 1:size(v,2)
@simd for i1 in 1:size(v,1)
tid=Threads.threadid()
@inbounds ss[tid]+=v[i1,i2]
end
end
return sum(ss)
end
@code_warntype foo(rand(100,100))Body::Any
│╻ Type3 1 ── %1 = %new(Core.Box)::Core.Box
│╻ size │ %2 = (Base.arraysize)(v, 1)::Int64
││ │ %3 = (Base.arraysize)(v, 2)::Int64
││╻╷ _eq │ %4 = (%2 === 10)::Bool
││╻ _eq │ %5 = (%4 === false)::Bool
│││ └─── goto #3 if not %5
│││ 2 ── goto #7
│││╻╷ _eq 3 ── %8 = (%3 === 10)::Bool
│││╻ _eq │ %9 = (%8 === false)::Bool
││││ └─── goto #5 if not %9
││││ 4 ── goto #6
││││ 5 ── goto #6
│││ 6 ┄─ %13 = φ (#4 => false, #5 => true)::Bool
│││ └─── goto #7
││ 7 ┄─ %15 = φ (#2 => false, #6 => %13)::Bool
││ └─── goto #8
│ 8 ── goto #10 if not %15
│ 9 ── invoke Main.error()
│ └─── $(Expr(:unreachable))
│╻ nthreads4 10 ┄ %20 = (Base.Threads.cglobal)(:jl_n_threads, Base.Threads.Cint)::Ptr{Int32}
││╻ unsafe_load │ %21 = (Base.pointerref)(%20, 1, 1)::Int32
│││╻ toInt64 │ %22 = (Core.sext_int)(Core.Int64, %21)::Int64
││╻╷╷ zeros │ %23 = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Float64,1}, svec(Any, Int64), :(:ccall), 2, Array{Float64,1}, :(%22), :(%22)))::Array{Float64,1}
│││ │ %24 = invoke Base.fill!(%23::Array{Float64,1}, 0.0::Float64)::Array{Float64,1}
│ │ (Core.setfield!)(%1, :contents, %24)
│╻╷ macro expansion9 │ %26 = (Base.arraysize)(v, 2)::Int64
││╻╷╷╷ Colon │ %27 = (Base.sle_int)(1, %26)::Bool
│││╻ Type │ (Base.sub_int)(%26, 1)
││││┃ unitrange_last │ %29 = (Base.ifelse)(%27, %26, 0)::Int64
││││ │ %30 = %new(UnitRange{Int64}, 1, %29)::UnitRange{Int64}
│╻ macro expansion │ %31 = %new(getfield(Main, Symbol("##1134#threadsfor_fun#280")){Array{Float64,2},UnitRange{Int64}}, v, %1, %30)::getfield(Main, Symbol("##1134#threadsfor_fun#280")){Array{Float64,2},UnitRange{Int64}}
││╻ threadid │ %32 = $(Expr(:foreigncall, :(:jl_threadid), Int16, svec(), :(:ccall), 0))::Int16
│││╻ + │ %33 = (Base.sext_int)(Int64, %32)::Int64
│││╻ + │ %34 = π (1, Int64)
││││╻ + │ %35 = (Base.add_int)(%33, %34)::Int64
│││╻ == │ %36 = (%35 === 1)::Bool
│││╻ ! │ %37 = (Base.not_int)(%36)::Bool
││ └─── goto #12 if not %37
││ 11 ─ goto #13
││ 12 ─ %40 = Base.Threads.in_threaded_loop::Core.Compiler.Const(Base.RefValue{Bool}(false), false)
│││╻ getproperty └─── %41 = (Base.getfield)(%40, :x)::Bool
││ 13 ┄ %42 = φ (#11 => %37, #12 => %41)::Bool
││ └─── goto #15 if not %42
││ 14 ─ invoke %31(true::Bool)
││ └─── goto #16
││ 15 ─ %46 = Base.Threads.in_threaded_loop::Core.Compiler.Const(Base.RefValue{Bool}(false), false)
│││╻ setproperty! │ (Base.setfield!)(%46, :x, true)
│╻ macro expansion │ $(Expr(:foreigncall, :(:jl_threading_run), Ref{Nothing}, svec(Any), :(:ccall), 1, :(%31), getfield(Main, Symbol("##1134#threadsfor_fun#280")){Array{Float64,2},UnitRange{Int64}}, :(v), :(%1)))
││ │ %49 = Base.Threads.in_threaded_loop::Core.Compiler.Const(Base.RefValue{Bool}(false), false)
││╻ setindex! └─── (Base.setfield!)(%49, :x, false)
│╻ macro expansion 16 ┄ %51 = (Core.isdefined)(%1, :contents)::Bool
││ └─── goto #18 if not %51
││ 17 ─ goto #19
││ 18 ─ $(Expr(:throw_undef_if_not, :ss, false))
││ 19 ┄ %55 = (Core.getfield)(%1, :contents)::Any
││ │ %56 = (Main.sum)(%55)::Any
││ └─── return %56
│ 20 ─ goto #10
I understand that this is 15276, but why is the error check before ss
causing it (checking after does not). I appreciate any help understanding this so I can catch it in the future (and other users may too).
Thanks!