From fb0c974d0fe4f065e1d8d328c9c3965e9b8db553 Mon Sep 17 00:00:00 2001 From: law Date: Tue, 26 Apr 2005 17:37:33 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@98780 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 12 +++++++++ gcc/tree-flow-inline.h | 59 ++++++++++++++++++++++++++++++++++------- gcc/tree-ssa-dse.c | 70 +++++++++++++++++++++++++++++-------------------- gcc/tree-ssa-operands.h | 7 +++++ 4 files changed, 110 insertions(+), 38 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0efc2a853b9..7e9b9341ae9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2005-04-26 Jeff Law + + * 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 * tree-cfg.c (bsi_replace): Delink immediate uses for the original stmt. diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h index 9fbf4282de1..87a243daa3c 100644 --- a/gcc/tree-flow-inline.h +++ b/gcc/tree-flow-inline.h @@ -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 diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 1f376c4b964..42b61553832 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -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)); diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h index 288831900a7..2d531c8b64c 100644 --- a/gcc/tree-ssa-operands.h +++ b/gcc/tree-ssa-operands.h @@ -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 */ -- 2.11.4.GIT