]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/gimple-ssa-backprop.c
PR fortran/95090 - ICE: identifier overflow
[thirdparty/gcc.git] / gcc / gimple-ssa-backprop.c
index 3e64a7010c6efafe44e081a10e7e2eb77b96dce8..ced0e6ed83c3e372a74cc3d4ab3283059a33c335 100644 (file)
@@ -1,5 +1,5 @@
 /* Back-propagation of usage information to definitions.
-   Copyright (C) 2015-2016 Free Software Foundation, Inc.
+   Copyright (C) 2015-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -107,8 +107,9 @@ along with GCC; see the file COPYING3.  If not see
 namespace {
 
 /* Information about a group of uses of an SSA name.  */
-struct usage_info
+class usage_info
 {
+public:
   usage_info () : flag_word (0) {}
   usage_info &operator &= (const usage_info &);
   usage_info operator & (const usage_info &) const;
@@ -188,7 +189,7 @@ static void
 dump_usage_prefix (FILE *file, tree var)
 {
   fprintf (file, "  ");
-  print_generic_expr (file, var, 0);
+  print_generic_expr (file, var);
   fprintf (file, ": ");
 }
 
@@ -258,7 +259,12 @@ private:
 
   /* A bitmap of blocks that we have finished processing in the initial
      post-order walk.  */
-  sbitmap m_visited_blocks;
+  auto_sbitmap m_visited_blocks;
+
+  /* A bitmap of phis that we have finished processing in the initial
+     post-order walk, excluding those from blocks mentioned in
+     M_VISITED_BLOCKS.  */
+  auto_bitmap m_visited_phis;
 
   /* A worklist of SSA names whose definitions need to be reconsidered.  */
   auto_vec <tree, 64> m_worklist;
@@ -272,7 +278,7 @@ private:
 backprop::backprop (function *fn)
   : m_fn (fn),
     m_info_pool ("usage_info"),
-    m_visited_blocks (sbitmap_alloc (last_basic_block_for_fn (m_fn))),
+    m_visited_blocks (last_basic_block_for_fn (m_fn)),
     m_worklist_names (BITMAP_ALLOC (NULL))
 {
   bitmap_clear (m_visited_blocks);
@@ -281,7 +287,6 @@ backprop::backprop (function *fn)
 backprop::~backprop ()
 {
   BITMAP_FREE (m_worklist_names);
-  sbitmap_free (m_visited_blocks);
   m_info_pool.release ();
 }
 
@@ -310,7 +315,7 @@ backprop::push_to_worklist (tree var)
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "[WORKLIST] Pushing ");
-      print_generic_expr (dump_file, var, 0);
+      print_generic_expr (dump_file, var);
       fprintf (dump_file, "\n");
     }
 }
@@ -326,7 +331,7 @@ backprop::pop_from_worklist ()
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "[WORKLIST] Popping ");
-      print_generic_expr (dump_file, var, 0);
+      print_generic_expr (dump_file, var);
       fprintf (dump_file, "\n");
     }
   return var;
@@ -355,6 +360,7 @@ backprop::process_builtin_call_use (gcall *call, tree rhs, usage_info *info)
       break;
 
     CASE_CFN_COPYSIGN:
+    CASE_CFN_COPYSIGN_FN:
       /* The sign of the first input is ignored.  */
       if (rhs != gimple_call_arg (call, 1))
        info->flags.ignore_sign = true;
@@ -374,6 +380,10 @@ backprop::process_builtin_call_use (gcall *call, tree rhs, usage_info *info)
       }
 
     CASE_CFN_FMA:
+    CASE_CFN_FMA_FN:
+    case CFN_FMS:
+    case CFN_FNMA:
+    case CFN_FNMS:
       /* In X * X + Y, where Y is distinct from X, the sign of X doesn't
         matter.  */
       if (gimple_call_arg (call, 0) == rhs
@@ -404,6 +414,7 @@ backprop::process_assign_use (gassign *assign, tree rhs, usage_info *info)
   switch (gimple_assign_rhs_code (assign))
     {
     case ABS_EXPR:
+    case ABSU_EXPR:
       /* The sign of the input doesn't matter.  */
       info->flags.ignore_sign = true;
       break;
@@ -419,15 +430,6 @@ backprop::process_assign_use (gassign *assign, tree rhs, usage_info *info)
        }
       break;
 
-    case FMA_EXPR:
-      /* In X * X + Y, where Y is distinct from X, the sign of X doesn't
-        matter.  */
-      if (gimple_assign_rhs1 (assign) == rhs
-         && gimple_assign_rhs2 (assign) == rhs
-         && gimple_assign_rhs3 (assign) != rhs)
-       info->flags.ignore_sign = true;
-      break;
-
     case MULT_EXPR:
       /* In X * X, the sign of X doesn't matter.  */
       if (gimple_assign_rhs1 (assign) == rhs
@@ -470,7 +472,7 @@ backprop::process_use (gimple *stmt, tree rhs, usage_info *info)
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "[USE] ");
-      print_generic_expr (dump_file, rhs, 0);
+      print_generic_expr (dump_file, rhs);
       fprintf (dump_file, " in ");
       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
     }
@@ -495,22 +497,26 @@ bool
 backprop::intersect_uses (tree var, usage_info *info)
 {
   imm_use_iterator iter;
-  gimple *stmt;
+  use_operand_p use_p;
   *info = usage_info::intersection_identity ();
-  FOR_EACH_IMM_USE_STMT (stmt, iter, var)
+  FOR_EACH_IMM_USE_FAST (use_p, iter, var)
     {
+      gimple *stmt = USE_STMT (use_p);
       if (is_gimple_debug (stmt))
        continue;
-      if (is_a <gphi *> (stmt)
-         && !bitmap_bit_p (m_visited_blocks, gimple_bb (stmt)->index))
+      gphi *phi = dyn_cast <gphi *> (stmt);
+      if (phi
+         && !bitmap_bit_p (m_visited_blocks, gimple_bb (phi)->index)
+         && !bitmap_bit_p (m_visited_phis,
+                           SSA_NAME_VERSION (gimple_phi_result (phi))))
        {
          /* Skip unprocessed phis.  */
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file, "[BACKEDGE] ");
-             print_generic_expr (dump_file, var, 0);
+             print_generic_expr (dump_file, var);
              fprintf (dump_file, " in ");
-             print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+             print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
            }
        }
       else
@@ -519,10 +525,7 @@ backprop::intersect_uses (tree var, usage_info *info)
          process_use (stmt, var, &subinfo);
          *info &= subinfo;
          if (!info->is_useful ())
-           {
-             BREAK_FROM_IMM_USE_STMT (iter);
-             return false;
-           }
+           return false;
        }
     }
   return true;
@@ -634,7 +637,12 @@ backprop::process_block (basic_block bb)
     }
   for (gphi_iterator gpi = gsi_start_phis (bb); !gsi_end_p (gpi);
        gsi_next (&gpi))
-    process_var (gimple_phi_result (gpi.phi ()));
+    {
+      tree result = gimple_phi_result (gpi.phi ());
+      process_var (result);
+      bitmap_set_bit (m_visited_phis, SSA_NAME_VERSION (result));
+    }
+  bitmap_clear (m_visited_phis);
 }
 
 /* Delete the definition of VAR, which has no uses.  */
@@ -659,9 +667,9 @@ static void
 note_replacement (gimple *stmt, tree old_rhs, tree new_rhs)
 {
   fprintf (dump_file, "Replacing use of ");
-  print_generic_expr (dump_file, old_rhs, 0);
+  print_generic_expr (dump_file, old_rhs);
   fprintf (dump_file, " with ");
-  print_generic_expr (dump_file, new_rhs, 0);
+  print_generic_expr (dump_file, new_rhs);
   fprintf (dump_file, " in ");
   print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
 }
@@ -680,6 +688,7 @@ strip_sign_op_1 (tree rhs)
     switch (gimple_assign_rhs_code (assign))
       {
       case ABS_EXPR:
+      case ABSU_EXPR:
       case NEGATE_EXPR:
        return gimple_assign_rhs1 (assign);
 
@@ -690,6 +699,7 @@ strip_sign_op_1 (tree rhs)
     switch (gimple_call_combined_fn (call))
       {
       CASE_CFN_COPYSIGN:
+      CASE_CFN_COPYSIGN_FN:
        return gimple_call_arg (call, 0);
 
       default:
@@ -727,8 +737,9 @@ strip_sign_op (tree rhs)
 void
 backprop::prepare_change (tree var)
 {
-  if (MAY_HAVE_DEBUG_STMTS)
+  if (MAY_HAVE_DEBUG_BIND_STMTS)
     insert_debug_temp_for_var_def (NULL, var);
+  reset_flow_sensitive_info (var);
 }
 
 /* STMT has been changed.  Give the fold machinery a chance to simplify
@@ -831,15 +842,21 @@ backprop::optimize_assign (gassign *assign, tree lhs, const usage_info *info)
 void
 backprop::optimize_phi (gphi *phi, tree var, const usage_info *info)
 {
-  /* If the sign of the result doesn't matter, strip sign operations
-     from all arguments.  */
+  /* If the sign of the result doesn't matter, try to strip sign operations
+     from arguments.  */
   if (info->flags.ignore_sign)
     {
+      basic_block bb = gimple_bb (phi);
       use_operand_p use;
       ssa_op_iter oi;
       bool replaced = false;
       FOR_EACH_PHI_ARG (use, phi, oi, SSA_OP_USE)
        {
+         /* Propagating along abnormal edges is delicate, punt for now.  */
+         const int index = PHI_ARG_INDEX_FROM_USE (use);
+         if (EDGE_PRED (bb, index)->flags & EDGE_ABNORMAL)
+           continue;
+
          tree new_arg = strip_sign_op (USE_FROM_PTR (use));
          if (new_arg)
            {