OSDN Git Service

PR c++/55058
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-math-opts.c
index 6350647..bb60a62 100644 (file)
@@ -1,5 +1,5 @@
 /* Global, SSA-based optimizations using mathematical identities.
-   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -398,9 +398,10 @@ replace_reciprocal (use_operand_p use_p)
   if (optimize_bb_for_speed_p (bb)
       && 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);
       SET_USE (use_p, occ->recip_def);
-      fold_stmt_inplace (use_stmt);
+      fold_stmt_inplace (&gsi);
       update_stmt (use_stmt);
     }
 }
@@ -610,8 +611,9 @@ execute_cse_reciprocals (void)
 
                  FOR_EACH_IMM_USE_STMT (stmt, ui, arg1)
                    {
+                     gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
                      gimple_assign_set_rhs_code (stmt, MULT_EXPR);
-                     fold_stmt_inplace (stmt);
+                     fold_stmt_inplace (&gsi);
                      update_stmt (stmt);
                    }
                }
@@ -1385,12 +1387,18 @@ execute_cse_sincos (void)
   FOR_EACH_BB (bb)
     {
       gimple_stmt_iterator gsi;
+      bool cleanup_eh = false;
 
       for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
         {
          gimple stmt = gsi_stmt (gsi);
          tree fndecl;
 
+         /* Only the last stmt in a bb could throw, no need to call
+            gimple_purge_dead_eh_edges if we change something in the middle
+            of a basic block.  */
+         cleanup_eh = false;
+
          if (is_gimple_call (stmt)
              && gimple_call_lhs (stmt)
              && (fndecl = gimple_call_fndecl (stmt))
@@ -1428,6 +1436,7 @@ execute_cse_sincos (void)
                      gimple_set_location (new_stmt, loc);
                      unlink_stmt_vdef (stmt);
                      gsi_replace (&gsi, new_stmt, true);
+                     cleanup_eh = true;
                    }
                  break;
 
@@ -1448,6 +1457,7 @@ execute_cse_sincos (void)
                      gimple_set_location (new_stmt, loc);
                      unlink_stmt_vdef (stmt);
                      gsi_replace (&gsi, new_stmt, true);
+                     cleanup_eh = true;
                    }
                  break;
 
@@ -1463,6 +1473,7 @@ execute_cse_sincos (void)
                      gimple_set_location (new_stmt, loc);
                      unlink_stmt_vdef (stmt);
                      gsi_replace (&gsi, new_stmt, true);
+                     cleanup_eh = true;
                    }
                  break;
 
@@ -1470,6 +1481,8 @@ execute_cse_sincos (void)
                }
            }
        }
