diff mbox

[gimple-classes,committed,12/17] tree-ssa-math-opts.c: Use gassign

Message ID 1415321971-19808-13-git-send-email-dmalcolm@redhat.com
State New
Headers show

Commit Message

David Malcolm Nov. 7, 2014, 12:59 a.m. UTC
gcc/ChangeLog.gimple-classes:
	* tree-ssa-math-opts.c (is_division_by): Replace is_gimple_assign
	with dyn_cast, introducing local gassign * "use_assign", using it
	in place of "use_stmt" for typesafety.
	(replace_reciprocal): Add a checked cast.
	(pass_cse_reciprocals::execute): Replace is_gimple_assign
	with dyn_cast, introducing local gassign * "assign_stmt", using it
	to eliminate "stmt" for typesafety.  Likewise replace local gimple
	"stmt2" with new local gassign * "assign_stmt2". Reintroduce local
	gimple "stmt" near the end for the FOR_EACH_IMM_USE_STMT loop,
	adding a checked cast.
	(find_bswap_or_nop_1): Strengthen return type and locals
	"source_stmt1" and "source_stmt2" from gimple to gassign *.
	Replace is_gimple_assign with a dyn_cast, introducing local
	gassign * "assign_stmt", using it in place of "stmt for
	typesafety.
	(find_bswap_or_nop): Strengthen return type and local
	"source_stmt" from gimple to gassign *.
	(bswap_replace): Likewise for params "cur_stmt" and "src_stmt".
	(pass_optimize_bswap::execute): Likewise for locals "src_stmt" and
	"cur_stmt", replacing an is_gimple_assign with a dyn_cast.
	(widening_mult_conversion_strippable_p): Likewise for param
	"stmt".
	(is_widening_mult_rhs_p): Replace is_gimple_assign with a
	dyn_cast, introducing local gassign * "assign_stmt" and using it
	in place of "stmt" for typesafety.
	(is_widening_mult_p): Strengthen param "stmt" from gimple to
	gassign *.
	(convert_mult_to_widen): Likewise.
	(convert_plusminus_to_widen): Likewise, also for locals
	"conv1_stmt", "conv2_stmt", "conv_stmt".  Replace is_gimple_assign
	calls with dyn_casts, using them to introduce local gassign *
	"rhs1_assign" and "rhs2_assign", using them in place of
	"rhs1_stmt" and "rhs2_stmt" in the regions where we know we have
	a GIMPLE_ASSIGN, adding gcc_assert to ensure that the gassign *
	is equal to their plain gimple counterparts where we assume this.
	(convert_mult_to_fma): Replace is_gimple_assigns with dyn_casts,
	introducing locals gassign * "use_assign" and using them in place
	of "use_stmt" for typesafety.  Similarly for the region where
	"use_stmt" is known to be a GIMPLE_ASSIGN, via a checked cast.
	(pass_optimize_widening_mul::execute): Replace is_gimple_assign
	with dyn_cast, introducing local gassign * "assign_stmt", using it
	to eliminate "stmt" for typesafety.
---
 gcc/ChangeLog.gimple-classes |  45 ++++++++++
 gcc/tree-ssa-math-opts.c     | 198 ++++++++++++++++++++++++-------------------
 2 files changed, 154 insertions(+), 89 deletions(-)
diff mbox

Patch

diff --git a/gcc/ChangeLog.gimple-classes b/gcc/ChangeLog.gimple-classes
index 45e3bd7..f5d557c 100644
--- a/gcc/ChangeLog.gimple-classes
+++ b/gcc/ChangeLog.gimple-classes
@@ -1,5 +1,50 @@ 
 2014-11-06  David Malcolm  <dmalcolm@redhat.com>
 
