re PR tree-optimization/15991 (phi nodes with identical arguments still remain at t50.tailc)
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
This commit is contained in:
parent
f2b5cf977e
commit
d7621d3c74
7 changed files with 149 additions and 23 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue