re PR tree-optimization/15991 (phi nodes with identical arguments still remain at...
authorZdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
Thu, 17 Jun 2004 17:47:47 +0000 (19:47 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Thu, 17 Jun 2004 17:47:47 +0000 (17:47 +0000)
PR tree-optimization/15991
* tree-cfg.c (tree_block_label): Export.
* tree-flow-inline.h (bsi_after_labels): New function.
* tree-flow.h (bsi_after_labels, tree_block_label): Declare.
* tree-ssa.c (propagate_into_addr): New function.
(replace_immediate_uses): Handle propagation of pointer constants.
(raise_value): Do not restrict propagation of pointer constants.
* tree-ssanames.c (duplicate_ssa_name): New function.
* tree.h (duplicate_ssa_name): Declare.

From-SVN: r83297

gcc/ChangeLog
gcc/tree-cfg.c
gcc/tree-flow-inline.h
gcc/tree-flow.h
gcc/tree-ssa.c
gcc/tree-ssanames.c
gcc/tree.h

index 7d206e9f615d382b8ab7be71d4e6154056f1b745..3e237d1043220341d6b27bb3a05c528a853af341 100644 (file)
@@ -1,3 +1,15 @@
+2004-06-17  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+
+       PR tree-optimization/15991
+       * tree-cfg.c (tree_block_label): Export.
+       * tree-flow-inline.h (bsi_after_labels): New function.
+       * tree-flow.h (bsi_after_labels, tree_block_label): Declare.
+       * tree-ssa.c (propagate_into_addr): New function.
+       (replace_immediate_uses): Handle propagation of pointer constants.
+       (raise_value): Do not restrict propagation of pointer constants.
+       * tree-ssanames.c (duplicate_ssa_name): New function.
+       * tree.h (duplicate_ssa_name): Declare.
+
 2004-06-17  David Ayers  <d.ayers@inode.at>
  
        * c-parse.in: Unify Objective-C token names.
index 0624ade3db3175a6164e4bfb2115c9c427487b83..4b3ca40d134396e1639b0ef3c43c973d16c8796c 100644 (file)
@@ -74,7 +74,6 @@ static void free_blocks_annotations (void);
 static void clear_blocks_annotations (void);
 static void make_blocks (tree);
 static void factor_computed_gotos (void);
-static tree tree_block_label (basic_block bb);
 
 /* Edges.  */
 static void make_edges (void);
@@ -3973,7 +3972,7 @@ thread_jumps (void)
 /* Return a non-special label in the head of basic block BLOCK.
    Create one if it doesn't exist.  */
 
-static tree
+tree
 tree_block_label (basic_block bb)
 {
   block_stmt_iterator i, s = bsi_start (bb);
index 4fe44ef112e4055bfc620d1a4298aa4635f63db7..c47ba09c515c7a5c7fcc8ab34aee9245e495d393 100644 (file)
@@ -629,6 +629,53 @@ bsi_start (basic_block bb)
   return bsi;
 }
 
+/* Return a block statement iterator that points to the last label in
+   block BB.  */
+
+static inline block_stmt_iterator
+bsi_after_labels (basic_block bb)
+{
+  block_stmt_iterator bsi;
+  tree_stmt_iterator next;
+
+  bsi.bb = bb;
+
+  if (!bb->stmt_list)
+    {
+#ifdef ENABLE_CHECKING
+      if (bb->index >= 0)
+       abort ();
+#endif
+      bsi.tsi.ptr = NULL;
+      bsi.tsi.container = NULL;
+      return bsi;
+    }
+
+  bsi.tsi = tsi_start (bb->stmt_list);
+  if (tsi_end_p (bsi.tsi))
+    return bsi;
+
+  /* Ensure that there are some labels.  The rationale is that we want
+     to insert after the bsi that is returned, and these insertions should
+     be placed at the start of the basic block.  This would not work if the
+     first statement was not label; rather fail here than enable the user
+     proceed in wrong way.  */
+  if (TREE_CODE (tsi_stmt (bsi.tsi)) != LABEL_EXPR)
+    abort ();
+
+  next = bsi.tsi;
+  tsi_next (&next);
+
+  while (!tsi_end_p (next)
+        && TREE_CODE (tsi_stmt (next)) == LABEL_EXPR)
+    {
+      bsi.tsi = next;
+      tsi_next (&next);
+    }
+
+  return bsi;
+}
+
 /* Return a block statement iterator that points to the end of basic
    block BB.  */
 static inline block_stmt_iterator
index 4f3a4a6a99b15fb334d41df6730768842bf2b4f1..d9d0b1e33283c6f8d56325f2ad8bf55b5c8f20e0 100644 (file)
@@ -416,6 +416,7 @@ typedef struct {
 
 static inline block_stmt_iterator bsi_start (basic_block);
 static inline block_stmt_iterator bsi_last (basic_block);
+static inline block_stmt_iterator bsi_after_labels (basic_block);
 static inline bool bsi_end_p (block_stmt_iterator);
 static inline void bsi_next (block_stmt_iterator *);
 static inline void bsi_prev (block_stmt_iterator *);
@@ -486,6 +487,7 @@ extern void notice_special_calls (tree);
 extern void clear_special_calls (void);
 extern void compute_dominance_frontiers (bitmap *);
 extern void verify_stmts (void);
+extern tree tree_block_label (basic_block bb);
 extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
 
 /* In tree-pretty-print.c.  */
index 175ce4878a78e0bd415e978fba93470178ba6bf6..7d9e64d338a8a8b180bfa28a4e215df58337b8ab 100644 (file)
@@ -705,6 +705,52 @@ walk_use_def_chains (tree var, walk_use_def_chains_fn fn, void *data)
     }
 }
 
+/* Replaces VAR with REPL in memory reference expression *X in
+   statement STMT.  */
+
+static void
+propagate_into_addr (tree stmt, tree var, tree *x, tree repl)
+{
+  tree new_var, ass_stmt, addr_var;
+  basic_block bb;
+  block_stmt_iterator bsi;
+
+  /* There is nothing special to handle in the other cases.  */
+  if (TREE_CODE (repl) != ADDR_EXPR)
+    return;
+  addr_var = TREE_OPERAND (repl, 0);
+
+  while (TREE_CODE (*x) == ARRAY_REF
+        || TREE_CODE (*x) == COMPONENT_REF
+        || TREE_CODE (*x) == BIT_FIELD_REF)
+    x = &TREE_OPERAND (*x, 0);
+
+  if (TREE_CODE (*x) != INDIRECT_REF
+      || TREE_OPERAND (*x, 0) != var)
+    return;
+
+  modify_stmt (stmt);
+  if (TREE_TYPE (*x) == TREE_TYPE (addr_var))
+    {
+      *x = addr_var;
+      mark_new_vars_to_rename (stmt, vars_to_rename);
+      return;
+    }
+
+  /* Frontends sometimes produce expressions like *&a instead of a[0].
+     Create a temporary variable to handle this case.  */
+  ass_stmt = build2 (MODIFY_EXPR, void_type_node, NULL_TREE, repl);
+  new_var = duplicate_ssa_name (var, ass_stmt);
+  TREE_OPERAND (*x, 0) = new_var;
+  TREE_OPERAND (ass_stmt, 0) = new_var;
+
+  bb = bb_for_stmt (stmt);
+  tree_block_label (bb);
+  bsi = bsi_after_labels (bb);
+  bsi_insert_after (&bsi, ass_stmt, BSI_NEW_STMT);
+
+  mark_new_vars_to_rename (stmt, vars_to_rename);
+}
 
 /* Replaces immediate uses of VAR by REPL.  */
 
@@ -718,6 +764,7 @@ replace_immediate_uses (tree var, tree repl)
   dataflow_t df;
   tree stmt;
   stmt_ann_t ann;
+  bool mark_new_vars;
 
   df = get_immediate_uses (SSA_NAME_DEF_STMT (var));
   n = num_immediate_uses (df);
@@ -742,12 +789,22 @@ replace_immediate_uses (tree var, tree repl)
        }
 
       get_stmt_operands (stmt);
+      mark_new_vars = false;
       if (is_gimple_reg (SSA_NAME_VAR (var)))
        {
+         if (TREE_CODE (stmt) == MODIFY_EXPR)
+           {
+             propagate_into_addr (stmt, var, &TREE_OPERAND (stmt, 0), repl);
+             propagate_into_addr (stmt, var, &TREE_OPERAND (stmt, 1), repl);
+           }
+
          uses = USE_OPS (ann);
          for (j = 0; j < (int) NUM_USES (uses); j++)
            if (USE_OP (uses, j) == var)
-             propagate_value (USE_OP_PTR (uses, j), repl);
+             {
+               propagate_value (USE_OP_PTR (uses, j), repl);
+               mark_new_vars = POINTER_TYPE_P (TREE_TYPE (repl));
+             }
        }
       else
        {
@@ -762,15 +819,15 @@ replace_immediate_uses (tree var, tree repl)
              propagate_value (V_MAY_DEF_OP_PTR (v_may_defs, j), repl);
        }
 
-      modify_stmt (stmt);
-
       /* If REPL is a pointer, it may have different memory tags associated
         with it.  For instance, VAR may have had a name tag while REPL
         only had a type tag.  In these cases, the virtual operands (if
         any) in the statement will refer to different symbols which need
         to be renamed.  */
