https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128229
--- Comment #4 from liu zhenyu <lzy20000419 at outlook dot com> ---
The loop2_invariant dump (14.2, -O2) shows:
```
(unspec:SI [ (reg:DF ...) ] UNSPEC_FIX_NOTRUNC)) ... {sse2_cvtsd2si_2}
Set in insn 22 is invariant (0), cost 4, depends on
Decided to move invariant 0 -- gain 4
```
find_invariant_insn only refuses to move a conditionally executed insn if
may_trap_or_fault_p is true. For an UNSPEC that goes through
targetm.unspec_may_trap_p. i386 does not define the hook, so it uses
default_unspec_may_trap_p (targhooks.cc:125):
```c
/* Any floating arithmetic may trap. */
if ((SCALAR_FLOAT_MODE_P (GET_MODE (x)) && flag_trapping_math))
return 1;
for (i = 0; i < XVECLEN (x, 0); ++i)
if (may_trap_p_1 (XVECEXP (x, 0, i), flags))
return 1;
return 0;
```
As noted in PR127908 c6, this checks the result mode only, and the operand
modes are never considered. A REG:DF operand makes may_trap_p_1 return 0. So:
- cvtsd2si / lrint (`UNSPEC_FIX_NOTRUNC`): the result is SImode/DImode and the
operand is DFmode, so the insn counts as non-trapping.
- minpd (`UNSPEC_IEEE_MIN`): the result is V2DFmode, and SCALAR_FLOAT_MODE_P is
false for vector modes, so the result-mode check does not cover it either.
The per-version differences only reflect when each expansion became a bare REG
operand. For example, in 8.5 `_mm_cvtsd_si32 (_mm_set_sd (x))` still goes
through a V2DF vec_select, and the insn is not hoisted. The hook has not
changed.
Only loop2_invariant matters for these testcases. -fno-gcse,
-fno-gcse-after-reload, -fno-schedule-insns2 and -fno-if-conversion each still
print 1. The same predicate is also used by the scheduler's speculation, RTL
PRE/hoist and ifcvt, though.
Possible fixes:
1. Generic: in default_unspec_may_trap_p, under flag_trapping_math, return 1 if
the result mode or any operand mode satisfies FLOAT_MODE_P (which covers vector
float, unlike SCALAR_FLOAT_MODE_P). This also fixes the RISC-V case in
PR127908. It is conservative for FP unspecs that cannot trap (moves, shuffles,
bit ops in float modes), which could lose some hoisting.
2. Target: give i386 a TARGET_UNSPEC_MAY_TRAP_P that returns 1 for the
FP-arithmetic and conversion unspecs (UNSPEC_FIX_NOTRUNC, UNSPEC_IEEE_MIN/MAX,
rounding, rcp/rsqrt, …) when flag_trapping_math is set, and falls back to the
default otherwise.
Disclaimer: This test case was generated by a fuzzer, and the report was
written with LLM assistance.