+	* tree-ssa-math-opts.c (is_division_by): Replace is_gimple_assign
+	with dyn_cast, introducing local gassign * "use_assign", using it
+	in place of "use_stmt" for typesafety.
+	(replace_reciprocal): Add a checked cast.
+	(pass_cse_reciprocals::execute): Replace is_gimple_assign
+	with dyn_cast, introducing local gassign * "assign_stmt", using it
+	to eliminate "stmt" for typesafety.  Likewise replace local gimple
+	"stmt2" with new local gassign * "assign_stmt2". Reintroduce local
+	gimple "stmt" near the end for the FOR_EACH_IMM_USE_STMT loop,
+	adding a checked cast.
+	(find_bswap_or_nop_1): Strengthen return type and locals
+	"source_stmt1" and "source_stmt2" from gimple to gassign *.
+	Replace is_gimple_assign with a dyn_cast, introducing local
+	gassign * "assign_stmt", using it in place of "stmt for
+	typesafety.
+	(find_bswap_or_nop): Strengthen return type and local
+	"source_stmt" from gimple to gassign *.
+	(bswap_replace): Likewise for params "cur_stmt" and "src_stmt".
+	(pass_optimize_bswap::execute): Likewise for locals "src_stmt" and
+	"cur_stmt", replacing an is_gimple_assign with a dyn_cast.
+	(widening_mult_conversion_strippable_p): Likewise for param
+	"stmt".
+	(is_widening_mult_rhs_p): Replace is_gimple_assign with a
+	dyn_cast, introducing local gassign * "assign_stmt" and using it
+	in place of "stmt" for typesafety.
+	(is_widening_mult_p): Strengthen param "stmt" from gimple to
+	gassign *.
+	(convert_mult_to_widen): Likewise.
+	(convert_plusminus_to_widen): Likewise, also for locals
+	"conv1_stmt", "conv2_stmt", "conv_stmt".  Replace is_gimple_assign
+	calls with dyn_casts, using them to introduce local gassign *
+	"rhs1_assign" and "rhs2_assign", using them in place of
+	"rhs1_stmt" and "rhs2_stmt" in the regions where we know we have
+	a GIMPLE_ASSIGN, adding gcc_assert to ensure that the gassign *
+	is equal to their plain gimple counterparts where we assume this.
+	(convert_mult_to_fma): Replace is_gimple_assigns with dyn_casts,
+	introducing locals gassign * "use_assign" and using them in place
+	of "use_stmt" for typesafety.  Similarly for the region where
+	"use_stmt" is known to be a GIMPLE_ASSIGN, via a checked cast.
+	(pass_optimize_widening_mul::execute): Replace is_gimple_assign
+	with dyn_cast, introducing local gassign * "assign_stmt", using it
+	to eliminate "stmt" for typesafety.
+
+2014-11-06  David Malcolm  <dmalcolm@redhat.com>
+
 	* tree-ssa-live.c (remove_unused_locals): Add a checked cast in
 	region guarded by gimple_clobber_p.
 
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index be567e0..b98d584 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -343,13 +343,14 @@  compute_merit (struct occurrence *occ)
 static inline bool
 is_division_by (gimple use_stmt, tree def)
 {
-  return is_gimple_assign (use_stmt)
-	 && gimple_assign_rhs_code (use_stmt) == RDIV_EXPR
-	 && gimple_assign_rhs2 (use_stmt) == def
+  gassign *use_assign = dyn_cast <gassign *> (use_stmt);
+  return use_assign
+	 && gimple_assign_rhs_code (use_assign) == RDIV_EXPR
+	 && gimple_assign_rhs2 (use_assign) == def
 	 /* Do not recognize x / x as valid division, as we are getting
 	    confused later by replacing all immediate uses x in such
 	    a stmt.  */
-	 && gimple_assign_rhs1 (use_stmt) != def;
+	 && gimple_assign_rhs1 (use_assign) != def;
 }
 
 /* Walk the subset of the dominator tree rooted at OCC, setting the
@@ -429,7 +430,7 @@  replace_reciprocal (use_operand_p use_p)
       && occ->recip_def && use_stmt != occ->recip_def_stmt)
     {
       gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
-      gimple_assign_set_rhs_code (use_stmt, MULT_EXPR);
+      gimple_assign_set_rhs_code (as_a <gassign *> (use_stmt), MULT_EXPR);
       SET_USE (use_p, occ->recip_def);
       fold_stmt_inplace (&gsi);
       update_stmt (use_stmt);
@@ -607,13 +608,14 @@  pass_cse_reciprocals::execute (function *fun)
       for (gimple_stmt_iterator gsi = gsi_after_labels (bb); !gsi_end_p (gsi);
 	   gsi_next (&gsi))
         {
-	  gimple stmt = gsi_stmt (gsi);
+	  gassign *assign_stmt;
 	  tree fndecl;
 
-	  if (is_gimple_assign (stmt)
-	      && gimple_assign_rhs_code (stmt) == RDIV_EXPR)
+	  assign_stmt = dyn_cast <gassign *> (gsi_stmt (gsi));
+	  if (assign_stmt
+	      && gimple_assign_rhs_code (assign_stmt) == RDIV_EXPR)
 	    {
-	      tree arg1 = gimple_assign_rhs2 (stmt);
+	      tree arg1 = gimple_assign_rhs2 (assign_stmt);
 	      gimple stmt1;
 
 	      if (TREE_CODE (arg1) != SSA_NAME)
@@ -648,10 +650,11 @@  pass_cse_reciprocals::execute (function *fun)
 		      gimple stmt2 = USE_STMT (use_p);
 		      if (is_gimple_debug (stmt2))
 			continue;
-		      if (!is_gimple_assign (stmt2)
-			  || gimple_assign_rhs_code (stmt2) != RDIV_EXPR
-			  || gimple_assign_rhs1 (stmt2) == arg1
-			  || gimple_assign_rhs2 (stmt2) != arg1)
+		      gassign *assign_stmt2 = dyn_cast <gassign *> (stmt2);
+		      if (!assign_stmt2
+			  || gimple_assign_rhs_code (assign_stmt2) != RDIV_EXPR
+			  || gimple_assign_rhs1 (assign_stmt2) == arg1
+			  || gimple_assign_rhs2 (assign_stmt2) != arg1)
 			{
 			  fail = true;
 			  break;
@@ -665,10 +668,12 @@  pass_cse_reciprocals::execute (function *fun)
 		  update_stmt (stmt1);
 		  reciprocal_stats.rfuncs_inserted++;
 
+		  gimple stmt;
 		  FOR_EACH_IMM_USE_STMT (stmt, ui, arg1)
 		    {
 		      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
-		      gimple_assign_set_rhs_code (stmt, MULT_EXPR);
+		      gimple_assign_set_rhs_code (as_a <gassign *> (stmt),
+						  MULT_EXPR);
 		      fold_stmt_inplace (&gsi);
 		      update_stmt (stmt);
 		    }
@@ -1835,31 +1840,33 @@  find_bswap_or_nop_load (gimple stmt, tree ref, struct symbolic_number *n)
    rhs's first tree is the expression of the source operand and NULL
    otherwise.  */
 
