Commit db30731a by Jeff Law Committed by Jeff Law

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
parent 5635785a
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> 2005-04-26 Andrew MacLeod <amacleod@redhat.com>
* tree-cfg.c (bsi_replace): Delink immediate uses for the original stmt. * tree-cfg.c (bsi_replace): Delink immediate uses for the original stmt.
......
...@@ -1121,6 +1121,7 @@ op_iter_next_mustdef (use_operand_p *kill, def_operand_p *def, ssa_op_iter *ptr) ...@@ -1121,6 +1121,7 @@ op_iter_next_mustdef (use_operand_p *kill, def_operand_p *def, ssa_op_iter *ptr)
ptr->done = true; ptr->done = true;
return; return;
} }
/* Get the next iterator maydef value for PTR, returning the maydef values in /* Get the next iterator maydef value for PTR, returning the maydef values in
USE and DEF. */ USE and DEF. */
static inline void static inline void
...@@ -1141,6 +1142,34 @@ op_iter_next_maydef (use_operand_p *use, def_operand_p *def, ssa_op_iter *ptr) ...@@ -1141,6 +1142,34 @@ op_iter_next_maydef (use_operand_p *use, def_operand_p *def, ssa_op_iter *ptr)
return; 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 /* Initialize iterator PTR to the operands in STMT. Return the first operands
in USE and DEF. */ in USE and DEF. */
static inline void static inline void
...@@ -1151,16 +1180,6 @@ op_iter_init_maydef (ssa_op_iter *ptr, tree stmt, use_operand_p *use, ...@@ -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); 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 /* Initialize iterator PTR to the operands in STMT. Return the first operands
in KILL and DEF. */ in KILL and DEF. */
...@@ -1172,6 +1191,26 @@ op_iter_init_mustdef (ssa_op_iter *ptr, tree stmt, use_operand_p *kill, ...@@ -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); 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. */ /* Return true if REF, a COMPONENT_REF, has an ARRAY_REF somewhere in it. */
static inline bool static inline bool
......
...@@ -111,18 +111,8 @@ get_stmt_uid (tree stmt) ...@@ -111,18 +111,8 @@ get_stmt_uid (tree stmt)
return stmt_ann (stmt)->uid; 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. */ /* Set bit UID in bitmaps GLOBAL and *LOCAL, creating *LOCAL as needed. */
static void static void
record_voperand_set (bitmap global, bitmap *local, unsigned int uid) record_voperand_set (bitmap global, bitmap *local, unsigned int uid)
{ {
...@@ -136,6 +126,7 @@ 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 (*local, uid);
bitmap_set_bit (global, uid); bitmap_set_bit (global, uid);
} }
/* Initialize block local data structures. */ /* Initialize block local data structures. */
static void static void
...@@ -177,12 +168,15 @@ dse_optimize_stmt (struct dom_walk_data *walk_data, ...@@ -177,12 +168,15 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
tree stmt = bsi_stmt (bsi); tree stmt = bsi_stmt (bsi);
stmt_ann_t ann = stmt_ann (stmt); stmt_ann_t ann = stmt_ann (stmt);
v_may_def_optype v_may_defs; v_may_def_optype v_may_defs;
v_must_def_optype v_must_defs;
v_may_defs = V_MAY_DEF_OPS (ann); 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 /* If this statement has no virtual defs, then there is nothing
to do. */ 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; return;
/* We know we have virtual definitions. If this is a MODIFY_EXPR that's /* 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, ...@@ -195,33 +189,53 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
if (TREE_CODE (stmt) == MODIFY_EXPR) 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 first_use_p = NULL_USE_OPERAND_P;
use_operand_p use_p; use_operand_p use_p = NULL;
tree use, use_stmt; tree use, use_stmt, temp;
tree defvar = NULL_TREE, usevar = NULL_TREE; tree defvar = NULL_TREE, usevar = NULL_TREE;
bool fail = false;
use_operand_p var2; use_operand_p var2;
def_operand_p var1; def_operand_p var1;
ssa_op_iter op_iter; 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); defvar = DEF_FROM_PTR (var1);
usevar = USE_FROM_PTR (var2); 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) /* If this virtual def does not have precisely one use, then
{ we will not be able to eliminate STMT. */
single_imm_use (defvar, &use_p, &use_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); gcc_assert (use_p != NULL_USE_OPERAND_P);
first_use_p = use_p; first_use_p = use_p;
use = USE_FROM_PTR (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); record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
return; return;
...@@ -231,7 +245,7 @@ dse_optimize_stmt (struct dom_walk_data *walk_data, ...@@ -231,7 +245,7 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
represents the only use of this store. represents the only use of this store.
Note this does not handle the case where the store has 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. */ same block. */
while (use_p != NULL_USE_OPERAND_P while (use_p != NULL_USE_OPERAND_P
&& TREE_CODE (use_stmt) == PHI_NODE && TREE_CODE (use_stmt) == PHI_NODE
...@@ -295,7 +309,7 @@ dse_record_phis (struct dom_walk_data *walk_data, basic_block bb) ...@@ -295,7 +309,7 @@ dse_record_phis (struct dom_walk_data *walk_data, basic_block bb)
tree phi; tree phi;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (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, record_voperand_set (dse_gd->stores,
&bd->stores, &bd->stores,
get_stmt_uid (phi)); get_stmt_uid (phi));
......
...@@ -291,4 +291,11 @@ typedef struct ssa_operand_iterator_d ...@@ -291,4 +291,11 @@ typedef struct ssa_operand_iterator_d
!op_iter_done (&(ITER)); \ !op_iter_done (&(ITER)); \
op_iter_next_mustdef (&(KILLVAR), &(DEFVAR), &(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 */ #endif /* GCC_TREE_SSA_OPERANDS_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment