On Tue, 15 Feb 2022, Jakub Jelinek wrote: > Hi! > > For IBM double double I've added in PR95450 and PR99648 verification that > when we at the tree/GIMPLE or RTL level interpret target bytes as a REAL_CST > or CONST_DOUBLE constant, we try to encode it back to target bytes and > verify it is the same. > This is because our real.c support isn't able to represent all valid values > of IBM double double which has variable precision. > In PR104522, it has been noted that we have similar problem with the > Intel/Motorola extended XFmode formats, our internal representation isn't > able to record pseudo denormals, pseudo infinities, pseudo NaNs and unnormal > values. > So, the following patch is an attempt to extend that verification to all > floats. > Unfortunately, it wasn't that straightforward, because the > __builtin_clear_padding code exactly for the XFmode long doubles needs to > discover what bits are padding and does that by interpreting memory of > all 1s. That is actually a valid supported value, a qNaN with negative > sign with all mantissa bits set, but the verification includes also the > padding bits (exactly what __builtin_clear_padding wants to figure out) > and so fails the comparison check and so we ICE. > The patch fixes that case by moving that verification from > native_interpret_real to its caller, so that clear_padding_type can > call native_interpret_real and avoid that extra check. > > With this, the only thing that regresses in the testsuite is > +FAIL: gcc.target/i386/auto-init-4.c scan-assembler-times long\\t-16843010 5 > because it decides to use a pattern that has non-zero bits in the padding > bits of the long double, so the simplify-rtx.cc change prevents folding > a SUBREG into a constant. We emit (the testcase is -O0 but we emit worse > code at all opt levels) something like: > movabsq $-72340172838076674, %rax > movabsq $-72340172838076674, %rdx > movq %rax, -48(%rbp) > movq %rdx, -40(%rbp) > fldt -48(%rbp) > fstpt -32(%rbp) > instead of > fldt .LC2(%rip) > fstpt -32(%rbp) > ... > .LC2: > .long -16843010 > .long -16843010 > .long 65278 > .long 0 > Note, neither of those sequences actually stores the padding bits, fstpt > simply doesn't touch them. > For vars with clear_padding_real_needs_padding_p types that are allocated > to memory at expansion time, I'd say much better would be to do the stores > using integral modes rather than XFmode, so do that: > movabsq $-72340172838076674, %rax > movq %rax, -32(%rbp) > movq %rax, -24(%rbp) > directly. That is the only way to ensure the padding bits are initialized > (or expand __builtin_clear_padding, but then you initialize separately the > value bits and padding bits). > > Bootstrapped/regtested on x86_64-linux and i686-linux, though as mentioned > above, the gcc.target/i386/auto-init-4.c case is unresolved.
OK. Thanks, Richard. > 2022-02-15 Jakub Jelinek <ja...@redhat.com> > > PR middle-end/104522 > * fold-const.h (native_interpret_real): Declare. > * fold-const.cc (native_interpret_real): No longer static. Don't > perform MODE_COMPOSITE_P verification here. > (native_interpret_expr) <case REAL_TYPE>: But perform it here instead > for all modes. > * gimple-fold.cc (clear_padding_type): Call native_interpret_real > instead of native_interpret_expr. > * simplify-rtx.cc (simplify_immed_subreg): Perform the native_encode_rtx > and comparison verification for all FLOAT_MODE_P modes, not just > MODE_COMPOSITE_P. > > * gcc.dg/pr104522.c: New test. > > --- gcc/fold-const.h.jj 2022-02-07 21:26:50.717616208 +0100 > +++ gcc/fold-const.h 2022-02-15 01:16:14.509617954 +0100 > @@ -36,6 +36,7 @@ extern int native_encode_expr (const_tre > extern int native_encode_initializer (tree, unsigned char *, int, > int off = -1, unsigned char * = nullptr); > extern tree native_interpret_expr (tree, const unsigned char *, int); > +extern tree native_interpret_real (tree, const unsigned char *, int); > extern bool can_native_interpret_type_p (tree); > extern tree native_interpret_aggregate (tree, const unsigned char *, int, > int); > extern tree find_bitfield_repr_type (int, int); > --- gcc/fold-const.cc.jj 2022-02-09 22:15:31.805466094 +0100 > +++ gcc/fold-const.cc 2022-02-15 01:36:11.988496438 +0100 > @@ -8643,7 +8643,7 @@ native_interpret_fixed (tree type, const > the buffer PTR of length LEN as a REAL_CST of type TYPE. > If the buffer cannot be interpreted, return NULL_TREE. */ > > -static tree > +tree > native_interpret_real (tree type, const unsigned char *ptr, int len) > { > scalar_float_mode mode = SCALAR_FLOAT_TYPE_MODE (type); > @@ -8694,19 +8694,7 @@ native_interpret_real (tree type, const > } > > real_from_target (&r, tmp, mode); > - tree ret = build_real (type, r); > - if (MODE_COMPOSITE_P (mode)) > - { > - /* For floating point values in composite modes, punt if this folding > - doesn't preserve bit representation. As the mode doesn't have fixed > - precision while GCC pretends it does, there could be valid values that > - GCC can't really represent accurately. See PR95450. */ > - unsigned char buf[24]; > - if (native_encode_expr (ret, buf, total_bytes, 0) != total_bytes > - || memcmp (ptr, buf, total_bytes) != 0) > - ret = NULL_TREE; > - } > - return ret; > + return build_real (type, r); > } > > > @@ -8824,7 +8812,23 @@ native_interpret_expr (tree type, const > return native_interpret_int (type, ptr, len); > > case REAL_TYPE: > - return native_interpret_real (type, ptr, len); > + if (tree ret = native_interpret_real (type, ptr, len)) > + { > + /* For floating point values in composite modes, punt if this > + folding doesn't preserve bit representation. As the mode doesn't > + have fixed precision while GCC pretends it does, there could be > + valid values that GCC can't really represent accurately. > + See PR95450. Even for other modes, e.g. x86 XFmode can have some > + bit combinationations which GCC doesn't preserve. */ > + unsigned char buf[24]; > + scalar_float_mode mode = SCALAR_FLOAT_TYPE_MODE (type); > + int total_bytes = GET_MODE_SIZE (mode); > + if (native_encode_expr (ret, buf, total_bytes, 0) != total_bytes > + || memcmp (ptr, buf, total_bytes) != 0) > + return NULL_TREE; > + return ret; > + } > + return NULL_TREE; > > case FIXED_POINT_TYPE: > return native_interpret_fixed (type, ptr, len); > --- gcc/gimple-fold.cc.jj 2022-02-11 21:59:57.177698154 +0100 > +++ gcc/gimple-fold.cc 2022-02-15 01:21:08.706649224 +0100 > @@ -4807,10 +4807,10 @@ clear_padding_type (clear_padding_struct > clear_padding_flush (buf, false); > if (clear_padding_real_needs_padding_p (type)) > { > - /* Use native_interpret_expr + native_encode_expr to figure out > + /* Use native_interpret_real + native_encode_expr to figure out > which bits are padding. */ > memset (buf->buf + buf->size, ~0, sz); > - tree cst = native_interpret_expr (type, buf->buf + buf->size, sz); > + tree cst = native_interpret_real (type, buf->buf + buf->size, sz); > gcc_assert (cst && TREE_CODE (cst) == REAL_CST); > int len = native_encode_expr (cst, buf->buf + buf->size, sz); > gcc_assert (len > 0 && (size_t) len == (size_t) sz); > --- gcc/simplify-rtx.cc.jj 2022-01-20 21:24:40.611955521 +0100 > +++ gcc/simplify-rtx.cc 2022-02-14 22:14:29.258718212 +0100 > @@ -7302,7 +7302,7 @@ simplify_immed_subreg (fixed_size_mode o > else if (!native_encode_rtx (innermode, x, buffer, first_byte, > inner_bytes)) > return NULL_RTX; > rtx ret = native_decode_rtx (outermode, buffer, 0); > - if (ret && MODE_COMPOSITE_P (outermode)) > + if (ret && FLOAT_MODE_P (outermode)) > { > auto_vec<target_unit, 128> buffer2 (buffer_bytes); > if (!native_encode_rtx (outermode, ret, buffer2, 0, buffer_bytes)) > --- gcc/testsuite/gcc.dg/pr104522.c.jj 2022-02-14 22:14:29.258718212 > +0100 > +++ gcc/testsuite/gcc.dg/pr104522.c 2022-02-14 22:14:29.258718212 +0100 > @@ -0,0 +1,14 @@ > +/* PR middle-end/104522 */ > +/* { dg-do compile } */ > +/* { dg-options "-O -fcompare-debug -dP" } */ > + > +typedef short __attribute__((__vector_size__(16))) V; > +long double x; > + > +void > +foo (void) > +{ > + V t = { 512, 0, 0, 0, 16384 }; > + long double u = *(long double *) &t; > + x /= u; > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)