]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/106860 - fix profile scaling in split_loop
authorRichard Biener <rguenther@suse.de>
Wed, 7 Sep 2022 08:44:33 +0000 (10:44 +0200)
committerRichard Biener <rguenther@suse.de>
Wed, 7 Sep 2022 10:08:59 +0000 (12:08 +0200)
The following fixes a mistake in loop splitting which assumes loop
latches have a single predecessor and that edge is from the exit
test.  Instead work from the single exit edge we have to find the
edge towards the latch.

PR tree-optimization/106860
* tree-ssa-loop-split.cc (split_loop): Find the exit to
latch edge from the loop exit edge instead of from the
latch.  Verify we're going to find it.

* g++.dg/opt/pr106860.C: New testcase.

gcc/testsuite/g++.dg/opt/pr106860.C [new file with mode: 0644]
gcc/tree-ssa-loop-split.cc

diff --git a/gcc/testsuite/g++.dg/opt/pr106860.C b/gcc/testsuite/g++.dg/opt/pr106860.C
new file mode 100644 (file)
index 0000000..a0209dc
--- /dev/null
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-Ofast -ftrapv -fnon-call-exceptions -fno-tree-fre" }
+
+static const int N = 12;
+int nSlip;
+
+int main ()
+{
+  int i, j, k, fdot = 0;
+  int a[N][N];
+
+  for ( i = 1; i < nSlip; i++)
+    {
+      for ( j = i+1; j < nSlip; j++)
+        {
+          for ( k = 0; k < i; k++)
+            fdot += a[i][k] * a[k][j];
+          a[i][j] = a[i][j] - fdot;
+        }
+   }
+
+  return 0;
+}
index bccf621493b00d693fb72c962dd7f09da07e9a1a..fad4e8361b0e3d02a63e80694a8938f5fef5119d 100644 (file)
@@ -531,16 +531,17 @@ split_loop (class loop *loop1)
   tree guard_iv;
   tree border = NULL_TREE;
   affine_iv iv;
+  edge exit1;
 
-  if (!single_exit (loop1)
+  if (!(exit1 = single_exit (loop1))
+      || EDGE_COUNT (exit1->src->succs) != 2
       /* ??? We could handle non-empty latches when we split the latch edge
         (not the exit edge), and put the new exit condition in the new block.
         OTOH this executes some code unconditionally that might have been
         skipped by the original exit before.  */
       || !empty_block_p (loop1->latch)
       || !easy_exit_values (loop1)
-      || !number_of_iterations_exit (loop1, single_exit (loop1), &niter,
-                                    false, true)
+      || !number_of_iterations_exit (loop1, exit1, &niter, false, true)
       || niter.cmp == ERROR_MARK
       /* We can't yet handle loops controlled by a != predicate.  */
       || niter.cmp == NE_EXPR)
@@ -644,10 +645,13 @@ split_loop (class loop *loop1)
        fix_loop_bb_probability (loop1, loop2, true_edge, false_edge);
 
        /* Fix first loop's exit probability after scaling.  */
-       edge exit_to_latch1 = single_pred_edge (loop1->latch);
+       edge exit_to_latch1;
+       if (EDGE_SUCC (exit1->src, 0) == exit1)
+         exit_to_latch1 = EDGE_SUCC (exit1->src, 1);
+       else
+         exit_to_latch1 = EDGE_SUCC (exit1->src, 0);
        exit_to_latch1->probability *= true_edge->probability;
-       single_exit (loop1)->probability
-         = exit_to_latch1->probability.invert ();
+       exit1->probability = exit_to_latch1->probability.invert ();
 
        /* Finally patch out the two copies of the condition to be always
           true/false (or opposite).  */