]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-ssa-math-opts.c
PR c++/87554 - ICE with extern template and reference member.
[thirdparty/gcc.git] / gcc / tree-ssa-math-opts.c
index 5f1b3690239bebc243d0315040f04011a8c8eaac..b7bbde4e40288c1a3f93e06273652454f7ed0899 100644 (file)
@@ -334,7 +334,8 @@ is_division_by (gimple *use_stmt, tree 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_stmt) != def
+        && !stmt_can_throw_internal (cfun, use_stmt);
 }
 
 /* Return TRUE if USE_STMT is a multiplication of DEF by A.  */
@@ -367,13 +368,12 @@ is_division_by_square (gimple *use_stmt, tree def)
 {
   if (gimple_code (use_stmt) == GIMPLE_ASSIGN
       && gimple_assign_rhs_code (use_stmt) == RDIV_EXPR
-      && gimple_assign_rhs1 (use_stmt) != gimple_assign_rhs2 (use_stmt))
+      && gimple_assign_rhs1 (use_stmt) != gimple_assign_rhs2 (use_stmt)
+      && !stmt_can_throw_internal (cfun, use_stmt))
     {
       tree denominator = gimple_assign_rhs2 (use_stmt);
       if (TREE_CODE (denominator) == SSA_NAME)
-       {
-         return is_square_of (SSA_NAME_DEF_STMT (denominator), def);
-       }
+       return is_square_of (SSA_NAME_DEF_STMT (denominator), def);
     }
   return 0;
 }
@@ -799,7 +799,7 @@ execute_cse_reciprocals_1 (gimple_stmt_iterator *def_gsi, tree def)
 
   /* If it is more profitable to optimize 1 / x, don't optimize 1 / (x * x).  */
   if (sqrt_recip_count > square_recip_count)
-    return;
+    goto out;
 
   /* Do the expensive part only if we can hope to optimize something.  */
   if (count + square_recip_count >= threshold && count >= 1)
@@ -842,6 +842,7 @@ execute_cse_reciprocals_1 (gimple_stmt_iterator *def_gsi, tree def)
        }
     }
 
+out:
   for (occ = occ_head; occ; )
     occ = free_bb (occ);
 
@@ -2916,8 +2917,13 @@ convert_mult_to_fma_1 (tree mul_result, tree op1, tree op2)
       gsi_replace (&gsi, fma_stmt, true);
       /* Follow all SSA edges so that we generate FMS, FNMA and FNMS
         regardless of where the negation occurs.  */
+      gimple *orig_stmt = gsi_stmt (gsi);
       if (fold_stmt (&gsi, follow_all_ssa_edges))
-       update_stmt (gsi_stmt (gsi));
+       {
+         if (maybe_clean_or_replace_eh_stmt (orig_stmt, gsi_stmt (gsi)))
+           gcc_unreachable ();
+         update_stmt (gsi_stmt (gsi));
+       }
 
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
@@ -3088,6 +3094,7 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2,
        && (tree_to_shwi (TYPE_SIZE (type))
           <= PARAM_VALUE (PARAM_AVOID_FMA_MAX_BITS)));
   bool defer = check_defer;
+  bool seen_negate_p = 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
@@ -3121,6 +3128,12 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2,
          ssa_op_iter iter;
          use_operand_p usep;
 
+         /* If (due to earlier missed optimizations) we have two
+            negates of the same value, treat them as equivalent
+            to a single negate with multiple uses.  */
+         if (seen_negate_p)
+           return false;
+
          result = gimple_assign_lhs (use_stmt);
 
          /* Make sure the negate statement becomes dead with this
@@ -3139,7 +3152,7 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2,
          if (gimple_bb (use_stmt) != gimple_bb (mul_stmt))
            return false;
 
-         negate_p = true;
+         negate_p = seen_negate_p = true;
        }
 
       tree cond, else_value, ops[3];