diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0e371fa6ab4..e84d9cd5f27 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2004-09-11 Zdenek Dvorak + + * tree-cfg.c (set_bb_for_stmt): Use PHI_BB. + * tree-dfa.c (compute_immediate_uses, add_immediate_use, + redirect_immediate_use): Use PHI_DF. + * tree-flow-inline.h (stmt_ann): Abort on phi nodes. + (bb_for_stmt): Use PHI_BB. + (get_immediate_uses): Use PHI_DF. + * tree-ssa-dse.c (max_stmt_uid): New variable. + (get_stmt_uid): New function. + (dse_optimize_stmt, dse_record_phis, tree_ssa_dse): Do not use phi + node annotations. + * tree-ssa-loop-im.c (LIM_DATA): Do not use phi statement annotations. + (max_uid): Renamed to max_stmt_uid. + (get_stmt_uid): New function. + (maybe_queue_var, single_reachable_address, determine_lsm): Do not use + phi node annotations. + * tree-ssa.c (replace_immediate_uses): Do not use phi node annotations. + * tree.h (PHI_BB, PHI_DF): New accessor functions. + (struct tree_phi_node): Add bb and df fields. + 2004-09-11 Richard Henderson PR middle-end/17416 diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 14f7d1da8bd..8e9e5af64ac 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -2666,7 +2666,9 @@ last_and_only_stmt (basic_block bb) void set_bb_for_stmt (tree t, basic_block bb) { - if (TREE_CODE (t) == STATEMENT_LIST) + if (TREE_CODE (t) == PHI_NODE) + PHI_BB (t) = bb; + else if (TREE_CODE (t) == STATEMENT_LIST) { tree_stmt_iterator i; for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index 3ceb60afd3b..af6d9eddfc4 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -191,19 +191,31 @@ compute_immediate_uses (int flags, bool (*calc_for)(tree)) static void free_df_for_stmt (tree stmt) { - stmt_ann_t ann = stmt_ann (stmt); + dataflow_t *df; - if (ann && ann->df) + if (TREE_CODE (stmt) == PHI_NODE) + df = &PHI_DF (stmt); + else { - /* If we have a varray of immediate uses, then go ahead and release - it for re-use. */ - if (ann->df->immediate_uses) - ggc_free (ann->df->immediate_uses); + stmt_ann_t ann = stmt_ann (stmt); - /* Similarly for the main dataflow structure. */ - ggc_free (ann->df); - ann->df = NULL; + if (!ann) + return; + + df = &ann->df; } + + if (!*df) + return; + + /* If we have a varray of immediate uses, then go ahead and release + it for re-use. */ + if ((*df)->immediate_uses) + ggc_free ((*df)->immediate_uses); + + /* Similarly for the main dataflow structure. */ + ggc_free (*df); + *df = NULL; } @@ -302,28 +314,34 @@ compute_immediate_uses_for_stmt (tree stmt, int flags, bool (*calc_for)(tree)) static void add_immediate_use (tree stmt, tree use_stmt) { - stmt_ann_t ann = get_stmt_ann (stmt); - struct dataflow_d *df; + struct dataflow_d **df; - df = ann->df; - if (df == NULL) + if (TREE_CODE (stmt) == PHI_NODE) + df = &PHI_DF (stmt); + else { - df = ann->df = ggc_alloc (sizeof (struct dataflow_d)); - memset ((void *) df, 0, sizeof (struct dataflow_d)); - df->uses[0] = use_stmt; + stmt_ann_t ann = get_stmt_ann (stmt); + df = &ann->df; + } + + if (*df == NULL) + { + *df = ggc_alloc (sizeof (struct dataflow_d)); + memset ((void *) *df, 0, sizeof (struct dataflow_d)); + (*df)->uses[0] = use_stmt; return; } - if (!df->uses[1]) + if (!(*df)->uses[1]) { - df->uses[1] = use_stmt; + (*df)->uses[1] = use_stmt; return; } - if (ann->df->immediate_uses == NULL) - VARRAY_TREE_INIT (ann->df->immediate_uses, 4, "immediate_uses"); + if ((*df)->immediate_uses == NULL) + VARRAY_TREE_INIT ((*df)->immediate_uses, 4, "immediate_uses"); - VARRAY_PUSH_TREE (ann->df->immediate_uses, use_stmt); + VARRAY_PUSH_TREE ((*df)->immediate_uses, use_stmt); } @@ -333,7 +351,7 @@ static void redirect_immediate_use (tree use, tree old, tree new) { tree imm_stmt = SSA_NAME_DEF_STMT (use); - struct dataflow_d *df = get_stmt_ann (imm_stmt)->df; + struct dataflow_d *df = get_immediate_uses (imm_stmt); unsigned int num_uses = num_immediate_uses (df); unsigned int i; diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h index cd2bf9ec082..61ed11268f7 100644 --- a/gcc/tree-flow-inline.h +++ b/gcc/tree-flow-inline.h @@ -78,7 +78,12 @@ ann_type (tree_ann_t ann) static inline basic_block bb_for_stmt (tree t) { - stmt_ann_t ann = stmt_ann (t); + stmt_ann_t ann; + + if (TREE_CODE (t) == PHI_NODE) + return PHI_BB (t); + + ann = stmt_ann (t); return ann ? ann->bb : NULL; } @@ -305,7 +310,12 @@ addresses_taken (tree stmt) static dataflow_t get_immediate_uses (tree stmt) { - stmt_ann_t ann = stmt_ann (stmt); + stmt_ann_t ann; + + if (TREE_CODE (stmt) == PHI_NODE) + return PHI_DF (stmt); + + ann = stmt_ann (stmt); return ann ? ann->df : NULL; } diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 820b2c6378c..4cc136bf2dd 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -98,6 +98,21 @@ static void fix_phi_uses (tree, tree); static void fix_stmt_v_may_defs (tree, tree); static void record_voperand_set (bitmap, bitmap *, unsigned int); +static unsigned max_stmt_uid; /* Maximal uid of a statement. Uids to phi + nodes are assigned using the versions of + ssa names they define. */ + +/* Returns uid of statement STMT. */ + +static unsigned +get_stmt_uid (tree stmt) +{ + if (TREE_CODE (stmt) == PHI_NODE) + return SSA_NAME_VERSION (PHI_RESULT (stmt)) + max_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. */ @@ -270,7 +285,7 @@ dse_optimize_stmt (struct dom_walk_data *walk_data, same block. */ while (num_uses == 1 && TREE_CODE (use) == PHI_NODE - && bitmap_bit_p (dse_gd->stores, stmt_ann (use)->uid)) + && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use))) { /* Record the first PHI we skip so that we can fix its uses if we find that STMT is a dead store. */ @@ -287,7 +302,7 @@ dse_optimize_stmt (struct dom_walk_data *walk_data, /* If we have precisely one immediate use at this point, then we may have found redundant store. */ if (num_uses == 1 - && bitmap_bit_p (dse_gd->stores, stmt_ann (use)->uid) + && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use)) && operand_equal_p (TREE_OPERAND (stmt, 0), TREE_OPERAND (use, 0), 0)) { @@ -333,7 +348,7 @@ dse_record_phis (struct dom_walk_data *walk_data, basic_block bb) if (need_imm_uses_for (PHI_RESULT (phi))) record_voperand_set (dse_gd->stores, &bd->stores, - get_stmt_ann (phi)->uid); + get_stmt_uid (phi)); } static void @@ -356,21 +371,17 @@ tree_ssa_dse (void) { struct dom_walk_data walk_data; struct dse_global_data dse_gd; - unsigned int uid = 0; basic_block bb; /* Create a UID for each statement in the function. Ordering of the UIDs is not important for this pass. */ + max_stmt_uid = 0; FOR_EACH_BB (bb) { block_stmt_iterator bsi; - tree phi; for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) - stmt_ann (bsi_stmt (bsi))->uid = uid++; - - for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) - stmt_ann (phi)->uid = uid++; + stmt_ann (bsi_stmt (bsi))->uid = max_stmt_uid++; } /* We might consider making this a property of each pass so that it diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index c0d2c00ad9e..bc606e60a8a 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -76,7 +76,9 @@ struct lim_aux_data MAX_LOOP loop. */ }; -#define LIM_DATA(STMT) ((struct lim_aux_data *) (stmt_ann (STMT)->common.aux)) +#define LIM_DATA(STMT) (TREE_CODE (STMT) == PHI_NODE \ + ? NULL \ + : (struct lim_aux_data *) (stmt_ann (STMT)->common.aux)) /* Description of a memory reference for store motion. */ @@ -94,9 +96,20 @@ struct mem_ref block will be executed. */ #define ALWAYS_EXECUTED_IN(BB) ((struct loop *) (BB)->aux) -/* Maximum uid in the statement in the function. */ +static unsigned max_stmt_uid; /* Maximal uid of a statement. Uids to phi + nodes are assigned using the versions of + ssa names they define. */ -static unsigned max_uid; +/* Returns uid of statement STMT. */ + +static unsigned +get_stmt_uid (tree stmt) +{ + if (TREE_CODE (stmt) == PHI_NODE) + return SSA_NAME_VERSION (PHI_RESULT (stmt)) + max_stmt_uid; + + return stmt_ann (stmt)->uid; +} /* Calls CBCK for each index in memory reference ADDR_P. There are two kinds situations handled; in each of these cases, the memory reference @@ -805,10 +818,10 @@ maybe_queue_var (tree var, struct loop *loop, if (!def_bb || !flow_bb_inside_loop_p (loop, def_bb) - || TEST_BIT (seen, stmt_ann (stmt)->uid)) + || TEST_BIT (seen, get_stmt_uid (stmt))) return; - SET_BIT (seen, stmt_ann (stmt)->uid); + SET_BIT (seen, get_stmt_uid (stmt)); queue[(*in_queue)++] = stmt; } @@ -900,6 +913,7 @@ single_reachable_address (struct loop *loop, tree stmt, struct mem_ref **mem_refs, bool *seen_call_stmt) { + unsigned max_uid = max_stmt_uid + num_ssa_names; tree *queue = xmalloc (sizeof (tree) * max_uid); sbitmap seen = sbitmap_alloc (max_uid); unsigned in_queue = 1; @@ -917,7 +931,7 @@ single_reachable_address (struct loop *loop, tree stmt, sra_data.common_ref = NULL_TREE; queue[0] = stmt; - SET_BIT (seen, stmt_ann (stmt)->uid); + SET_BIT (seen, get_stmt_uid (stmt)); *seen_call_stmt = false; while (in_queue) @@ -975,9 +989,9 @@ single_reachable_address (struct loop *loop, tree stmt, if (!flow_bb_inside_loop_p (loop, bb_for_stmt (stmt))) continue; - if (TEST_BIT (seen, stmt_ann (stmt)->uid)) + if (TEST_BIT (seen, get_stmt_uid (stmt))) continue; - SET_BIT (seen, stmt_ann (stmt)->uid); + SET_BIT (seen, get_stmt_uid (stmt)); queue[in_queue++] = stmt; } @@ -1230,17 +1244,13 @@ determine_lsm (struct loops *loops) /* Create a UID for each statement in the function. Ordering of the UIDs is not important for this pass. */ - max_uid = 0; + max_stmt_uid = 0; FOR_EACH_BB (bb) { block_stmt_iterator bsi; - tree phi; for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) - stmt_ann (bsi_stmt (bsi))->uid = max_uid++; - - for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi)) - stmt_ann (phi)->uid = max_uid++; + stmt_ann (bsi_stmt (bsi))->uid = max_stmt_uid++; } compute_immediate_uses (TDFA_USE_VOPS, NULL); diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 2da6c99651e..c8ced3632a2 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -916,7 +916,6 @@ replace_immediate_uses (tree var, tree repl) int i, j, n; dataflow_t df; tree stmt; - stmt_ann_t ann; bool mark_new_vars; ssa_op_iter iter; use_operand_p use_p; @@ -927,7 +926,6 @@ replace_immediate_uses (tree var, tree repl) for (i = 0; i < n; i++) { stmt = immediate_use (df, i); - ann = stmt_ann (stmt); if (TREE_CODE (stmt) == PHI_NODE) { diff --git a/gcc/tree.h b/gcc/tree.h index 461b8676978..bdd95aab2a9 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1293,6 +1293,8 @@ struct tree_ssa_name GTY(()) #define PHI_ARG_ELT(NODE, I) PHI_NODE_ELT_CHECK (NODE, I) #define PHI_ARG_EDGE(NODE, I) PHI_NODE_ELT_CHECK (NODE, I).e #define PHI_ARG_NONZERO(NODE, I) PHI_NODE_ELT_CHECK (NODE, I).nonzero +#define PHI_BB(NODE) PHI_NODE_CHECK (NODE)->phi.bb +#define PHI_DF(NODE) PHI_NODE_CHECK (NODE)->phi.df struct edge_def; @@ -1314,6 +1316,12 @@ struct tree_phi_node GTY(()) SSA renamer. */ int rewritten; + /* Basic block to that the phi node belongs. */ + struct basic_block_def *bb; + + /* Dataflow information. */ + struct dataflow_d *df; + struct phi_arg_d GTY ((length ("((tree)&%h)->phi.capacity"))) a[1]; };