I was playing with `@code_warntype` in 0.4.0-rc1 and I jumped when I saw
the output of a simple function containing a for loop. Things get worse if
the range for the for loop decrements. (By the way, why does (Base.add_int)(
s::Int64,i::Int64)::Any returns ::Any?)
By contrast, the output for a while loop is simpler. I am not sure what to
make out of it.
michele
Here are the functions and their output
function test(q)
s = 0
for i = 1:q
s += i
end
s
end
output
julia> @code_warntype(test(10))
Variables:
q::Int64
s::Int64
#s2::Int64
i::Int64
Body:
begin # E:\euler\euler05.jl, line 39:
s = 0 # E:\euler\euler05.jl, line 40:
GenSym(0) = $(Expr(:new, UnitRange{Int64}, 1, :(((top(getfield))(Base.
Intrinsics,:select_value)::I)((Base.sle_int)(1,q::Int64)::Bool,q::Int64,(
Base.box)(Int64,(Base.sub_int)(1,1))::Int64)::Int64)))
#s2 = (top(getfield))(GenSym(0),:start)::Int64
unless (Base.box)(Base.Bool,(Base.not_int)(#s2::Int64 ===
(Base.box)(Base.Int,(Base.add_int)((top(getfield))(GenSym(0),:stop)::Int64,1)::Any)::Int64::Bool)::Any)::Bool
goto 1
2:
GenSym(2) = #s2::Int64
GenSym(3) = (Base.box)(Base.Int,(Base.add_int)(
#s2::Int64,1)::Any)::Int64
i = GenSym(2)
#s2 = GenSym(3) # E:\euler\euler05.jl, line 41:
s = (Base.box)(Base.Int,(Base.add_int)(s::Int64,i::Int64)::Any)::Int64
3:
unless (Base.box)(Base.Bool,(Base.not_int)((Base.box)(Base.Bool,(Base.
not_int)(#s2::Int64 ===
(Base.box)(Base.Int,(Base.add_int)((top(getfield))(GenSym(0),:stop)::Int64,1)::Any)::Int64::Bool)::Any)::Bool)::Any)::Bool
goto 2
1:
0: # E:\euler\euler05.jl, line 43:
return s::Int64
end::Int64
For loop decrementing
function test2(q)
s = 0
for i = q:-1:1
s += i
end
s
end
julia> @code_warntype(test2(10))
Variables:
q::Int64
s::Int64
#s2::Int64
i::Int64
Body:
begin # E:\euler\euler05.jl, line 47:
s = 0 # E:\euler\euler05.jl, line 48:
GenSym(2) = (Base.steprange_last)(q::Int64,-1,1)::Int64
GenSym(0) = $(Expr(:new, StepRange{Int64,Int64}, :(q::Int64), -1,
GenSym(2)))
#s2 = (top(getfield))(GenSym(0),:start)::Int64
unless (Base.box)(Base.Bool,(Base.not_int)((Base.box)(Base.Bool,(Base.
or_int)((Base.box)(Base.Bool,(Base.and_int)((Base.box)(Base.Bool,(Base.
not_int)((top(getfield))(GenSym(0),:start)::Int64 === (top(getfield))(GenSym
(0),:stop)::Int64::Bool)::Any)::Bool,(Base.box)(Base.Bool,(Base.not_int)((
Base.slt_int)(0,(top(getfield))(GenSym(0),:step)::Int64)::Bool === (Base.
slt_int)((top(getfield))(GenSym(0),:start)::Int64,(top(getfield))(GenSym(0
),:stop)::Int64)::Bool::Bool)::Any)::Bool)::Any)::Bool,#s2::Int64 ===
(Base.box)(Base.Int,(Base.add_int)((top(getfield))(GenSym(0),:stop)::Int64,(top(getfield))(GenSym(0),:step)::Int64)::Any)::Int64::Bool)::Any)::Bool)::Any)::Bool
goto 1
2:
GenSym(3) = #s2::Int64
GenSym(4) = (Base.box)(Base.Int,(Base.add_int)(
#s2::Int64,(top(getfield))(GenSym(0),:step)::Int64)::Any)::Int64
i = GenSym(3)
#s2 = GenSym(4) # E:\euler\euler05.jl, line 49:
s = (Base.box)(Base.Int,(Base.add_int)(s::Int64,i::Int64)::Any)::Int64
3:
unless (Base.box)(Base.Bool,(Base.not_int)((Base.box)(Base.Bool,(Base.
not_int)((Base.box)(Base.Bool,(Base.or_int)((Base.box)(Base.Bool,(Base.
and_int)((Base.box)(Base.Bool,(Base.not_int)((top(getfield))(GenSym(0),:
start)::Int64 === (top(getfield))(GenSym(0),:stop)::Int64::Bool)::Any)::Bool
,(Base.box)(Base.Bool,(Base.not_int)((Base.slt_int)(0,(top(getfield))(GenSym
(0),:step)::Int64)::Bool === (Base.slt_int)((top(getfield))(GenSym(0),:start
)::Int64,(top(getfield))(GenSym(0),:stop)::Int64)::Bool::Bool)::Any)::Bool
)::Any)::Bool,#s2::Int64 ===
(Base.box)(Base.Int,(Base.add_int)((top(getfield))(GenSym(0),:stop)::Int64,(top(getfield))(GenSym(0),:step)::Int64)::Any)::Int64::Bool)::Any)::Bool)::Any)::Bool)::Any)::Bool
goto 2
1:
0: # E:\euler\euler05.jl, line 51:
return s::Int64
end::Int64
By contrast, all is nice with a while loop:
function test3(q)
i, s = 1, 0
while i <= q
s += i
i += 1
end
s
end
julia> @code_warntype(test3(10))
Variables:
q::Int64
i::Int64
s::Int64
Body:
begin # E:\euler\euler05.jl, line 55:
i = 1
s = 0 # E:\euler\euler05.jl, line 56:
unless (Base.sle_int)(i::Int64,q::Int64)::Bool goto 1
2: # E:\euler\euler05.jl, line 57:
s = (Base.box)(Base.Int,(Base.add_int)(s::Int64,i::Int64)::Any)::Int64 #
E:\euler\euler05.jl, line 58:
i = (Base.box)(Base.Int,(Base.add_int)(i::Int64,1)::Any)::Int64
3:
unless (Base.box)(Base.Bool,(Base.not_int)((Base.sle_int)(i::Int64,q::
Int64)::Bool)::Any)::Bool goto 2
1:
0: # E:\euler\euler05.jl, line 60:
return s::Int64
end::Int64