<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/234102>234102</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[AArch64][SVE][StrictFP] Unused predicated FADD loses observable FP exception flags
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
matt-gretton-dann
</td>
</tr>
</table>
<pre>
## Summary
On current main built on AArch64:
With strict floating-point exception behaviour, Clang/LLVM eliminates an SVE `svadd_f32_z` call whose numerical result is unused. The equivalent scalar and Advanced SIMD additions are retained. This can silently lose the cumulative `FPSR.IOC` flag: adding `+infinity` and `-infinity` in an active lane generates an invalid-operation exception. No fast-math option is enabled.
This probably also applies to all other SVE floating-point intrinsics but I didn't dig deeper.
## Reproducer
This reproducer does not require SVE hardware, as the issue can be observed in the disassembly.
Save as `repro.c`:
```c
#include <arm_neon.h>
#include <arm_sve.h>
#pragma STDC FENV_ACCESS ON
void scalar(float a, float b) {
float unused = a + b;
}
void neon(float a, float b) {
float32x4_t unused = vaddq_f32(vdupq_n_f32(a), vdupq_n_f32(b));
}
void sve(float a, float b) {
svfloat32_t unused = svadd_f32_z(svptrue_pat_b32(SV_VL4),
svdup_f32(a), svdup_f32(b));
}
```
Compile with Clang:
```sh
clang -target aarch64-none-elf -march=armv8.2-a+sve+fp16 \
-msve-vector-bits=scalable -ffreestanding -fno-fast-math \
-ffp-contract=off -frounding-math -ffp-exception-behavior=strict \
-x c -std=c17 -O2 -S repro.c -o repro.s
```
## Actual behavior
At `-O2`, `scalar` emits `fadd s0, s0, s1`, `neon` emits
`fadd v0.4s, v0.4s, v1.4s`, and `sve` is reduced to `ret` with no `fadd`:
```asm
scalar:
fadd s0, s0, s1
ret
neon:
fadd v0.4s, v0.4s, v1.4s
ret
sve:
ret
```
## Expected behavior
Under the requested strict exception semantics, the SVE addition must retain its exception effect even when its result is unused. For `a = +infinity`, `b = -infinity`, and FPCR exception traps disabled, at least one of the four active SVE lanes must set `FPSR.IOC`, as the scalar and Neon additions can.
Returning without the addition leaves the flag unchanged.
## Architecture reference
Arm ARM issue M.d, [C8.2.155, predicated SVE FADD](https://support.arm.com/documentation/ddi0487/md/1818-isa_fadd_z_p_zz)
performs `FPAdd` on each active lane (Operation pseudocode, lines 117–136). [J1.4.318, `FPAdd`](https://support.arm.com/documentation/ddi0487/md/8628-asl_shared_functions_float_fpadd_fpadd) sets `fpexc = TRUE` (lines 31–34) and calls `FPProcessException(FPExc_InvalidOp, fpcr)` for opposite-sign infinities (lines 46–52). [J1.4.359, `FPProcessException`](https://support.arm.com/documentation/ddi0487/md/8669-asl_shared_functions_float_fpprocessexception_fpprocessexception) sets the cumulative FPSR bit when trapping is disabled (lines 34–39, 71–76). The [floating-point exceptions section](https://support.arm.com/documentation/ddi0487/md/061-beijddag) also states that predicated SVE FP instructions can generate exceptions for active elements (lines 29–35).
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJysV0tv27oS_jXMZiBDovxceOHYMdCLtgniNndpUOTI4oFEqiSlJv31F0PJjpPm3HMWLQpH4mMe38x8MxLe65NBXLPZLZvtbkQXKuvWjQghOTkMwZpECWNuCqte1oznjOdw6JpGuBeWbli6uTcgO-fQBGiENlB0ug5gDWw2TlbzKcs3w8H_6lCBD07LAGVtRdDmlLRWmwD4LLEN2hoosBK9tp1jfAvbWpgT4_vPn5--ANa60UYE9CAMHJ7ugM1T3wuljmXOj7_YPAUp6hp-VtYjmK5Bp6WowaHv6gDaQ2c6j2oC3yoE_NHpXtRktpeiFg6EUbBRvTASFRw-fdmBUEqTVR6EQ3AYhDbDfe1BCgNek4D6BWpSGSoE2TVdLYLukczbPxweJ5_ut2RbWYsTyzdRqDnRLuO32pTa6PBCB0g_m6fJ9Zo25KyQUWAtDMIJDbozCtr0otYqsS2tEX4XJCfw1UIpfEgaESqwA7zaAxpR1KgmQ1CiK62zhSjqFxC1tyDattboIVggOG2o0EW83wVNm-C08Vp6KLoAn0BpZRhfBFD6BAqxRTdqGfPmEVtnVSfRXSl3l0VQFj0YG8BRdBxGrZVw6qdwSAkhfARZe99hDECBYAuPrkdFWNGm0l54j01Rv4zaD6JHusrmaVQ2kQT-OS3pOf6Xg6HayLpTCCzfCtccDVozqVh-9-Gu7_Fqs3Xi1Ag4fNttYX_39em42W7vDge4_zqo6q1WY7YxvoxwgiC_hseC8RWwxS1LNzAuDRkLLN-BAMZvoWA57bPF7kok2fjvBOb8eXp8I5YK6AdVEOPLXnXtj6MZ3wTjK5L1drWIq6uPzPA9_qMVvh_teGvFdR3zpe_b4Do8tiIci6j18HR8-jwdDIpy_uGfJ6Pf-XG99pEX5zwYPNraptU1wk9irYGIfssYX7F0I2kPkiDcCQMIEUkvMdZggnUJSUMrLN8J1_TLCU8E47cRqduyzebAZoNDSeN7THqUwbqk0MGzfBdTpagRkrJ0iD4IE7kjKY1NXmv7IqIs20RaE5yQgeU7W5aQlM528dZwNp65kEQy0q0jZQMzX4Q9g4TEB8XyncwWkNxzSA4wFhAkdnz0v0M3VvtGhk7UcFER9zYhctw9j_y3jRw-FMQ8BWx0iGVaCqXAxwPjb_Z6Pmb7-fSgPZ7v08nUx4S9PGT0MFwc2ZWQJ14l3iHSUURzkRgCrcdoG3u24UOeEL5h6Wa0Ou5Sxn1k8rBDotNNtPrt6b8z-Poa2Xu5NSx9jPbdc4syoHqH93ej0EVeJE5FTyfGSL82XY-NMEHLaAOdJd49Nz9oOh_G5gcUn9d7WJZIgno08LPCYfv3dru3jgAVsdLfNr0xpEXcSt5tUMj2D9vHK43BidZHiqceFg8FqFF4mjgQbBnNL23nzk2TXKHG6Qc_PIZ3jfmqr1wNAl_Rmqv-L4UZm8kjhs4ZqkLKFduFePMCVo2ix0EaNXzojKyEOV367bk2nKx0QBm6OFiU6NBIHEvENbB5_DJ2uS-T6Cab3W6XEz7JZjN6bR0qLQVFkxzcb3Y7NtsxvqxCaD1lDN8zvvdd21oXJsI1E2kbxvfKyq5BE-K0QO9Kp9PlgvF9oxjfZ8tsmWgvjpSgx1_H9vjrF_FkumnRldY1fkBvE2uDpjwUsnozoDC-vL-MI63HTllpVWzftaY4ZNmC3XG2TNkqz_I546sJkH__ySbTSZ4tx5w4K_kjfi3nfJkIXx99JRyqY9kZGSN7jO3oWLax_9AvdSuPIw-1-Cxjbn57_H5HHjO-HLzIs4sTOTWmmDU0f44IPTgr0fu7c-oyvtw_3D3L46dhZrtvY4dspSN8aT60DmzbWq8DJjSUw1gONItd1E7nF7UzHqG7IDdbXZD7Tfkfg3G--v8wtoPmS8V-sHQB-N28TDUJhQ4DlVClt1Rm-rXer9CfvqIf3V68hmMxphRN-Wx2-3efGh48RuP_CDLpPEsK1H8pJU4xG2iS9iEO6qES4beKfQBtfHCdvBDMZbS_tpGyYqwurJEMuEoGvnpFYUZOs3Rzo9a5WuUrcYPrbLHis9VquZjeVGuc5nM5naXLbIZTRFlyJTJM51gucIELdaPXPOXzLOVZusxWnE_yeTbLVVHmBc7LdDZn0xQboetJXffNxLrTTaSoNc-nWcpvalFg7eOHJOcGfw4Exjin70q3pktJ0Z08m6a19sG_igk61PEL9PzJONux2e3h6W58iP1q_8BmO_g-zIxXaBL3xe8vP34KxIlp_3DVNYiJ_U3n6vXbKJ90qLpiDDBZM_5JWmf_QhkY30cfPOP70cl-zf8XAAD__1JXy1s">