From 667252e4489dc880428c5e69f1c1f7545852d608 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 13 May 2014 16:14:41 -0400
Subject: [PATCH 07/29] Introduce gassign and use it in various places

This corresponds to:
 "[PATCH 05/89] Introduce gimple_assign and use it in various places"
   http://gcc.gnu.org/ml/gcc-patches/2014-04/msg01151.html
from v1 of the patch series.

gcc/
	* coretypes.h (gassign): New forward declaration.

	* gimple.h (struct gassign): New subclass of
	gimple_with_memory_ops, adding the invariant that
	stmt->code == GIMPLE_ASSIGN.
	(is_a_helper <gassign *>::test): New.

	* gdbhooks.py (build_pretty_printer): Add gassign and its
	variants, using the gimple printer.

	* gimple-builder.c (build_assign): Return a gassign rather
	than just a gimple from each of the overloaded variants.
	(build_type_cast): Likewise.
	* gimple-builder.h (build_assign): Likewise.
	(build_type_cast): Likewise.
	* gimple.c (gimple_build_assign_stat): Likewise.
	(gimple_build_assign_with_ops): Likewise.
	* gimple.h (gimple_build_assign_stat): Likewise.
	(gimple_build_assign_with_ops): Likewise.

	* asan.c (get_mem_ref_of_assignment): Require a "const gassign *"
	rather than just a "const gimple *".
	* gimple-pretty-print.c (dump_unary_rhs): Require a gassign
	rather than just a gimple.
	(dump_binary_rhs): Likewise.
	(dump_ternary_rhs): Likewise.
	* tree-cfg.c (verify_gimple_assign_unary): Likewise.
	(verify_gimple_assign_binary): Likewise.
	(verify_gimple_assign_ternary): Likewise.
	(verify_gimple_assign_single): Likewise.
	(verify_gimple_assign): Likewise.
	* tree-ssa-sccvn.c (simplify_unary_expression): Likewise.
	(try_to_simplify): Likewise.
	* tree-tailcall.c (process_assignment): Likewise.
	* tree-vect-generic.c (expand_vector_operation): Likewise.
	* tree-vrp.c (extract_range_from_cond_expr): Likewise.
	(extract_range_from_assignment): Likewise.

	* asan.c (has_stmt_been_instrumented_p): Add checked cast to
	gassign in regions where a stmt is known to have code
	GIMPLE_ASSIGN.
	* gimple-pretty-print.c (pp_gimple_stmt_1): Likewise.
	* tree-cfg.c (verify_gimple_stmt): Likewise.
	* tree-ssa-sccvn.c (visit_use): Likewise.
	* tree-tailcall.c (find_tail_calls): Likewise.
	* tree-vrp.c (vrp_visit_assignment_or_call): Likewise.

	* tree-vrp.c (simplify_stmt_for_jump_threading): Replace a check
	against GIMPLE_ASSIGN with a dyn_cast to gassign, introducing
	a gassign local.

	* tree-vect-generic.c (expand_vector_condition): Convert local to a
	gassign, adding a checked cast when extracting from gsi, since
	this is only called when  underlying stmt has code GIMPLE_ASSIGN.
	(optimize_vector_constructor): Likewise.
	(lower_vec_perm): Likewise.
	(expand_vector_operations_1): Convert local to a gassign,
	introducing a dyn_cast.

	* doc/gimple.texi: Update for the above changes.
---
 gcc/asan.c                |  5 +++--
 gcc/coretypes.h           |  1 +
 gcc/doc/gimple.texi       | 11 +++++++----
 gcc/gdbhooks.py           |  1 +
 gcc/gimple-builder.c      | 16 ++++++++--------
 gcc/gimple-builder.h      | 16 ++++++++--------
 gcc/gimple-pretty-print.c | 10 +++++-----
 gcc/gimple.c              | 13 +++++++------
 gcc/gimple.h              | 28 +++++++++++++++++++++++-----
 gcc/tree-cfg.c            | 12 ++++++------
 gcc/tree-ssa-sccvn.c      |  6 +++---
 gcc/tree-tailcall.c       |  5 +++--
 gcc/tree-vect-generic.c   | 13 +++++++------
 gcc/tree-vrp.c            | 12 ++++++------
 14 files changed, 88 insertions(+), 61 deletions(-)

diff --git a/gcc/asan.c b/gcc/asan.c
index 6da3e68..ddea56e 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -434,7 +434,7 @@ has_mem_ref_been_instrumented (const asan_mem_ref *ref, tree len)
    otherwise.  */
 
 static bool
-get_mem_ref_of_assignment (const gimple *assignment,
+get_mem_ref_of_assignment (const gassign *assignment,
 			   asan_mem_ref *ref,
 			   bool *ref_is_store)
 {
@@ -802,7 +802,8 @@ has_stmt_been_instrumented_p (gimple *stmt)
       asan_mem_ref r;
       asan_mem_ref_init (&r, NULL, 1);
 
-      if (get_mem_ref_of_assignment (stmt, &r, &r_is_store))
+      if (get_mem_ref_of_assignment (as_a <gassign *> (stmt), &r,
+				     &r_is_store))
 	return has_mem_ref_been_instrumented (&r);
     }
   else if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index a9b1b5a..6eb5dcf 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -72,6 +72,7 @@ struct gimple_stmt_iterator;
    Keep this in the same order as the corresponding codes in gimple.def.  */
 class gcond;
 class gswitch;
+class gassign;
 class gbind;
 
 union section;
diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi
index 8f09f9a..7fc885c 100644
--- a/gcc/doc/gimple.texi
+++ b/gcc/doc/gimple.texi
@@ -326,8 +326,11 @@ kinds, along with their relationships to @code{GSS_} values (layouts) and
      |       |    layout: GSS_WITH_MEM_OPS_BASE
      |       |
      |       + gimple_with_memory_ops
-     |       |        layout: GSS_WITH_MEM_OPS.
-     |       |        used for codes GIMPLE_ASSIGN and GIMPLE_RETURN.
+     |       |   |    layout: GSS_WITH_MEM_OPS.
+     |       |   |    used for code GIMPLE_RETURN.
+     |       |   |
+     |       |   + gassign
+     |       |           code: GIMPLE_ASSIGN
      |       |
      |       + gcall
      |       |        layout: GSS_CALL, code: GIMPLE_CALL
@@ -1125,7 +1128,7 @@ Mark asm statement @code{G} as volatile.
 @subsection @code{GIMPLE_ASSIGN}
 @cindex @code{GIMPLE_ASSIGN}
 
-@deftypefn {GIMPLE function} gimple *gimple_build_assign (tree lhs, @
+@deftypefn {GIMPLE function} gassign *gimple_build_assign (tree lhs, @
 tree rhs)
 Build a @code{GIMPLE_ASSIGN} statement.  The left-hand side is an lvalue
 passed in lhs.  The right-hand side can be either a unary or
@@ -1152,7 +1155,7 @@ case they will be converted to a gimple operand if necessary.
 
 This function returns the newly created @code{GIMPLE_ASSIGN} tuple.
 
-@deftypefn {GIMPLE function} gimple *gimple_build_assign_with_ops @
+@deftypefn {GIMPLE function} gassign *gimple_build_assign_with_ops @
 (enum tree_code subcode, tree lhs, tree op1, tree op2)
 This function is similar to @code{gimple_build_assign}, but is used to
 build a @code{GIMPLE_ASSIGN} statement when the operands of the
diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py
index bdf49c1..2b689db 100644
--- a/gcc/gdbhooks.py
+++ b/gcc/gdbhooks.py
@@ -458,6 +458,7 @@ def build_pretty_printer():
                               # Keep this in the same order as gimple.def:
                               'gcond *', 'const gcond *',
                               'gswitch *', 'const gswitch *',
+                              'gassign *', 'const gassign *',
                               'gbind *', 'const gbind *'],
                              'gimple',
                              GimplePrinter)