-      if (POINTER_TYPE_P (TREE_TYPE (repl)))
+      if (mark_new_vars)
        mark_new_vars_to_rename (stmt, vars_to_rename);
+      else
+       modify_stmt (stmt);
     }
 }
 
@@ -788,23 +845,6 @@ raise_value (tree phi, tree val, tree *eq_to)
   if (eq_to[ver] == var)
     return;
 
-  switch (TREE_CODE (val))
-    {
-    case SSA_NAME:
-    case REAL_CST:
-    case COMPLEX_CST:
-      break;
-    case INTEGER_CST:
-      if (TREE_CODE (TREE_TYPE (var)) != POINTER_TYPE)
-       break;
-
-    default:
-      /* Do not propagate pointer constants.  This might require folding
-        things like *&foo and rewriting the ssa, which is not worth the
-        trouble.  */
-      val = var;
-    }
-
   if (eq_to[ver])
     {
       if (operand_equal_p (eq_to[ver], val, 0))
index 6a0fda6006fabb9872e29294061faa571ed3fd91..d4982706676cccc62146c21fdd6259d5a4847325 100644 (file)
@@ -191,4 +191,29 @@ release_ssa_name (tree var)
     }
 }
 
+/* Creates a duplicate of a ssa name NAME defined in statement STMT.  */
+
+tree
+duplicate_ssa_name (tree name, tree stmt)
+{
+  tree new_name = make_ssa_name (SSA_NAME_VAR (name), stmt);
+  struct ptr_info_def *old_ptr_info = SSA_NAME_PTR_INFO (name);
+  struct ptr_info_def *new_ptr_info;
+
+  if (!old_ptr_info)
+    return new_name;
+
+  new_ptr_info = ggc_alloc (sizeof (struct ptr_info_def));
+  *new_ptr_info = *old_ptr_info;
+
+  if (old_ptr_info->pt_vars)
+    {
+      new_ptr_info->pt_vars = BITMAP_GGC_ALLOC ();
+      bitmap_copy (new_ptr_info->pt_vars, old_ptr_info->pt_vars);
+    }
+
+  SSA_NAME_PTR_INFO (new_name) = new_ptr_info;
+  return new_name;
+}
+
 #include "gt-tree-ssanames.h"
index db32362ec7b55641f84bf8faafd2ccec993d8287..1a0f8545c1301d2dd13cee73d4676d318002100f 100644 (file)
@@ -2537,6 +2537,7 @@ extern void phinodes_print_statistics (void);
 extern void init_ssanames (void);
 extern void fini_ssanames (void);
 extern tree make_ssa_name (tree, tree);
+extern tree duplicate_ssa_name (tree, tree);
 extern void release_ssa_name (tree);
 #ifdef GATHER_STATISTICS
 extern void ssanames_print_statistics (void);