Index: tree-dfa.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-dfa.c,v retrieving revision 2.4 diff -c -p -u -p -r2.4 tree-dfa.c --- tree-dfa.c 15 May 2004 23:07:51 -0000 2.4 +++ tree-dfa.c 27 May 2004 18:32:54 -0000 @@ -59,8 +59,9 @@ struct dfa_stats_d long num_phis; long num_phi_args; int max_num_phi_args; - long num_vdefs; + long num_v_may_defs; long num_vuses; + long num_v_must_defs; }; @@ -280,7 +281,7 @@ compute_immediate_uses_for_stmt (tree st size_t i; use_optype uses; vuse_optype vuses; - vdef_optype vdefs; + v_may_def_optype v_may_defs; stmt_ann_t ann; #ifdef ENABLE_CHECKING @@ -314,10 +315,10 @@ compute_immediate_uses_for_stmt (tree st add_immediate_use (imm_rdef_stmt, stmt); } - vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - tree vuse = VDEF_OP (vdefs, i); + tree vuse = V_MAY_DEF_OP (v_may_defs, i); tree imm_rdef_stmt = SSA_NAME_DEF_STMT (vuse); if (!IS_EMPTY_STMT (imm_rdef_stmt) && (!calc_for || calc_for (vuse))) add_immediate_use (imm_rdef_stmt, stmt); @@ -390,7 +391,7 @@ redirect_immediate_uses (tree old, tree stmt_ann_t ann = get_stmt_ann (old); use_optype uses = USE_OPS (ann); vuse_optype vuses = VUSE_OPS (ann); - vdef_optype vdefs = VDEF_OPS (ann); + v_may_def_optype v_may_defs = V_MAY_DEF_OPS (ann); unsigned int i; /* Look at USE_OPS or VUSE_OPS according to FLAGS. */ @@ -400,8 +401,8 @@ redirect_immediate_uses (tree old, tree for (i = 0; i < NUM_VUSES (vuses); i++) redirect_immediate_use (VUSE_OP (vuses, i), old, new); - for (i = 0; i < NUM_VDEFS (vdefs); i++) - redirect_immediate_use (VDEF_OP (vdefs, i), old, new); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) + redirect_immediate_use (V_MAY_DEF_OP (v_may_defs, i), old, new); } @@ -723,9 +724,14 @@ dump_dfa_stats (FILE *file) fprintf (file, fmt_str_1, "VUSE operands", dfa_stats.num_vuses, SCALE (size), LABEL (size)); - size = dfa_stats.num_vdefs * sizeof (tree *); + size = dfa_stats.num_v_may_defs * sizeof (tree *); total += size; - fprintf (file, fmt_str_1, "VDEF operands", dfa_stats.num_vdefs, + fprintf (file, fmt_str_1, "V_MAY_DEF operands", dfa_stats.num_v_may_defs, + SCALE (size), LABEL (size)); + + size = dfa_stats.num_v_must_defs * sizeof (tree *); + total += size; + fprintf (file, fmt_str_1, "V_MUST_DEF operands", dfa_stats.num_v_must_defs, SCALE (size), LABEL (size)); size = dfa_stats.num_phis * sizeof (struct tree_phi_node); @@ -821,8 +827,9 @@ collect_dfa_stats_r (tree *tp, int *walk dfa_stats_p->num_stmt_anns++; dfa_stats_p->num_defs += NUM_DEFS (DEF_OPS (ann)); dfa_stats_p->num_uses += NUM_USES (USE_OPS (ann)); - dfa_stats_p->num_vdefs += NUM_VDEFS (VDEF_OPS (ann)); + dfa_stats_p->num_v_may_defs += NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)); dfa_stats_p->num_vuses += NUM_VUSES (VUSE_OPS (ann)); + dfa_stats_p->num_v_must_defs += NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)); break; } @@ -1036,21 +1043,39 @@ add_referenced_tmp_var (tree var) add_referenced_var (var, NULL); } +/* Return true if V_MAY_DEFS_AFTER contains fewer entries than V_MAY_DEFS_BEFORE. + Note that this assumes that both varrays are V_MAY_DEF operands for the same + statement. */ + +static inline bool +v_may_defs_disappeared_p (v_may_def_optype v_may_defs_before, v_may_def_optype v_may_defs_after) +{ + /* If there was nothing before, nothing could've disappeared. */ + if (v_may_defs_before == NULL) + return false; + + /* All/some of them gone. */ + if (v_may_defs_after == NULL + || NUM_V_MAY_DEFS (v_may_defs_before) > NUM_V_MAY_DEFS (v_may_defs_after)) + return true; + + return false; +} -/* Return true if VDEFS_AFTER contains fewer entries than VDEFS_BEFORE. - Note that this assumes that both varrays are VDEF operands for the same +/* Return true if V_MUST_DEFS_AFTER contains fewer entries than V_MUST_DEFS_BEFORE. + Note that this assumes that both varrays are V_MUST_DEF operands for the same statement. */ static inline bool -vdefs_disappeared_p (vdef_optype vdefs_before, vdef_optype vdefs_after) +v_must_defs_disappeared_p (v_must_def_optype v_must_defs_before, v_must_def_optype v_must_defs_after) { /* If there was nothing before, nothing could've disappeared. */ - if (vdefs_before == NULL) + if (v_must_defs_before == NULL) return false; /* All/some of them gone. */ - if (vdefs_after == NULL - || NUM_VDEFS (vdefs_before) > NUM_VDEFS (vdefs_after)) + if (v_must_defs_after == NULL + || NUM_V_MUST_DEFS (v_must_defs_before) > NUM_V_MUST_DEFS (v_must_defs_after)) return true; return false; @@ -1065,12 +1090,14 @@ mark_new_vars_to_rename (tree stmt, bitm { def_optype defs; use_optype uses; - vdef_optype vdefs; + v_may_def_optype v_may_defs; vuse_optype vuses; + v_must_def_optype v_must_defs; size_t i; bitmap vars_in_vops_to_rename; bool found_exposed_symbol = false; - vdef_optype vdefs_before, vdefs_after; + v_may_def_optype v_may_defs_before, v_may_defs_after; + v_must_def_optype v_must_defs_before, v_must_defs_after; stmt_ann_t ann; vars_in_vops_to_rename = BITMAP_XMALLOC (); @@ -1085,10 +1112,10 @@ mark_new_vars_to_rename (tree stmt, bitm rename them if there are not any newly exposed symbols in the statement operands. */ ann = stmt_ann (stmt); - vdefs_before = vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + v_may_defs_before = v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - tree var = VDEF_RESULT (vdefs, i); + tree var = V_MAY_DEF_RESULT (v_may_defs, i); if (!DECL_P (var)) var = SSA_NAME_VAR (var); bitmap_set_bit (vars_in_vops_to_rename, var_ann (var)->uid); @@ -1103,6 +1130,15 @@ mark_new_vars_to_rename (tree stmt, bitm bitmap_set_bit (vars_in_vops_to_rename, var_ann (var)->uid); } + v_must_defs_before = v_must_defs = V_MUST_DEF_OPS (ann); + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) + { + tree var = V_MUST_DEF_OP (v_must_defs, i); + if (!DECL_P (var)) + var = SSA_NAME_VAR (var); + bitmap_set_bit (vars_in_vops_to_rename, var_ann (var)->uid); + } + /* Now force an operand re-scan on the statement and mark any newly exposed variables. */ modify_stmt (stmt); @@ -1130,10 +1166,10 @@ mark_new_vars_to_rename (tree stmt, bitm } } - vdefs_after = vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + v_may_defs_after = v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - tree var = VDEF_RESULT (vdefs, i); + tree var = V_MAY_DEF_RESULT (v_may_defs, i); if (DECL_P (var)) { found_exposed_symbol = true; @@ -1151,6 +1187,17 @@ mark_new_vars_to_rename (tree stmt, bitm bitmap_set_bit (vars_to_rename, var_ann (var)->uid); } } + + v_must_defs_after = v_must_defs = V_MUST_DEF_OPS (ann); + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) + { + tree var = V_MUST_DEF_OP (v_must_defs, i); + if (DECL_P (var)) + { + found_exposed_symbol = true; + bitmap_set_bit (vars_to_rename, var_ann (var)->uid); + } + } /* If we found any newly exposed symbols, or if there are fewer VDEF operands in the statement, add the variables we had set in @@ -1158,7 +1205,8 @@ mark_new_vars_to_rename (tree stmt, bitm vanishing VDEFs because in those cases, the names that were formerly generated by this statement are not going to be available anymore. */ if (found_exposed_symbol - || vdefs_disappeared_p (vdefs_before, vdefs_after)) + || v_may_defs_disappeared_p (v_may_defs_before, v_may_defs_after) + || v_must_defs_disappeared_p (v_must_defs_before, v_must_defs_after)) bitmap_a_or_b (vars_to_rename, vars_to_rename, vars_in_vops_to_rename); BITMAP_XFREE (vars_in_vops_to_rename); Index: tree-flow.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v retrieving revision 2.4 diff -c -p -u -p -r2.4 tree-flow.h --- tree-flow.h 18 May 2004 02:53:55 -0000 2.4 +++ tree-flow.h 27 May 2004 18:32:54 -0000 @@ -238,9 +238,10 @@ struct stmt_ann_d GTY(()) struct def_optype_d * GTY (()) def_ops; struct use_optype_d * GTY (()) use_ops; - /* Virtual operands (VDEF and VUSE). */ - struct vdef_optype_d * GTY (()) vdef_ops; + /* Virtual operands (V_MAY_DEF, VUSE, and V_MUST_DEF). */ + struct v_may_def_optype_d * GTY (()) v_may_def_ops; struct vuse_optype_d * GTY (()) vuse_ops; + struct v_must_def_optype_d * GTY (()) v_must_def_ops; /* Dataflow information. */ dataflow_t df; @@ -310,7 +311,7 @@ static inline int get_lineno (tree); static inline const char *get_filename (tree); static inline bool is_exec_stmt (tree); static inline bool is_label_stmt (tree); -static inline vdef_optype get_vdef_ops (stmt_ann_t); +static inline v_may_def_optype get_v_may_def_ops (stmt_ann_t); static inline vuse_optype get_vuse_ops (stmt_ann_t); static inline use_optype get_use_ops (stmt_ann_t); static inline def_optype get_def_ops (stmt_ann_t); Index: tree-flow-inline.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-flow-inline.h,v retrieving revision 2.2 diff -c -p -u -p -r2.2 tree-flow-inline.h --- tree-flow-inline.h 21 May 2004 15:24:54 -0000 2.2 +++ tree-flow-inline.h 27 May 2004 18:32:54 -0000 @@ -193,10 +193,10 @@ get_use_ops (stmt_ann_t ann) return ann ? ann->use_ops : NULL; } -static inline vdef_optype -get_vdef_ops (stmt_ann_t ann) +static inline v_may_def_optype +get_v_may_def_ops (stmt_ann_t ann) { - return ann ? ann->vdef_ops : NULL; + return ann ? ann->v_may_def_ops : NULL; } static inline vuse_optype @@ -205,6 +205,12 @@ get_vuse_ops (stmt_ann_t ann) return ann ? ann->vuse_ops : NULL; } +static inline v_must_def_optype +get_v_must_def_ops (stmt_ann_t ann) +{ + return ann ? ann->v_must_def_ops : NULL; +} + static inline tree * get_use_op_ptr (use_optype uses, unsigned int index) { @@ -226,23 +232,23 @@ get_def_op_ptr (def_optype defs, unsigne } static inline tree * -get_vdef_result_ptr(vdef_optype vdefs, unsigned int index) +get_v_may_def_result_ptr(v_may_def_optype v_may_defs, unsigned int index) { #ifdef ENABLE_CHECKING - if (index >= vdefs->num_vdefs) + if (index >= v_may_defs->num_v_may_defs) abort(); #endif - return &(vdefs->vdefs[index * 2]); + return &(v_may_defs->v_may_defs[index * 2]); } static inline tree * -get_vdef_op_ptr(vdef_optype vdefs, unsigned int index) +get_v_may_def_op_ptr(v_may_def_optype v_may_defs, unsigned int index) { #ifdef ENABLE_CHECKING - if (index >= vdefs->num_vdefs) + if (index >= v_may_defs->num_v_may_defs) abort(); #endif - return &(vdefs->vdefs[index * 2 + 1]); + return &(v_may_defs->v_may_defs[index * 2 + 1]); } static inline tree * @@ -255,6 +261,16 @@ get_vuse_op_ptr(vuse_optype vuses, unsig return &(vuses->vuses[index]); } +static inline tree * +get_v_must_def_op_ptr (v_must_def_optype v_must_defs, unsigned int index) +{ +#ifdef ENABLE_CHECKING + if (index >= v_must_defs->num_v_must_defs) + abort(); +#endif + return &(v_must_defs->v_must_defs[index]); +} + static inline void start_ssa_stmt_operands (tree stmt ATTRIBUTE_UNUSED) { Index: tree-into-ssa.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-into-ssa.c,v retrieving revision 2.7 diff -c -p -u -p -r2.7 tree-into-ssa.c --- tree-into-ssa.c 19 May 2004 20:44:32 -0000 2.7 +++ tree-into-ssa.c 27 May 2004 18:32:54 -0000 @@ -211,7 +211,8 @@ mark_def_sites (struct dom_walk_data *wa { struct mark_def_sites_global_data *gd = walk_data->global_data; sbitmap kills = gd->kills; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; vuse_optype vuses; def_optype defs; use_optype uses; @@ -248,22 +249,35 @@ mark_def_sites (struct dom_walk_data *wa } /* Note that virtual definitions are irrelevant for computing KILLS - because a VDEF does not constitute a killing definition of the + because a V_MAY_DEF does not constitute a killing definition of the variable. However, the operand of a virtual definitions is a use of the variable, so it may cause the variable to be considered live-on-entry. */ - vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - if (prepare_operand_for_rename (VDEF_OP_PTR (vdefs, i), &uid, true)) + if (prepare_operand_for_rename (V_MAY_DEF_OP_PTR (v_may_defs, i), &uid, true)) { /* If we do not already have an SSA_NAME for our destination, then set the destination to the source. */ - if (TREE_CODE (VDEF_RESULT (vdefs, i)) != SSA_NAME) - VDEF_RESULT (vdefs, i) = VDEF_OP (vdefs, i); + if (TREE_CODE (V_MAY_DEF_RESULT (v_may_defs, i)) != SSA_NAME) + V_MAY_DEF_RESULT (v_may_defs, i) = V_MAY_DEF_OP (v_may_defs, i); + + set_livein_block (V_MAY_DEF_OP (v_may_defs, i), bb); + set_def_block (V_MAY_DEF_RESULT (v_may_defs, i), bb); + } + } + + /* Now process the virtual must-defs made by this statement. */ + v_must_defs = V_MUST_DEF_OPS (ann); + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) + { + tree *def_p = V_MUST_DEF_OP_PTR (v_must_defs, i); - set_livein_block (VDEF_OP (vdefs, i), bb); - set_def_block (VDEF_RESULT (vdefs, i), bb); + if (prepare_operand_for_rename (def_p, &uid, false)) + { + set_def_block (*def_p, bb); + SET_BIT (kills, uid); } } @@ -717,7 +731,8 @@ rewrite_stmt (struct dom_walk_data *walk stmt_ann_t ann; tree stmt; vuse_optype vuses; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; def_optype defs; use_optype uses; struct rewrite_block_data *bd; @@ -744,7 +759,8 @@ rewrite_stmt (struct dom_walk_data *walk defs = DEF_OPS (ann); uses = USE_OPS (ann); vuses = VUSE_OPS (ann); - vdefs = VDEF_OPS (ann); + v_may_defs = V_MAY_DEF_OPS (ann); + v_must_defs = V_MUST_DEF_OPS (ann); /* Step 1. Rewrite USES and VUSES in the statement. */ for (i = 0; i < NUM_USES (uses); i++) @@ -768,18 +784,32 @@ rewrite_stmt (struct dom_walk_data *walk } /* Register new virtual definitions made by the statement. */ - for (i = 0; i < NUM_VDEFS (vdefs); i++) + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - rewrite_operand (VDEF_OP_PTR (vdefs, i)); + rewrite_operand (V_MAY_DEF_OP_PTR (v_may_defs, i)); - if (TREE_CODE (VDEF_RESULT (vdefs, i)) != SSA_NAME) - *VDEF_RESULT_PTR (vdefs, i) - = make_ssa_name (VDEF_RESULT (vdefs, i), stmt); + if (TREE_CODE (V_MAY_DEF_RESULT (v_may_defs, i)) != SSA_NAME) + *V_MAY_DEF_RESULT_PTR (v_may_defs, i) + = make_ssa_name (V_MAY_DEF_RESULT (v_may_defs, i), stmt); /* FIXME: We shouldn't be registering new defs if the variable doesn't need to be renamed. */ - register_new_def (VDEF_RESULT (vdefs, i), &bd->block_defs); + register_new_def (V_MAY_DEF_RESULT (v_may_defs, i), &bd->block_defs); + } + + /* Register new virtual mustdefs made by the statement. */ + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) + { + tree *v_must_def_p = V_MUST_DEF_OP_PTR (v_must_defs, i); + + if (TREE_CODE (*v_must_def_p) != SSA_NAME) + *v_must_def_p = make_ssa_name (*v_must_def_p, stmt); + + /* FIXME: We shouldn't be registering new mustdefs if the variable + doesn't need to be renamed. */ + register_new_def (*v_must_def_p, &bd->block_defs); } + } Index: tree-outof-ssa.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-outof-ssa.c,v retrieving revision 2.3 diff -c -p -u -p -r2.3 tree-outof-ssa.c --- tree-outof-ssa.c 14 May 2004 02:29:22 -0000 2.3 +++ tree-outof-ssa.c 27 May 2004 18:32:54 -0000 @@ -1134,7 +1134,7 @@ coalesce_vars (var_map map, tree_live_in dependent on any virtual variable (via a VUSE) has a dependence added to the special partition defined by VIRTUAL_PARTITION. - Whenever a VDEF is seen, all expressions dependent this VIRTUAL_PARTITION + Whenever a V_MAY_DEF is seen, all expressions dependent this VIRTUAL_PARTITION are removed from consideration. At the end of a basic block, all expression are removed from consideration @@ -1171,7 +1171,7 @@ typedef struct temp_expr_table_d value_expr_p pending_dependence; } *temp_expr_table_p; -/* Used to indicate a dependancy on VDEFs. */ +/* Used to indicate a dependancy on V_MAY_DEFs. */ #define VIRTUAL_PARTITION(table) (table->virtual_partition) static temp_expr_table_p new_temp_expr_table (var_map); @@ -1437,8 +1437,12 @@ check_replaceable (temp_expr_table_p tab if (DECL_HARD_REGISTER (SSA_NAME_VAR (def))) return false; - /* There must be no VDEFS. */ - if (NUM_VDEFS (VDEF_OPS (ann)) != 0) + /* There must be no V_MAY_DEFS. */ + if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) != 0) + return false; + + /* There must be no V_MUST_DEFS. */ + if (NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) != 0) return false; /* Float expressions must go through memory if float-store is on. */ @@ -1646,8 +1650,12 @@ find_replaceable_in_bb (temp_expr_table_ free_value_expr (tab, p); } - /* A VDEF kills any expression using a virtual operand. */ - if (NUM_VDEFS (VDEF_OPS (ann)) > 0) + /* A V_MAY_DEF kills any expression using a virtual operand. */ + if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) > 0) + kill_virtual_exprs (tab, true); + + /* A V_MUST_DEF kills any expression using a virtual operand. */ + if (NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) > 0) kill_virtual_exprs (tab, true); } } Index: tree-pretty-print.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-pretty-print.c,v retrieving revision 2.2 diff -c -p -u -p -r2.2 tree-pretty-print.c --- tree-pretty-print.c 15 May 2004 23:07:52 -0000 2.2 +++ tree-pretty-print.c 27 May 2004 18:32:54 -0000 @@ -2045,15 +2045,25 @@ dump_vops (pretty_printer *buffer, tree { size_t i; stmt_ann_t ann = stmt_ann (stmt); - vdef_optype vdefs = VDEF_OPS (ann); + v_may_def_optype v_may_defs = V_MAY_DEF_OPS (ann); + v_must_def_optype v_must_defs = V_MUST_DEF_OPS (ann); vuse_optype vuses = VUSE_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { pp_string (buffer, "# "); - dump_generic_node (buffer, VDEF_RESULT (vdefs, i), spc + 2, flags, false); - pp_string (buffer, " = VDEF <"); - dump_generic_node (buffer, VDEF_OP (vdefs, i), spc + 2, flags, false); + dump_generic_node (buffer, V_MAY_DEF_RESULT (v_may_defs, i), spc + 2, flags, false); + pp_string (buffer, " = V_MAY_DEF <"); + dump_generic_node (buffer, V_MAY_DEF_OP (v_may_defs, i), spc + 2, flags, false); + pp_string (buffer, ">;"); + newline_and_indent (buffer, spc); + } + + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) + { + tree v_must_def = V_MUST_DEF_OP (v_must_defs, i); + pp_string (buffer, "# V_MUST_DEF <"); + dump_generic_node (buffer, v_must_def, spc + 2, flags, false); pp_string (buffer, ">;"); newline_and_indent (buffer, spc); } Index: tree-sra.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-sra.c,v retrieving revision 2.3 diff -c -p -u -p -r2.3 tree-sra.c --- tree-sra.c 14 May 2004 15:27:36 -0000 2.3 +++ tree-sra.c 27 May 2004 18:32:54 -0000 @@ -112,22 +112,42 @@ sra_elt_eq (const void *x, const void *y return true; } -/* Mark all the variables in VDEF operands for STMT for renaming. +/* Mark all the variables in V_MAY_DEF operands for STMT for renaming. This becomes necessary when we modify all of a non-scalar. */ static void -mark_all_vdefs (tree stmt) +mark_all_v_may_defs (tree stmt) { - vdef_optype vdefs; + v_may_def_optype v_may_defs; size_t i, n; get_stmt_operands (stmt); - vdefs = VDEF_OPS (stmt_ann (stmt)); - n = NUM_VDEFS (vdefs); + v_may_defs = V_MAY_DEF_OPS (stmt_ann (stmt)); + n = NUM_V_MAY_DEFS (v_may_defs); for (i = 0; i < n; i++) { - tree sym = VDEF_RESULT (vdefs, i); + tree sym = V_MAY_DEF_RESULT (v_may_defs, i); + bitmap_set_bit (vars_to_rename, var_ann (sym)->uid); + } +} + +/* Mark all the variables in V_MUST_DEF operands for STMT for renaming. + This becomes necessary when we modify all of a non-scalar. */ + +static void +mark_all_v_must_defs (tree stmt) +{ + v_must_def_optype v_must_defs; + size_t i, n; + + get_stmt_operands (stmt); + v_must_defs = V_MUST_DEF_OPS (stmt_ann (stmt)); + n = NUM_V_MUST_DEFS (v_must_defs); + + for (i = 0; i < n; i++) + { + tree sym = V_MUST_DEF_OP (v_must_defs, i); bitmap_set_bit (vars_to_rename, var_ann (sym)->uid); } } @@ -685,7 +705,8 @@ create_scalar_copies (tree lhs, tree rhs /* Mark all the variables in VDEF operands for renaming, because the VA_ARG_EXPR will now be in a different statement. */ - mark_all_vdefs (stmt); + mark_all_v_may_defs (stmt); + mark_all_v_must_defs (stmt); /* Set RHS to be the new temporary TMP. */ rhs = tmp; @@ -784,7 +805,8 @@ create_scalar_copies (tree lhs, tree rhs /* Otherwise, mark all the symbols in the VDEFs for the last scalarized statement just created. Since all the statements introduce the same VDEFs, we only need to check the last one. */ - mark_all_vdefs (tsi_stmt (tsi)); + mark_all_v_may_defs (tsi_stmt (tsi)); + mark_all_v_must_defs (tsi_stmt (tsi)); } else abort (); @@ -830,8 +852,9 @@ scalarize_structures (void) /* If the statement has no virtual operands, then it doesn't make structure references that we care about. */ - if (NUM_VDEFS (VDEF_OPS (ann)) == 0 - && NUM_VUSES (VUSE_OPS (ann)) == 0) + if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) == 0 + && NUM_VUSES (VUSE_OPS (ann)) == 0 + && NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) == 0) continue; /* Structure references may only appear in certain statements. */ @@ -899,17 +922,17 @@ scalarize_modify_expr (block_stmt_iterat if (is_sra_candidate_ref (lhs, false)) { tree sym; - vdef_optype vdefs; + v_may_def_optype v_may_defs; scalarize_component_ref (stmt, &TREE_OPERAND (stmt, 0)); /* Mark the LHS to be renamed, as we have just removed the previous - VDEF for AGGREGATE. The statement should have exactly one VDEF + V_MAY_DEF for AGGREGATE. The statement should have exactly one V_MAY_DEF for variable AGGREGATE. */ - vdefs = STMT_VDEF_OPS (stmt); - if (NUM_VDEFS (vdefs) != 1) + v_may_defs = STMT_V_MAY_DEF_OPS (stmt); + if (NUM_V_MAY_DEFS (v_may_defs) != 1) abort (); - sym = SSA_NAME_VAR (VDEF_RESULT (vdefs, 0)); + sym = SSA_NAME_VAR (V_MAY_DEF_RESULT (v_may_defs, 0)); bitmap_set_bit (vars_to_rename, var_ann (sym)->uid); } Index: tree-ssa-alias.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-alias.c,v retrieving revision 2.4 diff -c -p -u -p -r2.4 tree-ssa-alias.c --- tree-ssa-alias.c 15 May 2004 23:07:52 -0000 2.4 +++ tree-ssa-alias.c 27 May 2004 18:32:54 -0000 @@ -173,7 +173,7 @@ bool aliases_computed_p; this variable is used to represent the clobbering effects of function calls. In these cases, all the call clobbered variables in the program are forced to alias this variable. This reduces compile times by not - having to keep track of too many VDEF expressions at call sites. */ + having to keep track of too many V_MAY_DEF expressions at call sites. */ tree global_var; @@ -263,11 +263,11 @@ tree global_var; p_6 = &b; # p_1 = PHI ; - # a_7 = VDEF ; - # b_8 = VDEF ; + # a_7 = V_MAY_DEF ; + # b_8 = V_MAY_DEF ; *p_1 = 3; - # a_9 = VDEF + # a_9 = V_MAY_DEF # VUSE a_9 = b_8 + 2; @@ -535,7 +535,8 @@ compute_points_to_and_addr_escape (struc { use_optype uses; def_optype defs; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; stmt_ann_t ann; bitmap addr_taken; tree stmt = bsi_stmt (si); @@ -656,11 +657,21 @@ compute_points_to_and_addr_escape (struc (VARRAY_UINT (ai->num_references, ann->uid))++; } - /* Mark variables in VDEF operands as being written to. */ - vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + /* Mark variables in V_MAY_DEF operands as being written to. */ + v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - tree op = VDEF_OP (vdefs, i); + tree op = V_MAY_DEF_OP (v_may_defs, i); + tree var = SSA_NAME_VAR (op); + var_ann_t ann = var_ann (var); + bitmap_set_bit (ai->written_vars, ann->uid); + } + + /* Mark variables in V_MUST_DEF operands as being written to. */ + v_must_defs = V_MUST_DEF_OPS (ann); + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) + { + tree op = V_MUST_DEF_OP (v_must_defs, i); tree var = SSA_NAME_VAR (op); var_ann_t ann = var_ann (var); bitmap_set_bit (ai->written_vars, ann->uid); @@ -1036,7 +1047,7 @@ group_aliases (struct alias_info *ai) p_5 = &a; ... - # a_9 = VDEF + # a_9 = V_MAY_DEF p_5->field = 0 ... Several modifications to TMT.20 ... # VUSE @@ -1270,7 +1281,7 @@ setup_pointers_and_addressables (struct /* Determine whether to use .GLOBAL_VAR to model call clobbering semantics. At - every call site, we need to emit VDEF expressions to represent the + every call site, we need to emit V_MAY_DEF expressions to represent the clobbering effects of the call for variables whose address escapes the current function. @@ -1279,9 +1290,9 @@ setup_pointers_and_addressables (struct (.GLOBAL_VAR). This works well, but it ties the optimizer hands because references to any call clobbered variable is a reference to .GLOBAL_VAR. - The second approach is to emit a clobbering VDEF for every call-clobbered + The second approach is to emit a clobbering V_MAY_DEF for every call-clobbered variable at call sites. This is the preferred way in terms of optimization - opportunities but it may create too many VDEF operands if there are many + opportunities but it may create too many V_MAY_DEF operands if there are many call clobbered variables and function calls in the function. To decide whether or not to use .GLOBAL_VAR we multiply the number of Index: tree-ssa.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa.c,v retrieving revision 2.3 diff -c -p -u -p -r2.3 tree-ssa.c --- tree-ssa.c 14 May 2004 02:29:23 -0000 2.3 +++ tree-ssa.c 27 May 2004 18:32:54 -0000 @@ -314,17 +314,18 @@ verify_ssa (void) tree stmt; stmt_ann_t ann; unsigned int j; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; def_optype defs; stmt = bsi_stmt (bsi); ann = stmt_ann (stmt); get_stmt_operands (stmt); - vdefs = VDEF_OPS (ann); - for (j = 0; j < NUM_VDEFS (vdefs); j++) + v_may_defs = V_MAY_DEF_OPS (ann); + for (j = 0; j < NUM_V_MAY_DEFS (v_may_defs); j++) { - tree op = VDEF_RESULT (vdefs, j); + tree op = V_MAY_DEF_RESULT (v_may_defs, j); if (is_gimple_reg (op)) { error ("Found a virtual definition for a GIMPLE register"); @@ -334,6 +335,20 @@ verify_ssa (void) } err |= verify_def (bb, definition_block, op, stmt); } + + v_must_defs = STMT_V_MUST_DEF_OPS (stmt); + for (j = 0; j < NUM_V_MUST_DEFS (v_must_defs); j++) + { + tree op = V_MUST_DEF_OP (v_must_defs, j); + if (is_gimple_reg (op)) + { + error ("Found a virtual must-def for a GIMPLE register"); + debug_generic_stmt (op); + debug_generic_stmt (stmt); + err = true; + } + err |= verify_def (bb, definition_block, op, stmt); + } defs = DEF_OPS (ann); for (j = 0; j < NUM_DEFS (defs); j++) @@ -377,14 +392,14 @@ verify_ssa (void) /* Now verify all the uses and vuses in every statement of the block. - Remember, the RHS of a VDEF is a use as well. */ + Remember, the RHS of a V_MAY_DEF is a use as well. */ for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) { tree stmt = bsi_stmt (bsi); stmt_ann_t ann = stmt_ann (stmt); unsigned int j; vuse_optype vuses; - vdef_optype vdefs; + v_may_def_optype v_may_defs; use_optype uses; vuses = VUSE_OPS (ann); @@ -403,10 +418,10 @@ verify_ssa (void) op, stmt, false); } - vdefs = VDEF_OPS (ann); - for (j = 0; j < NUM_VDEFS (vdefs); j++) + v_may_defs = V_MAY_DEF_OPS (ann); + for (j = 0; j < NUM_V_MAY_DEFS (v_may_defs); j++) { - tree op = VDEF_OP (vdefs, j); + tree op = V_MAY_DEF_OP (v_may_defs, j); if (is_gimple_reg (op)) { @@ -695,7 +710,7 @@ replace_immediate_uses (tree var, tree r { use_optype uses; vuse_optype vuses; - vdef_optype vdefs; + v_may_def_optype v_may_defs; int i, j, n; dataflow_t df; tree stmt; @@ -738,10 +753,10 @@ replace_immediate_uses (tree var, tree r if (VUSE_OP (vuses, j) == var) propagate_value (VUSE_OP_PTR (vuses, j), repl); - vdefs = VDEF_OPS (ann); - for (j = 0; j < (int) NUM_VDEFS (vdefs); j++) - if (VDEF_OP (vdefs, j) == var) - propagate_value (VDEF_OP_PTR (vdefs, j), repl); + v_may_defs = V_MAY_DEF_OPS (ann); + for (j = 0; j < (int) NUM_V_MAY_DEFS (v_may_defs); j++) + if (V_MAY_DEF_OP (v_may_defs, j) == var) + propagate_value (V_MAY_DEF_OP_PTR (v_may_defs, j), repl); } modify_stmt (stmt); Index: tree-ssa-ccp.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-ccp.c,v retrieving revision 2.2 diff -c -p -u -p -r2.2 tree-ssa-ccp.c --- tree-ssa-ccp.c 14 May 2004 02:29:23 -0000 2.2 +++ tree-ssa-ccp.c 27 May 2004 18:32:54 -0000 @@ -575,7 +575,8 @@ visit_stmt (tree stmt) size_t i; stmt_ann_t ann; def_optype defs; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; /* If the statement has already been deemed to be VARYING, don't simulate it again. */ @@ -634,10 +635,15 @@ visit_stmt (tree stmt) add_outgoing_control_edges (bb_for_stmt (stmt)); } - /* Mark all VDEF operands VARYING. */ - vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) - def_to_varying (VDEF_RESULT (vdefs, i)); + /* Mark all V_MAY_DEF operands VARYING. */ + v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) + def_to_varying (V_MAY_DEF_RESULT (v_may_defs, i)); + + /* Mark all V_MUST_DEF operands VARYING. */ + v_must_defs = V_MUST_DEF_OPS (ann); + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) + def_to_varying (V_MUST_DEF_OP (v_must_defs, i)); } @@ -1093,7 +1099,8 @@ initialize (void) tree stmt; stmt_ann_t ann; def_optype defs; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; size_t x; int vary; @@ -1113,14 +1120,23 @@ initialize (void) } DONT_SIMULATE_AGAIN (stmt) = vary; - /* Mark all VDEF operands VARYING. */ - vdefs = VDEF_OPS (ann); - for (x = 0; x < NUM_VDEFS (vdefs); x++) + /* Mark all V_MAY_DEF operands VARYING. */ + v_may_defs = V_MAY_DEF_OPS (ann); + for (x = 0; x < NUM_V_MAY_DEFS (v_may_defs); x++) { - tree res = VDEF_RESULT (vdefs, x); + tree res = V_MAY_DEF_RESULT (v_may_defs, x); get_value (res)->lattice_val = VARYING; SET_BIT (virtual_var, SSA_NAME_VERSION (res)); } + + /* Mark all V_MUST_DEF operands VARYING. */ + v_must_defs = V_MUST_DEF_OPS (ann); + for (x = 0; x < NUM_V_MUST_DEFS (v_must_defs); x++) + { + tree v_must_def = V_MUST_DEF_OP (v_must_defs, x); + get_value (v_must_def)->lattice_val = VARYING; + SET_BIT (virtual_var, SSA_NAME_VERSION (v_must_def)); + } } for (e = bb->succ; e; e = e->succ_next) @@ -2024,7 +2040,8 @@ set_rhs (tree *stmt_p, tree expr) if (TREE_SIDE_EFFECTS (expr)) { def_optype defs; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; size_t i; /* Fix all the SSA_NAMEs created by *STMT_P to point to its new @@ -2037,10 +2054,18 @@ set_rhs (tree *stmt_p, tree expr) SSA_NAME_DEF_STMT (var) = *stmt_p; } - vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) + { + tree var = V_MAY_DEF_RESULT (v_may_defs, i); + if (TREE_CODE (var) == SSA_NAME) + SSA_NAME_DEF_STMT (var) = *stmt_p; + } + + v_must_defs = V_MUST_DEF_OPS (ann); + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) { - tree var = VDEF_RESULT (vdefs, i); + tree var = V_MUST_DEF_OP (v_must_defs, i); if (TREE_CODE (var) == SSA_NAME) SSA_NAME_DEF_STMT (var) = *stmt_p; } Index: tree-ssa-copy.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-copy.c,v retrieving revision 2.2 diff -c -p -u -p -r2.2 tree-ssa-copy.c --- tree-ssa-copy.c 18 May 2004 02:55:41 -0000 2.2 +++ tree-ssa-copy.c 27 May 2004 18:32:54 -0000 @@ -225,16 +225,16 @@ cprop_operand (stmt_ann_t ann, tree *op_ known value for that SSA_NAME (or NULL if no value is known). Propagate values from CONST_AND_COPIES into the uses, vuses and - vdef_ops of STMT. */ + v_may_def_ops of STMT. */ bool cprop_into_stmt (tree stmt, varray_type const_and_copies) { bool may_have_exposed_new_symbols = false; stmt_ann_t ann = stmt_ann (stmt); - size_t i, num_uses, num_vuses, num_vdefs; + size_t i, num_uses, num_vuses, num_v_may_defs; vuse_optype vuses; - vdef_optype vdefs; + v_may_def_optype v_may_defs; use_optype uses; uses = USE_OPS (ann); @@ -257,11 +257,11 @@ cprop_into_stmt (tree stmt, varray_type |= cprop_operand (ann, op_p, const_and_copies); } - vdefs = VDEF_OPS (ann); - num_vdefs = NUM_VDEFS (vdefs); - for (i = 0; i < num_vdefs; i++) + v_may_defs = V_MAY_DEF_OPS (ann); + num_v_may_defs = NUM_V_MAY_DEFS (v_may_defs); + for (i = 0; i < num_v_may_defs; i++) { - tree *op_p = VDEF_OP_PTR (vdefs, i); + tree *op_p = V_MAY_DEF_OP_PTR (v_may_defs, i); if (TREE_CODE (*op_p) == SSA_NAME) may_have_exposed_new_symbols |= cprop_operand (ann, op_p, const_and_copies); Index: tree-ssa-dce.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-dce.c,v retrieving revision 2.3 diff -c -p -u -p -r2.3 tree-ssa-dce.c --- tree-ssa-dce.c 14 May 2004 02:29:23 -0000 2.3 +++ tree-ssa-dce.c 27 May 2004 18:32:54 -0000 @@ -286,7 +286,8 @@ static void mark_stmt_if_obviously_necessary (tree stmt, bool aggressive) { def_optype defs; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; stmt_ann_t ann; size_t i; @@ -387,11 +388,22 @@ mark_stmt_if_obviously_necessary (tree s } } - vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - tree vdef = VDEF_RESULT (vdefs, i); - if (need_to_preserve_store (vdef)) + tree v_may_def = V_MAY_DEF_RESULT (v_may_defs, i); + if (need_to_preserve_store (v_may_def)) + { + mark_stmt_necessary (stmt, true); + return; + } + } + + v_must_defs = V_MUST_DEF_OPS (ann); + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) + { + tree v_must_def = V_MUST_DEF_OP (v_must_defs, i); + if (need_to_preserve_store (v_must_def)) { mark_stmt_necessary (stmt, true); return; @@ -558,10 +570,10 @@ propagate_necessity (struct edge_list *e else { /* Propagate through the operands. Examine all the USE, VUSE and - VDEF operands in this statement. Mark all the statements which + V_MAY_DEF operands in this statement. Mark all the statements which feed this statement's uses as necessary. */ vuse_optype vuses; - vdef_optype vdefs; + v_may_def_optype v_may_defs; use_optype uses; stmt_ann_t ann; size_t k; @@ -577,12 +589,12 @@ propagate_necessity (struct edge_list *e for (k = 0; k < NUM_VUSES (vuses); k++) mark_operand_necessary (VUSE_OP (vuses, k)); - /* The operands of VDEF expressions are also needed as they + /* The operands of V_MAY_DEF expressions are also needed as they represent potential definitions that may reach this - statement (VDEF operands allow us to follow def-def links). */ - vdefs = VDEF_OPS (ann); - for (k = 0; k < NUM_VDEFS (vdefs); k++) - mark_operand_necessary (VDEF_OP (vdefs, k)); + statement (V_MAY_DEF operands allow us to follow def-def links). */ + v_may_defs = V_MAY_DEF_OPS (ann); + for (k = 0; k < NUM_V_MAY_DEFS (v_may_defs); k++) + mark_operand_necessary (V_MAY_DEF_OP (v_may_defs, k)); } } } Index: tree-ssa-dom.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-dom.c,v retrieving revision 2.5 diff -c -p -u -p -r2.5 tree-ssa-dom.c --- tree-ssa-dom.c 18 May 2004 02:53:55 -0000 2.5 +++ tree-ssa-dom.c 27 May 2004 18:32:54 -0000 @@ -347,7 +347,8 @@ redirect_edges_and_update_ssa_graph (var { unsigned int j; def_optype defs; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; tree stmt = bsi_stmt (bsi); stmt_ann_t ann = stmt_ann (stmt); @@ -363,11 +364,18 @@ redirect_edges_and_update_ssa_graph (var bitmap_set_bit (vars_to_rename, var_ann (op)->uid); } - vdefs = VDEF_OPS (ann); - for (j = 0; j < NUM_VDEFS (vdefs); j++) + v_may_defs = STMT_V_MAY_DEF_OPS (stmt); + for (j = 0; j < NUM_V_MAY_DEFS (v_may_defs); j++) { - tree op = VDEF_RESULT (vdefs, j); - bitmap_set_bit (virtuals_to_rename, var_ann (op)->uid); + tree op = V_MAY_DEF_RESULT (v_may_defs, j); + bitmap_set_bit (vars_to_rename, var_ann (op)->uid); + } + + v_must_defs = STMT_V_MUST_DEF_OPS (stmt); + for (j = 0; j < NUM_V_MUST_DEFS (v_must_defs); j++) + { + tree op = V_MUST_DEF_OP (v_must_defs, j); + bitmap_set_bit (vars_to_rename, var_ann (op)->uid); } } @@ -2285,7 +2293,7 @@ static bool eliminate_redundant_computations (struct dom_walk_data *walk_data, tree stmt, stmt_ann_t ann) { - vdef_optype vdefs = VDEF_OPS (ann); + v_may_def_optype v_may_defs = V_MAY_DEF_OPS (ann); tree *expr_p, def = NULL_TREE; bool insert = true; tree cached_lhs; @@ -2302,7 +2310,7 @@ eliminate_redundant_computations (struct || ! def || TREE_CODE (def) != SSA_NAME || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def) - || NUM_VDEFS (vdefs) != 0) + || NUM_V_MAY_DEFS (v_may_defs) != 0) insert = false; /* Check if the expression has been computed before. */ @@ -2507,7 +2515,8 @@ record_equivalences_from_stmt (tree stmt if (rhs) { - vdef_optype vdefs = VDEF_OPS (ann); + v_may_def_optype v_may_defs = V_MAY_DEF_OPS (ann); + v_must_def_optype v_must_defs = V_MUST_DEF_OPS (ann); /* Build a new statement with the RHS and LHS exchanged. */ new = build (MODIFY_EXPR, TREE_TYPE (stmt), rhs, lhs); @@ -2519,14 +2528,21 @@ record_equivalences_from_stmt (tree stmt /* Clear out the virtual operands on the new statement, we are going to set them explicitly below. */ remove_vuses (new); - remove_vdefs (new); + remove_v_may_defs (new); + remove_v_must_defs (new); start_ssa_stmt_operands (new); /* For each VDEF on the original statement, we want to create a - VUSE of the VDEF result on the new statement. */ - for (j = 0; j < NUM_VDEFS (vdefs); j++) + VUSE of the V_MAY_DEF result or V_MUST_DEF op on the new statement. */ + for (j = 0; j < NUM_V_MAY_DEFS (v_may_defs); j++) { - tree op = VDEF_RESULT (vdefs, j); + tree op = V_MAY_DEF_RESULT (v_may_defs, j); + add_vuse (op, new); + } + + for (j = 0; j < NUM_V_MUST_DEFS (v_must_defs); j++) + { + tree op = V_MUST_DEF_OP (v_must_defs, j); add_vuse (op, new); } @@ -2561,7 +2577,6 @@ optimize_stmt (struct dom_walk_data *wal { stmt_ann_t ann; tree stmt; - vdef_optype vdefs; bool may_optimize_p; bool may_have_exposed_new_symbols = false; struct dom_walk_block_data *bd @@ -2571,7 +2586,6 @@ optimize_stmt (struct dom_walk_data *wal get_stmt_operands (stmt); ann = stmt_ann (stmt); - vdefs = VDEF_OPS (ann); opt_stats.num_stmts++; may_have_exposed_new_symbols = false; @@ -2581,7 +2595,7 @@ optimize_stmt (struct dom_walk_data *wal print_generic_stmt (dump_file, stmt, TDF_SLIM); } - /* Const/copy propagate into USES, VUSES and the RHS of VDEFs. */ + /* Const/copy propagate into USES, VUSES and the RHS of V_MAY_DEFs. */ may_have_exposed_new_symbols = cprop_into_stmt (stmt, const_and_copies); /* If the statement has been modified with constant replacements, @@ -3167,7 +3181,8 @@ static void register_definitions_for_stmt (stmt_ann_t ann, varray_type *block_defs_p) { def_optype defs; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; unsigned int i; defs = DEF_OPS (ann); @@ -3181,12 +3196,21 @@ register_definitions_for_stmt (stmt_ann_ } /* Register new virtual definitions made by the statement. */ - vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) + { + /* FIXME: We shouldn't be registering new defs if the variable + doesn't need to be renamed. */ + register_new_def (V_MAY_DEF_RESULT (v_may_defs, i), block_defs_p); + } + + /* Register new virtual mustdefs made by the statement. */ + v_must_defs = V_MUST_DEF_OPS (ann); + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) { /* FIXME: We shouldn't be registering new defs if the variable doesn't need to be renamed. */ - register_new_def (VDEF_RESULT (vdefs, i), block_defs_p); + register_new_def (V_MUST_DEF_OP (v_must_defs, i), block_defs_p); } } Index: tree-ssa-dse.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-dse.c,v retrieving revision 2.1 diff -c -p -u -p -r2.1 tree-ssa-dse.c --- tree-ssa-dse.c 13 May 2004 06:39:49 -0000 2.1 +++ tree-ssa-dse.c 27 May 2004 18:32:55 -0000 @@ -95,7 +95,7 @@ static void dse_optimize_stmt (struct do static void dse_record_phis (struct dom_walk_data *, basic_block); static void dse_finalize_block (struct dom_walk_data *, basic_block); static void fix_phi_uses (tree, tree); -static void fix_stmt_vdefs (tree, tree); +static void fix_stmt_v_may_defs (tree, tree); static void record_voperand_set (bitmap, bitmap *, unsigned int); /* Function indicating whether we ought to include information for 'var' @@ -109,70 +109,70 @@ need_imm_uses_for (tree var) } -/* Replace uses in PHI which match VDEF_RESULTs in STMT with the - corresponding VDEF_OP in STMT. */ +/* Replace uses in PHI which match V_MAY_DEF_RESULTs in STMT with the + corresponding V_MAY_DEF_OP in STMT. */ static void fix_phi_uses (tree phi, tree stmt) { stmt_ann_t ann = stmt_ann (stmt); - vdef_optype vdefs; + v_may_def_optype v_may_defs; unsigned int i; int j; get_stmt_operands (stmt); - vdefs = VDEF_OPS (ann); + v_may_defs = V_MAY_DEF_OPS (ann); - /* Walk each VDEF in STMT. */ - for (i = 0; i < NUM_VDEFS (vdefs); i++) + /* Walk each V_MAY_DEF in STMT. */ + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - tree vdef = VDEF_RESULT (vdefs, i); + tree v_may_def = V_MAY_DEF_RESULT (v_may_defs, i); - /* Find any uses in the PHI which match VDEF and replace - them with the appropriate VDEF_OP. */ + /* Find any uses in the PHI which match V_MAY_DEF and replace + them with the appropriate V_MAY_DEF_OP. */ for (j = 0; j < PHI_NUM_ARGS (phi); j++) - if (vdef == PHI_ARG_DEF (phi, j)) - PHI_ARG_DEF (phi, j) = VDEF_OP (vdefs, i); + if (v_may_def == PHI_ARG_DEF (phi, j)) + PHI_ARG_DEF (phi, j) = V_MAY_DEF_OP (v_may_defs, i); } } -/* Replace the VDEF_OPs in STMT1 which match VDEF_RESULTs in STMT2 with - the appropriate VDEF_OPs from STMT2. */ +/* Replace the V_MAY_DEF_OPs in STMT1 which match V_MAY_DEF_RESULTs in STMT2 with + the appropriate V_MAY_DEF_OPs from STMT2. */ static void -fix_stmt_vdefs (tree stmt1, tree stmt2) +fix_stmt_v_may_defs (tree stmt1, tree stmt2) { stmt_ann_t ann1 = stmt_ann (stmt1); stmt_ann_t ann2 = stmt_ann (stmt2); - vdef_optype vdefs1; - vdef_optype vdefs2; + v_may_def_optype v_may_defs1; + v_may_def_optype v_may_defs2; unsigned int i, j; get_stmt_operands (stmt1); get_stmt_operands (stmt2); - vdefs1 = VDEF_OPS (ann1); - vdefs2 = VDEF_OPS (ann2); + v_may_defs1 = V_MAY_DEF_OPS (ann1); + v_may_defs2 = V_MAY_DEF_OPS (ann2); - /* Walk each VDEF_OP in stmt1. */ - for (i = 0; i < NUM_VDEFS (vdefs1); i++) + /* Walk each V_MAY_DEF_OP in stmt1. */ + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs1); i++) { - tree vdef1 = VDEF_OP (vdefs1, i); + tree v_may_def1 = V_MAY_DEF_OP (v_may_defs1, i); - /* Find the appropriate VDEF_RESULT in STMT2. */ - for (j = 0; j < NUM_VDEFS (vdefs2); j++) + /* Find the appropriate V_MAY_DEF_RESULT in STMT2. */ + for (j = 0; j < NUM_V_MAY_DEFS (v_may_defs2); j++) { - if (vdef1 == VDEF_RESULT (vdefs2, j)) + if (v_may_def1 == V_MAY_DEF_RESULT (v_may_defs2, j)) { /* Update. */ - *VDEF_OP_PTR (vdefs1, i) = VDEF_OP (vdefs2, j); + *V_MAY_DEF_OP_PTR (v_may_defs1, i) = V_MAY_DEF_OP (v_may_defs2, j); break; } } #ifdef ENABLE_CHECKING - /* If we did not find a corresponding VDEF_RESULT, then something + /* If we did not find a corresponding V_MAY_DEF_RESULT, then something has gone terribly wrong. */ - if (j == NUM_VDEFS (vdefs2)) + if (j == NUM_V_MAY_DEFS (v_may_defs2)) abort (); #endif @@ -234,14 +234,14 @@ dse_optimize_stmt (struct dom_walk_data struct dse_global_data *dse_gd = walk_data->global_data; tree stmt = bsi_stmt (bsi); stmt_ann_t ann = stmt_ann (stmt); - vdef_optype vdefs; + v_may_def_optype v_may_defs; get_stmt_operands (stmt); - vdefs = VDEF_OPS (ann); + v_may_defs = V_MAY_DEF_OPS (ann); /* If this statement has no virtual uses, then there is nothing to do. */ - if (NUM_VDEFS (vdefs) == 0) + if (NUM_V_MAY_DEFS (v_may_defs) == 0) return; /* We know we have virtual definitions. If this is a MODIFY_EXPR, then @@ -269,7 +269,7 @@ dse_optimize_stmt (struct dom_walk_data represents the only use of this store. Note this does not handle the case where the store has - multiple VDEFs which all reach a set of PHI nodes in the + multiple V_MAY_DEFs which all reach a set of PHI nodes in the same block. */ while (num_uses == 1 && TREE_CODE (use) == PHI_NODE @@ -300,7 +300,7 @@ dse_optimize_stmt (struct dom_walk_data if (skipped_phi) fix_phi_uses (skipped_phi, stmt); else - fix_stmt_vdefs (use, stmt); + fix_stmt_v_may_defs (use, stmt); if (dump_file && (dump_flags & TDF_DETAILS)) { Index: tree-ssa-live.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-live.c,v retrieving revision 2.4 diff -c -p -u -p -r2.4 tree-ssa-live.c --- tree-ssa-live.c 14 May 2004 05:08:55 -0000 2.4 +++ tree-ssa-live.c 27 May 2004 18:32:55 -0000 @@ -298,7 +298,8 @@ create_ssa_var_map (int flags) tree stmt; stmt_ann_t ann; vuse_optype vuses; - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; use_optype uses; def_optype defs; unsigned x; @@ -383,16 +384,26 @@ create_ssa_var_map (int flags) #endif } - vdefs = VDEF_OPS (ann); - for (x = 0; x < NUM_VDEFS (vdefs); x++) + v_may_defs = V_MAY_DEF_OPS (ann); + for (x = 0; x < NUM_V_MAY_DEFS (v_may_defs); x++) { - tree var = VDEF_OP (vdefs, x); + tree var = V_MAY_DEF_OP (v_may_defs, x); set_is_used (var); #if defined ENABLE_CHECKING SET_BIT (used_in_virtual_ops, var_ann (SSA_NAME_VAR (var))->uid); #endif } + + v_must_defs = V_MUST_DEF_OPS (ann); + for (x = 0; x < NUM_V_MUST_DEFS (v_must_defs); x++) + { + tree var = V_MUST_DEF_OP (v_must_defs, x); + set_is_used (var); +#if defined ENABLE_CHECKING + SET_BIT (used_in_virtual_ops, var_ann (SSA_NAME_VAR (var))->uid); +#endif + } } } Index: tree-ssa-loop.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop.c,v retrieving revision 2.1 diff -c -p -u -p -r2.1 tree-ssa-loop.c --- tree-ssa-loop.c 13 May 2004 06:39:49 -0000 2.1 +++ tree-ssa-loop.c 27 May 2004 18:32:55 -0000 @@ -104,8 +104,9 @@ mark_defs_for_rewrite (basic_block bb) block_stmt_iterator bsi; stmt_ann_t ann; def_optype defs; - vdef_optype vdefs; + v_may_def_optype v_may_defs; vuse_optype vuses; + v_must_def_optype v_must_defs; unsigned i; for (stmt = phi_nodes (bb); stmt; stmt = TREE_CHAIN (stmt)) @@ -141,16 +142,23 @@ mark_defs_for_rewrite (basic_block bb) bitmap_set_bit (vars_to_rename, var_ann (var)->uid); } - vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - var = SSA_NAME_VAR (VDEF_RESULT (vdefs, i)); + var = SSA_NAME_VAR (V_MAY_DEF_RESULT (v_may_defs, i)); + bitmap_set_bit (vars_to_rename, var_ann (var)->uid); + } + + v_must_defs = V_MUST_DEF_OPS (ann); + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) + { + var = SSA_NAME_VAR (V_MUST_DEF_OP (v_must_defs, i)); bitmap_set_bit (vars_to_rename, var_ann (var)->uid); } /* We also need to rewrite vuses, since we will copy the statements and the ssa versions could not be recovered in the copy. We do - not have to do this for operands of VDEFS explicitly, since + not have to do this for operands of V_MAY_DEFS explicitly, since they have the same underlying variable as the results. */ vuses = VUSE_OPS (ann); for (i = 0; i < NUM_VUSES (vuses); i++) Index: tree-ssa-operands.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v retrieving revision 2.3 diff -c -p -u -p -r2.3 tree-ssa-operands.c --- tree-ssa-operands.c 17 May 2004 21:25:28 -0000 2.3 +++ tree-ssa-operands.c 27 May 2004 18:32:55 -0000 @@ -37,9 +37,12 @@ Boston, MA 02111-1307, USA. */ /* By default, operands are loaded. */ #define opf_none 0 -/* Operand is the target of an assignment expression. */ +/* Operand is the target of an assignment expression or a call-clobbered variable */ #define opf_is_def (1 << 0) +/* Operand is the target of an assignment expression. */ +#define opf_kill_def (1 << 2) + /* No virtual operands should be created in the expression. This is used when traversing ADDR_EXPR nodes which have different semantics than other expressions. Inside an ADDR_EXPR node, the only operands that we @@ -54,27 +57,32 @@ static GTY (()) varray_type build_defs; /* Array for building all the use operands. */ static GTY (()) varray_type build_uses; -/* Array for building all the vdef operands. */ -static GTY (()) varray_type build_vdefs; +/* Array for building all the v_may_def operands. */ +static GTY (()) varray_type build_v_may_defs; /* Array for building all the vuse operands. */ static GTY (()) varray_type build_vuses; +/* Array for building all the v_must_def operands. */ +static GTY (()) varray_type build_v_must_defs; + #ifdef ENABLE_CHECKING tree check_build_stmt; #endif typedef struct voperands_d { - vdef_optype vdef_ops; + v_may_def_optype v_may_def_ops; vuse_optype vuse_ops; + v_must_def_optype v_must_def_ops; } *voperands_t; static void note_addressable (tree, stmt_ann_t); static void get_expr_operands (tree, tree *, int, voperands_t); static inline void append_def (tree *, tree); static inline void append_use (tree *, tree); -static void append_vdef (tree, tree, voperands_t); +static void append_v_may_def (tree, tree, voperands_t); +static void append_v_must_def (tree, tree, voperands_t); static void add_call_clobber_ops (tree, voperands_t); static void add_call_read_ops (tree, voperands_t); static void add_stmt_operand (tree *, tree, int, voperands_t); @@ -85,8 +93,8 @@ struct freelist_d GTY((chain_next ("%h.n struct freelist_d *next; }; -#define NUM_FREE 4 -static GTY ((length ("NUM_FREE"))) struct freelist_d optype_freelist[NUM_FREE] = { {0}, {0}, {0}, {0} }; +#define NUM_FREE 5 +static GTY ((length ("NUM_FREE"))) struct freelist_d optype_freelist[NUM_FREE] = { {0}, {0}, {0}, {0}, {0} }; static inline void * @@ -155,17 +163,17 @@ allocate_use_optype (unsigned num) return use_ops; } -static inline vdef_optype -allocate_vdef_optype (unsigned num) +static inline v_may_def_optype +allocate_v_may_def_optype (unsigned num) { - vdef_optype vdef_ops; + v_may_def_optype v_may_def_ops; unsigned size; - size = sizeof (struct vdef_optype_d) + sizeof (tree) * ((num * 2) - 1); - vdef_ops = check_optype_freelist (num * 2); - if (!vdef_ops) - vdef_ops = ggc_alloc (size); - vdef_ops->num_vdefs = num; - return vdef_ops; + size = sizeof (struct v_may_def_optype_d) + sizeof (tree) * ((num * 2) - 1); + v_may_def_ops = check_optype_freelist (num * 2); + if (!v_may_def_ops) + v_may_def_ops = ggc_alloc (size); + v_may_def_ops->num_v_may_defs = num; + return v_may_def_ops; } static inline vuse_optype @@ -181,6 +189,19 @@ allocate_vuse_optype (unsigned num) return vuse_ops; } +static inline v_must_def_optype +allocate_v_must_def_optype (unsigned num) +{ + v_must_def_optype v_must_def_ops; + unsigned size; + size = sizeof (struct v_must_def_optype_d) + sizeof (tree *) * (num - 1); + v_must_def_ops = check_optype_freelist (num); + if (!v_must_def_ops) + v_must_def_ops = ggc_alloc (size); + v_must_def_ops->num_v_must_defs = num; + return v_must_def_ops; +} + static inline void free_uses (use_optype *uses, bool dealloc) { @@ -215,13 +236,24 @@ free_vuses (vuse_optype *vuses, bool dea } static inline void -free_vdefs (vdef_optype *vdefs, bool dealloc) +free_v_may_defs (v_may_def_optype *v_may_defs, bool dealloc) +{ + if (*v_may_defs) + { + if (dealloc) + add_optype_freelist (*v_may_defs, (*v_may_defs)->num_v_may_defs); + *v_may_defs = NULL; + } +} + +static inline void +free_v_must_defs (v_must_def_optype *v_must_defs, bool dealloc) { - if (*vdefs) + if (*v_must_defs) { if (dealloc) - add_optype_freelist (*vdefs, (*vdefs)->num_vdefs); - *vdefs = NULL; + add_optype_freelist (*v_must_defs, (*v_must_defs)->num_v_must_defs); + *v_must_defs = NULL; } } @@ -236,15 +268,24 @@ remove_vuses (tree stmt) } void -remove_vdefs (tree stmt) +remove_v_may_defs (tree stmt) { stmt_ann_t ann; ann = stmt_ann (stmt); if (ann) - free_vdefs (&(ann->vdef_ops), true); + free_v_may_defs (&(ann->v_may_def_ops), true); } +void +remove_v_must_defs (tree stmt) +{ + stmt_ann_t ann; + + ann = stmt_ann (stmt); + if (ann) + free_v_must_defs (&(ann->v_must_def_ops), true); +} void init_ssa_operands (void) @@ -253,8 +294,9 @@ init_ssa_operands (void) VARRAY_TREE_PTR_INIT (build_defs, 5, "build defs"); VARRAY_TREE_PTR_INIT (build_uses, 10, "build uses"); - VARRAY_TREE_INIT (build_vdefs, 10, "build vdefs"); + VARRAY_TREE_INIT (build_v_may_defs, 10, "build v_may_defs"); VARRAY_TREE_INIT (build_vuses, 10, "build vuses"); + VARRAY_TREE_INIT (build_v_must_defs, 10, "build v_must_defs"); for (x = 0; x < NUM_FREE; x++) optype_freelist[x].next = NULL; @@ -328,29 +370,29 @@ finalize_ssa_uses (tree stmt) } static void -finalize_ssa_vdefs (tree stmt) +finalize_ssa_v_may_defs (tree stmt) { unsigned num, x; - vdef_optype vdef_ops; + v_may_def_optype v_may_def_ops; stmt_ann_t ann; - num = VARRAY_ACTIVE_SIZE (build_vdefs); + num = VARRAY_ACTIVE_SIZE (build_v_may_defs); if (num == 0) return; #ifdef ENABLE_CHECKING - /* VDEFs must be entered in pairs of result/uses. */ + /* V_MAY_DEFs must be entered in pairs of result/uses. */ if (num % 2 != 0) abort(); #endif - vdef_ops = allocate_vdef_optype (num / 2); + v_may_def_ops = allocate_v_may_def_optype (num / 2); for (x = 0; x < num; x++) - vdef_ops->vdefs[x] = VARRAY_TREE (build_vdefs, x); - VARRAY_CLEAR (build_vdefs); + v_may_def_ops->v_may_defs[x] = VARRAY_TREE (build_v_may_defs, x); + VARRAY_CLEAR (build_v_may_defs); ann = stmt_ann (stmt); - ann->vdef_ops = vdef_ops; + ann->v_may_def_ops = v_may_def_ops; } static inline void @@ -359,12 +401,12 @@ finalize_ssa_vuses (tree stmt) unsigned num, x; stmt_ann_t ann; vuse_optype vuse_ops; - vdef_optype vdefs; + v_may_def_optype v_may_defs; #ifdef ENABLE_CHECKING - if (VARRAY_ACTIVE_SIZE (build_vdefs) > 0) + if (VARRAY_ACTIVE_SIZE (build_v_may_defs) > 0) { - fprintf (stderr, "Please finalize VDEFs before finalize VUSES.\n"); + fprintf (stderr, "Please finalize V_MAY_DEFs before finalize VUSES.\n"); abort (); } #endif @@ -374,42 +416,42 @@ finalize_ssa_vuses (tree stmt) return; /* Remove superfluous VUSE operands. If the statement already has a - VDEF operation for a variable 'a', then a VUSE for 'a' is not - needed because VDEFs imply a VUSE of the variable. For instance, + V_MAY_DEF operation for a variable 'a', then a VUSE for 'a' is not + needed because V_MAY_DEFs imply a VUSE of the variable. For instance, suppose that variable 'a' is aliased: # VUSE - # a_3 = VDEF + # a_3 = V_MAY_DEF a = a + 1; - The VUSE is superfluous because it is implied by the VDEF + The VUSE is superfluous because it is implied by the V_MAY_DEF operation. */ ann = stmt_ann (stmt); - vdefs = VDEF_OPS (ann); - if (NUM_VDEFS (vdefs) > 0) + v_may_defs = V_MAY_DEF_OPS (ann); + if (NUM_V_MAY_DEFS (v_may_defs) > 0) { size_t i, j; for (i = 0; i < VARRAY_ACTIVE_SIZE (build_vuses); i++) { bool found = false; - for (j = 0; j < NUM_VDEFS (vdefs); j++) + for (j = 0; j < NUM_V_MAY_DEFS (v_may_defs); j++) { - tree vuse_var, vdef_var; + tree vuse_var, v_may_def_var; tree vuse = VARRAY_TREE (build_vuses, i); - tree vdef = VDEF_OP (vdefs, j); + tree v_may_def = V_MAY_DEF_OP (v_may_defs, j); if (TREE_CODE (vuse) == SSA_NAME) vuse_var = SSA_NAME_VAR (vuse); else vuse_var = vuse; - if (TREE_CODE (vdef) == SSA_NAME) - vdef_var = SSA_NAME_VAR (vdef); + if (TREE_CODE (v_may_def) == SSA_NAME) + v_may_def_var = SSA_NAME_VAR (v_may_def); else - vdef_var = vdef; + v_may_def_var = v_may_def; - if (vuse_var == vdef_var) + if (vuse_var == v_may_def_var) { found = true; break; @@ -450,6 +492,32 @@ finalize_ssa_vuses (tree stmt) ann->vuse_ops = vuse_ops; } +static void +finalize_ssa_v_must_defs (tree stmt) +{ + unsigned num, x; + stmt_ann_t ann; + v_must_def_optype v_must_def_ops; + + num = VARRAY_ACTIVE_SIZE (build_v_must_defs); + if (num == 0) + return; + +#ifdef ENABLE_CHECKING + /* There should only be a single V_MUST_DEF per assignment. */ + if (TREE_CODE (stmt) == MODIFY_EXPR && num > 1) + abort (); +#endif + + v_must_def_ops = allocate_v_must_def_optype (num); + for (x = 0; x < num ; x++) + v_must_def_ops->v_must_defs[x] = VARRAY_TREE (build_v_must_defs, x); + VARRAY_POP_ALL (build_v_must_defs); + + ann = stmt_ann (stmt); + ann->v_must_def_ops = v_must_def_ops; +} + extern void finalize_ssa_stmt_operands (tree stmt) { @@ -460,7 +528,8 @@ finalize_ssa_stmt_operands (tree stmt) finalize_ssa_defs (stmt); finalize_ssa_uses (stmt); - finalize_ssa_vdefs (stmt); + finalize_ssa_v_must_defs (stmt); + finalize_ssa_v_may_defs (stmt); finalize_ssa_vuses (stmt); #ifdef ENABLE_CHECKING @@ -476,7 +545,8 @@ verify_start_operands (tree stmt ATTRIBU if (VARRAY_ACTIVE_SIZE (build_defs) > 0 || VARRAY_ACTIVE_SIZE (build_uses) > 0 || VARRAY_ACTIVE_SIZE (build_vuses) > 0 - || VARRAY_ACTIVE_SIZE (build_vdefs) > 0) + || VARRAY_ACTIVE_SIZE (build_v_may_defs) > 0 + || VARRAY_ACTIVE_SIZE (build_v_must_defs) > 0) abort (); if (check_build_stmt != NULL) abort(); @@ -517,7 +587,7 @@ append_use (tree *use_p, tree stmt ATTRI operands. */ static void -append_vdef (tree var, tree stmt, voperands_t prev_vops) +append_v_may_def (tree var, tree stmt, voperands_t prev_vops) { stmt_ann_t ann; size_t i; @@ -532,9 +602,9 @@ append_vdef (tree var, tree stmt, vopera /* Don't allow duplicate entries. */ - for (i = 0; i < VARRAY_ACTIVE_SIZE (build_vdefs); i += 2) + for (i = 0; i < VARRAY_ACTIVE_SIZE (build_v_may_defs); i += 2) { - tree result = VARRAY_TREE (build_vdefs, i); + tree result = VARRAY_TREE (build_v_may_defs, i); if (var == result || (TREE_CODE (result) == SSA_NAME && var == SSA_NAME_VAR (result))) @@ -542,32 +612,32 @@ append_vdef (tree var, tree stmt, vopera } /* If the statement already had virtual definitions, see if any of the - existing VDEFs matches VAR. If so, re-use it, otherwise add a new - VDEF for VAR. */ + existing V_MAY_DEFs matches VAR. If so, re-use it, otherwise add a new + V_MAY_DEF for VAR. */ result = NULL_TREE; source = NULL_TREE; if (prev_vops) - for (i = 0; i < NUM_VDEFS (prev_vops->vdef_ops); i++) + for (i = 0; i < NUM_V_MAY_DEFS (prev_vops->v_may_def_ops); i++) { - result = VDEF_RESULT (prev_vops->vdef_ops, i); + result = V_MAY_DEF_RESULT (prev_vops->v_may_def_ops, i); if (result == var || (TREE_CODE (result) == SSA_NAME && SSA_NAME_VAR (result) == var)) { - source = VDEF_OP (prev_vops->vdef_ops, i); + source = V_MAY_DEF_OP (prev_vops->v_may_def_ops, i); break; } } - /* If no previous VDEF operand was found for VAR, create one now. */ + /* If no previous V_MAY_DEF operand was found for VAR, create one now. */ if (source == NULL_TREE) { result = var; source = var; } - VARRAY_PUSH_TREE (build_vdefs, result); - VARRAY_PUSH_TREE (build_vdefs, source); + VARRAY_PUSH_TREE (build_v_may_defs, result); + VARRAY_PUSH_TREE (build_v_may_defs, source); } @@ -626,6 +696,61 @@ append_vuse (tree var, tree stmt, vopera VARRAY_PUSH_TREE (build_vuses, var); } +/* Add VAR to the list of virtual must definitions for STMT. If PREV_VOPS + is not NULL, the existing entries are preserved and no new entries are + added here. This is done to preserve the SSA numbering of virtual + operands. */ + +static void +append_v_must_def (tree var, tree stmt, voperands_t prev_vops) +{ + stmt_ann_t ann; + size_t i; + bool found; + tree v_must_def; + +#ifdef ENABLE_CHECKING + if (check_build_stmt != stmt) + abort(); +#endif + + ann = stmt_ann (stmt); + + /* Don't allow duplicate entries. */ + for (i = 0; i < VARRAY_ACTIVE_SIZE (build_v_must_defs); i++) + { + tree v_must_def_var = VARRAY_TREE (build_v_must_defs, i); + if (var == v_must_def_var + || (TREE_CODE (v_must_def_var) == SSA_NAME + && var == SSA_NAME_VAR (v_must_def_var))) + return; + } + + /* If the statement already had virtual must defs, see if any of the + existing V_MUST_DEFs matches VAR. If so, re-use it, otherwise add a new + V_MUST_DEF for VAR. */ + found = false; + v_must_def = NULL_TREE; + if (prev_vops) + for (i = 0; i < NUM_V_MUST_DEFS (prev_vops->v_must_def_ops); i++) + { + v_must_def = V_MUST_DEF_OP (prev_vops->v_must_def_ops, i); + if (v_must_def == var + || (TREE_CODE (v_must_def) == SSA_NAME + && SSA_NAME_VAR (v_must_def) == var)) + { + found = true; + break; + } + } + + /* If VAR existed already in PREV_VOPS, re-use it. */ + if (found) + var = v_must_def; + + VARRAY_PUSH_TREE (build_v_must_defs, var); +} + /* External entry point which by-passes the previous vops mechanism. */ void @@ -676,12 +801,14 @@ get_stmt_operands (tree stmt) /* Before removing existing virtual operands, save them in PREV_VOPS so that we can re-use their SSA versions. */ - prev_vops.vdef_ops = VDEF_OPS (ann); + prev_vops.v_may_def_ops = V_MAY_DEF_OPS (ann); prev_vops.vuse_ops = VUSE_OPS (ann); + prev_vops.v_must_def_ops = V_MUST_DEF_OPS (ann); /* Dont free the previous values to memory since we're still using them. */ - free_vdefs (&(ann->vdef_ops), false); + free_v_may_defs (&(ann->v_may_def_ops), false); free_vuses (&(ann->vuse_ops), false); + free_v_must_defs (&(ann->v_must_def_ops), false); start_ssa_stmt_operands (stmt); @@ -690,7 +817,13 @@ get_stmt_operands (tree stmt) { case MODIFY_EXPR: get_expr_operands (stmt, &TREE_OPERAND (stmt, 1), opf_none, &prev_vops); - get_expr_operands (stmt, &TREE_OPERAND (stmt, 0), opf_is_def, &prev_vops); + if (TREE_CODE (TREE_OPERAND (stmt, 0)) == ARRAY_REF + || TREE_CODE (TREE_OPERAND (stmt, 0)) == COMPONENT_REF + || TREE_CODE (TREE_OPERAND (stmt, 0)) == REALPART_EXPR + || TREE_CODE (TREE_OPERAND (stmt, 0)) == IMAGPART_EXPR) + get_expr_operands (stmt, &TREE_OPERAND (stmt, 0), opf_is_def, &prev_vops); + else + get_expr_operands (stmt, &TREE_OPERAND (stmt, 0), opf_is_def | opf_kill_def, &prev_vops); break; case COND_EXPR: @@ -792,8 +925,9 @@ get_stmt_operands (tree stmt) finalize_ssa_stmt_operands (stmt); /* Now free the previous virtual ops to memory. */ - free_vdefs (&(prev_vops.vdef_ops), true); + free_v_may_defs (&(prev_vops.v_may_def_ops), true); free_vuses (&(prev_vops.vuse_ops), true); + free_v_must_defs (&(prev_vops.v_must_def_ops), true); /* Clear the modified bit for STMT. Subsequent calls to get_stmt_operands for this statement will do nothing until the @@ -806,7 +940,7 @@ get_stmt_operands (tree stmt) /* Recursively scan the expression pointed by EXPR_P in statement STMT. FLAGS is one of the OPF_* constants modifying how to interpret the - operands found. PREV_VOPS is as in append_vdef and append_vuse. */ + operands found. PREV_VOPS is as in append_v_may_def and append_vuse. */ static void get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops) @@ -1053,7 +1187,13 @@ get_expr_operands (tree stmt, tree *expr if (code == MODIFY_EXPR) { get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none, prev_vops); - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_is_def, prev_vops); + if (TREE_CODE (TREE_OPERAND (expr, 0)) == ARRAY_REF + || TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF + || TREE_CODE (TREE_OPERAND (expr, 0)) == REALPART_EXPR + || TREE_CODE (TREE_OPERAND (expr, 0)) == IMAGPART_EXPR) + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_is_def, prev_vops); + else + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_is_def | opf_kill_def, prev_vops); return; } @@ -1104,7 +1244,7 @@ get_expr_operands (tree stmt, tree *expr operands. PREV_VOPS is used when adding virtual operands to statements that - already had them (See append_vdef and append_vuse). */ + already had them (See append_v_may_def and append_vuse). */ static void add_stmt_operand (tree *var_p, tree stmt, int flags, voperands_t prev_vops) @@ -1193,9 +1333,19 @@ add_stmt_operand (tree *var_p, tree stmt /* The variable is not aliased or it is an alias tag. */ if (flags & opf_is_def) { - append_vdef (var, stmt, prev_vops); if (v_ann->is_alias_tag) - s_ann->makes_aliased_stores = 1; + { + /* Alias tagged vars get regular V_MAY_DEF */ + s_ann->makes_aliased_stores = 1; + append_v_may_def (var, stmt, prev_vops); + } + else if ((flags & opf_kill_def) && v_ann->mem_tag_kind == NOT_A_TAG) + /* V_MUST_DEF for non-aliased non-GIMPLE register variable + definitions. Avoid memory tags. */ + append_v_must_def (var, stmt, prev_vops); + else + /* Call-clobbered variables & memory tags get V_MAY_DEF */ + append_v_may_def (var, stmt, prev_vops); } else { @@ -1220,10 +1370,10 @@ add_stmt_operand (tree *var_p, tree stmt references to the members of the variable's alias set. This fixes the bug in gcc.c-torture/execute/20020503-1.c. */ if (v_ann->is_alias_tag) - append_vdef (var, stmt, prev_vops); + append_v_may_def (var, stmt, prev_vops); for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++) - append_vdef (VARRAY_TREE (aliases, i), stmt, prev_vops); + append_v_may_def (VARRAY_TREE (aliases, i), stmt, prev_vops); s_ann->makes_aliased_stores = 1; } @@ -1267,7 +1417,7 @@ add_call_clobber_ops (tree stmt, voperan call-clobbered variables. */ stmt_ann (stmt)->makes_clobbering_call = true; - /* If we had created .GLOBAL_VAR earlier, use it. Otherwise, add a VDEF + /* If we had created .GLOBAL_VAR earlier, use it. Otherwise, add a V_MAY_DEF operand for every call clobbered variable. See compute_may_aliases for the heuristic used to decide whether to create .GLOBAL_VAR or not. */ if (global_var) @@ -1280,7 +1430,7 @@ add_call_clobber_ops (tree stmt, voperan { tree var = referenced_var (i); - /* If VAR is read-only, don't add a VDEF, just a VUSE operand. */ + /* If VAR is read-only, don't add a V_MAY_DEF, just a VUSE operand. */ if (!TREE_READONLY (var)) add_stmt_operand (&var, stmt, opf_is_def, prev_vops); else Index: tree-ssa-operands.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.h,v retrieving revision 2.1 diff -c -p -u -p -r2.1 tree-ssa-operands.h --- tree-ssa-operands.h 13 May 2004 06:39:49 -0000 2.1 +++ tree-ssa-operands.h 27 May 2004 18:32:55 -0000 @@ -39,13 +39,13 @@ typedef struct use_optype_d GTY(()) typedef use_optype_t *use_optype; -typedef struct vdef_optype_d GTY(()) +typedef struct v_may_def_optype_d GTY(()) { - unsigned num_vdefs; - tree GTY((length ("%h.num_vdefs * 2"))) vdefs[1]; -} vdef_optype_t; + unsigned num_v_may_defs; + tree GTY((length ("%h.num_v_may_defs * 2"))) v_may_defs[1]; +} v_may_def_optype_t; -typedef vdef_optype_t *vdef_optype; +typedef v_may_def_optype_t *v_may_def_optype; typedef struct vuse_optype_d GTY(()) { @@ -55,6 +55,14 @@ typedef struct vuse_optype_d GTY(()) typedef vuse_optype_t *vuse_optype; +typedef struct v_must_def_optype_d GTY(()) +{ + unsigned num_v_must_defs; + tree GTY((length("%h.num_v_must_defs"))) v_must_defs[1]; +} v_must_def_optype_t; + +typedef v_must_def_optype_t *v_must_def_optype; + #define USE_OPS(ANN) get_use_ops (ANN) #define STMT_USE_OPS(STMT) get_use_ops (stmt_ann (STMT)) #define NUM_USES(OPS) ((OPS) ? (OPS)->num_uses : 0) @@ -69,13 +77,13 @@ typedef vuse_optype_t *vuse_optype; #define DEF_OP(OPS, I) (*(DEF_OP_PTR ((OPS), (I)))) -#define VDEF_OPS(ANN) get_vdef_ops (ANN) -#define STMT_VDEF_OPS(STMT) get_vdef_ops (stmt_ann(STMT)) -#define NUM_VDEFS(OPS) ((OPS) ? (OPS)->num_vdefs : 0) -#define VDEF_RESULT_PTR(OPS, I) get_vdef_result_ptr ((OPS), (I)) -#define VDEF_RESULT(OPS, I) (*(VDEF_RESULT_PTR ((OPS), (I)))) -#define VDEF_OP_PTR(OPS, I) get_vdef_op_ptr ((OPS), (I)) -#define VDEF_OP(OPS, I) (*(VDEF_OP_PTR ((OPS), (I)))) +#define V_MAY_DEF_OPS(ANN) get_v_may_def_ops (ANN) +#define STMT_V_MAY_DEF_OPS(STMT) get_v_may_def_ops (stmt_ann(STMT)) +#define NUM_V_MAY_DEFS(OPS) ((OPS) ? (OPS)->num_v_may_defs : 0) +#define V_MAY_DEF_RESULT_PTR(OPS, I) get_v_may_def_result_ptr ((OPS), (I)) +#define V_MAY_DEF_RESULT(OPS, I) (*(V_MAY_DEF_RESULT_PTR ((OPS), (I)))) +#define V_MAY_DEF_OP_PTR(OPS, I) get_v_may_def_op_ptr ((OPS), (I)) +#define V_MAY_DEF_OP(OPS, I) (*(V_MAY_DEF_OP_PTR ((OPS), (I)))) #define VUSE_OPS(ANN) get_vuse_ops (ANN) @@ -85,6 +93,12 @@ typedef vuse_optype_t *vuse_optype; #define VUSE_OP(OPS, I) (*(VUSE_OP_PTR ((OPS), (I)))) +#define V_MUST_DEF_OPS(ANN) get_v_must_def_ops (ANN) +#define STMT_V_MUST_DEF_OPS(STMT) get_v_must_def_ops (stmt_ann (STMT)) +#define NUM_V_MUST_DEFS(OPS) ((OPS) ? (OPS)->num_v_must_defs : 0) +#define V_MUST_DEF_OP_PTR(OPS, I) get_v_must_def_op_ptr ((OPS), (I)) +#define V_MUST_DEF_OP(OPS, I) (*(V_MUST_DEF_OP_PTR ((OPS), (I)))) + extern void init_ssa_operands (void); extern void fini_ssa_operands (void); extern void verify_start_operands (tree); @@ -92,6 +106,7 @@ extern void finalize_ssa_stmt_operands ( void add_vuse (tree, tree); extern void get_stmt_operands (tree); extern void remove_vuses (tree); -extern void remove_vdefs (tree); +extern void remove_v_may_defs (tree); +extern void remove_v_must_defs (tree); #endif /* GCC_TREE_SSA_OPERANDS_H */ Index: tree-ssa-pre.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-ssa-pre.c,v retrieving revision 2.3 diff -c -p -u -p -r2.3 tree-ssa-pre.c --- tree-ssa-pre.c 14 May 2004 02:29:23 -0000 2.3 +++ tree-ssa-pre.c 27 May 2004 18:32:55 -0000 @@ -1312,7 +1312,8 @@ subst_phis (struct expr_info *ei, tree Z else { remove_vuses (stmt_copy); - remove_vdefs (stmt_copy); + remove_v_may_defs (stmt_copy); + remove_v_must_defs (stmt_copy); } if (pred->index < n_phi_preds) @@ -3016,13 +3017,16 @@ process_left_occs_and_kills (varray_type { size_t i, j, k; - stmt_ann_t ann = stmt_ann (expr); - vdef_optype vdefs; + v_may_def_optype v_may_defs; + v_must_def_optype v_must_defs; vuse_optype vuses; def_optype defs; - defs = DEF_OPS (ann); - vdefs = VDEF_OPS (ann); - if (NUM_DEFS (defs) == 0 && NUM_VDEFS (vdefs) == 0) + defs = STMT_DEF_OPS (expr); + v_may_defs = STMT_V_MAY_DEF_OPS (expr); + v_must_defs = STMT_V_MUST_DEF_OPS (expr); + if (NUM_DEFS (defs) == 0 + && NUM_V_MAY_DEFS (v_may_defs) == 0 + && NUM_V_MUST_DEFS (v_must_defs) == 0) return; for (j = 0; j < VARRAY_ACTIVE_SIZE (bexprs); j++) @@ -3052,19 +3056,36 @@ process_left_occs_and_kills (varray_type } } - /* If we VDEF the VUSE of the expression, it's also a left + /* If we virtually define the variable itself, + it's a left occurrence. */ + for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++) + { + if (names_match_p (V_MUST_DEF_OP (v_must_defs, i), ei->expr)) + { + if (TREE_CODE (expr) == ASM_EXPR) + { + ei->loadpre_cand = false; + continue; + } + VARRAY_PUSH_TREE (ei->lefts, expr); + VARRAY_PUSH_TREE (ei->occurs, NULL); + VARRAY_PUSH_TREE (ei->kills, NULL); + } + } + + /* If we V_MAY_DEF the VUSE of the expression, it's also a left occurrence. */ random_occur = VARRAY_TREE (ei->occurs, 0); ann = stmt_ann (random_occur); vuses = VUSE_OPS (ann); - if (NUM_VDEFS (vdefs) != 0) + if (NUM_V_MAY_DEFS (v_may_defs) != 0) { for (k = 0; k < NUM_VUSES (vuses); k++) { vuse_name = VUSE_OP (vuses, k); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - if (names_match_p (VDEF_OP (vdefs, i), vuse_name)) + if (names_match_p (V_MAY_DEF_OP (v_may_defs, i), vuse_name)) { VARRAY_PUSH_TREE (ei->lefts, expr); VARRAY_PUSH_TREE (ei->occurs, NULL); Index: tree-tailcall.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-tailcall.c,v retrieving revision 2.3 diff -c -p -u -p -r2.3 tree-tailcall.c --- tree-tailcall.c 15 May 2004 09:39:29 -0000 2.3 +++ tree-tailcall.c 27 May 2004 18:32:55 -0000 @@ -391,7 +391,8 @@ find_tail_calls (basic_block bb, struct /* If the statement has virtual operands, fail. */ ann = stmt_ann (stmt); - if (NUM_VDEFS (VDEF_OPS (ann)) + if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) + || NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) || NUM_VUSES (VUSE_OPS (ann))) return; } @@ -644,7 +645,7 @@ eliminate_tail_call (struct tailcall *t) edge e; tree phi; stmt_ann_t ann; - vdef_optype vdefs; + v_may_def_optype v_may_defs; unsigned i; stmt = bsi_stmt (t->call_bsi); @@ -696,10 +697,10 @@ eliminate_tail_call (struct tailcall *t) } /* Add phi nodes for the call clobbered variables. */ - vdefs = VDEF_OPS (ann); - for (i = 0; i < NUM_VDEFS (vdefs); i++) + v_may_defs = V_MAY_DEF_OPS (ann); + for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++) { - param = SSA_NAME_VAR (VDEF_RESULT (vdefs, i)); + param = SSA_NAME_VAR (V_MAY_DEF_RESULT (v_may_defs, i)); for (phi = phi_nodes (first); phi; phi = TREE_CHAIN (phi)) if (param == SSA_NAME_VAR (PHI_RESULT (phi))) break; @@ -721,7 +722,7 @@ eliminate_tail_call (struct tailcall *t) abort (); } - add_phi_arg (&phi, VDEF_OP (vdefs, i), e); + add_phi_arg (&phi, V_MAY_DEF_OP (v_may_defs, i), e); } /* Update the values of accumulators. */ Index: testsuite/gcc.dg/tree-ssa/20031015-1.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/tree-ssa/20031015-1.c,v retrieving revision 1.2 diff -c -p -u -p -r1.2 20031015-1.c --- testsuite/gcc.dg/tree-ssa/20031015-1.c 13 May 2004 06:40:51 -0000 1.2 +++ testsuite/gcc.dg/tree-ssa/20031015-1.c 27 May 2004 18:32:55 -0000 @@ -13,4 +13,4 @@ main(void) return 0; } -/* { dg-final { scan-tree-dump-times "VDEF" 2 "alias" } } */ +/* { dg-final { scan-tree-dump-times "V_MAY_DEF" 2 "alias" } } */ Index: testsuite/gcc.dg/tree-ssa/20040517-1.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/tree-ssa/20040517-1.c,v retrieving revision 1.1 diff -c -p -u -p -r1.1 20040517-1.c --- testsuite/gcc.dg/tree-ssa/20040517-1.c 17 May 2004 21:25:32 -0000 1.1 +++ testsuite/gcc.dg/tree-ssa/20040517-1.c 27 May 2004 18:32:55 -0000 @@ -16,5 +16,5 @@ void bar (void) malloc functions may clobber global memory. Only the function result does not alias any other pointer. Hence, we must have a VDEF for a before and after the call to foo(). */ -/* { dg-final { scan-tree-dump-times "VDEF" 2 "ssa"} } */ +/* { dg-final { scan-tree-dump-times "V_MAY_DEF" 1 "ssa"} } */