diff --git a/gcc/gimple-builder.c b/gcc/gimple-builder.c
index 5a03bf0..0d873b1 100644
--- a/gcc/gimple-builder.c
+++ b/gcc/gimple-builder.c
@@ -51,7 +51,7 @@ get_expr_type (enum tree_code code, tree op)
    the expression code for the RHS.  OP1 is the first operand and VAL
    is an integer value to be used as the second operand.  */
 
-gimple *
+gassign *
 build_assign (enum tree_code code, tree op1, int val, tree lhs)
 {
   tree op2 = build_int_cst (TREE_TYPE (op1), val);
@@ -60,7 +60,7 @@ build_assign (enum tree_code code, tree op1, int val, tree lhs)
   return gimple_build_assign_with_ops (code, lhs, op1, op2);
 }
 
-gimple *
+gassign *
 build_assign (enum tree_code code, gimple *g, int val, tree lhs )
 {
   return build_assign (code, gimple_assign_lhs (g), val, lhs);
@@ -75,7 +75,7 @@ build_assign (enum tree_code code, gimple *g, int val, tree lhs )
    in normal form depending on the type of builder invoking this
    function.  */
 
-gimple *
+gassign *
 build_assign (enum tree_code code, tree op1, tree op2, tree lhs)
 {
   if (lhs == NULL_TREE)
@@ -83,19 +83,19 @@ build_assign (enum tree_code code, tree op1, tree op2, tree lhs)
   return gimple_build_assign_with_ops (code, lhs, op1, op2);
 }
 
-gimple *
+gassign *
 build_assign (enum tree_code code, gimple *op1, tree op2, tree lhs)
 {
   return build_assign (code, gimple_assign_lhs (op1), op2, lhs);
 }
 
-gimple *
+gassign *
 build_assign (enum tree_code code, tree op1, gimple *op2, tree lhs)
 {
   return build_assign (code, op1, gimple_assign_lhs (op2), lhs);
 }
 
-gimple *
+gassign *
 build_assign (enum tree_code code, gimple *op1, gimple *op2, tree lhs)
 {
   return build_assign (code, gimple_assign_lhs (op1), gimple_assign_lhs (op2),
@@ -106,7 +106,7 @@ build_assign (enum tree_code code, gimple *op1, gimple *op2, tree lhs)
 /* Create and return a type cast assignment. This creates a NOP_EXPR
    that converts OP to TO_TYPE.  */
 
-gimple *
+gassign *
 build_type_cast (tree to_type, tree op, tree lhs)
 {
   if (lhs == NULL_TREE)
@@ -114,7 +114,7 @@ build_type_cast (tree to_type, tree op, tree lhs)
   return gimple_build_assign_with_ops (NOP_EXPR, lhs, op, NULL_TREE);
 }
 
-gimple *
+gassign *
 build_type_cast (tree to_type, gimple *op, tree lhs)
 {
   return build_type_cast (to_type, gimple_assign_lhs (op), lhs);
diff --git a/gcc/gimple-builder.h b/gcc/gimple-builder.h
index 61ccd47..21d4c46 100644
--- a/gcc/gimple-builder.h
+++ b/gcc/gimple-builder.h
@@ -21,13 +21,13 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_GIMPLE_BUILDER_H
 #define GCC_GIMPLE_BUILDER_H
 
-gimple *build_assign (enum tree_code, tree, int, tree lhs = NULL_TREE);
-gimple *build_assign (enum tree_code, gimple *, int, tree lhs = NULL_TREE);
-gimple *build_assign (enum tree_code, tree, tree, tree lhs = NULL_TREE);
-gimple *build_assign (enum tree_code, gimple *, tree, tree lhs = NULL_TREE);
-gimple *build_assign (enum tree_code, tree, gimple *, tree lhs = NULL_TREE);
-gimple *build_assign (enum tree_code, gimple *, gimple *, tree lhs = NULL_TREE);
-gimple *build_type_cast (tree, tree, tree lhs = NULL_TREE);
-gimple *build_type_cast (tree, gimple *, tree lhs = NULL_TREE);
+gassign *build_assign (enum tree_code, tree, int, tree lhs = NULL_TREE);
+gassign *build_assign (enum tree_code, gimple *, int, tree lhs = NULL_TREE);
+gassign *build_assign (enum tree_code, tree, tree, tree lhs = NULL_TREE);
+gassign *build_assign (enum tree_code, gimple *, tree, tree lhs = NULL_TREE);
+gassign *build_assign (enum tree_code, tree, gimple *, tree lhs = NULL_TREE);
+gassign *build_assign (enum tree_code, gimple *, gimple *, tree lhs = NULL_TREE);
+gassign *build_type_cast (tree, tree, tree lhs = NULL_TREE);
+gassign *build_type_cast (tree, gimple *, tree lhs = NULL_TREE);
 
 #endif /* GCC_GIMPLE_BUILDER_H */
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 41551e5..f323391 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -261,7 +261,7 @@ dump_gimple_fmt (pretty_printer *buffer, int spc, int flags,
    assignment GS.  BUFFER, SPC and FLAGS are as in pp_gimple_stmt_1.  */
 
 static void
-dump_unary_rhs (pretty_printer *buffer, gimple *gs, int spc, int flags)
+dump_unary_rhs (pretty_printer *buffer, gassign *gs, int spc, int flags)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (gs);
   tree lhs = gimple_assign_lhs (gs);
@@ -345,7 +345,7 @@ dump_unary_rhs (pretty_printer *buffer, gimple *gs, int spc, int flags)
    assignment GS.  BUFFER, SPC and FLAGS are as in pp_gimple_stmt_1.  */
 
 static void
-dump_binary_rhs (pretty_printer *buffer, gimple *gs, int spc, int flags)
+dump_binary_rhs (pretty_printer *buffer, gassign *gs, int spc, int flags)
 {
   const char *p;
   enum tree_code code = gimple_assign_rhs_code (gs);
@@ -401,7 +401,7 @@ dump_binary_rhs (pretty_printer *buffer, gimple *gs, int spc, int flags)
    assignment GS.  BUFFER, SPC and FLAGS are as in pp_gimple_stmt_1.  */
 
 static void
-dump_ternary_rhs (pretty_printer *buffer, gimple *gs, int spc, int flags)
+dump_ternary_rhs (pretty_printer *buffer, gassign *gs, int spc, int flags)
 {
   const char *p;
   enum tree_code code = gimple_assign_rhs_code (gs);
@@ -486,7 +486,7 @@ dump_ternary_rhs (pretty_printer *buffer, gimple *gs, int spc, int flags)
    pp_gimple_stmt_1.  */
 
 static void
-dump_gimple_assign (pretty_printer *buffer, gimple *gs, int spc, int flags)
+dump_gimple_assign (pretty_printer *buffer, gassign *gs, int spc, int flags)
 {
   if (flags & TDF_RAW)
     {
@@ -2088,7 +2088,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple *gs, int spc, int flags)
       break;
 
     case GIMPLE_ASSIGN:
-      dump_gimple_assign (buffer, gs, spc, flags);
+      dump_gimple_assign (buffer, as_a <gassign *> (gs), spc, flags);
       break;
 
     case GIMPLE_BIND:
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 924a7ef..e9a2024 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -377,7 +377,7 @@ gimple_build_call_from_tree (tree t)
    LHS of the assignment.
    RHS of the assignment which can be unary or binary.  */
 
-gimple *
+gassign *
 gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL)
 {
   enum tree_code subcode;
@@ -393,19 +393,20 @@ gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL)
    OP1 and OP2.  If OP2 is NULL then SUBCODE must be of class
    GIMPLE_UNARY_RHS or GIMPLE_SINGLE_RHS.  */
 
-gimple *
+gassign *
 gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1,
 			      tree op2, tree op3 MEM_STAT_DECL)
 {
   unsigned num_ops;
-  gimple *p;
+  gassign *p;
 
   /* Need 1 operand for LHS and 1 or 2 for the RHS (depending on the
      code).  */
   num_ops = get_gimple_rhs_num_ops (subcode) + 1;
 
-  p = gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode, num_ops
-  			          PASS_MEM_STAT);
+  p = as_a <gassign *> (
+	gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode,
+				    num_ops PASS_MEM_STAT));
   gimple_assign_set_lhs (p, lhs);
   gimple_assign_set_rhs1 (p, op1);
   if (op2)
@@ -423,7 +424,7 @@ gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1,
   return p;
 }
 
-gimple *
+gassign *
 gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1,
 			      tree op2 MEM_STAT_DECL)
 {
diff --git a/gcc/gimple.h b/gcc/gimple.h
index ef35ac4..576abec 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -784,6 +784,16 @@ struct GTY((tag("GSS_WITH_OPS")))
   /* no additional fields; this uses the layout for GSS_WITH_OPS. */
 };
 
+/* A statement with the invariant that
+      stmt->code == GIMPLE_ASSIGN
+   i.e. an assignment statement.  */
+
+struct GTY((tag("GSS_WITH_MEM_OPS")))
+  gassign : public gimple_with_memory_ops
+{
+  /* no additional fields; this uses the layout for GSS_WITH_MEM_OPS. */
+};
+
 template <>
 template <>
 inline bool
@@ -803,6 +813,14 @@ is_a_helper <gbind *>::test (gimple *gs)
 template <>
 template <>
 inline bool
+is_a_helper <gassign *>::test (gimple *gs)
+{
+  return gs->code == GIMPLE_ASSIGN;
+}
+
+template <>
+template <>
+inline bool
 is_a_helper <gcall *>::test (gimple *gs)
 {
   return gs->code == GIMPLE_CALL;
@@ -1213,12 +1231,12 @@ gimple *gimple_build_call_valist (tree, unsigned, va_list);
 gimple *gimple_build_call_internal (enum internal_fn, unsigned, ...);
 gimple *gimple_build_call_internal_vec (enum internal_fn, vec<tree> );
 gimple *gimple_build_call_from_tree (tree);
-gimple *gimple_build_assign_stat (tree, tree MEM_STAT_DECL);
+gassign *gimple_build_assign_stat (tree, tree MEM_STAT_DECL);
 #define gimple_build_assign(l,r) gimple_build_assign_stat (l, r MEM_STAT_INFO)
-gimple *gimple_build_assign_with_ops (enum tree_code, tree,
-				     tree, tree, tree CXX_MEM_STAT_INFO);
-gimple *gimple_build_assign_with_ops (enum tree_code, tree,
-				     tree, tree CXX_MEM_STAT_INFO);
+gassign *gimple_build_assign_with_ops (enum tree_code, tree,
+				       tree, tree, tree CXX_MEM_STAT_INFO);
+gassign *gimple_build_assign_with_ops (enum tree_code, tree,
+				       tree, tree CXX_MEM_STAT_INFO);
 gcond *gimple_build_cond (enum tree_code, tree, tree, tree, tree);
 gcond *gimple_build_cond_from_tree (tree, tree, tree);
 void gimple_cond_set_condition_from_tree (gcond *, tree);
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index ebf8a339..4b8bc05 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3402,7 +3402,7 @@ verify_gimple_comparison (tree type, tree op0, tree op1)
    Returns true if anything is wrong.  */
 
 static bool
-verify_gimple_assign_unary (gimple *stmt)
+verify_gimple_assign_unary (gassign *stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
   tree lhs = gimple_assign_lhs (stmt);
@@ -3556,7 +3556,7 @@ verify_gimple_assign_unary (gimple *stmt)
    Returns true if anything is wrong.  */
 
 static bool
-verify_gimple_assign_binary (gimple *stmt)
+verify_gimple_assign_binary (gassign *stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
   tree lhs = gimple_assign_lhs (stmt);
@@ -3830,7 +3830,7 @@ verify_gimple_assign_binary (gimple *stmt)
    Returns true if anything is wrong.  */
 
 static bool
-verify_gimple_assign_ternary (gimple *stmt)
+verify_gimple_assign_ternary (gassign *stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
   tree lhs = gimple_assign_lhs (stmt);
@@ -3973,7 +3973,7 @@ verify_gimple_assign_ternary (gimple *stmt)
    Returns true if anything is wrong.  */
 
 static bool
-verify_gimple_assign_single (gimple *stmt)
+verify_gimple_assign_single (gassign *stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
   tree lhs = gimple_assign_lhs (stmt);
@@ -4175,7 +4175,7 @@ verify_gimple_assign_single (gimple *stmt)
    is a problem, otherwise false.  */
 
 static bool
-verify_gimple_assign (gimple *stmt)
+verify_gimple_assign (gassign *stmt)
 {
   switch (gimple_assign_rhs_class (stmt))
     {
@@ -4414,7 +4414,7 @@ verify_gimple_stmt (gimple *stmt)
   switch (gimple_code (stmt))
     {
     case GIMPLE_ASSIGN:
-      return verify_gimple_assign (stmt);
+      return verify_gimple_assign (as_a <gassign *> (stmt));
 
     case GIMPLE_LABEL:
       return verify_gimple_label (stmt);
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 7a7fce4..34ee79a 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -3282,7 +3282,7 @@ simplify_binary_expression (gimple *stmt)
    simplified. */
 
 static tree
-simplify_unary_expression (gimple *stmt)
+simplify_unary_expression (gassign *stmt)
 {
   tree result = NULL_TREE;
   tree orig_op0, op0 = gimple_assign_rhs1 (stmt);
@@ -3345,7 +3345,7 @@ simplify_unary_expression (gimple *stmt)
 /* Try to simplify RHS using equivalences and constant folding.  */
 
 static tree
-try_to_simplify (gimple *stmt)
+try_to_simplify (gassign *stmt)
 {
   enum tree_code code = gimple_assign_rhs_code (stmt);
   tree tem;
@@ -3433,7 +3433,7 @@ visit_use (tree use)
 	      changed = visit_copy (lhs, rhs1);
 	      goto done;
 	    }
-	  simplified = try_to_simplify (stmt);
+	  simplified = try_to_simplify (as_a <gassign *> (stmt));
 	  if (simplified)
 	    {
 	      if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index 06cd18d..4d7c2e9 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -267,7 +267,7 @@ independent_of_stmt_p (tree expr, gimple *at, gimple_stmt_iterator gsi)
    additive factor for the real return value.  */
 
 static bool
-process_assignment (gimple *stmt, gimple_stmt_iterator call, tree *m,
+process_assignment (gassign *stmt, gimple_stmt_iterator call, tree *m,
 		    tree *a, tree *ass_var)
 {
   tree op0, op1 = NULL_TREE, non_ass_var = NULL_TREE;
@@ -559,7 +559,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
 	return;
 
       /* This is a gimple assign. */
-      if (! process_assignment (stmt, gsi, &tmp_m, &tmp_a, &ass_var))
+      if (! process_assignment (as_a <gassign *> (stmt), gsi, &tmp_m,
+				&tmp_a, &ass_var))
 	return;
 
       if (tmp_a)
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index e427504..3addfdb 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -835,7 +835,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
 static void
 expand_vector_condition (gimple_stmt_iterator *gsi)
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
   tree type = gimple_expr_type (stmt);
   tree a = gimple_assign_rhs1 (stmt);
   tree a1 = a;
@@ -898,7 +898,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
 
 static tree
 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
-			 gimple *assign, enum tree_code code)
+			 gassign *assign, enum tree_code code)
 {
   enum machine_mode compute_mode = TYPE_MODE (compute_type);
 
@@ -1004,7 +1004,7 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type
 static void
 optimize_vector_constructor (gimple_stmt_iterator *gsi)
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
   tree lhs = gimple_assign_lhs (stmt);
   tree rhs = gimple_assign_rhs1 (stmt);
   tree type = TREE_TYPE (rhs);
@@ -1219,7 +1219,7 @@ vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
 static void
 lower_vec_perm (gimple_stmt_iterator *gsi)
 {
-  gimple *stmt = gsi_stmt (*gsi);
+  gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
   tree mask = gimple_assign_rhs3 (stmt);
   tree vec0 = gimple_assign_rhs1 (stmt);
   tree vec1 = gimple_assign_rhs2 (stmt);
@@ -1339,7 +1339,6 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
 static void
 expand_vector_operations_1 (gimple_stmt_iterator *gsi)
 {
-  gimple *stmt = gsi_stmt (*gsi);
   tree lhs, rhs1, rhs2 = NULL, type, compute_type;
   enum tree_code code;
   enum machine_mode compute_mode;
@@ -1347,7 +1346,9 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
   enum gimple_rhs_class rhs_class;
   tree new_rhs;
 
-  if (gimple_code (stmt) != GIMPLE_ASSIGN)
+  /* Only consider code == GIMPLE_ASSIGN. */
+  gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
+  if (!stmt)
     return;
 
   code = gimple_assign_rhs_code (stmt);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index cb78747..66a354e 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3432,7 +3432,7 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
    the ranges of each of its operands and the expression code.  */
 
 static void
-extract_range_from_cond_expr (value_range_t *vr, gimple *stmt)
+extract_range_from_cond_expr (value_range_t *vr, gassign *stmt)
 {
   tree op0, op1;
   value_range_t vr0 = VR_INITIALIZER;
@@ -3739,7 +3739,7 @@ extract_range_basic (value_range_t *vr, gimple *stmt)
    in *VR.  */
 
 static void
-extract_range_from_assignment (value_range_t *vr, gimple *stmt)
+extract_range_from_assignment (value_range_t *vr, gassign *stmt)
 {
   enum tree_code code = gimple_assign_rhs_code (stmt);
 
@@ -6672,7 +6672,7 @@ vrp_visit_assignment_or_call (gimple *stmt, tree *output_p)
       else if (code == GIMPLE_CALL)
 	extract_range_basic (&new_vr, stmt);
       else
-	extract_range_from_assignment (&new_vr, stmt);
+	extract_range_from_assignment (&new_vr, as_a <gassign *> (stmt));
 
       if (update_value_range (lhs, &new_vr))
 	{
@@ -9450,16 +9450,16 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt)
 				     gimple_cond_lhs (stmt),
 				     gimple_cond_rhs (stmt), within_stmt);
 
-  if (gimple_code (stmt) == GIMPLE_ASSIGN)
+  if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
     {
       value_range_t new_vr = VR_INITIALIZER;
-      tree lhs = gimple_assign_lhs (stmt);
+      tree lhs = gimple_assign_lhs (assign_stmt);
 
       if (TREE_CODE (lhs) == SSA_NAME
 	  && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
 	      || POINTER_TYPE_P (TREE_TYPE (lhs))))
 	{
-	  extract_range_from_assignment (&new_vr, stmt);
+	  extract_range_from_assignment (&new_vr, assign_stmt);
 	  if (range_int_cst_singleton_p (&new_vr))
 	    return new_vr.min;
 	}
-- 
1.8.5.3

