https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125084
--- Comment #1 from JingYao Zhang <220245569 at seu dot edu.cn> ---
Gentle ping on this issue. To make this easier to review without unpacking the
attachment, we re-verified this on current GCC 16.2 / 17 trunk
(x86_64-linux-gnu) and pinpointed the exact root cause and 1-line fix:
### Root Cause in `gcc/config/i386/predicates.md`
In `ix86_endbr_immediate_operand` (`gcc/config/i386/predicates.md`), the 64-bit
scan loop currently checks whole-word equality (`imm == val`):
```c
if (TARGET_LP64)
{
unsigned HOST_WIDE_INT imm = UINTVAL (op);
unsigned HOST_WIDE_INT val = TARGET_64BIT ? 0xfa1e0ff3 : 0xfb1e0ff3;
for (; imm >= val; imm >>= 8)
if (imm == val)
return true;
return false;
}
```
Because `imm == val` compares the entire remaining 64-bit word against the
32-bit `val` (`0xfa1e0ff3`, little-endian `f3 0f 1e fa`), any 64-bit immediate
that contains `f3 0f 1e fa` at byte offset `k` AND has any non-zero byte at
offset `>= k + 4` (for example `0x1fa1e0ff3abULL`) keeps `imm > val` at the
matching shift position and returns `false`. As a result,
`ix86_cannot_force_const_mem` does not spill the constant to `.rodata`, and
`movabsq $0x1fa1e0ff3ab, %rax` emits an unintended `endbr64` (`f3 0f 1e fa`) at
`movabs + 3` in `.text`.
### Proposed Fix
Masking `imm` to 32 bits at each byte step (both in the `TARGET_LP64` loop and
the 32-bit loop below it):
```c
for (; imm >= val; imm >>= 8)
if ((imm & 0xffffffffULL) == val)
return true;
```
ensures that embedded `ENDBR64`/`ENDBR32` byte sequences are detected
regardless of whether upper bytes are non-zero. Please let us know if you would
like us to send this patch to `gcc-patches`.