-static gimple
+static gassign *
 find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
 {
   enum tree_code code;
   tree rhs1, rhs2 = NULL;
-  gimple rhs1_stmt, rhs2_stmt, source_stmt1;
+  gimple rhs1_stmt, rhs2_stmt;
+  gassign *source_stmt1;
   enum gimple_rhs_class rhs_class;
+  gassign *assign_stmt = dyn_cast <gassign *> (stmt);
 
-  if (!limit || !is_gimple_assign (stmt))
+  if (!limit || !assign_stmt)
     return NULL;
 
-  rhs1 = gimple_assign_rhs1 (stmt);
+  rhs1 = gimple_assign_rhs1 (assign_stmt);
 
-  if (find_bswap_or_nop_load (stmt, rhs1, n))
-    return stmt;
+  if (find_bswap_or_nop_load (assign_stmt, rhs1, n))
+    return assign_stmt;
 
   if (TREE_CODE (rhs1) != SSA_NAME)
     return NULL;
 
-  code = gimple_assign_rhs_code (stmt);
-  rhs_class = gimple_assign_rhs_class (stmt);
+  code = gimple_assign_rhs_code (assign_stmt);
+  rhs_class = gimple_assign_rhs_class (assign_stmt);
   rhs1_stmt = SSA_NAME_DEF_STMT (rhs1);
 
   if (rhs_class == GIMPLE_BINARY_RHS)
-    rhs2 = gimple_assign_rhs2 (stmt);
+    rhs2 = gimple_assign_rhs2 (assign_stmt);
 
   /* Handle unary rhs and binary rhs with integer constants as second
      operand.  */
@@ -1883,10 +1890,10 @@  find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
 	 we have to initialize the symbolic number.  */
       if (!source_stmt1)
 	{
-	  if (gimple_assign_load_p (stmt)
+	  if (gimple_assign_load_p (assign_stmt)
 	      || !init_symbolic_number (n, rhs1))
 	    return NULL;
-	  source_stmt1 = stmt;
+	  source_stmt1 = assign_stmt;
 	}
 
       switch (code)
@@ -1919,7 +1926,7 @@  find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
 	    int i, type_size, old_type_size;
 	    tree type;
 
-	    type = gimple_expr_type (stmt);
+	    type = gimple_expr_type (assign_stmt);
 	    type_size = TYPE_PRECISION (type);
 	    if (type_size % BITS_PER_UNIT != 0)
 	      return NULL;
@@ -1949,7 +1956,7 @@  find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
 	default:
 	  return NULL;
 	};
-      return verify_symbolic_number_p (n, stmt) ? source_stmt1 : NULL;
+      return verify_symbolic_number_p (n, assign_stmt) ? source_stmt1 : NULL;
     }
 
   /* Handle binary rhs.  */
