<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">