tree-flow-inline.h (op_iter_next_must_and_may_def): New.

* tree-flow-inline.h (op_iter_next_must_and_may_def): New.
	(op_iter_init_must_and_may_def): Likewise.
	(unmodifiable_var_p): Move to a later point in the file.
	* tree-ssa-operands.h (FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND): New.
	* tree-ssa-dse.c (need_imm_uses_for): Remove, no longer needed.
	(dse_record_phis): Directly check for virtual operands rather than
	using need_imm_uses_for.
	(dse_optimize_stmt): Handle V_MUST_DEF operands.  Handle case where
	store has multiple V_{MAY,MUST}_DEF operands.

From-SVN: r98780
This commit is contained in:
Jeff Law 2005-04-26 11:37:33 -06:00 committed by Jeff Law
parent 5635785a64
commit db30731aa4
4 changed files with 110 additions and 38 deletions

View File

@ -1,3 +1,15 @@
2005-04-26 Jeff Law <law@redhat.com>
* tree-flow-inline.h (op_iter_next_must_and_may_def): New.
(op_iter_init_must_and_may_def): Likewise.
(unmodifiable_var_p): Move to a later point in the file.
* tree-ssa-operands.h (FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND): New.
* tree-ssa-dse.c (need_imm_uses_for): Remove, no longer needed.
(dse_record_phis): Directly check for virtual operands rather than
using need_imm_uses_for.
(dse_optimize_stmt): Handle V_MUST_DEF operands. Handle case where
store has multiple V_{MAY,MUST}_DEF operands.
2005-04-26 Andrew MacLeod <amacleod@redhat.com>
* tree-cfg.c (bsi_replace): Delink immediate uses for the original stmt.

View File

@ -1121,6 +1121,7 @@ op_iter_next_mustdef (use_operand_p *kill, def_operand_p *def, ssa_op_iter *ptr)
ptr->done = true;
return;
}
/* Get the next iterator maydef value for PTR, returning the maydef values in
USE and DEF. */
static inline void
@ -1141,6 +1142,34 @@ op_iter_next_maydef (use_operand_p *use, def_operand_p *def, ssa_op_iter *ptr)
return;
}
/* Get the next iterator mustdef or maydef value for PTR, returning the
mustdef or maydef values in KILL and DEF. */
static inline void
op_iter_next_must_and_may_def (use_operand_p *kill,
def_operand_p *def,
ssa_op_iter *ptr)
{
if (ptr->v_mustu_i < ptr->num_v_mustu)
{
*def = V_MUST_DEF_RESULT_PTR (ptr->ops->v_must_def_ops, ptr->v_mustu_i);
*kill = V_MUST_DEF_KILL_PTR (ptr->ops->v_must_def_ops, (ptr->v_mustu_i)++);
return;
}
else if (ptr->v_mayu_i < ptr->num_v_mayu)
{
*def = V_MAY_DEF_RESULT_PTR (ptr->ops->v_may_def_ops, ptr->v_mayu_i);
*kill = V_MAY_DEF_OP_PTR (ptr->ops->v_may_def_ops, (ptr->v_mayu_i)++);
return;
}
else
{
*def = NULL_DEF_OPERAND_P;
*kill = NULL_USE_OPERAND_P;
}
ptr->done = true;
return;
}
/* Initialize iterator PTR to the operands in STMT. Return the first operands
in USE and DEF. */
static inline void
@ -1151,16 +1180,6 @@ op_iter_init_maydef (ssa_op_iter *ptr, tree stmt, use_operand_p *use,
op_iter_next_maydef (use, def, ptr);
}
/* Return true if VAR cannot be modified by the program. */
static inline bool
unmodifiable_var_p (tree var)
{
if (TREE_CODE (var) == SSA_NAME)
var = SSA_NAME_VAR (var);
return TREE_READONLY (var) && (TREE_STATIC (var) || DECL_EXTERNAL (var));
}
/* Initialize iterator PTR to the operands in STMT. Return the first operands
in KILL and DEF. */
@ -1172,6 +1191,26 @@ op_iter_init_mustdef (ssa_op_iter *ptr, tree stmt, use_operand_p *kill,
op_iter_next_mustdef (kill, def, ptr);
}
/* Initialize iterator PTR to the operands in STMT. Return the first operands
in KILL and DEF. */
static inline void
op_iter_init_must_and_may_def (ssa_op_iter *ptr, tree stmt,
use_operand_p *kill, def_operand_p *def)
{
op_iter_init (ptr, stmt, SSA_OP_VMUSTDEFKILL | SSA_OP_VMAYUSE);
op_iter_next_must_and_may_def (kill, def, ptr);
}
/* Return true if VAR cannot be modified by the program. */
static inline bool
unmodifiable_var_p (tree var)
{
if (TREE_CODE (var) == SSA_NAME)
var = SSA_NAME_VAR (var);
return TREE_READONLY (var) && (TREE_STATIC (var) || DECL_EXTERNAL (var));
}
/* Return true if REF, a COMPONENT_REF, has an ARRAY_REF somewhere in it. */
static inline bool

