diff mbox

[3/3] Introduce gimple_switch and use it in various places

Message ID 1399067771-11711-4-git-send-email-dmalcolm@redhat.com
State New
Headers show

Commit Message

David Malcolm May 2, 2014, 9:56 p.m. UTC
gcc/
	* gimple.h (gimple_switch): New subclass of gimple_stmt_with_ops,
	adding the invariant that stmt->code == GIMPLE_SWITCH.
	(is_a_helper <gimple_switch *>::test): New.
	(is_a_helper <const gimple_switch *>::test): New.
	(gimple_try): Likewise.

	* coretypes.h (gimple_switch): Add forward declaration here.

	* gdbhooks.py (build_pretty_printer): Add gimple_switch,
	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_stmt * 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.

	* doc/gimple.texi (Class hierarchy of GIMPLE statements): Add
	gimple_switch class.
	(GIMPLE_SWITCH): Update signatures of accessor functions to reflect
	above gimple_stmt to gimple_switch changes.
---
 gcc/cfgexpand.c              |  2 +-
 gcc/coretypes.h              |  5 ++++
 gcc/doc/gimple.texi          | 34 ++++++++++++++-----------
 gcc/expr.h                   |  2 +-
 gcc/gdbhooks.py              |  4 ++-
 gcc/gimple-pretty-print.c    |  4 +--
 gcc/gimple.c                 | 11 +++++----
 gcc/gimple.h                 | 44 ++++++++++++++++++++++++++-------
 gcc/ipa-inline-analysis.c    |  7 +++---
 gcc/omp-low.c                |  5 ++--
 gcc/stmt.c                   |  4 +--
 gcc/tree-cfg.c               | 59 ++++++++++++++++++++++----------------------
 gcc/tree-cfg.h               |  2 +-
 gcc/tree-eh.c                |  5 ++--
 gcc/tree-inline.c            | 21 +++++++++-------
 gcc/tree-loop-distribution.c |  5 ++--
 gcc/tree-ssa-dom.c           |  8 +++---
 gcc/tree-ssa-forwprop.c      |  6 ++---
 gcc/tree-ssa-uncprop.c       |  8 +++---
 gcc/tree-switch-conversion.c | 18 +++++++-------
 gcc/tree-vrp.c               | 24 +++++++++---------
 21 files changed, 162 insertions(+), 116 deletions(-)

Comments

Jeff Law May 9, 2014, 6:54 a.m. UTC | #1
On 05/02/14 15:56, David Malcolm wrote:
> gcc/
> 	* gimple.h (gimple_switch): New subclass of gimple_stmt_with_ops,
> 	adding the invariant that stmt->code == GIMPLE_SWITCH.
> 	(is_a_helper <gimple_switch *>::test): New.
> 	(is_a_helper <const gimple_switch *>::test): New.
> 	(gimple_try): Likewise.
>
> 	* coretypes.h (gimple_switch): Add forward declaration here.
>
> 	* gdbhooks.py (build_pretty_printer): Add gimple_switch,
> 	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_stmt * 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.
>
> 	* doc/gimple.texi (Class hierarchy of GIMPLE statements): Add
> 	gimple_switch class.
> 	(GIMPLE_SWITCH): Update signatures of accessor functions to reflect
> 	above gimple_stmt to gimple_switch changes.
OK after the "gimple_stmt" to "gimple" change referenced in prior 
messages related to this patchkit.

jeff
diff mbox

Patch

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 00d0db2..992521c 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3161,7 +3161,7 @@  expand_gimple_stmt_1 (gimple_stmt *stmt)
     case GIMPLE_PREDICT:
       break;
     case GIMPLE_SWITCH:
-      expand_case (stmt);
+      expand_case (as_a <gimple_switch *> (stmt));
       break;
     case GIMPLE_ASM:
       expand_asm_stmt (stmt);
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index c48f146..6aeb2b6 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -64,6 +64,11 @@  typedef const union tree_node *const_tree;
 class gimple_stmt;
 typedef gimple_stmt *gimple_seq;
 struct gimple_stmt_iterator;