@@ -1959,7 +1966,7 @@  find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
       int i, size;
       struct symbolic_number n1, n2;
       uint64_t mask;
-      gimple source_stmt2;
+      gassign *source_stmt2;
 
       if (code != BIT_IOR_EXPR)
 	return NULL;
@@ -2064,7 +2071,7 @@  find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
 	    }
 	  n->n = n1.n | n2.n;
 
-	  if (!verify_symbolic_number_p (n, stmt))
+	  if (!verify_symbolic_number_p (n, assign_stmt))
 	    return NULL;
 
 	  break;
@@ -2084,7 +2091,7 @@  find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
    function returns a stmt whose rhs's first tree is the source
    expression.  */
 
-static gimple
+static gassign *
 find_bswap_or_nop (gimple stmt, struct symbolic_number *n, bool *bswap)
 {
 /* The number which the find_bswap_or_nop_1 result should match in order
@@ -2093,7 +2100,7 @@  find_bswap_or_nop (gimple stmt, struct symbolic_number *n, bool *bswap)
   uint64_t cmpxchg = CMPXCHG;
   uint64_t cmpnop = CMPNOP;
 
-  gimple source_stmt;
+  gassign *source_stmt;
   int limit;
 
   /* The last parameter determines the depth search limit.  It usually
@@ -2188,7 +2195,7 @@  public:
    some statistics.  */
 
 static bool
-bswap_replace (gimple cur_stmt, gimple_stmt_iterator gsi, gimple src_stmt,
+bswap_replace (gassign *cur_stmt, gimple_stmt_iterator gsi, gassign *src_stmt,
 	       tree fndecl, tree bswap_type, tree load_type,
 	       struct symbolic_number *n, bool bswap)
 {
@@ -2392,12 +2399,14 @@  pass_optimize_bswap::execute (function *fun)
 	 patterns, the wider variant wouldn't be detected.  */
       for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
         {
-	  gimple src_stmt, cur_stmt = gsi_stmt (gsi);
+	  gassign *src_stmt;
+	  gassign *cur_stmt;
 	  tree fndecl = NULL_TREE, bswap_type = NULL_TREE, load_type;
 	  struct symbolic_number n;
 	  bool bswap;
 
-	  if (!is_gimple_assign (cur_stmt)
+	  cur_stmt = dyn_cast <gassign *> (gsi_stmt (gsi));
+	  if (!cur_stmt
 	      || gimple_assign_rhs_code (cur_stmt) != BIT_IOR_EXPR)
 	    continue;
 
@@ -2472,7 +2481,7 @@  make_pass_optimize_bswap (gcc::context *ctxt)
 /* Return true if stmt is a type conversion operation that can be stripped
    when used in a widening multiply operation.  */
 static bool
-widening_mult_conversion_strippable_p (tree result_type, gimple stmt)
+widening_mult_conversion_strippable_p (tree result_type, gassign *stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
 
@@ -2530,13 +2539,13 @@  is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out,
   if (TREE_CODE (rhs) == SSA_NAME)
     {
       stmt = SSA_NAME_DEF_STMT (rhs);
-      if (is_gimple_assign (stmt))
+      if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
 	{
-	  if (! widening_mult_conversion_strippable_p (type, stmt))
+	  if (! widening_mult_conversion_strippable_p (type, assign_stmt))
 	    rhs1 = rhs;
 	  else
 	    {
-	      rhs1 = gimple_assign_rhs1 (stmt);
+	      rhs1 = gimple_assign_rhs1 (assign_stmt);
 
 	      if (TREE_CODE (rhs1) == INTEGER_CST)
 		{
@@ -2577,7 +2586,7 @@  is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out,
    and *TYPE2_OUT would give the operands of the multiplication.  */
 
 static bool
-is_widening_mult_p (gimple stmt,
+is_widening_mult_p (gassign *stmt,
 		    tree *type1_out, tree *rhs1_out,
 		    tree *type2_out, tree *rhs2_out)
 {
@@ -2629,7 +2638,7 @@  is_widening_mult_p (gimple stmt,
    value is true iff we converted the statement.  */
 
 static bool
-convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi)
+convert_mult_to_widen (gassign *stmt, gimple_stmt_iterator *gsi)
 {
   tree lhs, rhs1, rhs2, type, type1, type2;
   enum insn_code handler;
@@ -2730,11 +2739,12 @@  convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi)
    is true iff we converted the statement.  */
 
 static bool
-convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
+convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gassign *stmt,
 			    enum tree_code code)
 {
   gimple rhs1_stmt = NULL, rhs2_stmt = NULL;
-  gimple conv1_stmt = NULL, conv2_stmt = NULL, conv_stmt;
+  gassign *rhs1_assign = NULL, *rhs2_assign = NULL;
+  gassign *conv1_stmt = NULL, *conv2_stmt = NULL, *conv_stmt;
   tree type, type1, type2, optype;
   tree lhs, rhs1, rhs2, mult_rhs1, mult_rhs2, add_rhs;
   enum tree_code rhs1_code = ERROR_MARK, rhs2_code = ERROR_MARK;
@@ -2763,15 +2773,17 @@  convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
   if (TREE_CODE (rhs1) == SSA_NAME)
     {
       rhs1_stmt = SSA_NAME_DEF_STMT (rhs1);
-      if (is_gimple_assign (rhs1_stmt))
-	rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
+      rhs1_assign = dyn_cast <gassign *> (rhs1_stmt);
+      if (rhs1_assign)
+	rhs1_code = gimple_assign_rhs_code (rhs1_assign);
     }
 
   if (TREE_CODE (rhs2) == SSA_NAME)
     {
       rhs2_stmt = SSA_NAME_DEF_STMT (rhs2);
-      if (is_gimple_assign (rhs2_stmt))
-	rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
+      rhs2_assign = dyn_cast <gassign *> (rhs2_stmt);
+      if (rhs2_assign)
+	rhs2_code = gimple_assign_rhs_code (rhs2_assign);
     }
 
   /* Allow for one conversion statement between the multiply
@@ -2781,26 +2793,28 @@  convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
      been folded before now.  */
   if (CONVERT_EXPR_CODE_P (rhs1_code))
     {
-      conv1_stmt = rhs1_stmt;
-      rhs1 = gimple_assign_rhs1 (rhs1_stmt);
+      conv1_stmt = rhs1_assign;
+      rhs1 = gimple_assign_rhs1 (rhs1_assign);
       if (TREE_CODE (rhs1) == SSA_NAME)
 	{
 	  rhs1_stmt = SSA_NAME_DEF_STMT (rhs1);
-	  if (is_gimple_assign (rhs1_stmt))
-	    rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
+	  rhs1_assign = dyn_cast <gassign *> (rhs1_stmt);
+	  if (rhs1_assign)
+	    rhs1_code = gimple_assign_rhs_code (rhs1_assign);
 	}
       else
 	return false;
     }
   if (CONVERT_EXPR_CODE_P (rhs2_code))
     {
-      conv2_stmt = rhs2_stmt;
-      rhs2 = gimple_assign_rhs1 (rhs2_stmt);
+      conv2_stmt = rhs2_assign;
+      rhs2 = gimple_assign_rhs1 (as_a <gassign *> (rhs2_stmt));
       if (TREE_CODE (rhs2) == SSA_NAME)
 	{
 	  rhs2_stmt = SSA_NAME_DEF_STMT (rhs2);
-	  if (is_gimple_assign (rhs2_stmt))
-	    rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
+	  rhs2_assign = dyn_cast <gassign *> (rhs2_stmt);
+	  if (rhs2_assign)
+	    rhs2_code = gimple_assign_rhs_code (rhs2_assign);
 	}
       else
 	return false;
@@ -2818,8 +2832,9 @@  convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
   if (code == PLUS_EXPR
       && (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR))
     {
+      gcc_assert (rhs1_stmt == rhs1_assign);
       if (!has_single_use (rhs1)
-	  || !is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
+	  || !is_widening_mult_p (rhs1_assign, &type1, &mult_rhs1,
 				  &type2, &mult_rhs2))
 	return false;
       add_rhs = rhs2;
@@ -2827,8 +2842,9 @@  convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
     }
   else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR)
     {
+      gcc_assert (rhs2_stmt == rhs2_assign);
       if (!has_single_use (rhs2)
-	  || !is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
+	  || !is_widening_mult_p (rhs2_assign, &type1, &mult_rhs1,
 				  &type2, &mult_rhs2))
 	return false;
       add_rhs = rhs1;
@@ -2998,10 +3014,11 @@  convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2)
       if (gimple_bb (use_stmt) != gimple_bb (mul_stmt))
 	return false;
 
-      if (!is_gimple_assign (use_stmt))
+      gassign *use_assign = dyn_cast <gassign *> (use_stmt);
+      if (!use_assign)
 	return false;
 
-      use_code = gimple_assign_rhs_code (use_stmt);
+      use_code = gimple_assign_rhs_code (use_assign);
 
       /* A negate on the multiplication leads to FNMA.  */
       if (use_code == NEGATE_EXPR)
@@ -3009,11 +3026,11 @@  convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2)
 	  ssa_op_iter iter;
 	  use_operand_p usep;
 
-	  result = gimple_assign_lhs (use_stmt);
+	  result = gimple_assign_lhs (use_assign);
 
 	  /* Make sure the negate statement becomes dead with this
 	     single transformation.  */
-	  if (!single_imm_use (gimple_assign_lhs (use_stmt),
+	  if (!single_imm_use (gimple_assign_lhs (use_assign),
 			       &use_p, &neguse_stmt))
 	    return false;
 
@@ -3026,17 +3043,18 @@  convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2)
 	  use_stmt = neguse_stmt;
 	  if (gimple_bb (use_stmt) != gimple_bb (mul_stmt))
 	    return false;
-	  if (!is_gimple_assign (use_stmt))
+	  use_assign = dyn_cast <gassign *> (use_stmt);
+	  if (!use_assign)
 	    return false;
 
-	  use_code = gimple_assign_rhs_code (use_stmt);
+	  use_code = gimple_assign_rhs_code (use_assign);
 	  negate_p = true;
 	}
 
       switch (use_code)
 	{
 	case MINUS_EXPR:
-	  if (gimple_assign_rhs2 (use_stmt) == result)
+	  if (gimple_assign_rhs2 (use_assign) == result)
 	    negate_p = !negate_p;
 	  break;
 	case PLUS_EXPR:
@@ -3046,30 +3064,31 @@  convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2)
 	  return false;
 	}
 
-      /* If the subtrahend (gimple_assign_rhs2 (use_stmt)) is computed
+      /* If the subtrahend (gimple_assign_rhs2 (use_assign)) is computed
 	 by a MULT_EXPR that we'll visit later, we might be able to
 	 get a more profitable match with fnma.
 	 OTOH, if we don't, a negate / fma pair has likely lower latency
 	 that a mult / subtract pair.  */
       if (use_code == MINUS_EXPR && !negate_p
-	  && gimple_assign_rhs1 (use_stmt) == result
+	  && gimple_assign_rhs1 (use_assign) == result
 	  && optab_handler (fms_optab, TYPE_MODE (type)) == CODE_FOR_nothing
 	  && optab_handler (fnma_optab, TYPE_MODE (type)) != CODE_FOR_nothing)
 	{
-	  tree rhs2 = gimple_assign_rhs2 (use_stmt);
+	  tree rhs2 = gimple_assign_rhs2 (use_assign);
 
 	  if (TREE_CODE (rhs2) == SSA_NAME)
 	    {
 	      gimple stmt2 = SSA_NAME_DEF_STMT (rhs2);
 	      if (has_single_use (rhs2)
 		  && is_gimple_assign (stmt2)
-		  && gimple_assign_rhs_code (stmt2) == MULT_EXPR)
+		  && (gimple_assign_rhs_code (as_a <gassign *> (stmt2))
+		      == MULT_EXPR))
 	      return false;
 	    }
 	}
 
       /* We can't handle a * b + a * b.  */
-      if (gimple_assign_rhs1 (use_stmt) == gimple_assign_rhs2 (use_stmt))
+      if (gimple_assign_rhs1 (use_assign) == gimple_assign_rhs2 (use_assign))
 	return false;
 
       /* While it is possible to validate whether or not the exact form
@@ -3092,25 +3111,26 @@  convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2)
       if (is_gimple_debug (use_stmt))
 	continue;
 
-      use_code = gimple_assign_rhs_code (use_stmt);
+      gassign *use_assign = as_a <gassign *> (use_stmt);
+      use_code = gimple_assign_rhs_code (use_assign);
       if (use_code == NEGATE_EXPR)
 	{
-	  result = gimple_assign_lhs (use_stmt);
-	  single_imm_use (gimple_assign_lhs (use_stmt), &use_p, &neguse_stmt);
+	  result = gimple_assign_lhs (use_assign);
+	  single_imm_use (gimple_assign_lhs (use_assign), &use_p, &neguse_stmt);
 	  gsi_remove (&gsi, true);
-	  release_defs (use_stmt);
+	  release_defs (use_assign);
 
-	  use_stmt = neguse_stmt;
-	  gsi = gsi_for_stmt (use_stmt);
-	  use_code = gimple_assign_rhs_code (use_stmt);
+	  use_assign = as_a <gassign *> (neguse_stmt);
+	  gsi = gsi_for_stmt (use_assign);
+	  use_code = gimple_assign_rhs_code (use_assign);
 	  negate_p = true;
 	}
 
-      if (gimple_assign_rhs1 (use_stmt) == result)
+      if (gimple_assign_rhs1 (use_assign) == result)
 	{
-	  addop = gimple_assign_rhs2 (use_stmt);
+	  addop = gimple_assign_rhs2 (use_assign);
 	  /* a * b - c -> a * b + (-c)  */
-	  if (gimple_assign_rhs_code (use_stmt) == MINUS_EXPR)
+	  if (gimple_assign_rhs_code (use_assign) == MINUS_EXPR)
 	    addop = force_gimple_operand_gsi (&gsi,
 					      build1 (NEGATE_EXPR,
 						      type, addop),
@@ -3119,9 +3139,9 @@  convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2)
 	}
       else
 	{
-	  addop = gimple_assign_rhs1 (use_stmt);
+	  addop = gimple_assign_rhs1 (use_assign);
 	  /* a - b * c -> (-b) * c + a */
-	  if (gimple_assign_rhs_code (use_stmt) == MINUS_EXPR)
+	  if (gimple_assign_rhs_code (use_assign) == MINUS_EXPR)
 	    negate_p = !negate_p;
 	}
 
@@ -3133,7 +3153,7 @@  convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2)
 					   GSI_SAME_STMT);
 
       fma_stmt = gimple_build_assign_with_ops (FMA_EXPR,
-					       gimple_assign_lhs (use_stmt),
+					       gimple_assign_lhs (use_assign),
 					       mulop1, op2,
 					       addop);
       gsi_replace (&gsi, fma_stmt, true);
@@ -3196,26 +3216,26 @@  pass_optimize_widening_mul::execute (function *fun)
 	  gimple stmt = gsi_stmt (gsi);
 	  enum tree_code code;
 
-	  if (is_gimple_assign (stmt))
+	  if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
 	    {
-	      code = gimple_assign_rhs_code (stmt);
+	      code = gimple_assign_rhs_code (assign_stmt);
 	      switch (code)
 		{
 		case MULT_EXPR:
-		  if (!convert_mult_to_widen (stmt, &gsi)
-		      && convert_mult_to_fma (stmt,
-					      gimple_assign_rhs1 (stmt),
-					      gimple_assign_rhs2 (stmt)))
+		  if (!convert_mult_to_widen (assign_stmt, &gsi)
+		      && convert_mult_to_fma (assign_stmt,
+					      gimple_assign_rhs1 (assign_stmt),
+					      gimple_assign_rhs2 (assign_stmt)))
 		    {
 		      gsi_remove (&gsi, true);
-		      release_defs (stmt);
+		      release_defs (assign_stmt);
 		      continue;
 		    }
 		  break;
 
 		case PLUS_EXPR:
 		case MINUS_EXPR:
-		  convert_plusminus_to_widen (&gsi, stmt, code);
+		  convert_plusminus_to_widen (&gsi, assign_stmt, code);
 		  break;
 
 		default:;