summaryrefslogtreecommitdiff
path: root/gcc/tree-switch-conversion.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-switch-conversion.c')
-rw-r--r--gcc/tree-switch-conversion.c259
1 files changed, 123 insertions, 136 deletions
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 2205c1a8b71..8bcfcfde5ca 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -147,10 +147,10 @@ struct switch_conv_info
/* The first load statement that loads a temporary from a new static array.
*/
- tree arr_ref_first;
+ gimple arr_ref_first;
/* The last load statement that loads a temporary from a new static array. */
- tree arr_ref_last;
+ gimple arr_ref_last;
/* String reason why the case wasn't a good candidate that is written to the
dump file, if there is one. */
@@ -166,22 +166,21 @@ static struct switch_conv_info info;
satisfies the size of the new array. */
static bool
-check_range (tree swtch)
+check_range (gimple swtch)
{
tree min_case, max_case;
- tree cases = SWITCH_LABELS (swtch);
- unsigned int branch_num = TREE_VEC_LENGTH (cases);
+ unsigned int branch_num = gimple_switch_num_labels (swtch);
tree range_max;
/* The gimplifier has already sorted the cases by CASE_LOW and ensured there
is a default label which is the last in the vector. */
- min_case = TREE_VEC_ELT (cases, 0);
+ min_case = gimple_switch_label (swtch, 1);
info.range_min = CASE_LOW (min_case);
gcc_assert (branch_num > 1);
- gcc_assert (CASE_LOW (TREE_VEC_ELT (cases, branch_num - 1)) == NULL_TREE);
- max_case = TREE_VEC_ELT (cases, branch_num - 2);
+ gcc_assert (CASE_LOW (gimple_switch_label (swtch, 0)) == NULL_TREE);
+ max_case = gimple_switch_label (swtch, branch_num - 1);
if (CASE_HIGH (max_case) != NULL_TREE)
range_max = CASE_HIGH (max_case);
else
@@ -283,25 +282,26 @@ check_process_case (tree cs)
static bool
check_final_bb (void)
{
- tree phi;
+ gimple_stmt_iterator gsi;
info.phi_count = 0;
- for (phi = phi_nodes (info.final_bb); phi; phi = PHI_CHAIN (phi))
+ for (gsi = gsi_start_phis (info.final_bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
- int i;
+ gimple phi = gsi_stmt (gsi);
+ unsigned int i;
info.phi_count++;
- for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+ for (i = 0; i < gimple_phi_num_args (phi); i++)
{
- basic_block bb = PHI_ARG_EDGE (phi, i)->src;
+ basic_block bb = gimple_phi_arg_edge (phi, i)->src;
if ((bb == info.switch_bb
|| (single_pred_p (bb) && single_pred (bb) == info.switch_bb))
- && !is_gimple_min_invariant (PHI_ARG_ELT (phi, i).def))
+ && !is_gimple_min_invariant (gimple_phi_arg_def (phi, i)))
{
info.reason = " Non-invariant value from a case\n";
- return false; /* non invariant argument */
+ return false; /* Non-invariant argument. */
}
}
}
@@ -326,10 +326,8 @@ create_temp_arrays (void)
sizeof (tree));
for (i = 0; i < info.phi_count; i++)
- {
- info.constructors[i] = VEC_alloc (constructor_elt, gc,
- tree_low_cst (info.range_size, 1) + 1);
- }
+ info.constructors[i]
+ = VEC_alloc (constructor_elt, gc, tree_low_cst (info.range_size, 1) + 1);
}
/* Free the arrays created by create_temp_arrays(). The vectors that are
@@ -351,10 +349,10 @@ free_temp_arrays (void)
static void
gather_default_values (tree default_case)
{
- tree phi;
+ gimple_stmt_iterator gsi;
basic_block bb = label_to_block (CASE_LABEL (default_case));
edge e;
- int i;
+ int i = 0;
gcc_assert (CASE_LOW (default_case) == NULL_TREE);
@@ -363,11 +361,12 @@ gather_default_values (tree default_case)
else
e = single_succ_edge (bb);
- for (phi = phi_nodes (info.final_bb), i = 0; phi; phi = PHI_CHAIN (phi), i++)
+ for (gsi = gsi_start_phis (info.final_bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
+ gimple phi = gsi_stmt (gsi);
tree val = PHI_ARG_DEF_FROM_EDGE (phi, e);
gcc_assert (val);
- info.default_values[i] = val;
+ info.default_values[i++] = val;
}
}
@@ -376,18 +375,18 @@ gather_default_values (tree default_case)
order of phi nodes. SWTCH is the switch statement being converted. */
static void
-build_constructors (tree swtch)
+build_constructors (gimple swtch)
{
- int i;
- tree cases = SWITCH_LABELS (swtch);
+ unsigned i, branch_num = gimple_switch_num_labels (swtch);
tree pos = info.range_min;
- for (i = 0; i < TREE_VEC_LENGTH (cases) - 1; i++)
+ for (i = 1; i < branch_num; i++)
{
- tree cs = TREE_VEC_ELT (cases, i);
+ tree cs = gimple_switch_label (swtch, i);
basic_block bb = label_to_block (CASE_LABEL (cs));
edge e;
- tree phi, high;
+ tree high;
+ gimple_stmt_iterator gsi;
int j;
if (bb == info.final_bb)
@@ -405,7 +404,8 @@ build_constructors (tree swtch)
elt = VEC_quick_push (constructor_elt,
info.constructors[k], NULL);
- elt->index = int_const_binop (MINUS_EXPR, pos, info.range_min, 0);
+ elt->index = int_const_binop (MINUS_EXPR, pos,
+ info.range_min, 0);
elt->value = info.default_values[k];
}
@@ -418,8 +418,10 @@ build_constructors (tree swtch)
high = CASE_HIGH (cs);
else
high = CASE_LOW (cs);
- for (phi = phi_nodes (info.final_bb); phi; phi = PHI_CHAIN (phi))
+ for (gsi = gsi_start_phis (info.final_bb);
+ !gsi_end_p (gsi); gsi_next (&gsi))
{
+ gimple phi = gsi_stmt (gsi);
tree val = PHI_ARG_DEF_FROM_EDGE (phi, e);
pos = CASE_LOW (cs);
@@ -449,15 +451,12 @@ build_constructors (tree swtch)
is a temporary variable holding the index for loads from the new array. */
static void
-build_one_array (tree swtch, int num, tree arr_index_type, tree phi, tree tidx)
+build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi,
+ tree tidx)
{
- tree array_type;
- tree ctor;
- tree decl;
- tree value_type;
- tree name;
- tree fetch, load;
- block_stmt_iterator bsi;
+ tree array_type, ctor, decl, value_type, name, fetch;
+ gimple load;
+ gimple_stmt_iterator gsi;
gcc_assert (info.default_values[num]);
value_type = TREE_TYPE (info.default_values[num]);
@@ -478,21 +477,19 @@ build_one_array (tree swtch, int num, tree arr_index_type, tree phi, tree tidx)
varpool_finalize_decl (decl);
mark_sym_for_renaming (decl);
- name = make_ssa_name (SSA_NAME_VAR (PHI_RESULT (phi)), NULL_TREE);
+ name = make_ssa_name (SSA_NAME_VAR (PHI_RESULT (phi)), NULL);
info.target_inbound_names[num] = name;
fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE,
NULL_TREE);
- load = build_gimple_modify_stmt (name, fetch);
+ load = gimple_build_assign (name, fetch);
SSA_NAME_DEF_STMT (name) = load;
- bsi = bsi_for_stmt (swtch);
- bsi_insert_before (&bsi, load, BSI_SAME_STMT);
+ gsi = gsi_for_stmt (swtch);
+ gsi_insert_before (&gsi, load, GSI_SAME_STMT);
mark_symbols_for_renaming (load);
info.arr_ref_last = load;
-
- return;
}
/* Builds and initializes static arrays initialized with values gathered from
@@ -500,54 +497,53 @@ build_one_array (tree swtch, int num, tree arr_index_type, tree phi, tree tidx)
them. */
static void
-build_arrays (tree swtch)
+build_arrays (gimple swtch)
{
tree arr_index_type;
tree tidx, sub;
- block_stmt_iterator bsi;
- tree phi = phi_nodes (info.final_bb);
+ gimple stmt;
+ gimple_stmt_iterator gsi;
int i;
- bsi = bsi_for_stmt (swtch);
+ gsi = gsi_for_stmt (swtch);
arr_index_type = build_index_type (info.range_size);
tidx = make_rename_temp (arr_index_type, "csti");
sub = fold_build2 (MINUS_EXPR, TREE_TYPE (info.index_expr), info.index_expr,
fold_convert (TREE_TYPE (info.index_expr),
info.range_min));
- sub = force_gimple_operand_bsi (&bsi, fold_convert (arr_index_type, sub),
- false, NULL, true, BSI_SAME_STMT);
- sub = build_gimple_modify_stmt (tidx, sub);
-
- bsi_insert_before (&bsi, sub, BSI_SAME_STMT);
- mark_symbols_for_renaming (sub);
- info.arr_ref_first = sub;
+ sub = force_gimple_operand_gsi (&gsi, fold_convert (arr_index_type, sub),
+ false, NULL, true, GSI_SAME_STMT);
+ stmt = gimple_build_assign (tidx, sub);
- for (phi = phi_nodes (info.final_bb), i = 0; phi; phi = PHI_CHAIN (phi), i++)
- build_one_array (swtch, i, arr_index_type, phi, tidx);
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+ mark_symbols_for_renaming (stmt);
+ info.arr_ref_first = stmt;
- return;
+ for (gsi = gsi_start_phis (info.final_bb), i = 0;
+ !gsi_end_p (gsi); gsi_next (&gsi), i++)
+ build_one_array (swtch, i, arr_index_type, gsi_stmt (gsi), tidx);
}
/* Generates and appropriately inserts loads of default values at the position
given by BSI. Returns the last inserted statement. */
-static tree
-gen_def_assigns (block_stmt_iterator *bsi)
+static gimple
+gen_def_assigns (gimple_stmt_iterator *gsi)
{
int i;
- tree assign = NULL_TREE;
+ gimple assign = NULL;
for (i = 0; i < info.phi_count; i++)
{
- tree name = make_ssa_name (SSA_NAME_VAR (info.target_inbound_names[i]),
- NULL_TREE);
+ tree name
+ = make_ssa_name (SSA_NAME_VAR (info.target_inbound_names[i]), NULL);
info.target_outbound_names[i] = name;
- assign = build_gimple_modify_stmt (name, info.default_values[i]);
+ assign = gimple_build_assign (name, info.default_values[i]);
SSA_NAME_DEF_STMT (name) = assign;
- bsi_insert_before (bsi, assign, BSI_SAME_STMT);
- find_new_referenced_vars (&assign);
+ gsi_insert_before (gsi, assign, GSI_SAME_STMT);
+ find_new_referenced_vars (assign);
mark_symbols_for_renaming (assign);
}
return assign;
@@ -583,11 +579,13 @@ prune_bbs (basic_block bbd, basic_block final)
static void
fix_phi_nodes (edge e1f, edge e2f, basic_block bbf)
{
- tree phi;
+ gimple_stmt_iterator gsi;
int i;
- for (phi = phi_nodes (bbf), i = 0; phi; phi = PHI_CHAIN (phi), i++)
+ for (gsi = gsi_start_phis (bbf), i = 0;
+ !gsi_end_p (gsi); gsi_next (&gsi), i++)
{
+ gimple phi = gsi_stmt (gsi);
add_phi_arg (phi, info.target_inbound_names[i], e1f);
add_phi_arg (phi, info.target_outbound_names[i], e2f);
}
@@ -616,28 +614,29 @@ fix_phi_nodes (edge e1f, edge e2f, basic_block bbf)
*/
static void
-gen_inbound_check (tree swtch)
+gen_inbound_check (gimple swtch)
{
tree label_decl1 = create_artificial_label ();
tree label_decl2 = create_artificial_label ();
tree label_decl3 = create_artificial_label ();
- tree label1, label2, label3;
+ gimple label1, label2, label3;
tree utype;
tree tmp_u;
- tree cast, cast_assign;
- tree ulb, minus, minus_assign;
+ tree cast;
+ gimple cast_assign, minus_assign;
+ tree ulb, minus;
tree bound;
- tree if_expr;
+ gimple cond_stmt;
- tree last_assign;
- block_stmt_iterator bsi;
+ gimple last_assign;
+ gimple_stmt_iterator gsi;
basic_block bb0, bb1, bb2, bbf, bbd;
edge e01, e02, e21, e1d, e1f, e2f;
gcc_assert (info.default_values);
- bb0 = bb_for_stmt (swtch);
+ bb0 = gimple_bb (swtch);
/* Make sure we do not generate arithmetics in a subrange. */
if (TREE_TYPE (TREE_TYPE (info.index_expr)))
@@ -646,52 +645,50 @@ gen_inbound_check (tree swtch)
utype = unsigned_type_for (TREE_TYPE (info.index_expr));
/* (end of) block 0 */
- bsi = bsi_for_stmt (info.arr_ref_first);
+ gsi = gsi_for_stmt (info.arr_ref_first);
tmp_u = make_rename_temp (utype, "csui");
cast = fold_convert (utype, info.index_expr);
- cast_assign = build_gimple_modify_stmt (tmp_u, cast);
- find_new_referenced_vars (&cast_assign);
- bsi_insert_before (&bsi, cast_assign, BSI_SAME_STMT);
+ cast_assign = gimple_build_assign (tmp_u, cast);
+ find_new_referenced_vars (cast_assign);
+ gsi_insert_before (&gsi, cast_assign, GSI_SAME_STMT);
mark_symbols_for_renaming (cast_assign);
ulb = fold_convert (utype, info.range_min);
minus = fold_build2 (MINUS_EXPR, utype, tmp_u, ulb);
- minus = force_gimple_operand_bsi (&bsi, minus, false, NULL, true,
- BSI_SAME_STMT);
- minus_assign = build_gimple_modify_stmt (tmp_u, minus);
- find_new_referenced_vars (&minus_assign);
- bsi_insert_before (&bsi, minus_assign, BSI_SAME_STMT);
+ minus = force_gimple_operand_gsi (&gsi, minus, false, NULL, true,
+ GSI_SAME_STMT);
+ minus_assign = gimple_build_assign (tmp_u, minus);
+ find_new_referenced_vars (minus_assign);
+ gsi_insert_before (&gsi, minus_assign, GSI_SAME_STMT);
mark_symbols_for_renaming (minus_assign);
bound = fold_convert (utype, info.range_size);
- if_expr = build3 (COND_EXPR, void_type_node,
- build2 (LE_EXPR, boolean_type_node, tmp_u, bound),
- NULL_TREE, NULL_TREE);
+ cond_stmt = gimple_build_cond (LE_EXPR, tmp_u, bound, NULL_TREE, NULL_TREE);
- find_new_referenced_vars (&if_expr);
- bsi_insert_before (&bsi, if_expr, BSI_SAME_STMT);
- mark_symbols_for_renaming (if_expr);
+ find_new_referenced_vars (cond_stmt);
+ gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
+ mark_symbols_for_renaming (cond_stmt);
/* block 2 */
- bsi = bsi_for_stmt (info.arr_ref_first);
- label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
- bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
- last_assign = gen_def_assigns (&bsi);
+ gsi = gsi_for_stmt (info.arr_ref_first);
+ label2 = gimple_build_label (label_decl2);
+ gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
+ last_assign = gen_def_assigns (&gsi);
/* block 1 */
- bsi = bsi_for_stmt (info.arr_ref_first);
- label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
- bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
+ gsi = gsi_for_stmt (info.arr_ref_first);
+ label1 = gimple_build_label (label_decl1);
+ gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
/* block F */
- bsi = bsi_start (info.final_bb);
- label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
- bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
+ gsi = gsi_start_bb (info.final_bb);
+ label3 = gimple_build_label (label_decl3);
+ gsi_insert_before (&gsi, label3, GSI_SAME_STMT);
/* cfg fix */
- e02 = split_block (bb0, if_expr);
+ e02 = split_block (bb0, cond_stmt);
bb2 = e02->dest;
e21 = split_block (bb2, last_assign);
@@ -728,8 +725,8 @@ gen_inbound_check (tree swtch)
bb2->frequency = EDGE_FREQUENCY (e02);
bbf->frequency = EDGE_FREQUENCY (e1f) + EDGE_FREQUENCY (e2f);
- prune_bbs (bbd, info.final_bb); /* to keep calc_dfs_tree() in dominance.c
- happy */
+ prune_bbs (bbd, info.final_bb); /* To keep calc_dfs_tree() in dominance.c
+ happy. */
fix_phi_nodes (e1f, e2f, bbf);
@@ -742,31 +739,24 @@ gen_inbound_check (tree swtch)
one after another until one fails or the conversion is completed. */
static bool
-process_switch (tree swtch)
+process_switch (gimple swtch)
{
- int i;
- tree cases;
+ unsigned int i, branch_num = gimple_switch_num_labels (swtch);
tree index_type;
/* Operand 2 is either NULL_TREE or a vector of cases (stmt.c). */
- if (TREE_OPERAND (swtch, 2) == NULL_TREE)
+ if (branch_num < 2)
{
- info.reason = "swtch has no labels\n";
+ info.reason = "switch has no labels\n";
return false;
}
- /* Comment from stmt.c:
- The switch body is lowered in gimplify.c, we should never have switches
- with a non-NULL SWITCH_BODY here. */
- gcc_assert (!SWITCH_BODY (swtch));
-
- cases = SWITCH_LABELS (swtch);
info.final_bb = NULL;
- info.switch_bb = bb_for_stmt (swtch);
- info.index_expr = SWITCH_COND (swtch);
+ info.switch_bb = gimple_bb (swtch);
+ info.index_expr = gimple_switch_index (swtch);
index_type = TREE_TYPE (info.index_expr);
- info.arr_ref_first = NULL_TREE;
- info.arr_ref_last = NULL_TREE;
+ info.arr_ref_first = NULL;
+ info.arr_ref_last = NULL;
info.default_prob = 0;
info.default_count = 0;
info.other_count = 0;
@@ -785,16 +775,13 @@ process_switch (tree swtch)
/* For all the cases, see whether they are empty, the assignments they
represent constant and so on... */
- for (i = 0; i < TREE_VEC_LENGTH (cases); i++)
- {
- tree part_case = TREE_VEC_ELT (cases, i);
- if (!check_process_case (part_case))
- {
- if (dump_file)
- fprintf (dump_file, "Processing of case %i failed\n", i);
- return false;
- }
- }
+ for (i = 0; i < branch_num; i++)
+ if (!check_process_case (gimple_switch_label (swtch, i)))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Processing of case %i failed\n", i);
+ return false;
+ }
if (!check_final_bb ())
return false;
@@ -803,7 +790,7 @@ process_switch (tree swtch)
transformation. */
create_temp_arrays ();
- gather_default_values (TREE_VEC_ELT (cases, TREE_VEC_LENGTH (cases) - 1));
+ gather_default_values (gimple_switch_label (swtch, 0));
build_constructors (swtch);
build_arrays (swtch); /* Build the static arrays and assignments. */
@@ -824,17 +811,17 @@ do_switchconv (void)
FOR_EACH_BB (bb)
{
- tree stmt = last_stmt (bb);
- if (stmt && TREE_CODE (stmt) == SWITCH_EXPR)
+ gimple stmt = last_stmt (bb);
+ if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
{
- expanded_location loc = expand_location (EXPR_LOCATION (stmt));
-
if (dump_file)
{
+ expanded_location loc = expand_location (gimple_location (stmt));
+
fprintf (dump_file, "beginning to process the following "
"SWITCH statement (%s:%d) : ------- \n",
loc.file, loc.line);
- print_generic_stmt (dump_file, stmt, 2);
+ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
fprintf (dump_file, "\n");
}