+
+/* Forward declarations of gimple subclasses.
+   Keep this in the same order as the corresponding codes in gimple.def.  */
+class gimple_switch;
+
 union section;
 typedef union section section;
 struct gcc_options;
diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi
index 6fc4360..311c586 100644
--- a/gcc/doc/gimple.texi
+++ b/gcc/doc/gimple.texi
@@ -311,12 +311,14 @@  kinds, along with their relationships to @code{GSS_} values (layouts) and
      |   |    (no GSS layout)
      |   |
      |   + gimple_stmt_with_ops
-     |   |        layout: GSS_WITH_OPS
-     |   |        Used for 5 codes: GIMPLE_COND
-     |   |                          GIMPLE_DEBUG
-     |   |                          GIMPLE_GOTO
-     |   |                          GIMPLE_LABEL
-     |   |                          GIMPLE_SWITCH
+     |   |   |    layout: GSS_WITH_OPS
+     |   |   |    Used for 4 codes: GIMPLE_COND
+     |   |   |                      GIMPLE_DEBUG
+     |   |   |                      GIMPLE_GOTO
+     |   |   |                      GIMPLE_LABEL
+     |   |   |
+     |   |   + gimple_switch
+     |   |            code: GIMPLE_SWITCH
      |   |
      |   + gimple_stmt_with_memory_ops_base
      |       |    layout: GSS_WITH_MEM_OPS_BASE
@@ -2252,7 +2254,7 @@  Set @code{RETVAL} to be the return value for @code{GIMPLE_RETURN} @code{G}.
 @subsection @code{GIMPLE_SWITCH}
 @cindex @code{GIMPLE_SWITCH}
 
-@deftypefn {GIMPLE function} gimple_stmt *gimple_build_switch (tree index, @
+@deftypefn {GIMPLE function} gimple_switch *gimple_build_switch (tree index, @
 tree default_label, @code{VEC}(tree,heap) *args)
 Build a @code{GIMPLE_SWITCH} statement.  @code{INDEX} is the index variable
 to switch on, and @code{DEFAULT_LABEL} represents the default label.
@@ -2260,44 +2262,46 @@  to switch on, and @code{DEFAULT_LABEL} represents the default label.
 non-default case labels.  Each label is a tree of code @code{CASE_LABEL_EXPR}.
 @end deftypefn
 
-@deftypefn {GIMPLE function} unsigned gimple_switch_num_labels (gimple_stmt *g)
+@deftypefn {GIMPLE function} unsigned gimple_switch_num_labels (@
+const gimple_switch *g)
 Return the number of labels associated with the switch statement
 @code{G}.
 @end deftypefn
 
 @deftypefn {GIMPLE function} void gimple_switch_set_num_labels (@
-gimple_stmt *g, unsigned nlabels)
+gimple_switch *g, unsigned nlabels)
 Set @code{NLABELS} to be the number of labels for the switch statement
 @code{G}.
 @end deftypefn
 
-@deftypefn {GIMPLE function} tree gimple_switch_index (gimple_stmt *g)
+@deftypefn {GIMPLE function} tree gimple_switch_index (const gimple_switch *g)
 Return the index variable used by the switch statement @code{G}.
 @end deftypefn
 
-@deftypefn {GIMPLE function} void gimple_switch_set_index (gimple_stmt *g, @
+@deftypefn {GIMPLE function} void gimple_switch_set_index (gimple_switch *g, @
 tree index)
 Set @code{INDEX} to be the index variable for switch statement @code{G}.
 @end deftypefn
 
-@deftypefn {GIMPLE function} tree gimple_switch_label (gimple_stmt *g, @
+@deftypefn {GIMPLE function} tree gimple_switch_label (const gimple_switch *g, @
 unsigned index)
 Return the label numbered @code{INDEX}. The default label is 0, followed
 by any labels in a switch statement.
 @end deftypefn
 
-@deftypefn {GIMPLE function} void gimple_switch_set_label (gimple_stmt *g, @
+@deftypefn {GIMPLE function} void gimple_switch_set_label (gimple_switch *g, @
 unsigned index, tree label)
 Set the label number @code{INDEX} to @code{LABEL}. 0 is always the default
 label.
 @end deftypefn
 
-@deftypefn {GIMPLE function} tree gimple_switch_default_label (gimple_stmt *g)
+@deftypefn {GIMPLE function} tree gimple_switch_default_label (@
+const gimple_switch *g)
 Return the default label for a switch statement.
 @end deftypefn
 
 @deftypefn {GIMPLE function} void gimple_switch_set_default_label (@
-gimple_stmt *g, tree label)
+gimple_switch *g, tree label)
 Set the default label for a switch statement.
 @end deftypefn
 
diff --git a/gcc/expr.h b/gcc/expr.h
index 73a32f7..807dad5 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -777,7 +777,7 @@  rtx get_personality_function (tree);
 /* In stmt.c */
 
 /* Expand a GIMPLE_SWITCH statement.  */
-extern void expand_case (gimple_stmt *);
+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 2bc67f0..f5171f3 100644
--- a/gcc/gdbhooks.py
+++ b/gcc/gdbhooks.py
@@ -454,7 +454,9 @@  def build_pretty_printer():
                              'tree', TreePrinter)
     pp.add_printer_for_types(['cgraph_node *'],
                              'cgraph_node', CGraphNodePrinter)
-    pp.add_printer_for_types(['gimple_stmt *'],
+    pp.add_printer_for_types(['gimple_stmt *',
+                              # Keep this in the same order as gimple.def:
+                              'gimple_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 268b43bb..03ad971 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -775,7 +775,7 @@  dump_gimple_call (pretty_printer *buffer, gimple_stmt *gs, int spc, int flags)
    pp_gimple_stmt_1.  */
 
 static void
-dump_gimple_switch (pretty_printer *buffer, gimple_stmt *gs, int spc, int flags)
+dump_gimple_switch (pretty_printer *buffer, gimple_switch *gs, int spc, int flags)
 {
   unsigned int i;
 
@@ -2126,7 +2126,7 @@  pp_gimple_stmt_1 (pretty_printer *buffer, gimple_stmt *gs, int spc, int flags)
       break;
 
     case GIMPLE_SWITCH:
-      dump_gimple_switch (buffer, gs, spc, flags);
+      dump_gimple_switch (buffer, as_a <gimple_switch *> (gs), spc, flags);
       break;
 
     case GIMPLE_TRY:
diff --git a/gcc/gimple.c b/gcc/gimple.c
index bc8d757..9701f49 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_stmt *
+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_stmt *p = gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
-				    1 + 1 + nlabels);
+  gimple_switch *p =
+    as_a <gimple_switch *> (gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
+						   1 + 1 + nlabels));
   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_stmt *
+gimple_switch *
 gimple_build_switch (tree index, tree default_label, vec<tree> args)
 {
   unsigned i, nlabels = args.length ();
 
-  gimple_stmt *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 4cc88f0..0bf8853 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -764,6 +764,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_switch : public gimple_stmt_with_ops
+{
+  /* no additional fields; this uses the layout for GSS_WITH_OPS. */
+};
+
 template <>
 template <>
 inline bool
@@ -951,6 +961,14 @@  is_a_helper <gimple_phi *>::test (gimple_stmt *gs)
 template <>
 template <>
 inline bool
+is_a_helper <gimple_switch *>::test (gimple_stmt *gs)
+{
+  return gs->code == GIMPLE_SWITCH;
+}
+
+template <>
+template <>
+inline bool
 is_a_helper <gimple_transaction *>::test (gimple_stmt *gs)
 {
   return gs->code == GIMPLE_TRANSACTION;
@@ -1143,6 +1161,14 @@  is_a_helper <const gimple_phi *>::test (const gimple_stmt *gs)
 template <>
 template <>
 inline bool
+is_a_helper <const gimple_switch *>::test (const gimple_stmt *gs)
+{
+  return gs->code == GIMPLE_SWITCH;
+}
+
+template <>
+template <>
+inline bool
 is_a_helper <const gimple_transaction *>::test (const gimple_stmt *gs)
 {
   return gs->code == GIMPLE_TRANSACTION;
@@ -1193,8 +1219,8 @@  gimple_try *gimple_build_try (gimple_seq, gimple_seq,
 			      enum gimple_try_flags);
 gimple_stmt *gimple_build_wce (gimple_seq);
 gimple_stmt *gimple_build_resx (int);
-gimple_stmt *gimple_build_switch_nlabels (unsigned, tree, tree);
-gimple_stmt *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_stmt *gimple_build_eh_dispatch (int);
 gimple_stmt *gimple_build_debug_bind_stat (tree, tree, gimple_stmt *MEM_STAT_DECL);
 #define gimple_build_debug_bind(var,val,stmt)			\
@@ -3942,7 +3968,7 @@  gimple_eh_dispatch_set_region (gimple_stmt *gs, int region)
 /* Return the number of labels associated with the switch statement GS.  */
 
 static inline unsigned
-gimple_switch_num_labels (const gimple_stmt *gs)
+gimple_switch_num_labels (const gimple_switch *gs)
 {
   unsigned num_ops;
   GIMPLE_CHECK (gs, GIMPLE_SWITCH);
@@ -3955,7 +3981,7 @@  gimple_switch_num_labels (const gimple_stmt *gs)
 /* Set NLABELS to be the number of labels for the switch statement GS.  */
 
 static inline void
-gimple_switch_set_num_labels (gimple_stmt *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);
@@ -3985,7 +4011,7 @@  gimple_switch_index_ptr (const gimple_stmt *gs)
 /* Set INDEX to be the index variable for switch statement GS.  */
 
 static inline void
-gimple_switch_set_index (gimple_stmt *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));
@@ -3997,7 +4023,7 @@  gimple_switch_set_index (gimple_stmt *gs, tree index)
    labels in a switch statement.  */
 
 static inline tree
-gimple_switch_label (const gimple_stmt *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);
@@ -4007,7 +4033,7 @@  gimple_switch_label (const gimple_stmt *gs, unsigned index)
 /* Set the label number INDEX to LABEL.  0 is always the default label.  */
 
 static inline void
-gimple_switch_set_label (gimple_stmt *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
@@ -4019,7 +4045,7 @@  gimple_switch_set_label (gimple_stmt *gs, unsigned index, tree label)
 /* Return the default label for a switch statement.  */
 
 static inline tree
-gimple_switch_default_label (const gimple_stmt *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));
@@ -4029,7 +4055,7 @@  gimple_switch_default_label (const gimple_stmt *gs)
 /* Set the default label for a switch statement.  */
 
 static inline void
-gimple_switch_set_default_label (gimple_stmt *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 d4ecc09..35517c8 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -1801,7 +1801,7 @@  set_switch_stmt_execution_predicate (struct ipa_node_params *info,
 				     struct inline_summary *summary,
 				     basic_block bb)
 {
-  gimple_stmt *last;
+  gimple_stmt *lastg;
   tree op;
   int index;
   struct agg_position_info aggpos;
@@ -1810,9 +1810,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 = as_a <gimple_switch *> (lastg);
   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 f402d50..b6c845b 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -10462,10 +10462,11 @@  diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
 
     case GIMPLE_SWITCH:
       {
+	gimple_switch *switch_stmt = as_a <gimple_switch *> (stmt);
 	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_stmt *) n->value))
 	      break;
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 32dffaa..c1ae362 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 *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 *stmt)
    Generate the code to test it and jump to the right place.  */
 
 void
-expand_case (gimple_stmt *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 22621d2..e75c3b4 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -150,7 +150,7 @@  static void make_blocks (gimple_seq);
 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 bool make_goto_expr_edges (basic_block);
 static void make_gimple_asm_edges (basic_block);
 static edge gimple_redirect_edge_and_branch (edge, basic_block);
@@ -169,8 +169,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_stmt *, 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)
@@ -769,7 +769,7 @@  make_edges (void)
 	      fallthru = false;
 	      break;
 	    case GIMPLE_SWITCH:
-	      make_gimple_switch_edges (bb);
+	      make_gimple_switch_edges (as_a <gimple_switch *> (last), bb);
 	      fallthru = false;
 	      break;
 	    case GIMPLE_RESX:
@@ -1094,7 +1094,7 @@  end_recording_case_labels (void)
 	{
 	  gimple_stmt *stmt = last_stmt (bb);
 	  if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
-	    group_case_labels_stmt (stmt);
+	    group_case_labels_stmt (as_a <gimple_switch *> (stmt));
 	}
     }
   BITMAP_FREE (touched_switch_bbs);
@@ -1106,7 +1106,7 @@  end_recording_case_labels (void)
    Otherwise return NULL.  */
 
 static tree
-get_cases_for_edge (edge e, gimple_stmt *t)
+get_cases_for_edge (edge e, gimple_switch *t)
 {
   void **slot;
   size_t i, n;
@@ -1145,9 +1145,8 @@  get_cases_for_edge (edge e, gimple_stmt *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_stmt *entry = last_stmt (bb);
   size_t i, n;
 
   n = gimple_switch_num_labels (entry);
@@ -1398,12 +1397,13 @@  cleanup_dead_labels (void)
 
 	case GIMPLE_SWITCH:
 	  {
-	    size_t i, n = gimple_switch_num_labels (stmt);
+	    gimple_switch *switch_stmt = as_a <gimple_switch *> (stmt);
+	    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)
@@ -1500,7 +1500,7 @@  cleanup_dead_labels (void)
    Eg. three separate entries 1: 2: 3: become one entry 1..3:  */
 
 void
-group_case_labels_stmt (gimple_stmt *stmt)
+group_case_labels_stmt (gimple_switch *stmt)
 {
   int old_size = gimple_switch_num_labels (stmt);
   int i, j, new_size = old_size;
@@ -1588,7 +1588,7 @@  group_case_labels (void)
     {
       gimple_stmt *stmt = last_stmt (bb);
       if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
-	group_case_labels_stmt (stmt);
+	group_case_labels_stmt (as_a <gimple_switch *> (stmt));
     }
 }
 
@@ -2053,8 +2053,8 @@  find_taken_edge (basic_block bb, tree val)
   if (gimple_code (stmt) == GIMPLE_COND)
     return find_taken_edge_cond_expr (bb, val);
 
-  if (gimple_code (stmt) == GIMPLE_SWITCH)
-    return find_taken_edge_switch_expr (bb, val);
+  if (gimple_switch *switch_stmt = dyn_cast <gimple_switch *> (stmt))
+    return find_taken_edge_switch_expr (switch_stmt, bb, val);
 
   if (computed_goto_p (stmt))
     {
@@ -2113,14 +2113,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_stmt *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));
 
@@ -2135,7 +2134,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_stmt *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);
@@ -4262,7 +4261,7 @@  verify_gimple_goto (gimple_stmt *stmt)
    is a problem, otherwise false.  */
 
 static bool
-verify_gimple_switch (gimple_stmt *stmt)
+verify_gimple_switch (gimple_switch *stmt)
 {
   unsigned int i, n;
   tree elt, prev_upper_bound = NULL_TREE;
@@ -4444,7 +4443,7 @@  verify_gimple_stmt (gimple_stmt *stmt)
       return verify_gimple_goto (stmt);
 
     case GIMPLE_SWITCH:
-      return verify_gimple_switch (stmt);
+      return verify_gimple_switch (as_a <gimple_switch *> (stmt));
 
     case GIMPLE_RETURN:
       return verify_gimple_return (stmt);
@@ -5177,26 +5176,27 @@  gimple_verify_flow_info (void)
 
 	case GIMPLE_SWITCH:
 	  {
+	    gimple_switch *switch_stmt = as_a <gimple_switch *> (stmt);
 	    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 "
@@ -5242,7 +5242,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)
@@ -5430,8 +5430,9 @@  gimple_redirect_edge_and_branch (edge e, basic_block dest)
 
     case GIMPLE_SWITCH:
       {
+	gimple_switch *switch_stmt = as_a <gimple_switch *> (stmt);
 	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.  */
@@ -5452,7 +5453,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;
@@ -5461,11 +5462,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 347b55e..39fd302 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -32,7 +32,7 @@  extern void end_recording_case_labels (void);
 extern basic_block label_to_block_fn (struct function *, tree);
 #define label_to_block(t) (label_to_block_fn (cfun, t))
 extern void cleanup_dead_labels (void);
-extern void group_case_labels_stmt (gimple_stmt *);
+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 08e23ef..44bfd0c3 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 *stmt)
    of the labels will leave outer GIMPLE_TRY_FINALLY nodes. Verify this.  */
 
 static void
-verify_norecord_switch_expr (struct leh_state *state, gimple_stmt *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, as_a <gimple_switch *> (stmt));
       break;
 
     case GIMPLE_TRY:
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index ce4b0fb..32ae17a 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3813,15 +3813,18 @@  estimate_num_insns (gimple_stmt *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 = as_a <gimple_switch *> (stmt);
+	/* 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 41a5559..7eca65a 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -685,10 +685,11 @@  generate_loops_for_partition (struct loop *loop, partition_t partition,
 		  gimple_cond_make_false (stmt);
 		  update_stmt (stmt);
 		}
-	      else if (gimple_code (stmt) == GIMPLE_SWITCH)
+	      else if (gimple_switch *switch_stmt =
+		         dyn_cast <gimple_switch *> (stmt))
 		{
 		  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 7f5b4bb..244d79d 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -1784,21 +1784,21 @@  record_edge_info (basic_block bb)
       gimple_stmt *stmt = gsi_stmt (gsi);
       location_t loc = gimple_location (stmt);
 
-      if (gimple_code (stmt) == GIMPLE_SWITCH)
+      if (gimple_switch *switch_stmt = dyn_cast <gimple_switch *> (stmt))
 	{
-	  tree index = gimple_switch_index (stmt);
+	  tree index = gimple_switch_index (switch_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_for_fn (cfun));
 	      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 793f0fa..893a62c 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 *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 *stmt, tree index_type)
    the condition which we may be able to optimize better.  */
 
 static bool
-simplify_gimple_switch (gimple_stmt *stmt)
+simplify_gimple_switch (gimple_switch *stmt)
 {
   /* The optimization that we really care about is removing unnecessary
      casts.  That will let us do much better in propagating the inferred
@@ -3809,7 +3809,7 @@  pass_forwprop::execute (function *fun)
 	      }
 
 	    case GIMPLE_SWITCH:
-	      changed = simplify_gimple_switch (stmt);
+	      changed = simplify_gimple_switch (as_a <gimple_switch *> (stmt));
 	      break;
 
 	    case GIMPLE_COND:
diff --git a/gcc/tree-ssa-uncprop.c b/gcc/tree-ssa-uncprop.c
index 50ae88f..9b07967 100644
--- a/gcc/tree-ssa-uncprop.c
+++ b/gcc/tree-ssa-uncprop.c
@@ -171,14 +171,14 @@  associate_equivalences_with_edges (void)
       /* For a SWITCH_EXPR, a case label which represents a single
 	 value and which is the only case label which reaches the
 	 target block creates an equivalence.  */
-      else if (gimple_code (stmt) == GIMPLE_SWITCH)
+      else if (gimple_switch *switch_stmt = dyn_cast <gimple_switch *> (stmt))
 	{
-	  tree cond = gimple_switch_index (stmt);
+	  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_for_fn (cfun));
 
 	      /* Walk over the case label vector.  Record blocks
@@ -186,7 +186,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 a831a64..909355c 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -299,7 +299,7 @@  case_bit_test_cmp (const void *p1, const void *p2)
     node targets.  */
 
 static void
-emit_case_bit_tests (gimple_stmt *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];
@@ -609,7 +609,7 @@  struct switch_conv_info
 /* Collect information about GIMPLE_SWITCH statement SWTCH into INFO.  */
 
 static void
-collect_switch_conv_info (gimple_stmt *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;
@@ -853,7 +853,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_stmt *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;
@@ -945,7 +945,7 @@  constructor_contains_same_values_p (vec<constructor_elt, va_gc> *vec)
    all the constants.  */
 
 static tree
-array_value_type (gimple_stmt *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]);
@@ -1022,7 +1022,7 @@  array_value_type (gimple_stmt *swtch, tree type, int num,
    new array.  */
 
 static void
-build_one_array (gimple_stmt *swtch, int num, tree arr_index_type, gimple_stmt *phi,
+build_one_array (gimple_switch *swtch, int num, tree arr_index_type, gimple_stmt *phi,
 		 tree tidx, struct switch_conv_info *info)
 {
   tree name, cst;
@@ -1088,7 +1088,7 @@  build_one_array (gimple_stmt *swtch, int num, tree arr_index_type, gimple_stmt *
    them.  */
 
 static void
-build_arrays (gimple_stmt *swtch, struct switch_conv_info *info)
+build_arrays (gimple_switch *swtch, struct switch_conv_info *info)
 {
   tree arr_index_type;
   tree tidx, sub, utype;
@@ -1209,7 +1209,7 @@  fix_phi_nodes (edge e1f, edge e2f, basic_block bbf,
 */
 
 static void
-gen_inbound_check (gimple_stmt *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);
@@ -1329,7 +1329,7 @@  gen_inbound_check (gimple_stmt *swtch, struct switch_conv_info *info)
    conversion failed.  */
 
 static const char *
-process_switch (gimple_stmt *swtch)
+process_switch (gimple_switch *swtch)
 {
   struct switch_conv_info info;
 
@@ -1467,7 +1467,7 @@  pass_convert_switch::execute (function *fun)
 	    putc ('\n', dump_file);
 	  }
 
-	failure_reason = process_switch (stmt);
+	failure_reason = process_switch (as_a <gimple_switch *> (stmt));
 	if (! failure_reason)
 	  {
 	    if (dump_file)
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index b8db7a3..9252219 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 *stmt;
+  gimple_switch *stmt;
   tree vec;
 } switch_update;
 
@@ -5616,7 +5616,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_stmt *last)
+find_switch_asserts (basic_block bb, gimple_switch *last)
 {
   bool need_assert;
   gimple_stmt_iterator bsi;
@@ -5787,7 +5787,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, as_a <gimple_switch *> (last));
 
   /* Traverse all the statements in BB marking used names and looking
      for statements that may infer assertions for their used operands.  */
@@ -7269,7 +7269,7 @@  vrp_visit_cond_stmt (gimple_stmt *stmt, edge *taken_edge_p)
    returned. */
 
 static bool
-find_case_label_index (gimple_stmt *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;
@@ -7319,7 +7319,7 @@  find_case_label_index (gimple_stmt *stmt, size_t start_idx, tree val, size_t *id
    Returns true if the default label is not needed. */
 
 static bool
-find_case_label_range (gimple_stmt *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;
@@ -7375,7 +7375,7 @@  find_case_label_range (gimple_stmt *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 *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)
 {
@@ -7453,7 +7453,7 @@  find_case_label_ranges (gimple_stmt *stmt, value_range_t *vr, size_t *min_idx1,
    SSA_PROP_VARYING.  */
 
 static enum ssa_prop_result
-vrp_visit_switch_stmt (gimple_stmt *stmt, edge *taken_edge_p)
+vrp_visit_switch_stmt (gimple_switch *stmt, edge *taken_edge_p)
 {
   tree op, val;
   value_range_t *vr;
@@ -7568,8 +7568,8 @@  vrp_visit_stmt (gimple_stmt *stmt, edge *taken_edge_p, tree *output_p)
     return vrp_visit_assignment_or_call (stmt, 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);
+  else if (gimple_switch *switch_stmt = dyn_cast <gimple_switch *> (stmt))
+    return vrp_visit_switch_stmt (switch_stmt, taken_edge_p);
 
   /* All other statements produce nothing of interest for VRP, so mark
      their outputs varying and prevent further simulation.  */
@@ -9020,7 +9020,7 @@  simplify_cond_using_ranges (gimple_stmt *stmt)
    argument.  */
 
 static bool
-simplify_switch_using_ranges (gimple_stmt *stmt)
+simplify_switch_using_ranges (gimple_switch *stmt)
 {
   tree op = gimple_switch_index (stmt);
   value_range_t *vr;
@@ -9414,8 +9414,8 @@  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);
+  else if (gimple_switch *switch_stmt = dyn_cast <gimple_switch *> (stmt))
+    return simplify_switch_using_ranges (switch_stmt);
   else if (is_gimple_call (stmt)
 	   && gimple_call_internal_p (stmt))
     return simplify_internal_call_using_ranges (gsi, stmt);