View File

@ -111,18 +111,8 @@ get_stmt_uid (tree stmt)
return stmt_ann (stmt)->uid;
}
/* Function indicating whether we ought to include information for 'var'
when calculating immediate uses. For this pass we only want use
information for virtual variables. */
static bool
need_imm_uses_for (tree var)
{
return !is_gimple_reg (var);
}
/* Set bit UID in bitmaps GLOBAL and *LOCAL, creating *LOCAL as needed. */
static void
record_voperand_set (bitmap global, bitmap *local, unsigned int uid)
{
@ -136,6 +126,7 @@ record_voperand_set (bitmap global, bitmap *local, unsigned int uid)
bitmap_set_bit (*local, uid);
bitmap_set_bit (global, uid);
}
/* Initialize block local data structures. */
static void
@ -177,12 +168,15 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
tree stmt = bsi_stmt (bsi);
stmt_ann_t ann = stmt_ann (stmt);
v_may_def_optype v_may_defs;
v_must_def_optype v_must_defs;
v_may_defs = V_MAY_DEF_OPS (ann);
v_must_defs = V_MUST_DEF_OPS (ann);
/* If this statement has no virtual defs, then there is nothing
to do. */
if (NUM_V_MAY_DEFS (v_may_defs) == 0)
if (NUM_V_MAY_DEFS (v_may_defs) == 0
&& NUM_V_MUST_DEFS (v_must_defs) == 0)
return;
/* We know we have virtual definitions. If this is a MODIFY_EXPR that's
@ -195,33 +189,53 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
if (TREE_CODE (stmt) == MODIFY_EXPR)
{
unsigned int num_uses = 0, count = 0;
use_operand_p first_use_p = NULL_USE_OPERAND_P;
use_operand_p use_p;
tree use, use_stmt;
use_operand_p use_p = NULL;
tree use, use_stmt, temp;
tree defvar = NULL_TREE, usevar = NULL_TREE;
bool fail = false;
use_operand_p var2;
def_operand_p var1;
ssa_op_iter op_iter;
FOR_EACH_SSA_MAYDEF_OPERAND (var1, var2, stmt, op_iter)
{
/* We want to verify that each virtual definition in STMT has
precisely one use and that all the virtual definitions are
used by the same single statement. When complete, we
want USE_STMT to refer to the one statment which uses
all of the virtual definitions from STMT. */
use_stmt = NULL;
FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND (var1, var2, stmt, op_iter)
{
defvar = DEF_FROM_PTR (var1);
usevar = USE_FROM_PTR (var2);
num_uses += num_imm_uses (defvar);
count++;
if (num_uses > 1 || count > 1)
break;
}
if (count == 1 && num_uses == 1)
{
single_imm_use (defvar, &use_p, &use_stmt);
/* If this virtual def does not have precisely one use, then
we will not be able to eliminate STMT. */
if (num_imm_uses (defvar) != 1)
{
fail = true;
break;
}
/* Get the one and only immediate use of DEFVAR. */
single_imm_use (defvar, &use_p, &temp);
gcc_assert (use_p != NULL_USE_OPERAND_P);
first_use_p = use_p;
use = USE_FROM_PTR (use_p);
/* If the immediate use of DEF_VAR is not the same as the
previously find immediate uses, then we will not be able
to eliminate STMT. */
if (use_stmt == NULL)
use_stmt = temp;
else if (temp != use_stmt)
{
fail = true;
break;
}
}
else
if (fail)
{
record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
return;
@ -231,7 +245,7 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
represents the only use of this store.
Note this does not handle the case where the store has
multiple V_MAY_DEFs which all reach a set of PHI nodes in the
multiple V_{MAY,MUST}_DEFs which all reach a set of PHI nodes in the
same block. */
while (use_p != NULL_USE_OPERAND_P
&& TREE_CODE (use_stmt) == PHI_NODE
@ -295,7 +309,7 @@ dse_record_phis (struct dom_walk_data *walk_data, basic_block bb)
tree phi;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
if (need_imm_uses_for (PHI_RESULT (phi)))
if (!is_gimple_reg (PHI_RESULT (phi)))
record_voperand_set (dse_gd->stores,
&bd->stores,
get_stmt_uid (phi));

View File

@ -291,4 +291,11 @@ typedef struct ssa_operand_iterator_d
!op_iter_done (&(ITER)); \
op_iter_next_mustdef (&(KILLVAR), &(DEFVAR), &(ITER)))
/* This macro executes a loop over the V_{MUST,MAY}_DEF of STMT. The def
and kill for each V_{MUST,MAY}_DEF is returned in DEFVAR and KILLVAR.
ITER is an ssa_op_iter structure used to control the loop. */
#define FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND(DEFVAR, KILLVAR, STMT, ITER)\
for (op_iter_init_must_and_may_def (&(ITER), STMT, &(KILLVAR), &(DEFVAR));\
!op_iter_done (&(ITER)); \
op_iter_next_must_and_may_def (&(KILLVAR), &(DEFVAR), &(ITER)))
#endif /* GCC_TREE_SSA_OPERANDS_H */