2012-06-05 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Jun 2012 09:24:43 +0000 (09:24 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Jun 2012 09:24:43 +0000 (09:24 +0000)
PR tree-optimization/53081
* tree-loop-distribution.c (generate_memset_builtin): Handle all
kinds of byte-sized stores.
(classify_partition): Likewise.
(tree_loop_distribution): Adjust seed statements used for
!flag_tree_loop_distribution.

* gcc.dg/tree-ssa/ldist-19.c: New testcase.
* gcc.c-torture/execute/builtins/builtins.exp: Always pass
-fno-tree-loop-distribute-patterns.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@188232 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
gcc/testsuite/gcc.dg/tree-ssa/ldist-19.c [new file with mode: 0644]
gcc/tree-loop-distribution.c

index faae6b7..1ebee7b 100644 (file)
@@ -1,3 +1,12 @@
+2012-06-05  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/53081
+       * tree-loop-distribution.c (generate_memset_builtin): Handle all
+       kinds of byte-sized stores.
+       (classify_partition): Likewise.
+       (tree_loop_distribution): Adjust seed statements used for
+       !flag_tree_loop_distribution.
+
 2012-06-05  Alan Modra  <amodra@gmail.com>
 
        * config/rs6000/rs6000.c (ptr_regno_for_savres): Comment.
index c87ae14..3bfc678 100644 (file)
@@ -1,3 +1,10 @@
+2012-06-05  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/53081
+       * gcc.dg/tree-ssa/ldist-19.c: New testcase.
+       * gcc.c-torture/execute/builtins/builtins.exp: Always pass
+       -fno-tree-loop-distribute-patterns.
+
 2012-06-05  Alan Modra  <amodra@gmail.com>
 
        * gcc.target/powerpc/savres.c: Add -mdynamic-no-pic for darwin.
index a54f3c1..f7cc82b 100644 (file)
@@ -37,7 +37,7 @@ load_lib c-torture.exp
 torture-init
 set-torture-options $C_TORTURE_OPTIONS {{}} $LTO_TORTURE_OPTIONS
 
-set additional_flags ""
+set additional_flags "-fno-tree-loop-distribute-patterns"
 if [istarget "powerpc-*-darwin*"] {
    lappend additional_flags "-Wl,-multiply_defined,suppress"
 }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-19.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-19.c
new file mode 100644 (file)
index 0000000..332fedf
--- /dev/null
@@ -0,0 +1,72 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-ldist-details" } */
+
+struct Foo
+{
+  char a;
+};
+
+struct Foo x[256];
+
+static void __attribute__((noinline,noclone))
+foo()
+{
+  int i;
+  for (i = 0; i < 256; ++i)
+    x[i] = (struct Foo){};
+}
+
+static void __attribute__((noinline,noclone))
+bar()
+{
+  int i;
+  for (i = 0; i < 256; ++i)
+    x[i].a = 1;
+}
+
+static void __attribute__((noinline,noclone))
+foobar(unsigned char c)
+{
+  int i;
+  for (i = 0; i < 256; ++i)
+    x[i].a = c;
+}
+
+static void __attribute__((noinline,noclone))
+foobar2(char c)
+{
+  int i;
+  for (i = 0; i < 256; ++i)
+    x[i].a = c;
+}
+
+struct Baz
+{
+  short a;
+};
+
+struct Baz y[256];
+
+static void __attribute__((noinline,noclone))
+baz()
+{
+  int i;
+  for (i = 0; i < 256; ++i)
+    y[i].a = -1;
+}
+
+int main()
+{
+  volatile int x;
+  foo();
+  bar();
+  foobar(x);
+  foobar2(x);
+  baz();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "generated memset zero" 1 "ldist" } } */
+/* { dg-final { scan-tree-dump-times "generated memset minus one" 1 "ldist" } } */
+/* { dg-final { scan-tree-dump-times "generated memset" 5 "ldist" } } */
+/* { dg-final { cleanup-tree-dump "ldist" } } */
index db4fefc..5903918 100644 (file)
@@ -332,6 +332,7 @@ generate_memset_builtin (struct loop *loop, struct graph *rdg,
   gimple_seq stmt_list = NULL, stmts;
   struct data_reference *dr = XCNEW (struct data_reference);
   location_t loc;
+  tree val;
 
   stmt = partition->main_stmt;
   loc = gimple_location (stmt);
@@ -364,13 +365,44 @@ generate_memset_builtin (struct loop *loop, struct graph *rdg,
   mem = force_gimple_operand (addr_base, &stmts, true, NULL);
   gimple_seq_add_seq (&stmt_list, stmts);
 
+  /* This exactly matches the pattern recognition in classify_partition.  */
+  val = gimple_assign_rhs1 (stmt);
+  if (integer_zerop (val)
+      || real_zerop (val)
+      || TREE_CODE (val) == CONSTRUCTOR)
+    val = integer_zero_node;
+  else if (integer_all_onesp (val))
+    val = build_int_cst (integer_type_node, -1);
+  else
+    {
+      if (TREE_CODE (val) == INTEGER_CST)
+       val = fold_convert (integer_type_node, val);
+      else if (!useless_type_conversion_p (integer_type_node, TREE_TYPE (val)))
+       {
+         gimple cstmt;
+         tree tem = create_tmp_reg (integer_type_node, NULL);
+         tem = make_ssa_name (tem, NULL);
+         cstmt = gimple_build_assign_with_ops (NOP_EXPR, tem, val, NULL_TREE);
+         gimple_seq_add_stmt (&stmt_list, cstmt);
+         val = tem;
+       }
+    }
+
   fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_MEMSET));
