Skip to content

Vector<T>.SquareRoot no longer vectorizing in .NET 10.0 #118848

Description

@alexcovington

Description

The codegen for Vector<T>.SquareRoot in .NET 10.0 is no longer producing vectorized code like it did in .NET 9.0. This can be reproduced with this microbenchmark.

Regression?

Yes, this is a regression going from .NET 9.0 to .NET 10.0.

Data

.NET 9.0

BenchmarkDotNet v0.14.1-nightly.20250107.205, Windows 11 (10.0.26100.4946)
.NET SDK 10.0.100-preview.7.25380.108
[Host] : .NET 9.0.8 (9.0.825.36511), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Job-DCSEPH : .NET 9.0.8 (9.0.825.36511), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
PowerPlanMode=00000000-0000-0000-0000-000000000000 IterationTime=250ms MaxIterationCount=20
MinIterationCount=15 WarmupCount=1
| Type | Method | Mean | Error | StdDev | Median | Min | Max | Allocated |
|---------------------- |-------------------- |----------:|----------:|----------:|----------:|----------:|----------:|----------:|
| Perf_VectorOf<Double> | SquareRootBenchmark | 0.6996 ns | 0.0113 ns | 0.0106 ns | 0.6984 ns | 0.6827 ns | 0.7205 ns | - |
| Perf_VectorOf<Single> | SquareRootBenchmark | 0.0445 ns | 0.0119 ns | 0.0111 ns | 0.0449 ns | 0.0257 ns | 0.0605 ns | - |

.NET 10.0

BenchmarkDotNet v0.14.1-nightly.20250107.205, Windows 11 (10.0.26100.4946)
.NET SDK 10.0.100-preview.7.25380.108
[Host] : .NET 10.0.0 (10.0.25.38108), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Job-CCVXYZ : .NET 10.0.0 (10.0.25.38108), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
PowerPlanMode=00000000-0000-0000-0000-000000000000 IterationTime=250ms MaxIterationCount=20
MinIterationCount=15 WarmupCount=1
| Type | Method | Mean | Error | StdDev | Median | Min | Max | Allocated |
|---------------------- |-------------------- |---------:|----------:|----------:|---------:|---------:|---------:|----------:|
| Perf_VectorOf<Double> | SquareRootBenchmark | 5.737 ns | 0.0415 ns | 0.0389 ns | 5.735 ns | 5.678 ns | 5.798 ns | - |
| Perf_VectorOf<Single> | SquareRootBenchmark | 6.508 ns | 0.0496 ns | 0.0440 ns | 6.502 ns | 6.448 ns | 6.586 ns | - |

Analysis

The issue is related to codegen.

.NET 9.0 is able to produce vectorized codegen for Vector<T>.SquareRoot, but .NET 10.0 does not vectorize the same code.

Here is the codegen for Vector<Single>.SquareRoot as an example:

.NET 9.0

 vsqrtps ymm0,[7FF816FAB740]
vmovups [rdx],ymm0
mov rax,rdx
vzeroupper
ret

.NET 10.0

 sub rsp,58
vbroadcastss ymm0,dword ptr [7FF7D9EDB4A8]
vmovups [rsp],ymm0
vsqrtss xmm0,xmm0,dword ptr [rsp]
vmovss dword ptr [rsp+20],xmm0
vsqrtss xmm0,xmm0,dword ptr [rsp+4]
vmovss dword ptr [rsp+24],xmm0
vsqrtss xmm0,xmm0,dword ptr [rsp+8]
vmovss dword ptr [rsp+28],xmm0
vsqrtss xmm0,xmm0,dword ptr [rsp+0C]
vmovss dword ptr [rsp+2C],xmm0
vsqrtss xmm0,xmm0,dword ptr [rsp+10]
vmovss dword ptr [rsp+30],xmm0
vsqrtss xmm0,xmm0,dword ptr [rsp+14]
vmovss dword ptr [rsp+34],xmm0
vsqrtss xmm0,xmm0,dword ptr [rsp+18]
vmovss dword ptr [rsp+38],xmm0
vsqrtss xmm0,xmm0,dword ptr [rsp+1C]
vmovss dword ptr [rsp+3C],xmm0
vmovups ymm0,[rsp+20]
vmovups [rdx],ymm0
mov rax,rdx
vzeroupper
add rsp,58
ret

I think this can be resolved by checking the method name during import similar to these intrinsics to make sure that Vector<T>.SquareRoot gets generated as the appropriate NI_Vector128_Sqrt/NI_Vector256_Sqrt/NI_Vector512_Sqrt intrinsic.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions