On Mon, Dec 19, 2022 at 09:49:36AM +0100, Richard Biener wrote: > On Mon, Dec 19, 2022 at 9:12 AM Kewen.Lin <li...@linux.ibm.com> wrote: > > In function fold_convert_const_real_from_real, when the modes of > > two types involved in fp conversion are the same, we can simply > > take it as copy, rebuild with the exactly same TREE_REAL_CST and > > the target type. It is more efficient and helps to avoid possible > > unexpected signalling bit clearing in [1]. > > > > Bootstrapped and regtested on x86_64-redhat-linux, aarch64-linux-gnu > > and powerpc64{,le}-linux-gnu. > > > > Is it ok for trunk? > > But shouldn't > > double x = (double) __builtin_nans("sNAN"); > > result in a quiet NaN?
I think it doesn't already, fold_convert_const starts with tree arg_type = TREE_TYPE (arg1); if (arg_type == type) return arg1; and so if it is a conversion to the same type, fold_convert_const_real_from_real won't be called at all. It is just cast to a different type with same mode (say typedef double doublet) that triggers it right now. Try: double foo (void) { return __builtin_nans (""); } double bar (void) { return (double) __builtin_nans (""); } typedef double doublet; doublet baz (void) { return __builtin_nans (""); } doublet qux (void) { return (doublet) __builtin_nans (""); } float corge (void) { return (float) __builtin_nans (""); } GCC right now returns a sNaN in foo and bar and qNaN in baz, qux and corge, clang and ICC (tried 19.0.1 on godbolt) return sNaN in foo, bar, baz, qux and qNaN in corge. The last case is required by C: convertFormat - different formats cast and implicit conversions 6.3.1.5, 6.5.4 convertFormat - same format canonicalize 7.12.11.7, F.10.8.7 As for the rest, C n3047.pdf has: Whether C assignment (6.5.16) (and conversion as if by assignment) to the same format is an IEC 60559 convertFormat or copy operation439) is implementation-defined, even if <fenv.h> defines the macro FE_SNANS_ALWAYS_SIGNAL (F.2.1). If the return expression of a return statement is evaluated to the floating-point format of the return type, it is implementation-defined whether a convertFormat operation is applied to the result of the return expression. 439) Where the source and destination formats are the same, convertFormat operations differ from copy operations in that convertFormat operations raise the "invalid" floating-point exception on signaling NaN inputs and do not propagate non-canonical encodings. I think the posted patch is good for consistency, treating conversion to the same format sometimes as convertFormat and sometimes as copy is maybe valid but confusing, especially when on: double foo (double x) { return x; } double bar (double x) { return (double) x; } typedef double doublet; doublet baz (double x) { return x; } doublet qux (double x) { return (doublet) x; } float corge (double x) { return (float) x; } we actually use copy operations in all of foo, bar, baz and qux. Jakub