On Fri, Nov 04, 2022 at 08:14:23PM +0100, Jakub Jelinek via Gcc-patches wrote: > One thing that is clear is that real_isdenormal is never true for these > (but then a question is if flush_denormals_to_zero actually works).
So, after some more investigation, I think that is actually the case, real_isdenormal is only meaningful (will ever return true) right after round_for_format. The uses inside of real.cc are fine, real_to_target first calls round_for_format and then calls fmt->encode in which the real_isdenormal calls are done. And, round_for_format is what transforms the normalized way of expressing the number into the denormal form: /* Check the range of the exponent. If we're out of range, either underflow or overflow. */ if (REAL_EXP (r) > emax2) goto overflow; else if (REAL_EXP (r) <= emin2m1) { int diff; if (!fmt->has_denorm) { /* Don't underflow completely until we've had a chance to round. */ if (REAL_EXP (r) < emin2m1) goto underflow; } else { diff = emin2m1 - REAL_EXP (r) + 1; if (diff > p2) goto underflow; /* De-normalize the significand. */ r->sig[0] |= sticky_rshift_significand (r, r, diff); SET_REAL_EXP (r, REAL_EXP (r) + diff); } } But, real_to_target is one of the 4 callers of static round_for_format, another one is real_convert, but that one undoes that immediately: round_for_format (fmt, r); /* Make resulting NaN value to be qNaN. The caller has the responsibility to avoid the operation if flag_signaling_nans is on. */ if (r->cl == rvc_nan) r->signalling = 0; /* round_for_format de-normalizes denormals. Undo just that part. */ if (r->cl == rvc_normal) normalize (r); and the last two are inside of encoding the IBM double double composite. So, I think everywhere in the frange you'll see normalized REAL_VALUE_TYPE and so real_isdenormal will always be false there. You need to check for REAL_EXP (r) < fmt->emin or so (and ideally only on REAL_VALUE_TYPE already real_converted to the right mode (your frange_arithmetics does that already, which is good, but say conversions and other unary ops might need it too). If I in the hack from last mail replace - fprintf (stderr, "%d %d %s %s\n", i, real_isdenormal (&result), buf, buf2); + fprintf (stderr, "%d %d %s %s\n", i, REAL_EXP (&result) < REAL_MODE_FORMAT (mode)->emin, buf, buf2); then it is 1 until: 102 1 0x0.8p-971 0x0.80000000000008p-971 103 1 0x0.8p-970 0x0.80000000000008p-970 104 1 0x0.8p-969 0x0.80000000000008p-969 105 0 0x0.8p-968 0x0.80000000000008p-968 106 0 0x0.8p-967 0x0.80000000000008p-967 107 0 0x0.8p-966 0x0.80000000000008p-966 Now, the __LDBL_MIN__ powerpc64 gcc announces is 2.00416836000897277799610805135016205e-292L which is equivalent to: 0x1p-969 and that is equivalent to 0x0.8p-968, so I think that is exactly what we want. Jakub