On Wed, Apr 06, 2016 at 10:46:48AM +0200, Richard Biener wrote: > On Wed, Apr 6, 2016 at 10:31 AM, Alan Modra <amo...@gmail.com> wrote: > > On Tue, Apr 05, 2016 at 11:29:30AM +0200, Richard Biener wrote: > >> In general the patch looks like a good approach to me but can we > >> hide that > >> > >> > + const struct real_format *fmt = FLOAT_MODE_FORMAT (mode); > >> > + bool is_ibm_extended = fmt->pnan < fmt->p; > >> > >> in a function somewhere in real.[ch]? > > > > On looking in real.h, I see there is already a macro to do it. > > > > Here's the revised version that properly tests the long double > > subnormal limit. Bootstrapped and regression tested > > powerpc64le-linux. > > Can you add a testcase or two for the isnormal () case?
Sure. I'll adapt the testcase I was using to verify the output, attached in case you're interested. > I wonder whether the isnormal tests are too excessive to put in > inline code and thus libgcc code wouldn't be better to handle this... Out-of-line would be better for -Os at least. > At least the glibc implementation looks a lot simpler to me ... > (if ./sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c is the correct one). It looks more or less the same to me, except done by bit twiddling on integers. :) > Thus an alternative is to inline sth similar via the folding or via > an optab and not folding (I'd prefer the latter). > > That said, did you inspect the generated code for a isnormal (x) > call for non-constant x? Yes, I spent quite a bit of time fiddling trying to get optimal code. I'm not claiming I succeeded.. > What does XLC do here? Not sure, sorry. I don't have xlc handy. Will try later. -- Alan Modra Australia Development Lab, IBM
int __attribute__ ((noclone, noinline)) isnormal (double x) { return __builtin_isnormal (x); } int __attribute__ ((noclone, noinline)) isnormal_ld (long double x) { return __builtin_isnormal (x); } double min_norm = 0x1p-1022; double min_denorm = 0x1p-1074; double ld_low = 0x1p-969; int main (void) { static union { long double ld; unsigned long l[2]; } x; __builtin_printf ("%a %d\n", min_norm, isnormal (min_norm)); __builtin_printf ("%a %d\n", min_norm * 0.5, isnormal (min_norm * 0.5)); x.ld = ld_low; __builtin_printf ("%La (%016lx %016lx) %d\n", x.ld, x.l[0], x.l[1], isnormal_ld (x.ld)); x.ld = -ld_low; __builtin_printf ("%La (%016lx %016lx) %d\n", x.ld, x.l[0], x.l[1], isnormal_ld (x.ld)); x.ld = -min_norm * 0.5; x.ld += ld_low; __builtin_printf ("%La (%016lx %016lx) %d\n", x.ld, x.l[0], x.l[1], isnormal_ld (x.ld)); x.ld = min_norm * 0.5; x.ld -= ld_low; __builtin_printf ("%La (%016lx %016lx) %d\n", x.ld, x.l[0], x.l[1], isnormal_ld (x.ld)); x.ld = -min_norm; x.ld += ld_low; __builtin_printf ("%La (%016lx %016lx) %d\n", x.ld, x.l[0], x.l[1], isnormal_ld (x.ld)); x.ld = min_norm; x.ld -= ld_low; __builtin_printf ("%La (%016lx %016lx) %d\n", x.ld, x.l[0], x.l[1], isnormal_ld (x.ld)); x.ld = -min_denorm; x.ld += ld_low; __builtin_printf ("%La (%016lx %016lx) %d\n", x.ld, x.l[0], x.l[1], isnormal_ld (x.ld)); x.ld = min_denorm; x.ld -= ld_low; __builtin_printf ("%La (%016lx %016lx) %d\n", x.ld, x.l[0], x.l[1], isnormal_ld (x.ld)); x.ld = min_denorm; x.ld += ld_low; __builtin_printf ("%La (%016lx %016lx) %d\n", x.ld, x.l[0], x.l[1], isnormal_ld (x.ld)); x.ld = -min_denorm; x.ld -= ld_low; __builtin_printf ("%La (%016lx %016lx) %d\n", x.ld, x.l[0], x.l[1], isnormal_ld (x.ld)); return 0; }