diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 9d9939642f6..7b21240ba76 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -8643,7 +8643,7 @@ native_interpret_fixed (tree type, const unsigned char *ptr, int len) 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 unsigned char *ptr, int len) } 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 unsigned char *ptr, int len) 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); diff --git a/gcc/fold-const.h b/gcc/fold-const.h index f217598d06a..926c775e696 100644 --- a/gcc/fold-const.h +++ b/gcc/fold-const.h @@ -36,6 +36,7 @@ extern int native_encode_expr (const_tree, unsigned char *, int, int off = -1); 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); diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index d9b1a442a7a..16f02c2d098 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -4807,10 +4807,10 @@ clear_padding_type (clear_padding_struct *buf, tree type, 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); diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index bd176e86adf..85ad9904143 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -7302,7 +7302,7 @@ simplify_immed_subreg (fixed_size_mode outermode, rtx x, 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 buffer2 (buffer_bytes); if (!native_encode_rtx (outermode, ret, buffer2, 0, buffer_bytes)) diff --git a/gcc/testsuite/gcc.dg/pr104522.c b/gcc/testsuite/gcc.dg/pr104522.c new file mode 100644 index 00000000000..4d1d6309ca3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr104522.c @@ -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; +}