Oftentimes using such a style will enable this kind of optimization, but here I believe that
is not considered “pure” from the compiler’s perspective. If we use a slightly tweaked version of your function:
function test2(z::Bool, array::AbstractVector)
x = sum(abs2, array)
if z
return x
else
return 10.0
end
end
The sum
(or in the original function, the array comprehension, will eventually call jl_alloc_array_1d
in the C(++) runtime. To my knowledge, the compiler has very little knowledge about what this function does side effect-wise and whether it is safe to move into, say, a conditional. Indeed, the generated native code unconditionally calculates the sum before running the conditional:
julia> @code_native test2(true, rand(2))
.text
; ┌ @ REPL[19]:1 within `test2`
pushq %rbx
movl %edi, %ebx
; │ @ REPL[19]:2 within `test2`
; │┌ @ reducedim.jl:890 within `sum`
; ││┌ @ reducedim.jl:890 within `#sum#733`
; │││┌ @ reducedim.jl:894 within `_sum`
; ││││┌ @ reducedim.jl:894 within `#_sum#735`
; │││││┌ @ reducedim.jl:322 within `mapreduce`
; ││││││┌ @ reducedim.jl:322 within `#mapreduce#725`
; │││││││┌ @ reducedim.jl:330 within `_mapreduce_dim`
movabsq $_mapreduce, %rax # <-- eventually calls into C to allocate memory
movq %rsi, %rdi
callq *%rax
; │└└└└└└└
; │ @ REPL[19]:3 within `test2`
testb $1, %bl
jne L37
; │ @ REPL[19] within `test2`
movabsq $.rodata.cst8, %rax
vmovsd (%rax), %xmm0 # xmm0 = mem[0],zero
; │ @ REPL[19]:4 within `test2`
L37:
popq %rbx
retq
nopw (%rax,%rax)
; └
But if you try with a type that doesn’t require any heap allocation or other black box operations, the compiler can guard the sum calculation behind the conditional:
julia> using StaticArrays
julia> @code_native test2(false, @SArray rand(2))
.text
; ┌ @ REPL[19]:3 within `test2`
testb $1, %dil
je L25
; │ @ REPL[19] within `test2`
vmovupd (%rsi), %xmm0
vmulpd %xmm0, %xmm0, %xmm0
vpermilpd $1, %xmm0, %xmm1 # xmm1 = xmm0[1,0]
vaddsd %xmm1, %xmm0, %xmm0
; │ @ REPL[19]:4 within `test2`
retq
; │ @ REPL[19] within `test2`
L25:
movabsq $.rodata.cst8, %rax # <-- $.rodata.cst8 contains the value 10.0
vmovsd (%rax), %xmm0 # xmm0 = mem[0],zero
; │ @ REPL[19]:4 within `test2`
retq
nopl (%rax,%rax)
; └