llvm / llvm/llvm-project

[AArch64] -ftrapping-math replaces vector fcmeq with scalar fcmp.

Open
#213,117 2 comments 0 reactions 0 assignees View on GitHub
backend:AArch64
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

```c++
const float32x4_t zero = vdupq_n_f32(0.0f);
for (size_t i = 0; i < n; i += 4) {
const float32x4_t v = vld1q_f32(src + i);
const uint32x4_t nn = vceqq_f32(v, v);
vst1q_f32(dst + i, vbslq_f32(nn, v, zero));
}
```
With the -ftrapping-math flag enabled, the vector comparison is scalarized, even though it is written with intrinsics.
([-fno-trapping-math](https://godbolt.org/z/14oK9rchq) [-ftrapping-math](https://godbolt.org/z/8vG6Wfs86)).
This is presumably done to prevent flags from being lost during a floating-point exception. But fcmeq and fcmp raise the same flags (quiet equal).
The code proving this:
```c++
#pragma STDC FENV_ACCESS ON
...
uint32_t i = -1;
do {
++i;
float x;
std::memcpy(&x, &i, sizeof(float));
const float32x4_t xv = vdupq_n_f32(x);
uint32x4_t v_res;
uint32_t s_res;

std::feclearexcept(FE_ALL_EXCEPT);
asm volatile("fcmeq %[o].4s, %[a].4s, %[a].4s" : [o]"=w"(v_res) : [a]"w"(xv) : "memory");
const int v_flags = std::fetestexcept(FE_ALL_EXCEPT);

std::feclearexcept(FE_ALL_EXCEPT);
asm volatile("fcmp %s[a], %s[a]\n\tcsetm %w[o], eq" : [o]"=r"(s_res) : [a]"w"(x) : "cc", "memory");
const int s_flags = std::fetestexcept(FE_ALL_EXCEPT);

if (s_flags != v_flags || vgetq_lane_u32(v_res, 0) != s_res) {
std::cout << i << std::endl;
return 1;
}
} while (i != -1);
std::cout << "done" << std::endl;
```

(btw even -ffp-exception-behavior=maytrap removes vectorization)

clang 22.1.3 (homebrew) , apple m5

Contributor guide

Open the contributing guide

Research direction

Reproduce the two linked Godbolt cases with clang 22.1.3 for AArch64, comparing the generated code with and without -ftrapping-math and -ffp-exception-behavior=maytrap. Trace the compiler's handling of the vceqq_f32 intrinsic and floating-point exception flags; done means the vector fcmeq is retained when its flags match scalar fcmp behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.