+      if (cleanup_eh)
+       cfg_changed |= gimple_purge_dead_eh_edges (bb);
     }
 
   statistics_counter_event (cfun, "sincos statements inserted",
@@ -1803,9 +1816,9 @@ execute_optimize_bswap (void)
   if (sizeof (HOST_WIDEST_INT) < 8)
     return 0;
 
-  bswap32_p = (built_in_decls[BUILT_IN_BSWAP32]
+  bswap32_p = (builtin_decl_explicit_p (BUILT_IN_BSWAP32)
               && optab_handler (bswap_optab, SImode) != CODE_FOR_nothing);
-  bswap64_p = (built_in_decls[BUILT_IN_BSWAP64]
+  bswap64_p = (builtin_decl_explicit_p (BUILT_IN_BSWAP64)
               && (optab_handler (bswap_optab, DImode) != CODE_FOR_nothing
                   || (bswap32_p && word_mode == SImode)));
 
@@ -1816,13 +1829,13 @@ execute_optimize_bswap (void)
      assumes that the return and argument type are the same.  */
   if (bswap32_p)
     {
-      tree fndecl = built_in_decls[BUILT_IN_BSWAP32];
+      tree fndecl = builtin_decl_explicit (BUILT_IN_BSWAP32);
       bswap32_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
     }
 
   if (bswap64_p)
     {
-      tree fndecl = built_in_decls[BUILT_IN_BSWAP64];
+      tree fndecl = builtin_decl_explicit (BUILT_IN_BSWAP64);
       bswap64_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
     }
 
@@ -1856,14 +1869,14 @@ execute_optimize_bswap (void)
            case 32:
              if (bswap32_p)
                {
-                 fndecl = built_in_decls[BUILT_IN_BSWAP32];
+                 fndecl = builtin_decl_explicit (BUILT_IN_BSWAP32);
                  bswap_type = bswap32_type;
                }
              break;
            case 64:
              if (bswap64_p)
                {
-                 fndecl = built_in_decls[BUILT_IN_BSWAP64];
+                 fndecl = builtin_decl_explicit (BUILT_IN_BSWAP64);
                  bswap_type = bswap64_type;
                }
              break;
@@ -2037,10 +2050,12 @@ 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 (tree type, gimple stmt,
+is_widening_mult_p (gimple stmt,
                    tree *type1_out, tree *rhs1_out,
                    tree *type2_out, tree *rhs2_out)
 {
+  tree type = TREE_TYPE (gimple_assign_lhs (stmt));
+
   if (TREE_CODE (type) != INTEGER_TYPE
       && TREE_CODE (type) != FIXED_POINT_TYPE)
     return false;
@@ -2102,7 +2117,7 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi)
   if (TREE_CODE (type) != INTEGER_TYPE)
     return false;
 
-  if (!is_widening_mult_p (type, stmt, &type1, &rhs1, &type2, &rhs2))
+  if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))
     return false;
 
   to_mode = TYPE_MODE (type);
@@ -2279,7 +2294,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
   if (code == PLUS_EXPR
       && (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR))
     {
-      if (!is_widening_mult_p (type, rhs1_stmt, &type1, &mult_rhs1,
+      if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
                               &type2, &mult_rhs2))
        return false;
       add_rhs = rhs2;
@@ -2287,7 +2302,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
     }
   else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR)
     {
-      if (!is_widening_mult_p (type, rhs2_stmt, &type1, &mult_rhs1,
+      if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
                               &type2, &mult_rhs2))
        return false;
       add_rhs = rhs1;
@@ -2300,10 +2315,13 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
   from_mode = TYPE_MODE (type1);
   from_unsigned1 = TYPE_UNSIGNED (type1);
   from_unsigned2 = TYPE_UNSIGNED (type2);
+  optype = type1;
 
   /* There's no such thing as a mixed sign madd yet, so use a wider mode.  */
   if (from_unsigned1 != from_unsigned2)
     {
+      if (!INTEGRAL_TYPE_P (type))
+       return false;
       /* We can use a signed multiply with unsigned types as long as
         there is a wider mode to use, or it is the smaller of the two
         types that is unsigned.  Note that type1 >= type2, always.  */
@@ -2318,6 +2336,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
        }
 
       from_unsigned1 = from_unsigned2 = false;
+      optype = build_nonstandard_integer_type (GET_MODE_PRECISION (from_mode),
+                                              false);
     }
 
   /* If there was a conversion between the multiply and addition
@@ -2351,7 +2371,6 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
   /* Verify that the machine can perform a widening multiply
      accumulate in this mode/signedness combination, otherwise
      this transformation is likely to pessimize code.  */
-  optype = build_nonstandard_integer_type (from_mode, from_unsigned1);
   this_optab = optab_for_tree_code (wmult_code, optype, optab_default);
   handler = find_widening_optab_handler_and_mode (this_optab, to_mode,
                                                  from_mode, 0, &actual_mode);
@@ -2386,9 +2405,9 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
 
   /* Handle constants.  */
   if (TREE_CODE (mult_rhs1) == INTEGER_CST)
-    rhs1 = fold_convert (type1, mult_rhs1);
+    mult_rhs1 = fold_convert (type1, mult_rhs1);
   if (TREE_CODE (mult_rhs2) == INTEGER_CST)
-    rhs2 = fold_convert (type2, mult_rhs2);
+    mult_rhs2 = fold_convert (type2, mult_rhs2);
 
   gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, mult_rhs1, mult_rhs2,
                                    add_rhs);
@@ -2425,6 +2444,12 @@ convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2)
   if (optab_handler (fma_optab, TYPE_MODE (type)) == CODE_FOR_nothing)
     return false;
 
+  /* If the multiplication has zero uses, it is kept around probably because
+     of -fnon-call-exceptions.  Don't optimize it away in that case,
+     it is DCE job.  */
+  if (has_zero_uses (mul_result))
+    return false;
+
   /* Make sure that the multiplication statement becomes dead after
      the transformation, thus that all uses are transformed to FMAs.
      This means we assume that an FMA operation has the same cost