# How to get vectorized code for single-field structs?

**URL:** <https://discourse.julialang.org/t/how-to-get-vectorized-code-for-single-field-structs/132875>\
**Category:** Performance\
**Created:** [October 4, 2025, 3:24pm UTC](https://discourse.julialang.org/t/how-to-get-vectorized-code-for-single-field-structs/132875 "2025-10-04T15:24:37Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [October 4, 2025, 3:24pm UTC](https://discourse.julialang.org/t/how-to-get-vectorized-code-for-single-field-structs/132875/1 "2025-10-04T15:24:37Z")

</div>

I have noticed that structs with a single field do not vectorize the same way as the underlying type. Here is an example:

```julia-auto
struct A
    x::Int
end

function f(s::NTuple{N,T}, t::NTuple{N,T}, i) where {N,T}
    ntuple(j -> ifelse(j <= i, s[j], t[j]), Val(N))
end

```

Then `f` is vectorized for `Int` [output shortened below]

```julia-auto
julia> t = ntuple(Int, 2); @code_native f(t, t, 1)
; Function Signature: f(Tuple{Int64, Int64}, Tuple{Int64, Int64}, Int64)
; ┌ @ REPL[1]:1 within `f`
# %bb.0: # %top
	#DEBUG_VALUE: f:s <- [DW_OP_deref] [$rsi+0]
	#DEBUG_VALUE: f:t <- [DW_OP_deref] [$rdx+0]
; │ @ REPL[1] within `f`
	#DEBUG_VALUE: f:i <- $rcx
	push	rbp
	mov	rbp, rsp
	mov	rax, rdi
; │ @ REPL[1]:2 within `f`
; │┌ @ ntuple.jl:49 within `ntuple`
; ││┌ @ REPL[1]:2 within `#7`
; │││┌ @ int.jl:514 within `<=`
	vmovq	xmm0, rcx
	vpbroadcastq	xmm0, xmm0
	movabs	rcx, offset .LCPI0_0
	vmovdqa	xmm1, xmmword ptr [rcx]
	vpcmpgtq	xmm0, xmm1, xmm0
; │││└
; │││┌ @ essentials.jl:796 within `ifelse`
	vmovupd	xmm1, xmmword ptr [rsi]
	vblendvpd	xmm0, xmm1, xmmword ptr [rdx], xmm0
; ││└└
	vmovupd	xmmword ptr [rdi], xmm0
	pop	rbp
	ret

```

but not for `A`:

```julia-auto
julia> t = ntuple(A, 2); @code_native f(t, t, 1)
; Function Signature: f(Tuple{Main.A, Main.A}, Tuple{Main.A, Main.A}, Int64)
; ┌ @ REPL[1]:1 within `f`
# %bb.0: # %top
	#DEBUG_VALUE: f:s <- [DW_OP_deref] [$rsi+0]
	#DEBUG_VALUE: f:t <- [DW_OP_deref] [$rdx+0]
; │ @ REPL[1] within `f`
	#DEBUG_VALUE: f:i <- $rcx
	push	rbp
	mov	rbp, rsp
	mov	rax, rdi
; │ @ REPL[1]:2 within `f`
; │┌ @ ntuple.jl:49 within `ntuple`
; ││┌ @ REPL[1]:2 within `#7`
; │││┌ @ int.jl:514 within `<=`
	test	rcx, rcx
; │││└
; │││┌ @ essentials.jl:796 within `ifelse`
	jg	.LBB0_1
# %bb.2: # %top
	mov	rdi, qword ptr [rdx]
; │││└
; │││┌ @ int.jl:514 within `<=`
	cmp	rcx, 2
; │││└
; │││┌ @ essentials.jl:796 within `ifelse`
	jl	.LBB0_5
.LBB0_4:
	mov	rcx, qword ptr [rsi + 8]
	jmp	.LBB0_6
.LBB0_1:
	mov	rdi, qword ptr [rsi]
; │││└
; │││┌ @ int.jl:514 within `<=`
	cmp	rcx, 2
; │││└
; │││┌ @ essentials.jl:796 within `ifelse`
	jge	.LBB0_4
.LBB0_5: # %top
	mov	rcx, qword ptr [rdx + 8]
.LBB0_6: # %top
; ││└└
	mov	qword ptr [rax], rdi
	mov	qword ptr [rax + 8], rcx
	pop	rbp
	ret

```

In the second case, `@code_llvm` shows instructions of the form

```julia-auto
     %.fca.0.extract8 = extractvalue [1 x i64] %1, 0

```

to retrieve the single field of the `struct`. Maybe that’s the problem. A way to get around this would be to unwrap and rewrap the `struct` manually, as in

```julia-auto
function g(s::NTuple{N,A}, t::NTuple{N,A}, i) where N
    ntuple(j -> A(ifelse(j <= i, s[j].x, t[j].x)), Val(N))
end

```

Then it’s again vectorized.

Ideally, the same function would give vectorized code both for `Int` and `A`. Is there a way to achieve this?

EDIT: This seems to be related to `ifelse`. If one defines

```julia-auto
Base.:+(a::A, b::A) = A(a.x+b.x)

```

then `map(+, t, t)` is vectorized also for tuples with `A` elements.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [October 4, 2025, 3:36pm UTC](https://discourse.julialang.org/t/how-to-get-vectorized-code-for-single-field-structs/132875/2 "2025-10-04T15:36:25Z")

</div>

> [@matthias314](#):
>
> Is there a way to achieve this?

Use Julia v1.13
