This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] for PR15991


Hello,

this PR is caused by the fact that we avoid propagation of pointer
constants in kill_redundant_phi_nodes.  This patch extends
the function to handle them as well.

Bootstrapped & regtested on i686.

Zdenek

	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.

Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.12
diff -c -3 -p -r2.12 tree-cfg.c
*** tree-cfg.c	16 Jun 2004 23:03:27 -0000	2.12
--- tree-cfg.c	17 Jun 2004 14:34:52 -0000
*************** static void free_blocks_annotations (voi
*** 74,80 ****
  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);
--- 74,79 ----
*************** thread_jumps (void)
*** 3973,3979 ****
  /* Return a non-special label in the head of basic block BLOCK.
     Create one if it doesn't exist.  */
  
! static tree
  tree_block_label (basic_block bb)
  {
    block_stmt_iterator i, s = bsi_start (bb);
--- 3972,3978 ----
  /* Return a non-special label in the head of basic block BLOCK.
     Create one if it doesn't exist.  */
  
! tree
  tree_block_label (basic_block bb)
  {
    block_stmt_iterator i, s = bsi_start (bb);
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow-inline.h,v
retrieving revision 2.8
diff -c -3 -p -r2.8 tree-flow-inline.h
*** tree-flow-inline.h	16 Jun 2004 23:03:28 -0000	2.8
--- tree-flow-inline.h	17 Jun 2004 14:34:52 -0000
*************** bsi_start (basic_block bb)
*** 629,634 ****
--- 629,681 ----
    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: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 2.8
diff -c -3 -p -r2.8 tree-flow.h
*** tree-flow.h	12 Jun 2004 00:18:31 -0000	2.8
--- tree-flow.h	17 Jun 2004 14:34:52 -0000
*************** typedef struct {
*** 416,421 ****
--- 416,422 ----
  
  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 *);
*************** extern void notice_special_calls (tree);
*** 486,491 ****
--- 487,493 ----
  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: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa.c,v
retrieving revision 2.9
diff -c -3 -p -r2.9 tree-ssa.c
*** tree-ssa.c	16 Jun 2004 23:03:33 -0000	2.9
--- tree-ssa.c	17 Jun 2004 14:34:52 -0000
*************** walk_use_def_chains (tree var, walk_use_
*** 705,710 ****
--- 705,756 ----
      }
  }
  
+ /* 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.  */
  
*************** replace_immediate_uses (tree var, tree r
*** 718,723 ****
--- 764,770 ----
    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);
*************** replace_immediate_uses (tree var, tree r
*** 742,753 ****
  	}
  
        get_stmt_operands (stmt);
        if (is_gimple_reg (SSA_NAME_VAR (var)))
  	{
  	  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);
  	}
        else
  	{
--- 789,810 ----
  	}
  
        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);
! 		mark_new_vars = POINTER_TYPE_P (TREE_TYPE (repl));
! 	      }
  	}
        else
  	{
*************** replace_immediate_uses (tree var, tree r
*** 762,776 ****
  	      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)))
  	mark_new_vars_to_rename (stmt, vars_to_rename);
      }
  }
  
--- 819,833 ----
  	      propagate_value (V_MAY_DEF_OP_PTR (v_may_defs, j), repl);
  	}
  
        /* 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 (mark_new_vars)
  	mark_new_vars_to_rename (stmt, vars_to_rename);
+       else
+ 	modify_stmt (stmt);
      }
  }
  
*************** raise_value (tree phi, tree val, tree *e
*** 788,810 ****
    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))
--- 845,850 ----
Index: tree-ssanames.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssanames.c,v
retrieving revision 2.2
diff -c -3 -p -r2.2 tree-ssanames.c
*** tree-ssanames.c	10 Jun 2004 22:37:05 -0000	2.2
--- tree-ssanames.c	17 Jun 2004 14:34:52 -0000
*************** release_ssa_name (tree var)
*** 191,194 ****
--- 191,219 ----
      }
  }
  
+ /* 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: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.519
diff -c -3 -p -r1.519 tree.h
*** tree.h	17 Jun 2004 01:23:58 -0000	1.519
--- tree.h	17 Jun 2004 14:34:52 -0000
*************** extern void phinodes_print_statistics (v
*** 2537,2542 ****
--- 2537,2543 ----
  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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]