unsigned int total_bytes)
{
unsigned int first_byte = bitpos / BITS_PER_UNIT;
- tree tmp_int = expr;
bool sub_byte_op_p = ((bitlen % BITS_PER_UNIT)
|| (bitpos % BITS_PER_UNIT)
|| !int_mode_for_size (bitlen, 0).exists ());
+ bool empty_ctor_p
+ = (TREE_CODE (expr) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (expr) == 0
+ && TYPE_SIZE_UNIT (TREE_TYPE (expr))
+ && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (expr))));
if (!sub_byte_op_p)
- return native_encode_expr (tmp_int, ptr + first_byte, total_bytes) != 0;
+ {
+ if (first_byte >= total_bytes)
+ return false;
+ total_bytes -= first_byte;
+ if (empty_ctor_p)
+ {
+ unsigned HOST_WIDE_INT rhs_bytes
+ = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
+ if (rhs_bytes > total_bytes)
+ return false;
+ memset (ptr + first_byte, '\0', rhs_bytes);
+ return true;
+ }
+ return native_encode_expr (expr, ptr + first_byte, total_bytes) != 0;
+ }
/* LITTLE-ENDIAN
We are writing a non byte-sized quantity or at a position that is not
/* We must be dealing with fixed-size data at this point, since the
total size is also fixed. */
- fixed_size_mode mode = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (expr)));
+ unsigned int byte_size;
+ if (empty_ctor_p)
+ {
+ unsigned HOST_WIDE_INT rhs_bytes
+ = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
+ if (rhs_bytes > total_bytes)
+ return false;
+ byte_size = rhs_bytes;
+ }
+ else
+ {
+ fixed_size_mode mode
+ = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (expr)));
+ byte_size = GET_MODE_SIZE (mode);
+ }
/* Allocate an extra byte so that we have space to shift into. */
- unsigned int byte_size = GET_MODE_SIZE (mode) + 1;
+ byte_size++;
unsigned char *tmpbuf = XALLOCAVEC (unsigned char, byte_size);
memset (tmpbuf, '\0', byte_size);
/* The store detection code should only have allowed constants that are
- accepted by native_encode_expr. */
- if (native_encode_expr (expr, tmpbuf, byte_size - 1) == 0)
+ accepted by native_encode_expr or empty ctors. */
+ if (!empty_ctor_p
+ && native_encode_expr (expr, tmpbuf, byte_size - 1) == 0)
gcc_unreachable ();
/* The native_encode_expr machinery uses TYPE_MODE to determine how many
tree_code code = TREE_CODE (lhs);
if (code == ARRAY_REF || code == ARRAY_RANGE_REF || code == MEM_REF
- || code == COMPONENT_REF || code == BIT_FIELD_REF)
+ || code == COMPONENT_REF || code == BIT_FIELD_REF
+ || DECL_P (lhs))
return true;
return false;
rhs_valid_for_store_merging_p (tree rhs)
{
unsigned HOST_WIDE_INT size;
+ if (TREE_CODE (rhs) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (rhs) == 0
+ && TYPE_SIZE_UNIT (TREE_TYPE (rhs))
+ && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (rhs))))
+ return true;
return (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (rhs))).is_constant (&size)
&& native_encode_expr (rhs, NULL, size) != 0);
}
--- /dev/null
+/* PR tree-optimization/89475 */
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "link_error " "optimized" } } */
+
+void link_error (void);
+
+unsigned short
+f0 (unsigned short x)
+{
+ x &= 0xaa55;
+ x = __builtin_bswap16 (x);
+ if (x & 0xaa55)
+ link_error ();
+ return x;
+}
+
+unsigned short
+f1 (unsigned short x)
+{
+ x &= 0x55aa;
+ x = __builtin_bswap16 (x);
+ if (x & 0x55aa)
+ link_error ();
+ return x;
+}
+
+unsigned int
+f2 (unsigned int x)
+{
+ x &= 0x55aa5aa5U;
+ x = __builtin_bswap32 (x);
+ if (x & 0x5aa555aaU)
+ link_error ();
+ return x;
+}
+
+unsigned long long int
+f3 (unsigned long long int x)
+{
+ x &= 0x55aa5aa544cc2211ULL;
+ x = __builtin_bswap64 (x);
+ if (x & 0xeedd33bb5aa555aaULL)
+ link_error ();
+ return x;
+}
+
+unsigned short
+f4 (unsigned short x)
+{
+ x = __builtin_bswap32 (x);
+ if (x != 0)
+ link_error ();
+ return x;
+}
+
+unsigned int
+f5 (unsigned int x)
+{
+ x = __builtin_bswap64 (x);
+ if (x != 0)
+ link_error ();
+ return x;
+}
+
+unsigned short
+f6 (unsigned short x)
+{
+ x |= 0xaa55;
+ x = __builtin_bswap16 (x);
+ if ((x | 0xaa55) != 0xffff)
+ link_error ();
+ return x;
+}
+
+unsigned short
+f7 (unsigned short x)
+{
+ x |= 0x55aa;
+ x = __builtin_bswap16 (x);
+ if ((x | 0x55aa) != 0xffff)
+ link_error ();
+ return x;
+}
+
+unsigned int
+f8 (unsigned int x)
+{
+ x |= 0x55aa5aa5U;
+ x = __builtin_bswap32 (x);
+ if ((x | 0x5aa555aaU) != 0xffffffffU)
+ link_error ();
+ return x;
+}
+
+unsigned long long int
+f9 (unsigned long long int x)
+{
+ x |= 0x55aa5aa544cc2211ULL;
+ x = __builtin_bswap64 (x);
+ if ((x | 0xeedd33bb5aa555aaULL) != 0xffffffffffffffffULL)
+ link_error ();
+ return x;
+}
break;
}
+ case BUILT_IN_BSWAP16:
+ case BUILT_IN_BSWAP32:
+ case BUILT_IN_BSWAP64:
+ val = get_value_for_expr (gimple_call_arg (stmt, 0), true);
+ if (val.lattice_val == UNDEFINED)
+ break;
+ else if (val.lattice_val == CONSTANT
+ && val.value
+ && TREE_CODE (val.value) == INTEGER_CST)
+ {
+ tree type = TREE_TYPE (gimple_call_lhs (stmt));
+ int prec = TYPE_PRECISION (type);
+ wide_int wval = wi::to_wide (val.value);
+ val.value
+ = wide_int_to_tree (type,
+ wide_int::from (wval, prec,
+ UNSIGNED).bswap ());
+ val.mask
+ = widest_int::from (wide_int::from (val.mask, prec,
+ UNSIGNED).bswap (),
+ UNSIGNED);
+ if (wi::sext (val.mask, prec) != -1)
+ break;
+ }
+ val.lattice_val = VARYING;
+ val.value = NULL_TREE;
+ val.mask = -1;
+ break;
+
default:;
}
}