[PATCH 02/16] Introduce gimple_switch and use it in various places
David Malcolm
dmalcolm@redhat.com
Fri Dec 13 15:59:00 GMT 2013
gcc/
* gimple.h (gimple_statement_switch): New subclass of
gimple_statement_with_ops, adding the invariant that
stmt->code == GIMPLE_SWITCH.
(gimple_statement_base::as_a_gimple_switch): New.
(gimple_statement_base::dyn_cast_gimple_switch): New.
(is_a_helper <gimple_statement_switch>::test (gimple)): New.
* coretypes.h (gimple_switch): New typedef
(const_gimple_switch): Likewise.
* gdbhooks.py (build_pretty_printer): Add gimple_switch
and its variants, using the gimple printer.
* gimple.c (gimple_build_switch_nlabels): Return a gimple_switch
rather than just a gimple.
(gimple_build_switch): Likewise.
* gimple.h (gimple_build_switch_nlabels): Likewise.
(gimple_build_switch): Likewise.
* gimple.h (gimple_switch_num_labels): Update type-signature to
require a gimple_switch rather than just a gimple.
(gimple_switch_set_num_labels): Likewise.
(gimple_switch_set_index): Likewise.
(gimple_switch_label): Likewise.
(gimple_switch_set_label): Likewise.
(gimple_switch_default_label): Likewise.
(gimple_switch_set_default_label): Likewise.
* expr.h (expand_case): Likewise.
* gimple-pretty-print.c (dump_gimple_call): Likewise.
* stmt.c (compute_cases_per_edge): Likewise.
(expand_case): Likewise.
* tree-cfg.h (group_case_labels_stmt): Likewise.
* tree-cfg.c (make_gimple_switch_edges): Likewise.
(find_taken_edge_switch_expr) Likewise.
(find_case_label_for_value) Likewise.
(get_cases_for_edge): Likewise.
(group_case_labels_stmt): Likewise.
(verify_gimple_switch): Likewise.
* tree-eh.c (verify_norecord_switch_expr): Likewise.
* tree-eh.c (lower_eh_constructs_2): Likewise.
* tree-loop-distribution.c (generate_loops_for_partition): Likewise.
* tree-ssa-dom.c (record_edge_info): Likewise.
* tree-ssa-forwprop.c (simplify_gimple_switch_label_vec): Likewise.
(simplify_gimple_switch): Likewise.
* tree-switch-conversion.c (emit_case_bit_tests): Likewise.
(collect_switch_conv_info): Likewise.
(build_constructors): Likewise.
(array_value_type): Likewise.
(build_one_array): Likewise.
(build_arrays): Likewise.
(gen_inbound_check): Likewise.
* tree-vrp.c (find_switch_asserts): Likewise.
(find_case_label_range): Likewise.
(find_case_label_ranges): Likewise.
(vrp_visit_switch_stmt): Likewise.
(simplify_switch_using_ranges): Likewise.
* tree-vrp.c (switch_update): Strengthen field "stmt" from being
merely a gimple to being a gimple_switch.
* cfgexpand.c (expand_gimple_stmt_1): Add checked cast to
gimple_switch in regions where the stmt code has been tested as
GIMPLE_SWITCH.
* gimple-pretty-print.c (pp_gimple_stmt_1): Likewise.
* tree-cfg.c (make_edges): Likewise.
(end_recording_case_labels): Likewise.
(cleanup_dead_labels): Likewise.
(cleanup_dead_labels): Likewise.
(group_case_labels): Likewise.
(find_taken_edge): Likewise.
(find_case_label_for_value): Likewise.
(verify_gimple_stmt): Likewise.
(gimple_verify_flow_info): Likewise.
(gimple_redirect_edge_and_branch): Likewise.
* tree-inline.c (estimate_num_insns): Likewise.
* tree-ssa-forwprop.c (ssa_forward_propagate_and_combine): Likewise.
* tree-ssa-uncprop.c (associate_equivalences_with_edges): Likewise.
* tree-switch-conversion.c (do_switchconv): Likewise.
* tree-vrp.c (find_assert_locations_1): Likewise.
(vrp_visit_stmt): Likewise.
(simplify_stmt_using_ranges): Likewise.
* ipa-inline-analysis.c (set_switch_stmt_execution_predicate):
Introduce local "lastg" as a generic gimple, so that local "last"
can be of type gimple_switch once lastg's code has been verified.
* omp-low.c (diagnose_sb_2): Introduce switch_stmt local to handle
the GIMPLE_SWITCH case.
* tree-cfg.c (find_taken_edge_switch_expr): Add gimple_switch
argument, since the caller (find_taken_edge) has checked that
last_stmt is a switch.
---
gcc/cfgexpand.c | 2 +-
gcc/coretypes.h | 8 +++++
gcc/expr.h | 2 +-
gcc/gdbhooks.py | 7 ++++-
gcc/gimple-pretty-print.c | 5 ++--
gcc/gimple.c | 11 +++----
gcc/gimple.h | 71 ++++++++++++++++++++++++++++++++++++++------
gcc/ipa-inline-analysis.c | 7 +++--
gcc/omp-low.c | 5 ++--
gcc/stmt.c | 4 +--
gcc/tree-cfg.c | 57 ++++++++++++++++++-----------------
gcc/tree-cfg.h | 2 +-
gcc/tree-eh.c | 5 ++--
gcc/tree-inline.c | 21 +++++++------
gcc/tree-loop-distribution.c | 3 +-
gcc/tree-ssa-dom.c | 5 ++--
gcc/tree-ssa-forwprop.c | 6 ++--
gcc/tree-ssa-uncprop.c | 7 +++--
gcc/tree-switch-conversion.c | 20 ++++++-------
gcc/tree-vrp.c | 20 ++++++-------
20 files changed, 173 insertions(+), 95 deletions(-)
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 853ace2..fcee483 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3145,7 +3145,7 @@ expand_gimple_stmt_1 (gimple stmt)
case GIMPLE_PREDICT:
break;
case GIMPLE_SWITCH:
- expand_case (stmt);
+ expand_case (stmt->as_a_gimple_switch ());
break;
case GIMPLE_ASM:
expand_asm_stmt (stmt);
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 5d60240..250d19f 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -66,6 +66,14 @@ typedef const struct gimple_statement_base *const_gimple;
typedef gimple gimple_seq;
struct gimple_stmt_iterator_d;
typedef struct gimple_stmt_iterator_d gimple_stmt_iterator;
+
+/* Typedefs for leaf gimple subclasses (for individual gimple codes).
+ Keep this in the same order as the corresponding codes in gimple.def. */
+
+struct gimple_statement_switch;
+typedef struct gimple_statement_switch *gimple_switch;
+typedef const struct gimple_statement_switch *const_gimple_switch;
+
union section;
typedef union section section;
struct gcc_options;
diff --git a/gcc/expr.h b/gcc/expr.h
index e734ef4..0c5b978 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -765,7 +765,7 @@ rtx get_personality_function (tree);
/* In stmt.c */
/* Expand a GIMPLE_SWITCH statement. */
-extern void expand_case (gimple);
+extern void expand_case (gimple_switch);
/* Like expand_case but special-case for SJLJ exception dispatching. */
extern void expand_sjlj_dispatch_table (rtx, vec<tree> );
diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py
index f0a925c..04f9cde 100644
--- a/gcc/gdbhooks.py
+++ b/gcc/gdbhooks.py
@@ -454,7 +454,12 @@ def build_pretty_printer():
'tree', TreePrinter)
pp.add_printer_for_types(['cgraph_node *'],
'cgraph_node', CGraphNodePrinter)
- pp.add_printer_for_types(['gimple', 'gimple_statement_base *'],
+ pp.add_printer_for_types(['gimple', 'gimple_statement_base *',
+
+ # Keep this in the same order as gimple.def:
+ 'gimple_switch', 'const_gimple_switch',
+ 'gimple_statement_switch *'],
+
'gimple',
GimplePrinter)
pp.add_printer_for_types(['basic_block', 'basic_block_def *'],
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 42e3f5f..fce6af0 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -775,7 +775,8 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags)
pp_gimple_stmt_1. */
static void
-dump_gimple_switch (pretty_printer *buffer, gimple gs, int spc, int flags)
+dump_gimple_switch (pretty_printer *buffer, gimple_switch gs, int spc,
+ int flags)
{
unsigned int i;
@@ -2125,7 +2126,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
break;
case GIMPLE_SWITCH:
- dump_gimple_switch (buffer, gs, spc, flags);
+ dump_gimple_switch (buffer, gs->as_a_gimple_switch (), spc, flags);
break;
case GIMPLE_TRY:
diff --git a/gcc/gimple.c b/gcc/gimple.c
index f11362a..c9518e2 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -714,13 +714,14 @@ gimple_build_resx (int region)
NLABELS is the number of labels in the switch excluding the default.
DEFAULT_LABEL is the default label for the switch statement. */
-gimple
+gimple_switch
gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label)
{
/* nlabels + 1 default label + 1 index. */
gcc_checking_assert (default_label);
- gimple p = gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
- 1 + 1 + nlabels);
+ gimple_switch p =
+ gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
+ 1 + 1 + nlabels)->as_a_gimple_switch ();
gimple_switch_set_index (p, index);
gimple_switch_set_default_label (p, default_label);
return p;
@@ -732,12 +733,12 @@ gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label)
DEFAULT_LABEL is the default label
ARGS is a vector of labels excluding the default. */
-gimple
+gimple_switch
gimple_build_switch (tree index, tree default_label, vec<tree> args)
{
unsigned i, nlabels = args.length ();
- gimple p = gimple_build_switch_nlabels (nlabels, index, default_label);
+ gimple_switch p = gimple_build_switch_nlabels (nlabels, index, default_label);
/* Copy the labels from the vector to the switch statement. */
for (i = 0; i < nlabels; i++)
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 7337c18..f1f5e8d 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -196,6 +196,41 @@ struct GTY((desc ("gimple_statement_structure (&%h)"), tag ("GSS_BASE"),
and the prev pointer being the last. */
gimple next;
gimple GTY((skip)) prev;
+
+public:
+ /* Downcasting methods, where the stmt *must* be of a given kind.
+ The cast is checked in a checked build, and a no-op in an
+ unchecked build.
+
+ Writing
+ stmt->as_a_gimple_foo ()
+ is less verbose than
+ as_a <gimple_statement_foo> (stmt)
+ and makes more sense when read as an English phrase.
+
+ Keep these in the same order as the corresponding entries in
+ gimple.def. */
+
+ inline gimple_switch
+ as_a_gimple_switch ()
+ {
+ return as_a <gimple_statement_switch> (this);
+ }
+
+ /* Dynamic casting methods, where the cast returns NULL if the
+ stmt is not of the required kind.
+
+ As above, writing
+ stmt->dyn_cast_gimple_foo ()
+ is less verbose than
+ dyn_cast <gimple_statement_foo> (stmt). */
+
+ inline gimple_switch
+ dyn_cast_gimple_switch ()
+ {
+ return dyn_cast <gimple_statement_switch> (this);
+ }
+
};
@@ -761,6 +796,16 @@ enum gimple_statement_structure_enum {
};
#undef DEFGSSTRUCT
+/* A statement with the invariant that
+ stmt->code == GIMPLE_SWITCH
+ i.e. a switch statement. */
+
+struct GTY((tag("GSS_WITH_OPS")))
+ gimple_statement_switch : public gimple_statement_with_ops
+{
+ /* no additional fields; this uses the layout for GSS_WITH_OPS. */
+};
+
template <>
template <>
inline bool
@@ -948,6 +993,14 @@ is_a_helper <gimple_statement_phi>::test (gimple gs)
template <>
template <>
inline bool
+is_a_helper <gimple_statement_switch>::test (gimple gs)
+{
+ return gs->code == GIMPLE_SWITCH;
+}
+
+template <>
+template <>
+inline bool
is_a_helper <gimple_statement_transaction>::test (gimple gs)
{
return gs->code == GIMPLE_TRANSACTION;
@@ -1190,8 +1243,8 @@ gimple_statement_try *gimple_build_try (gimple_seq, gimple_seq,
enum gimple_try_flags);
gimple gimple_build_wce (gimple_seq);
gimple gimple_build_resx (int);
-gimple gimple_build_switch_nlabels (unsigned, tree, tree);
-gimple gimple_build_switch (tree, tree, vec<tree> );
+gimple_switch gimple_build_switch_nlabels (unsigned, tree, tree);
+gimple_switch gimple_build_switch (tree, tree, vec<tree> );
gimple gimple_build_eh_dispatch (int);
gimple gimple_build_debug_bind_stat (tree, tree, gimple MEM_STAT_DECL);
#define gimple_build_debug_bind(var,val,stmt) \
@@ -3938,7 +3991,7 @@ gimple_eh_dispatch_set_region (gimple gs, int region)
/* Return the number of labels associated with the switch statement GS. */
static inline unsigned
-gimple_switch_num_labels (const_gimple gs)
+gimple_switch_num_labels (const_gimple_switch gs)
{
unsigned num_ops;
GIMPLE_CHECK (gs, GIMPLE_SWITCH);
@@ -3951,7 +4004,7 @@ gimple_switch_num_labels (const_gimple gs)
/* Set NLABELS to be the number of labels for the switch statement GS. */
static inline void
-gimple_switch_set_num_labels (gimple g, unsigned nlabels)
+gimple_switch_set_num_labels (gimple_switch g, unsigned nlabels)
{
GIMPLE_CHECK (g, GIMPLE_SWITCH);
gimple_set_num_ops (g, nlabels + 1);
@@ -3981,7 +4034,7 @@ gimple_switch_index_ptr (const_gimple gs)
/* Set INDEX to be the index variable for switch statement GS. */
static inline void
-gimple_switch_set_index (gimple gs, tree index)
+gimple_switch_set_index (gimple_switch gs, tree index)
{
GIMPLE_CHECK (gs, GIMPLE_SWITCH);
gcc_gimple_checking_assert (SSA_VAR_P (index) || CONSTANT_CLASS_P (index));
@@ -3993,7 +4046,7 @@ gimple_switch_set_index (gimple gs, tree index)
labels in a switch statement. */
static inline tree
-gimple_switch_label (const_gimple gs, unsigned index)
+gimple_switch_label (const_gimple_switch gs, unsigned index)
{
GIMPLE_CHECK (gs, GIMPLE_SWITCH);
gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 1);
@@ -4003,7 +4056,7 @@ gimple_switch_label (const_gimple gs, unsigned index)
/* Set the label number INDEX to LABEL. 0 is always the default label. */
static inline void
-gimple_switch_set_label (gimple gs, unsigned index, tree label)
+gimple_switch_set_label (gimple_switch gs, unsigned index, tree label)
{
GIMPLE_CHECK (gs, GIMPLE_SWITCH);
gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 1
@@ -4015,7 +4068,7 @@ gimple_switch_set_label (gimple gs, unsigned index, tree label)
/* Return the default label for a switch statement. */
static inline tree
-gimple_switch_default_label (const_gimple gs)
+gimple_switch_default_label (const_gimple_switch gs)
{
tree label = gimple_switch_label (gs, 0);
gcc_checking_assert (!CASE_LOW (label) && !CASE_HIGH (label));
@@ -4025,7 +4078,7 @@ gimple_switch_default_label (const_gimple gs)
/* Set the default label for a switch statement. */
static inline void
-gimple_switch_set_default_label (gimple gs, tree label)
+gimple_switch_set_default_label (gimple_switch gs, tree label)
{
gcc_checking_assert (!CASE_LOW (label) && !CASE_HIGH (label));
gimple_switch_set_label (gs, 0, label);
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index ad6fe8f..a8336d8 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -1774,7 +1774,7 @@ set_switch_stmt_execution_predicate (struct ipa_node_params *info,
struct inline_summary *summary,
basic_block bb)
{
- gimple last;
+ gimple lastg;
tree op;
int index;
struct agg_position_info aggpos;
@@ -1783,9 +1783,10 @@ set_switch_stmt_execution_predicate (struct ipa_node_params *info,
size_t n;
size_t case_idx;
- last = last_stmt (bb);
- if (!last || gimple_code (last) != GIMPLE_SWITCH)
+ lastg = last_stmt (bb);
+ if (!lastg || gimple_code (lastg) != GIMPLE_SWITCH)
return;
+ gimple_switch last = lastg->as_a_gimple_switch ();
op = gimple_switch_index (last);
if (!unmodified_parm_or_parm_agg_item (info, last, op, &index, &aggpos))
return;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index c929157..13fe3b2 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -10413,10 +10413,11 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
case GIMPLE_SWITCH:
{
+ gimple_switch switch_stmt = stmt->as_a_gimple_switch ();
unsigned int i;
- for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
+ for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
{
- tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
+ tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
break;
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 0d891b4..52617c7 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -1130,7 +1130,7 @@ reset_out_edges_aux (basic_block bb)
STMT. Record this information in the aux field of the edge. */
static inline void
-compute_cases_per_edge (gimple stmt)
+compute_cases_per_edge (gimple_switch stmt)
{
basic_block bb = gimple_bb (stmt);
reset_out_edges_aux (bb);
@@ -1152,7 +1152,7 @@ compute_cases_per_edge (gimple stmt)
Generate the code to test it and jump to the right place. */
void
-expand_case (gimple stmt)
+expand_case (gimple_switch stmt)
{
tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE;
rtx default_label = NULL_RTX;
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 6d1ebe6..290bda1 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -154,7 +154,7 @@ static void factor_computed_gotos (void);
static void make_edges (void);
static void assign_discriminators (void);
static void make_cond_expr_edges (basic_block);
-static void make_gimple_switch_edges (basic_block);
+static void make_gimple_switch_edges (gimple_switch, basic_block);
static void make_goto_expr_edges (basic_block);
static void make_gimple_asm_edges (basic_block);
static edge gimple_redirect_edge_and_branch (edge, basic_block);
@@ -174,8 +174,8 @@ static bool gimple_can_merge_blocks_p (basic_block, basic_block);
static void remove_bb (basic_block);
static edge find_taken_edge_computed_goto (basic_block, tree);
static edge find_taken_edge_cond_expr (basic_block, tree);
-static edge find_taken_edge_switch_expr (basic_block, tree);
-static tree find_case_label_for_value (gimple, tree);
+static edge find_taken_edge_switch_expr (gimple_switch, basic_block, tree);
+static tree find_case_label_for_value (gimple_switch, tree);
void
init_empty_tree_cfg_for_function (struct function *fn)
@@ -701,7 +701,7 @@ make_edges (void)
fallthru = false;
break;
case GIMPLE_SWITCH:
- make_gimple_switch_edges (bb);
+ make_gimple_switch_edges (last->as_a_gimple_switch (), bb);
fallthru = false;
break;
case GIMPLE_RESX:
@@ -950,7 +950,7 @@ end_recording_case_labels (void)
{
gimple stmt = last_stmt (bb);
if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
- group_case_labels_stmt (stmt);
+ group_case_labels_stmt (stmt->as_a_gimple_switch ());
}
}
BITMAP_FREE (touched_switch_bbs);
@@ -962,7 +962,7 @@ end_recording_case_labels (void)
Otherwise return NULL. */
static tree
-get_cases_for_edge (edge e, gimple t)
+get_cases_for_edge (edge e, gimple_switch t)
{
void **slot;
size_t i, n;
@@ -1001,9 +1001,8 @@ get_cases_for_edge (edge e, gimple t)
/* Create the edges for a GIMPLE_SWITCH starting at block BB. */
static void
-make_gimple_switch_edges (basic_block bb)
+make_gimple_switch_edges (gimple_switch entry, basic_block bb)
{
- gimple entry = last_stmt (bb);
size_t i, n;
n = gimple_switch_num_labels (entry);
@@ -1296,12 +1295,13 @@ cleanup_dead_labels (void)
case GIMPLE_SWITCH:
{
- size_t i, n = gimple_switch_num_labels (stmt);
+ gimple_switch switch_stmt = stmt->as_a_gimple_switch ();
+ size_t i, n = gimple_switch_num_labels (switch_stmt);
/* Replace all destination labels. */
for (i = 0; i < n; ++i)
{
- tree case_label = gimple_switch_label (stmt, i);
+ tree case_label = gimple_switch_label (switch_stmt, i);
label = CASE_LABEL (case_label);
new_label = main_block_label (label);
if (new_label != label)
@@ -1398,7 +1398,7 @@ cleanup_dead_labels (void)
Eg. three separate entries 1: 2: 3: become one entry 1..3: */
void
-group_case_labels_stmt (gimple stmt)
+group_case_labels_stmt (gimple_switch stmt)
{
int old_size = gimple_switch_num_labels (stmt);
int i, j, new_size = old_size;
@@ -1486,7 +1486,7 @@ group_case_labels (void)
{
gimple stmt = last_stmt (bb);
if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
- group_case_labels_stmt (stmt);
+ group_case_labels_stmt (stmt->as_a_gimple_switch ());
}
}
@@ -1952,7 +1952,7 @@ find_taken_edge (basic_block bb, tree val)
return find_taken_edge_cond_expr (bb, val);
if (gimple_code (stmt) == GIMPLE_SWITCH)
- return find_taken_edge_switch_expr (bb, val);
+ return find_taken_edge_switch_expr (stmt->as_a_gimple_switch (), bb, val);
if (computed_goto_p (stmt))
{
@@ -2011,14 +2011,13 @@ find_taken_edge_cond_expr (basic_block bb, tree val)
NULL if any edge may be taken. */
static edge
-find_taken_edge_switch_expr (basic_block bb, tree val)
+find_taken_edge_switch_expr (gimple_switch switch_stmt, basic_block bb,
+ tree val)
{
basic_block dest_bb;
edge e;
- gimple switch_stmt;
tree taken_case;
- switch_stmt = last_stmt (bb);
taken_case = find_case_label_for_value (switch_stmt, val);
dest_bb = label_to_block (CASE_LABEL (taken_case));
@@ -2033,7 +2032,7 @@ find_taken_edge_switch_expr (basic_block bb, tree val)
sorted: We can do a binary search for a case matching VAL. */
static tree
-find_case_label_for_value (gimple switch_stmt, tree val)
+find_case_label_for_value (gimple_switch switch_stmt, tree val)
{
size_t low, high, n = gimple_switch_num_labels (switch_stmt);
tree default_case = gimple_switch_default_label (switch_stmt);
@@ -4158,7 +4157,7 @@ verify_gimple_goto (gimple stmt)
is a problem, otherwise false. */
static bool
-verify_gimple_switch (gimple stmt)
+verify_gimple_switch (gimple_switch stmt)
{
unsigned int i, n;
tree elt, prev_upper_bound = NULL_TREE;
@@ -4339,7 +4338,7 @@ verify_gimple_stmt (gimple stmt)
return verify_gimple_goto (stmt);
case GIMPLE_SWITCH:
- return verify_gimple_switch (stmt);
+ return verify_gimple_switch (stmt->as_a_gimple_switch ());
case GIMPLE_RETURN:
return verify_gimple_return (stmt);
@@ -5071,26 +5070,27 @@ gimple_verify_flow_info (void)
case GIMPLE_SWITCH:
{
+ gimple_switch switch_stmt = stmt->as_a_gimple_switch ();
tree prev;
edge e;
size_t i, n;
- n = gimple_switch_num_labels (stmt);
+ n = gimple_switch_num_labels (switch_stmt);
/* Mark all the destination basic blocks. */
for (i = 0; i < n; ++i)
{
- tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
+ tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
basic_block label_bb = label_to_block (lab);
gcc_assert (!label_bb->aux || label_bb->aux == (void *)1);
label_bb->aux = (void *)1;
}
/* Verify that the case labels are sorted. */
- prev = gimple_switch_label (stmt, 0);
+ prev = gimple_switch_label (switch_stmt, 0);
for (i = 1; i < n; ++i)
{
- tree c = gimple_switch_label (stmt, i);
+ tree c = gimple_switch_label (switch_stmt, i);
if (!CASE_LOW (c))
{
error ("found default case not at the start of "
@@ -5136,7 +5136,7 @@ gimple_verify_flow_info (void)
/* Check that we have all of them. */
for (i = 0; i < n; ++i)
{
- tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
+ tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
basic_block label_bb = label_to_block (lab);
if (label_bb->aux != (void *)2)
@@ -5324,8 +5324,9 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
case GIMPLE_SWITCH:
{
+ gimple_switch switch_stmt = stmt->as_a_gimple_switch ();
tree label = gimple_block_label (dest);
- tree cases = get_cases_for_edge (e, stmt);
+ tree cases = get_cases_for_edge (e, switch_stmt);
/* If we have a list of cases associated with E, then use it
as it's a lot faster than walking the entire case vector. */
@@ -5346,7 +5347,7 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
to move all the cases associated with E to E2. */
if (e2)
{
- tree cases2 = get_cases_for_edge (e2, stmt);
+ tree cases2 = get_cases_for_edge (e2, switch_stmt);
CASE_CHAIN (last) = CASE_CHAIN (cases2);
CASE_CHAIN (cases2) = first;
@@ -5355,11 +5356,11 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
}
else
{
- size_t i, n = gimple_switch_num_labels (stmt);
+ size_t i, n = gimple_switch_num_labels (switch_stmt);
for (i = 0; i < n; i++)
{
- tree elt = gimple_switch_label (stmt, i);
+ tree elt = gimple_switch_label (switch_stmt, i);
if (label_to_block (CASE_LABEL (elt)) == e->dest)
CASE_LABEL (elt) = label;
}
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
index c5c105d..2906f9d 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -33,7 +33,7 @@ extern basic_block label_to_block_fn (struct function *, tree);
#define label_to_block(t) (label_to_block_fn (cfun, t))
extern void make_abnormal_goto_edges (basic_block, bool);
extern void cleanup_dead_labels (void);
-extern void group_case_labels_stmt (gimple);
+extern void group_case_labels_stmt (gimple_switch);
extern void group_case_labels (void);
extern void replace_uses_by (tree, tree);
extern basic_block single_noncomplex_succ (basic_block bb);
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 85dc79f..63424a7 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -713,7 +713,8 @@ maybe_record_in_goto_queue (struct leh_state *state, gimple stmt)
of the labels will leave outer GIMPLE_TRY_FINALLY nodes. Verify this. */
static void
-verify_norecord_switch_expr (struct leh_state *state, gimple switch_expr)
+verify_norecord_switch_expr (struct leh_state *state,
+ gimple_switch switch_expr)
{
struct leh_tf_state *tf = state->tf;
size_t i, n;
@@ -2057,7 +2058,7 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
break;
case GIMPLE_SWITCH:
- verify_norecord_switch_expr (state, stmt);
+ verify_norecord_switch_expr (state, stmt->as_a_gimple_switch ());
break;
case GIMPLE_TRY:
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index f42ade02..b1682b4 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3784,15 +3784,18 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
break;
case GIMPLE_SWITCH:
- /* Take into account cost of the switch + guess 2 conditional jumps for
- each case label.
-
- TODO: once the switch expansion logic is sufficiently separated, we can
- do better job on estimating cost of the switch. */
- if (weights->time_based)
- cost = floor_log2 (gimple_switch_num_labels (stmt)) * 2;
- else
- cost = gimple_switch_num_labels (stmt) * 2;
+ {
+ gimple_switch switch_stmt = stmt->as_a_gimple_switch ();
+ /* Take into account cost of the switch + guess 2 conditional jumps for
+ each case label.
+
+ TODO: once the switch expansion logic is sufficiently separated, we can
+ do better job on estimating cost of the switch. */
+ if (weights->time_based)
+ cost = floor_log2 (gimple_switch_num_labels (switch_stmt)) * 2;
+ else
+ cost = gimple_switch_num_labels (switch_stmt) * 2;
+ }
break;
case GIMPLE_CALL:
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index abf69f4..d9620e3 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -687,8 +687,9 @@ generate_loops_for_partition (struct loop *loop, partition_t partition,
}
else if (gimple_code (stmt) == GIMPLE_SWITCH)
{
+ gimple_switch switch_stmt = stmt->as_a_gimple_switch ();
gimple_switch_set_index
- (stmt, CASE_LOW (gimple_switch_label (stmt, 1)));
+ (switch_stmt, CASE_LOW (gimple_switch_label (switch_stmt, 1)));
update_stmt (stmt);
}
else
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 82005af..f2dc4d4 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -1787,19 +1787,20 @@ record_edge_info (basic_block bb)
if (gimple_code (stmt) == GIMPLE_SWITCH)
{
+ gimple_switch switch_stmt = stmt->as_a_gimple_switch ();
tree index = gimple_switch_index (stmt);
if (TREE_CODE (index) == SSA_NAME)
{
int i;
- int n_labels = gimple_switch_num_labels (stmt);
+ int n_labels = gimple_switch_num_labels (switch_stmt);
tree *info = XCNEWVEC (tree, last_basic_block);
edge e;
edge_iterator ei;
for (i = 0; i < n_labels; i++)
{
- tree label = gimple_switch_label (stmt, i);
+ tree label = gimple_switch_label (switch_stmt, i);
basic_block target_bb = label_to_block (CASE_LABEL (label));
if (CASE_HIGH (label)
|| !CASE_LOW (label)
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 6e6d115..7fad33c 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1284,7 +1284,7 @@ simplify_not_neg_expr (gimple_stmt_iterator *gsi_p)
have values outside the range of the new type. */
static void
-simplify_gimple_switch_label_vec (gimple stmt, tree index_type)
+simplify_gimple_switch_label_vec (gimple_switch stmt, tree index_type)
{
unsigned int branch_num = gimple_switch_num_labels (stmt);
auto_vec<tree> labels (branch_num);
@@ -1354,7 +1354,7 @@ simplify_gimple_switch_label_vec (gimple stmt, tree index_type)
the condition which we may be able to optimize better. */
static bool
-simplify_gimple_switch (gimple stmt)
+simplify_gimple_switch (gimple_switch stmt)
{
tree cond = gimple_switch_index (stmt);
tree def, to, ti;
@@ -3576,7 +3576,7 @@ ssa_forward_propagate_and_combine (void)
}
case GIMPLE_SWITCH:
- changed = simplify_gimple_switch (stmt);
+ changed = simplify_gimple_switch (stmt->as_a_gimple_switch ());
break;
case GIMPLE_COND:
diff --git a/gcc/tree-ssa-uncprop.c b/gcc/tree-ssa-uncprop.c
index 44194b8..6b0ffdc 100644
--- a/gcc/tree-ssa-uncprop.c
+++ b/gcc/tree-ssa-uncprop.c
@@ -173,12 +173,13 @@ associate_equivalences_with_edges (void)
target block creates an equivalence. */
else if (gimple_code (stmt) == GIMPLE_SWITCH)
{
- tree cond = gimple_switch_index (stmt);
+ gimple_switch switch_stmt = stmt->as_a_gimple_switch ();
+ tree cond = gimple_switch_index (switch_stmt);
if (TREE_CODE (cond) == SSA_NAME
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond))
{
- int i, n_labels = gimple_switch_num_labels (stmt);
+ int i, n_labels = gimple_switch_num_labels (switch_stmt);
tree *info = XCNEWVEC (tree, last_basic_block);
/* Walk over the case label vector. Record blocks
@@ -186,7 +187,7 @@ associate_equivalences_with_edges (void)
a single value. */
for (i = 0; i < n_labels; i++)
{
- tree label = gimple_switch_label (stmt, i);
+ tree label = gimple_switch_label (switch_stmt, i);
basic_block bb = label_to_block (CASE_LABEL (label));
if (CASE_HIGH (label)
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index f6b17b8..2a7976a 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -302,7 +302,7 @@ case_bit_test_cmp (const void *p1, const void *p2)
node targets. */
static void
-emit_case_bit_tests (gimple swtch, tree index_expr,
+emit_case_bit_tests (gimple_switch swtch, tree index_expr,
tree minval, tree range)
{
struct case_bit_test test[MAX_CASE_BIT_TESTS];
@@ -612,7 +612,7 @@ struct switch_conv_info
/* Collect information about GIMPLE_SWITCH statement SWTCH into INFO. */
static void
-collect_switch_conv_info (gimple swtch, struct switch_conv_info *info)
+collect_switch_conv_info (gimple_switch swtch, struct switch_conv_info *info)
{
unsigned int branch_num = gimple_switch_num_labels (swtch);
tree min_case, max_case;
@@ -856,7 +856,7 @@ gather_default_values (tree default_case, struct switch_conv_info *info)
order of phi nodes. SWTCH is the switch statement being converted. */
static void
-build_constructors (gimple swtch, struct switch_conv_info *info)
+build_constructors (gimple_switch swtch, struct switch_conv_info *info)
{
unsigned i, branch_num = gimple_switch_num_labels (swtch);
tree pos = info->range_min;
@@ -948,7 +948,7 @@ constructor_contains_same_values_p (vec<constructor_elt, va_gc> *vec)
all the constants. */
static tree
-array_value_type (gimple swtch, tree type, int num,
+array_value_type (gimple_switch swtch, tree type, int num,
struct switch_conv_info *info)
{
unsigned int i, len = vec_safe_length (info->constructors[num]);
@@ -1025,8 +1025,8 @@ array_value_type (gimple swtch, tree type, int num,
new array. */
static void
-build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi,
- tree tidx, struct switch_conv_info *info)
+build_one_array (gimple_switch swtch, int num, tree arr_index_type,
+ gimple phi, tree tidx, struct switch_conv_info *info)
{
tree name, cst;
gimple load;
@@ -1091,7 +1091,7 @@ build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi,
them. */
static void
-build_arrays (gimple swtch, struct switch_conv_info *info)
+build_arrays (gimple_switch swtch, struct switch_conv_info *info)
{
tree arr_index_type;
tree tidx, sub, utype;
@@ -1212,7 +1212,7 @@ fix_phi_nodes (edge e1f, edge e2f, basic_block bbf,
*/
static void
-gen_inbound_check (gimple swtch, struct switch_conv_info *info)
+gen_inbound_check (gimple_switch swtch, struct switch_conv_info *info)
{
tree label_decl1 = create_artificial_label (UNKNOWN_LOCATION);
tree label_decl2 = create_artificial_label (UNKNOWN_LOCATION);
@@ -1332,7 +1332,7 @@ gen_inbound_check (gimple swtch, struct switch_conv_info *info)
conversion failed. */
static const char *
-process_switch (gimple swtch)
+process_switch (gimple_switch swtch)
{
struct switch_conv_info info;
@@ -1437,7 +1437,7 @@ do_switchconv (void)
putc ('\n', dump_file);
}
- failure_reason = process_switch (stmt);
+ failure_reason = process_switch (stmt->as_a_gimple_switch ());
if (! failure_reason)
{
if (dump_file)
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index d9da996..c52702c 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -168,7 +168,7 @@ static bool values_propagated;
static int *vr_phi_edge_counts;
typedef struct {
- gimple stmt;
+ gimple_switch stmt;
tree vec;
} switch_update;
@@ -5656,7 +5656,7 @@ compare_case_labels (const void *p1, const void *p2)
list of assertions for the corresponding operands. */
static bool
-find_switch_asserts (basic_block bb, gimple last)
+find_switch_asserts (basic_block bb, gimple_switch last)
{
bool need_assert;
gimple_stmt_iterator bsi;
@@ -5827,7 +5827,7 @@ find_assert_locations_1 (basic_block bb, sbitmap live)
if (last
&& gimple_code (last) == GIMPLE_SWITCH
&& !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
- need_assert |= find_switch_asserts (bb, last);
+ need_assert |= find_switch_asserts (bb, last->as_a_gimple_switch ());
/* Traverse all the statements in BB marking used names and looking
for statements that may infer assertions for their used operands. */
@@ -7309,7 +7309,7 @@ vrp_visit_cond_stmt (gimple stmt, edge *taken_edge_p)
returned. */
static bool
-find_case_label_index (gimple stmt, size_t start_idx, tree val, size_t *idx)
+find_case_label_index (gimple_switch stmt, size_t start_idx, tree val, size_t *idx)
{
size_t n = gimple_switch_num_labels (stmt);
size_t low, high;
@@ -7359,7 +7359,7 @@ find_case_label_index (gimple stmt, size_t start_idx, tree val, size_t *idx)
Returns true if the default label is not needed. */
static bool
-find_case_label_range (gimple stmt, tree min, tree max, size_t *min_idx,
+find_case_label_range (gimple_switch stmt, tree min, tree max, size_t *min_idx,
size_t *max_idx)
{
size_t i, j;
@@ -7415,7 +7415,7 @@ find_case_label_range (gimple stmt, tree min, tree max, size_t *min_idx,
Returns true if the default label is not needed. */
static bool
-find_case_label_ranges (gimple stmt, value_range_t *vr, size_t *min_idx1,
+find_case_label_ranges (gimple_switch stmt, value_range_t *vr, size_t *min_idx1,
size_t *max_idx1, size_t *min_idx2,
size_t *max_idx2)
{
@@ -7493,7 +7493,7 @@ find_case_label_ranges (gimple stmt, value_range_t *vr, size_t *min_idx1,
SSA_PROP_VARYING. */
static enum ssa_prop_result
-vrp_visit_switch_stmt (gimple stmt, edge *taken_edge_p)
+vrp_visit_switch_stmt (gimple_switch stmt, edge *taken_edge_p)
{
tree op, val;
value_range_t *vr;
@@ -7609,7 +7609,7 @@ vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
else if (gimple_code (stmt) == GIMPLE_COND)
return vrp_visit_cond_stmt (stmt, taken_edge_p);
else if (gimple_code (stmt) == GIMPLE_SWITCH)
- return vrp_visit_switch_stmt (stmt, taken_edge_p);
+ return vrp_visit_switch_stmt (stmt->as_a_gimple_switch (), taken_edge_p);
/* All other statements produce nothing of interest for VRP, so mark
their outputs varying and prevent further simulation. */
@@ -9060,7 +9060,7 @@ simplify_cond_using_ranges (gimple stmt)
argument. */
static bool
-simplify_switch_using_ranges (gimple stmt)
+simplify_switch_using_ranges (gimple_switch stmt)
{
tree op = gimple_switch_index (stmt);
value_range_t *vr;
@@ -9366,7 +9366,7 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
else if (gimple_code (stmt) == GIMPLE_COND)
return simplify_cond_using_ranges (stmt);
else if (gimple_code (stmt) == GIMPLE_SWITCH)
- return simplify_switch_using_ranges (stmt);
+ return simplify_switch_using_ranges (stmt->as_a_gimple_switch ());
return false;
}
--
1.7.11.7
More information about the Gcc-patches
mailing list