]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-ssa-tail-merge.c
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / tree-ssa-tail-merge.c
index e88072c1836799ca2d6358060b7006a27e3f31bc..48f94217d16ede158d81ef2d3d556c6548a54e8c 100644 (file)
@@ -1,5 +1,5 @@
 /* Tail merging for gimple.
-   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   Copyright (C) 2011-2021 Free Software Foundation, Inc.
    Contributed by Tom de Vries (tom@codesourcery.com)
 
 This file is part of GCC.
@@ -201,12 +201,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "tree-cfg.h"
 #include "tree-into-ssa.h"
-#include "params.h"
 #include "tree-ssa-sccvn.h"
 #include "cfgloop.h"
 #include "tree-eh.h"
 #include "tree-cfgcleanup.h"
 
+const int ignore_edge_flags = EDGE_DFS_BACK | EDGE_EXECUTABLE;
+
 /* Describes a group of bbs with the same successors.  The successor bbs are
    cached in succs, and the successor edge flags are cached in succ_flags.
    If a bb has the EDGE_TRUE/FALSE_VALUE flags swapped compared to succ_flags,
@@ -284,6 +285,21 @@ struct aux_bb_info
 #define BB_VOP_AT_EXIT(bb) (((struct aux_bb_info *)bb->aux)->vop_at_exit)
 #define BB_DEP_BB(bb) (((struct aux_bb_info *)bb->aux)->dep_bb)
 
+/* Valueization helper querying the VN lattice.  */
+
+static tree
+tail_merge_valueize (tree name)
+{
+  if (TREE_CODE (name) == SSA_NAME
+      && has_VN_INFO (name))
+    {
+      tree tem = VN_INFO (name)->valnum;
+      if (tem != VN_TOP)
+       return tem;
+    }
+  return name;
+}
+
 /* Returns true if the only effect a statement STMT has, is to define locally
    used SSA_NAMEs.  */
 
@@ -299,7 +315,15 @@ stmt_local_def (gimple *stmt)
   if (gimple_vdef (stmt) != NULL_TREE
       || gimple_has_side_effects (stmt)
       || gimple_could_trap_p_1 (stmt, false, false)
-      || gimple_vuse (stmt) != NULL_TREE)
+      || gimple_vuse (stmt) != NULL_TREE
+      /* Copied from tree-ssa-ifcombine.c:bb_no_side_effects_p():
+        const calls don't match any of the above, yet they could
+        still have some side-effects - they could contain
+        gimple_could_trap_p statements, like floating point
+        exceptions or integer division by zero.  See PR70586.
+        FIXME: perhaps gimple_has_side_effects or gimple_could_trap_p
+        should handle this.  */
+      || is_gimple_call (stmt))
     return false;
 
   def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
@@ -361,7 +385,7 @@ gvn_uses_equal (tree val1, tree val2)
   if (val1 == val2)
     return true;
 
-  if (vn_valueize (val1) != vn_valueize (val2))
+  if (tail_merge_valueize (val1) != tail_merge_valueize (val2))
     return false;
 
   return ((TREE_CODE (val1) == SSA_NAME || CONSTANT_CLASS_P (val1))
@@ -471,7 +495,7 @@ same_succ_hash (const same_succ *e)
       for (i = 0; i < gimple_call_num_args (stmt); i++)
        {
          arg = gimple_call_arg (stmt, i);
-         arg = vn_valueize (arg);
+         arg = tail_merge_valueize (arg);
          inchash::add_expr (arg, hstate);
        }
     }
@@ -479,6 +503,8 @@ same_succ_hash (const same_succ *e)
   hstate.add_int (size);
   BB_SIZE (bb) = size;
 
