--- /dev/null
+/* { dg-options "-O2 -fno-strict-aliasing -fdump-tree-dse-details -fno-tree-fre -fdump-tree-optimized" } */
+
+/* PR tree-optimization/87901 */
+
+
+int i;
+int foo ()
+{
+ i = 0;
+ *((short *)&i + 1) = 1;
+ return i;
+}
+
+/* we should get:
+ MEM <char[2]> [(int *)&i] = {};
+ MEM[(short int *)&i + 2B] = 1;
+ in DSE1.
+
+ Note later on the stores will be merged. */
+/* { dg-final { scan-tree-dump "return 65536;" "optimized" { target le } } } */
+/* { dg-final { scan-tree-dump "return 1;" "optimized" { target be } } } */
+/* { dg-final { scan-tree-dump "\\\[2\\\]" "dse1" } } */
+
+/* { dg-final { scan-tree-dump-times "Trimming statement " 1 "dse1" } } */
+
+
--- /dev/null
+/* { dg-options "-O2 -fdump-tree-dse-details -fno-tree-fre -fdump-tree-optimized" } */
+
+/* PR tree-optimization/87901 */
+
+int z[128];
+void foo1(void)
+{
+ int z1;
+ int z2[24/sizeof(int)];
+ __builtin_memset (&z1, 0, sizeof(int));
+ __builtin_memcpy (z, &z1, sizeof(int));
+ __builtin_memset (z2, 0, 24);
+ __builtin_memcpy (((char*)z)+1, z2, 24);
+}
+
+/* we should get:
+ MEM[(char * {ref-all})&z] = {};
+ __builtin_memset (&MEM <int[128]> [(void *)&z + 1B], 0, 24);
+ */
+
+/* { dg-final { scan-tree-dump-not "MEM <unsigned int>" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "MEM \\\[" "dse1" } } */
+/* { dg-final { scan-tree-dump-times "Trimming statement " 1 "dse1" } } */
+/* { dg-final { scan-tree-dump-times "Deleted dead call:" 1 "dse1" } } */
+
The most common case for getting here is a CONSTRUCTOR with no elements
being used to zero initialize an object. We do not try to handle other
cases as those would force us to fully cover the object with the
- CONSTRUCTOR node except for the components that are dead. */
+ CONSTRUCTOR node except for the components that are dead.
+ Also handles integer stores of 0 which can happen with memset/memcpy optimizations. */
static void
-maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt)
+maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt, bool was_integer_cst)
{
tree ctor = gimple_assign_rhs1 (stmt);
/* This is the only case we currently handle. It actually seems to
catch most cases of actual interest. */
- gcc_assert (CONSTRUCTOR_NELTS (ctor) == 0);
+ gcc_assert (was_integer_cst ? integer_zerop (ctor) : CONSTRUCTOR_NELTS (ctor) == 0);
int head_trim = 0;
int tail_trim = 0;
switch (gimple_assign_rhs_code (stmt))
{
case CONSTRUCTOR:
- maybe_trim_constructor_store (ref, live, stmt);
+ maybe_trim_constructor_store (ref, live, stmt, false);
break;
case COMPLEX_CST:
maybe_trim_complex_store (ref, live, stmt);
break;
+ case INTEGER_CST:
+ if (integer_zerop (gimple_assign_rhs1 (stmt))
+ && type_has_mode_precision_p (TREE_TYPE (gimple_assign_lhs (stmt))))
+ maybe_trim_constructor_store (ref, live, stmt, true);
+ break;
default:
break;
}