čt 18. 12. 2025 v 1:16 odesílatel Sam James <[email protected]> napsal:
> >
> > [1] Built with a patch disabling late combine by default on IA-64 as
> > that was shown to produce incorrect code in some cases.
>
> What's this about?
>

I saw this with GCC 15.2.0 when building Python 3.14:

tglozar@epic-t2 /tmp/tglozar $ Python-3.14.0/python -c 'print(5 ** 2.0)'
1.0 # with -O2
tglozar@epic-t2 /tmp/tglozar $ Python-3.14.0/python -c 'print(5 ** 2.0)'
25.0 # with -O1

GDB reveals that the second operand to ** is read as zero:

$ gdb --args Python-3.14.0/python -c '5 ** 2.0'
...
(gdb) b Objects/floatobject.c:810
Breakpoint 3 at 0x4000000000153590: file Objects/floatobject.c, line 810.
(gdb) r
Starting program: /tmp/tglozar/Python-3.14.0/python -c 5\ \*\*\ 2.0
...
Breakpoint 3, float_pow (v=<optimized out>, w=<optimized out>,
z=0x6000000000071110 <_Py_NoneStruct>) at Objects/floatobject.c:810
810         ix = pow(iv, iw);
(gdb) p iv
$1 = 5
(gdb) p iw
$2 = 0

Here, v is supposed to be decoded into iv, and w into iw (it's an
offset read from the object pointer). I did some investigation and it
seems like it gets loaded from memory into floating-point register,
but never gets stored into the local variable on the stack; yet, the
uninitialized variable gets used, not the register for passing the
value to pow() (e.g. when I initialize iw with 42, 42 stays there).
The other variable (v/iv) is not affected, as the same floating-point
register is re-used to load iw, which triggers a store onto the stack.

Adding -fnolate-combine-instructions gets rid of the issue. For this
particular reproducer at least, it also needs -fcaller-saves to
reproduce. I wanted to report or fix this but got sidetracked (maybe I
can post a variant of this writeup).

Tomas

Reply via email to