Bug 27321

Summary: Compare against constant infinity fails with IBM long double format
Product: gcc Reporter: David Friedman <dvdfrdmn>
Component: middle-endAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: gcc-bugs, msebor
Priority: P3 Keywords: wrong-code
Version: 4.0.3   
Target Milestone: ---   
Host: Target: powerpc*-*-*
Build: Known to work: 5.3.0, 6.0
Known to fail: Last reconfirmed: 2006-04-30 07:33:00

Description David Friedman 2006-04-26 02:17:48 UTC
Test code:
    long double x = __builtin_infl();
    int main() {
	int r = x == __builtin_infl();
	return r ? 0 : 1;
    }

Commands to reproduce:

    gcc -mlong-double-128 tc.c
    ./a.out && echo ok || echo fail

No problem with -mlong-double-64.

Cause:

GCC first transforms (x == infinity) to (x > long_double_max_val).
The maximum value returned by real_maxval is encoded as infinity due
to rounding in encode_ibm_extended.  This does not happen with the
LDBL_MAX declared in system headers because one of the bits is
cleared.

Potential fix:

--- real.c.orig 2005-09-19 12:56:24.000000000 -0400
+++ real.c      2006-04-25 21:18:32.000000000 -0400
@@ -2205,6 +2205,8 @@ real_maxval (REAL_VALUE_TYPE *r, int sig
   np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b;
   memset (r->sig, -1, SIGSZ * sizeof (unsigned long));
   clear_significand_below (r, np2);
+  if (REAL_MODE_FORMAT_COMPOSITE_P (mode))
+      clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan - 1);
 }
Comment 1 Andrew Pinski 2006-04-26 02:27:08 UTC
This works in the mainline.
Comment 2 Andrew Pinski 2006-04-30 07:33:00 UTC
Actually I am wrong in saying it worked.  I usually forget to test the return value as I assume people use abort to signal a failure.
Comment 3 Bernhard Kaindl 2012-03-02 19:25:55 UTC
Verification using powerpc-linux-gcc-4.4.6 (--host=i686-linux):

Testcase works, it seems this may be fixed. Suggest closing after soon 6 years.
Comment 4 Martin Sebor 2016-01-19 21:59:57 UTC
Looks like this has worked correctly for some time and is being tested by at least one of the gcc.c-torture/execute/ieee/inf-*.c tests.  Resolving as fixed.