]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR tree-optimization/46099 (ICE: in replace_ssa_name, at tree-cfg.c...
authorJakub Jelinek <jakub@redhat.com>
Thu, 11 Nov 2010 20:38:12 +0000 (21:38 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 11 Nov 2010 20:38:12 +0000 (21:38 +0100)
Backport from mainline
2010-11-05  Jakub Jelinek  <jakub@redhat.com>

PR tree-optimization/46099
* tree-parloops.c (take_address_of): Add GSI argument.  Return NULL
if it is NULL and uid wasn't found in the hash table.  Just fold the
result if it is NULL otherwise.  Insert other potentially needed
stmts right before current stmt instead of on the entry edge.
(struct elv_data): Add gsi and reset fields.
(eliminate_local_variables_1): Adjust caller.  If take_address_of
failed for debug stmt, set dta->reset and return.
(eliminate_local_variables_stmt): Change STMT argument for GSI,
pass GSI through to the callback, handle resetting of debug stmts.
(eliminate_local_variables): Adjust caller.  Process debug stmts
in second phase.

* gcc.dg/autopar/pr46099.c: New test.

From-SVN: r166618

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/autopar/pr46099.c [new file with mode: 0644]
gcc/tree-parloops.c

index d06874155c360772c4657cb5cef7fa5eeea70e80..8d0a103f3a0b2d8b1855880bb1ab4e2414ebe807 100644 (file)
@@ -3,6 +3,19 @@
        Backport from mainline
        2010-11-05  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/46099
+       * tree-parloops.c (take_address_of): Add GSI argument.  Return NULL
+       if it is NULL and uid wasn't found in the hash table.  Just fold the
+       result if it is NULL otherwise.  Insert other potentially needed
+       stmts right before current stmt instead of on the entry edge.
+       (struct elv_data): Add gsi and reset fields.
+       (eliminate_local_variables_1): Adjust caller.  If take_address_of
+       failed for debug stmt, set dta->reset and return.
+       (eliminate_local_variables_stmt): Change STMT argument for GSI,
+       pass GSI through to the callback, handle resetting of debug stmts.
+       (eliminate_local_variables): Adjust caller.  Process debug stmts
+       in second phase.
+
        PR middle-end/43690
        * gimplify.c (gimplify_asm_expr): If a "m" input is a
        {pre,post}{in,de}crement, fail.
index 43ff2fa456b207f69133f5a0cb48b19eaccfa3c3..b629fb960db5c4ed852ae5952f265b587b4d40d6 100644 (file)
@@ -3,6 +3,9 @@
        Backport from mainline
        2010-11-05  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/46099
+       * gcc.dg/autopar/pr46099.c: New test.
+
        PR middle-end/43690
        * c-c++-common/pr43690.c: New test.
 
diff --git a/gcc/testsuite/gcc.dg/autopar/pr46099.c b/gcc/testsuite/gcc.dg/autopar/pr46099.c
new file mode 100644 (file)
index 0000000..074278e
--- /dev/null
@@ -0,0 +1,47 @@
+/* PR tree-optimization/46099 */
+/* { dg-do compile } */
+/* { dg-options "-ftree-parallelize-loops=2 -fcompare-debug -O" } */
+
+static inline void
+bar (int *i)
+{
+  int j = *i;
+}
+
+void baz (int *, int *, int *);
+
+void
+f1 (int n)
+{
+  int i;
+  for (i = 0; i < n; i++)
+    bar (&i);
+}
+
+void
+f2 (int n)
+{
+  int i;
+  int a[10000], b[10000], c[10000];
+  baz (a, b, c);
+  for (i = 0; i < n; i++)
+    {
+      void *p = c;
+      a[i] = b[i] + c[i];
+    }
+  baz (a, b, c);
+}
+
+void
+f3 (int n)
+{
+  int i;
+  int a[10000], b[10000], c[10000];
+  baz (a, b, c);
+  for (i = 0; i < n; i++)
+    {
+      a[i] = b[i] + c[i];
+      void *p = c;
+    }
+  baz (a, b, c);
+}
index 41cef89ac9ed9aa1cc0859802446315b484eaf4e..c9a537b6a1c7d690ce92102d68afca5056daa9e2 100644 (file)
@@ -315,10 +315,12 @@ loop_has_blocks_with_irreducible_flag (struct loop *loop)
 /* Assigns the address of OBJ in TYPE to an ssa name, and returns this name.
    The assignment statement is placed on edge ENTRY.  DECL_ADDRESS maps decls
    to their addresses that can be reused.  The address of OBJ is known to
-   be invariant in the whole function.  */
+   be invariant in the whole function.  Other needed statements are placed
+   right before GSI.  */
 
 static tree
-take_address_of (tree obj, tree type, edge entry, htab_t decl_address)
+take_address_of (tree obj, tree type, edge entry, htab_t decl_address,
+                gimple_stmt_iterator *gsi)
 {
   int uid;
   void **dslot;
@@ -340,6 +342,8 @@ take_address_of (tree obj, tree type, edge entry, htab_t decl_address)
   dslot = htab_find_slot_with_hash (decl_address, &ielt, uid, INSERT);
   if (!*dslot)
     {
+      if (gsi == NULL)
+       return NULL;
       addr = build_addr (*var_p, current_function_decl);
       bvar = create_tmp_var (TREE_TYPE (addr), get_name (*var_p));
       add_referenced_var (bvar);
@@ -356,13 +360,22 @@ take_address_of (tree obj, tree type, edge entry, htab_t decl_address)
   else
     name = ((struct int_tree_map *) *dslot)->to;
 
+  if (gsi == NULL)
+    {
+      if (var_p != &obj)
+       {
+         *var_p = build1 (INDIRECT_REF, TREE_TYPE (*var_p), name);
+         name = build_fold_addr_expr_with_type (obj, type);
+       }
+      return fold_convert (type, name);
+    }
   if (var_p != &obj)
     {
       *var_p = build1 (INDIRECT_REF, TREE_TYPE (*var_p), name);
       name = force_gimple_operand (build_addr (obj, current_function_decl),
                                   &stmts, true, NULL_TREE);
       if (!gimple_seq_empty_p (stmts))
-       gsi_insert_seq_on_edge_immediate (entry, stmts);
+       gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
     }
 
   if (TREE_TYPE (name) != type)
@@ -370,7 +383,7 @@ take_address_of (tree obj, tree type, edge entry, htab_t decl_address)
       name = force_gimple_operand (fold_convert (type, name), &stmts, true,
                                   NULL_TREE);
       if (!gimple_seq_empty_p (stmts))
-       gsi_insert_seq_on_edge_immediate (entry, stmts);
+       gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
     }
 
   return name;
@@ -432,7 +445,9 @@ struct elv_data
   struct walk_stmt_info info;
   edge entry;
   htab_t decl_address;
+  gimple_stmt_iterator *gsi;
   bool changed;
+  bool reset;
 };
 
 /* Eliminates references to local variables in *TP out of the single
@@ -456,7 +471,14 @@ eliminate_local_variables_1 (tree *tp, int *walk_subtrees, void *data)
 
       type = TREE_TYPE (t);
       addr_type = build_pointer_type (type);
-      addr = take_address_of (t, addr_type, dta->entry, dta->decl_address);
+      addr = take_address_of (t, addr_type, dta->entry, dta->decl_address,
+                             dta->gsi);
+      if (dta->gsi == NULL && addr == NULL_TREE)
+       {
+         dta->reset = true;
+         return NULL_TREE;
+       }
+
       *tp = build1 (INDIRECT_REF, TREE_TYPE (*tp), addr);
 
       dta->changed = true;
@@ -486,7 +508,13 @@ eliminate_local_variables_1 (tree *tp, int *walk_subtrees, void *data)
        return NULL_TREE;
 
       addr_type = TREE_TYPE (t);
-      addr = take_address_of (obj, addr_type, dta->entry, dta->decl_address);
+      addr = take_address_of (obj, addr_type, dta->entry, dta->decl_address,
+                             dta->gsi);
+      if (dta->gsi == NULL && addr == NULL_TREE)
+       {
+         dta->reset = true;
+         return NULL_TREE;
+       }
       *tp = addr;
 
       dta->changed = true;
@@ -499,27 +527,40 @@ eliminate_local_variables_1 (tree *tp, int *walk_subtrees, void *data)
   return NULL_TREE;
 }
 
-/* Moves the references to local variables in STMT out of the single
+/* Moves the references to local variables in STMT at *GSI out of the single
    entry single exit region starting at ENTRY.  DECL_ADDRESS contains
    addresses of the references that had their address taken
    already.  */
 
 static void
-eliminate_local_variables_stmt (edge entry, gimple stmt,
+eliminate_local_variables_stmt (edge entry, gimple_stmt_iterator *gsi,
                                htab_t decl_address)
 {
   struct elv_data dta;
+  gimple stmt = gsi_stmt (*gsi);
 
   memset (&dta.info, '\0', sizeof (dta.info));
   dta.entry = entry;
   dta.decl_address = decl_address;
   dta.changed = false;
+  dta.reset = false;
 
   if (gimple_debug_bind_p (stmt))
-    walk_tree (gimple_debug_bind_get_value_ptr (stmt),
-              eliminate_local_variables_1, &dta.info, NULL);
+    {
+      dta.gsi = NULL;
+      walk_tree (gimple_debug_bind_get_value_ptr (stmt),
+                eliminate_local_variables_1, &dta.info, NULL);
+      if (dta.reset)
+       {
+         gimple_debug_bind_reset_value (stmt);
+         dta.changed = true;
+       }
+    }
   else
-    walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info);
+    {
+      dta.gsi = gsi;
+      walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info);
+    }
 
   if (dta.changed)
     update_stmt (stmt);
@@ -543,6 +584,7 @@ eliminate_local_variables (edge entry, edge exit)
   VEC (basic_block, heap) *body = VEC_alloc (basic_block, heap, 3);
   unsigned i;
   gimple_stmt_iterator gsi;
+  bool has_debug_stmt = false;
   htab_t decl_address = htab_create (10, int_tree_map_hash, int_tree_map_eq,
                                     free);
   basic_block entry_bb = entry->src;
@@ -553,8 +595,17 @@ eliminate_local_variables (edge entry, edge exit)
   for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
     if (bb != entry_bb && bb != exit_bb)
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-       eliminate_local_variables_stmt (entry, gsi_stmt (gsi),
-                                       decl_address);
+       if (gimple_debug_bind_p (gsi_stmt (gsi)))
+         has_debug_stmt = true;
+       else
+         eliminate_local_variables_stmt (entry, &gsi, decl_address);
+
+  if (has_debug_stmt)
+    for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
+      if (bb != entry_bb && bb != exit_bb)
+       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+         if (gimple_debug_bind_p (gsi_stmt (gsi)))
+           eliminate_local_variables_stmt (entry, &gsi, decl_address);
 
   htab_delete (decl_address);
   VEC_free (basic_block, heap, body);