JIT compilation does not avoid useless computations

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)
; └
4 Likes