-  fn_call = gimple_build_call (fn, 3, mem, integer_zero_node, nb_bytes);
+  fn_call = gimple_build_call (fn, 3, mem, val, nb_bytes);
   gimple_seq_add_stmt (&stmt_list, fn_call);
   gsi_insert_seq_after (&gsi, stmt_list, GSI_CONTINUE_LINKING);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-    fprintf (dump_file, "generated memset zero\n");
+    {
+      fprintf (dump_file, "generated memset");
+      if (integer_zerop (val))
+       fprintf (dump_file, " zero\n");
+      else if (integer_all_onesp (val))
+       fprintf (dump_file, " minus one\n");
+      else
+       fprintf (dump_file, "\n");
+    }
 }
 
 /* Remove and destroy the loop LOOP.  */
@@ -865,7 +897,19 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
            return;
          partition->main_stmt = stmt;
          rhs = gimple_assign_rhs1 (stmt);
-         if (!(integer_zerop (rhs) || real_zerop (rhs)))
+         if (!(integer_zerop (rhs)
+               || integer_all_onesp (rhs)
+               || real_zerop (rhs)
+               || (TREE_CODE (rhs) == CONSTRUCTOR
+                   && !TREE_CLOBBER_P (rhs))
+               || (INTEGRAL_TYPE_P (TREE_TYPE (rhs))
+                   && (TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)))
+                       == TYPE_MODE (unsigned_char_type_node)))))
+           return;
+         if (TREE_CODE (rhs) == SSA_NAME
+             && !SSA_NAME_IS_DEFAULT_DEF (rhs)
+             && flow_bb_inside_loop_p
+                  (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs))))
            return;
          if (VEC_length (data_reference_p, RDG_DATAREFS (rdg, i)) != 1)
            return;
@@ -1346,9 +1390,19 @@ tree_loop_distribution (void)
 
              /* If we are only performing pattern detection restrict
                 what we try to distribute to stores from constants.  */
-             if (!flag_tree_loop_distribution
-                 && !is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
-               continue;
+             if (!flag_tree_loop_distribution)
+               {
+                 tree rhs = gimple_assign_rhs1 (stmt);
+                 if (!is_gimple_min_invariant (rhs)
+                     && TREE_CODE (rhs) != CONSTRUCTOR
+                     && TREE_CODE (rhs) != SSA_NAME)
+                   continue;
+                 if (TREE_CODE (rhs) == SSA_NAME
+                     && !SSA_NAME_IS_DEFAULT_DEF (rhs)
+                     && flow_bb_inside_loop_p
+                          (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs))))
+                   continue;
+               }
 
              VEC_safe_push (gimple, heap, work_list, stmt);
            }