llvm / llvm/llvm-project

[X86] allow vector integer division without prefer-vector-width=512 under strictfp

Open
#217,834 3 comments 0 reactions 0 assignees View on GitHub
backend:X86 missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

https://godbolt.org/z/Gacejv3v9

```c
#include
#include

typedef uint32_t u32 [[clang::ext_vector_type(4)]];
typedef int32_t s32 [[clang::ext_vector_type(4)]];
typedef double f64 [[clang::ext_vector_type(4)]];
typedef _Bool i1 [[clang::ext_vector_type(4)]];

u32 foo(u32 a,u32 b){
f64 x = __builtin_convertvector(a ,f64);
f64 y = __builtin_convertvector(__builtin_elementwise_max(b,(u32)1),f64);
return __builtin_convertvector(x /y, u32);
}

s32 bar(s32 a,s32 b){
f64 x = __builtin_convertvector(a ,f64);
f64 y = __builtin_convertvector(b, f64);
i1 mask = (a == INT32_MIN) && (b == -1) || b == 0;
return __builtin_convertvector(x / (mask ? (1.0) : y), s32);
}
```

To comply with strictfp, we cannot introduce floating-point exceptions. Luckily, for integer division use cases, exceptions are only triggered when division by zero and overflow in signed cases. We should be able to implement vectorization by safeguarding such scenarios.

avx2
```asm
.LCPI0_0:
.quad 0x4330000000000000
.LCPI0_2:
.quad 0x41e0000000000000
.LCPI0_1:
.long 1
.LCPI0_4:
.long 2147483648
.LCPI0_5:
.long 0
.long 2
.long 4
.long 6
foo:
vpmovzxdq ymm0, xmm0
vpbroadcastq ymm2, qword ptr [rip + .LCPI0_0]
vpor ymm0, ymm0, ymm2
vsubpd ymm0, ymm0, ymm2
vpbroadcastd xmm3, dword ptr [rip + .LCPI0_1]
vpmaxud xmm1, xmm1, xmm3
vpmovzxdq ymm1, xmm1
vpor ymm1, ymm1, ymm2
vsubpd ymm1, ymm1, ymm2
vdivpd ymm0, ymm0, ymm1
vbroadcastsd ymm1, qword ptr [rip + .LCPI0_2]
vcmpltpd ymm2, ymm0, ymm1
vpxor xmm3, xmm3, xmm3
vblendvpd ymm1, ymm1, ymm3, ymm2
vsubpd ymm0, ymm0, ymm1
vcvttpd2dq xmm0, ymm0
vbroadcastf128 ymm1, xmmword ptr [rip + .LCPI0_5]
vpermps ymm1, ymm1, ymm2
vbroadcastss xmm2, dword ptr [rip + .LCPI0_4]
vblendvps xmm1, xmm2, xmm3, xmm1
vxorpd xmm0, xmm0, xmm1
vzeroupper
ret

.LCPI1_0:
.long 2147483648
.LCPI1_1:
.quad 0x3ff0000000000000
bar:
vcvtdq2pd ymm2, xmm0
vcvtdq2pd ymm3, xmm1
vpbroadcastd xmm4, dword ptr [rip + .LCPI1_0]
vpcmpeqd xmm0, xmm0, xmm4
vpcmpeqd xmm4, xmm4, xmm4
vpcmpeqd xmm4, xmm1, xmm4
vpand xmm0, xmm0, xmm4
vpxor xmm4, xmm4, xmm4
vpcmpeqd xmm1, xmm1, xmm4
vpor xmm0, xmm1, xmm0
vpmovsxdq ymm0, xmm0
vbroadcastsd ymm1, qword ptr [rip + .LCPI1_1]
vblendvpd ymm0, ymm3, ymm1, ymm0
vdivpd ymm0, ymm2, ymm0
vcvttpd2dq xmm0, ymm0
vzeroupper
ret
```
avx512 (prefer-vector-width=256)
```asm
.LCPI0_0:
.long 1
foo:
vcvtudq2pd ymm0, xmm0
vpmaxud xmm1, xmm1, dword ptr [rip + .LCPI0_0]{1to4}
vcvtudq2pd ymm1, xmm1
vdivpd ymm0, ymm0, ymm1
vcvttpd2udq xmm0, ymm0
vzeroupper
ret

.LCPI1_0:
.long 2147483648
.LCPI1_1:
.quad 0x3ff0000000000000
bar:
vcvtdq2pd ymm2, xmm0
vcvtdq2pd ymm3, xmm1
vpcmpeqd xmm4, xmm4, xmm4
vpcmpeqd k1, xmm1, xmm4
vpcmpeqd k0 {k1}, xmm0, dword ptr [rip + .LCPI1_0]{1to4}
vptestnmd k1, xmm1, xmm1
korw k1, k1, k0
vbroadcastsd ymm3 {k1}, qword ptr [rip + .LCPI1_1]
vdivpd ymm0, ymm2, ymm3
vcvttpd2dq xmm0, ymm0
vzeroupper
ret
```

Contributor guide

Open the contributing guide

Research direction

Start with the Compiler Explorer reproducer in the issue and compare the shown AVX2 and AVX512 output for foo and bar under strictfp. Trace the x86 vectorization and integer-division handling from those cases; done means vector integer division is allowed without prefer-vector-width=512 while preserving the stated division-by-zero and signed-overflow safeguards.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers, performance
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.