+  hstate.add_int (bb->loop_father->num);
+
   for (i = 0; i < e->succ_flags.length (); ++i)
     {
       flags = e->succ_flags[i];
@@ -568,6 +594,9 @@ same_succ::equal (const same_succ *e1, const same_succ *e2)
   if (BB_SIZE (bb1) != BB_SIZE (bb2))
     return 0;
 
+  if (bb1->loop_father != bb2->loop_father)
+    return 0;
+
   gsi1 = gsi_start_nondebug_bb (bb1);
   gsi2 = gsi_start_nondebug_bb (bb2);
   gsi_advance_fw_nondebug_nonlocal (&gsi1);
@@ -695,22 +724,14 @@ find_same_succ_bb (basic_block bb, same_succ **same_p)
   edge_iterator ei;
   edge e;
 
-  if (bb == NULL
-      /* Be conservative with loop structure.  It's not evident that this test
-        is sufficient.  Before tail-merge, we've just called
-        loop_optimizer_finalize, and LOOPS_MAY_HAVE_MULTIPLE_LATCHES is now
-        set, so there's no guarantee that the loop->latch value is still valid.
-        But we assume that, since we've forced LOOPS_HAVE_SIMPLE_LATCHES at the
-        start of pre, we've kept that property intact throughout pre, and are
-        keeping it throughout tail-merge using this test.  */
-      || bb->loop_father->latch == bb)
+  if (bb == NULL)
     return;
   bitmap_set_bit (same->bbs, bb->index);
   FOR_EACH_EDGE (e, ei, bb->succs)
     {
       int index = e->dest->index;
       bitmap_set_bit (same->succs, index);
-      same_succ_edge_flags[index] = e->flags;
+      same_succ_edge_flags[index] = (e->flags & ~ignore_edge_flags);
     }
   EXECUTE_IF_SET_IN_BITMAP (same->succs, 0, j, bj)
     same->succ_flags.safe_push (same_succ_edge_flags[j]);
@@ -1140,7 +1161,7 @@ gimple_equal_p (same_succ *same_succ, gimple *s1, gimple *s2)
       if (lhs1 == NULL_TREE || lhs2 == NULL_TREE)
        return false;
       if (TREE_CODE (lhs1) == SSA_NAME && TREE_CODE (lhs2) == SSA_NAME)
-       return vn_valueize (lhs1) == vn_valueize (lhs2);
+       return tail_merge_valueize (lhs1) == tail_merge_valueize (lhs2);
       return operand_equal_p (lhs1, lhs2, 0);
 
     case GIMPLE_ASSIGN:
@@ -1168,8 +1189,8 @@ gimple_equal_p (same_succ *same_succ, gimple *s1, gimple *s2)
       if (!gimple_operand_equal_value_p (t1, t2))
        return false;
 
-      code1 = gimple_expr_code (s1);
-      code2 = gimple_expr_code (s2);
+      code1 = gimple_cond_code (s1);
+      code2 = gimple_cond_code (s2);
       inv_cond = (bitmap_bit_p (same_succ->inverse, bb1->index)
                  != bitmap_bit_p (same_succ->inverse, bb2->index));
       if (inv_cond)
@@ -1242,6 +1263,7 @@ merge_stmts_p (gimple *stmt1, gimple *stmt2)
       case IFN_UBSAN_CHECK_SUB:
       case IFN_UBSAN_CHECK_MUL:
       case IFN_UBSAN_OBJECT_SIZE:
+      case IFN_UBSAN_PTR:
       case IFN_ASAN_CHECK:
        /* For these internal functions, gimple_location is an implicit
           parameter, which will be used explicitly after expansion.
@@ -1446,7 +1468,7 @@ find_clusters_1 (same_succ *same_succ)
   unsigned int i, j;
   bitmap_iterator bi, bj;
   int nr_comparisons;
-  int max_comparisons = PARAM_VALUE (PARAM_MAX_TAIL_MERGE_COMPARISONS);
+  int max_comparisons = param_max_tail_merge_comparisons;
 
   EXECUTE_IF_SET_IN_BITMAP (same_succ->bbs, 0, i, bi)
     {
@@ -1455,7 +1477,8 @@ find_clusters_1 (same_succ *same_succ)
       /* TODO: handle blocks with phi-nodes.  We'll have to find corresponding
         phi-nodes in bb1 and bb2, with the same alternatives for the same
         preds.  */
-      if (bb_has_non_vop_phi (bb1) || bb_has_eh_pred (bb1))
+      if (bb_has_non_vop_phi (bb1) || bb_has_eh_pred (bb1)
+         || bb_has_abnormal_pred (bb1))
        continue;
 
       nr_comparisons = 0;
@@ -1463,7 +1486,8 @@ find_clusters_1 (same_succ *same_succ)
        {
          bb2 = BASIC_BLOCK_FOR_FN (cfun, j);
 
-         if (bb_has_non_vop_phi (bb2) || bb_has_eh_pred (bb2))
+         if (bb_has_non_vop_phi (bb2) || bb_has_eh_pred (bb2)
+             || bb_has_abnormal_pred (bb2))
            continue;
 
          if (BB_CLUSTER (bb1) != NULL && BB_CLUSTER (bb1) == BB_CLUSTER (bb2))
@@ -1530,8 +1554,6 @@ static void
 replace_block_by (basic_block bb1, basic_block bb2)
 {
   edge pred_edge;
-  edge e1, e2;
-  edge_iterator ei;
   unsigned int i;
   gphi *bb2_phi;
 
@@ -1558,52 +1580,24 @@ replace_block_by (basic_block bb1, basic_block bb2)
                   pred_edge, UNKNOWN_LOCATION);
     }
 
-  bb2->count += bb1->count;
 
   /* Merge the outgoing edge counts from bb1 onto bb2.  */
-  profile_count out_sum = profile_count::zero ();
-  int out_freq_sum = 0;
-
-  /* Recompute the edge probabilities from the new merged edge count.
-     Use the sum of the new merged edge counts computed above instead
-     of bb2's merged count, in case there are profile count insanities
-     making the bb count inconsistent with the edge weights.  */
-  FOR_EACH_EDGE (e1, ei, bb1->succs)
-    {
-      if (e1->count.initialized_p ())
-       out_sum += e1->count;
-      out_freq_sum += EDGE_FREQUENCY (e1);
-    }
-  FOR_EACH_EDGE (e1, ei, bb2->succs)
-    {
-      if (e1->count.initialized_p ())
-       out_sum += e1->count;
-      out_freq_sum += EDGE_FREQUENCY (e1);
-    }
+  edge e1, e2;
+  edge_iterator ei;
 
-  FOR_EACH_EDGE (e1, ei, bb1->succs)
-    {
-      e2 = find_edge (bb2, e1->dest);
-      gcc_assert (e2);
-      e2->count += e1->count;
-      if (out_sum > 0 && e2->count.initialized_p ())
-       {
-         e2->probability = e2->count.probability_in (bb2->count);
-       }
-      else if (bb1->frequency && bb2->frequency)
-       e2->probability = e1->probability;
-      else if (bb2->frequency && !bb1->frequency)
-       ;
-      else if (out_freq_sum)
-       e2->probability = profile_probability::from_reg_br_prob_base
-               (GCOV_COMPUTE_SCALE (EDGE_FREQUENCY (e1)
-                                    + EDGE_FREQUENCY (e2),
-                                    out_freq_sum));
-      out_sum += e2->count;
-    }
-  bb2->frequency += bb1->frequency;
-  if (bb2->frequency > BB_FREQ_MAX)
-    bb2->frequency = BB_FREQ_MAX;
+  if (bb2->count.initialized_p ())
+    FOR_EACH_EDGE (e1, ei, bb1->succs)
+      {
+        e2 = find_edge (bb2, e1->dest);
+        gcc_assert (e2);
+
+       /* If probabilities are same, we are done.
+          If counts are nonzero we can distribute accordingly. In remaining
+          cases just avreage the values and hope for the best.  */
+       e2->probability = e1->probability.combine_with_count
+                            (bb1->count, e2->probability, bb2->count);
+      }
+  bb2->count += bb1->count;
 
   /* Move over any user labels from bb1 after the bb2 labels.  */
   gimple_stmt_iterator gsi1 = gsi_start_bb (bb1);
@@ -1736,7 +1730,7 @@ tail_merge_optimize (unsigned int todo)
   int nr_bbs_removed;
   bool loop_entered = false;
   int iteration_nr = 0;
-  int max_iterations = PARAM_VALUE (PARAM_MAX_TAIL_MERGE_ITERATIONS);
+  int max_iterations = param_max_tail_merge_iterations;
 
   if (!flag_tree_tail_merge
       || max_iterations == 0)
@@ -1751,7 +1745,7 @@ tail_merge_optimize (unsigned int todo)
     {
       cleanup_tree_cfg ();
       todo &= ~TODO_cleanup_cfg;
-      split_critical_edges ();
+      split_edges_for_insertion ();
     }
 
   if (!dom_info_available_p (CDI_DOMINATORS))
@@ -1802,7 +1796,7 @@ tail_merge_optimize (unsigned int todo)
 
   if (nr_bbs_removed_total > 0)
     {
-      if (MAY_HAVE_DEBUG_STMTS)
+      if (MAY_HAVE_DEBUG_BIND_STMTS)
        {
          calculate_dominance_info (CDI_DOMINATORS);
          update_debug_stmts ();