https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126469
Bug ID: 126469
Summary: (double)float1 CMP (double)float2 into float1 CMP
float2 picks the wrong comparison type
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: ktkachov at gcc dot gnu.org
Target Milestone: ---
__attribute__((noipa)) int feq (__bf16 b, _Float16 h)
{ float x = (float) b; float y = (float) h; return x == y; }
__attribute__((noipa)) int flt (__bf16 b, _Float16 h)
{ float x = (float) b; float y = (float) h; return x < y; }
__attribute__((noipa)) int geq (_Float16 h, __bf16 b)
{ float y = (float) h; float x = (float) b; return y == x; }
__attribute__((noipa)) int ggt (_Float16 h, __bf16 b)
{ float y = (float) h; float x = (float) b; return y > x; }
__attribute__((noipa)) __bf16 mkb (float f) { return (__bf16) f; }
__attribute__((noipa)) _Float16 mkh (float f) { return (_Float16) f; }
int main (void)
{
/* Case A: bf16 exponent range exceeds _Float16 range. */
__bf16 b1 = mkb (3.0e38f); /* finite, 3.00406e+38 */
_Float16 h1 = mkh (__builtin_inff ()); /* +Inf */
__builtin_printf ("A: (float)b=%g (float)h=%g eq=%d lt=%d\n",
(double)(float) b1, (double)(float) h1,
feq (b1, h1), flt (b1, h1));
if (feq (b1, h1) != 0) __builtin_abort ();
if (flt (b1, h1) != 1) __builtin_abort ();
/* Case B: _Float16 significand exceeds bf16 significand. */
__bf16 b2 = mkb (1.0f);
_Float16 h2 = mkh (1.0f + 1.0f / 1024.0f); /* 1.0009765625, exact in fp16 */
__builtin_printf ("B: (float)h=%.10g (float)b=%.10g eq=%d gt=%d\n",
(double)(float) h2, (double)(float) b2,
geq (h2, b2), ggt (h2, b2));
if (geq (h2, b2) != 0) __builtin_abort ();
if (ggt (h2, b2) != 1) __builtin_abort ();
return 0;
}
passes at -O0 and aborts at -O1 and works fine with Clang.
__bf16 and _Float16 both have element_precision 16 but neither format contains
the other, so one operand is converted lossily