This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] for PR15991
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 17 Jun 2004 16:50:41 +0200
- Subject: [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);