Hi,

On 2021/5/17 16:11, Richard Biener wrote:
On Fri, 14 May 2021, Xionghu Luo wrote:

Hi Richi,

On 2021/4/21 19:54, Richard Biener wrote:
On Tue, 20 Apr 2021, Xionghu Luo wrote:



On 2021/4/15 19:34, Richard Biener wrote:
On Thu, 15 Apr 2021, Xionghu Luo wrote:

Thanks,

On 2021/4/14 14:41, Richard Biener wrote:
"#538,#235,#234,#233" will all be sunk from bb 35 to bb 37 by rtl-sink,
but it moves #538 first, then #235, there is strong dependency here. It
seemsdoesn't like the LCM framework that could solve all and do the
delete-insert in one iteration.
So my question was whether we want to do both within the LCM store
sinking framework.  The LCM dataflow is also used by RTL PRE which
handles both loads and non-loads so in principle it should be able
to handle stores and non-stores for the sinking case (PRE on the
reverse CFG).

A global dataflow is more powerful than any local ad-hoc method.

My biggest concern is whether the LCM DF framework could support sinking
*multiple* reverse-dependent non-store instructions together by *one*
calling of LCM DF.   If this is not supported, we need run multiple LCM
until no new changes, it would be time consuming obviously (unless
compiling time is not important here).

As said it is used for PRE and there it most definitely can do that.

I did some investigation about PRE and attached a case to show how it
works, it is quite like store-motion, and actually there is a rtl-hoist
pass in gcse.c which only works for code size.  All of them are
leveraging the LCM framework to move instructions upward or downward.

PRE and rtl-hoist move instructions upward, they analyze/hash the SOURCE
exprs and call pre_edge_lcm, store-motion and rtl-sink move instructions
downward, so they analyze/hash the DEST exprs and call pre_edge_rev_lcm.
The four problems are all converted to the LCM DF problem with
n_basic_blocks * m_exprs of 4 matrix (antic, transp, avail, kill) as input
and two outputs of where to insert/delete.

PRE scan each instruction and hash the SRC to table without *checking the
relationship between instructions*, for the case attached, BB 37, BB 38
and BB 41 both contains SOURCE expr "r262:DI+r139:DI", but BB 37 and BB 41
save it to index 106, BB 38 save it to index 110. After finishing this pass,
"r262:DI+r139:DI" BB41 is replaced with "r194:DI=r452:DI", then insert
expr to BB 75~BB 80 to create full redundancies from partial redundancies,
finally update instruction in BB 37.

I'm not familiar with the actual PRE code but reading the toplevel comment
it seems that indeed it can only handle expressions contained in a single
insn unless a REG_EQUAL note provides a short-hand for the larger one.

That of course means it would need to mark things as not transparent
for correctness where they'd be if moved together.  Now, nothing
prevents you changing the granularity of what you feed LCM.

So originally we arrived at looking into LCM because there's already
a (store) sinking pass on RTL (using LCM) so adding another (loop-special)
one didn't look like the best obvious solution.

That said, LCM would work for single-instruction expressions.
Alternatively a greedy algorithm like you prototyped could be used.
Another pass to look at would be RTL invariant motion which seems to
compute some kind of dependency graph - not sure if that would be
adaptable for the reverse CFG problem.


Actually my RTL sinking pass patch is borrowed from RTL loop invariant
motion, it is  quite limited since only moves instructions from loop header
to loop exits, though it could be refined with various of algorithms.
Compared to the initial method of running gimple sink pass once more,
it seems much more complicated and limited without gaining obvious performance
benefit, shall we turn back to consider gimple sink2 pass from original since
we are in stage1 now?

OK, so while there might be new sinking opportunities exposed during
RTL expansion and early RTL opts we can consider adding another sink pass
on GIMPLE.  Since it's basically a scheduling optimization placement
shouldn't matter much but I suppose we should run it before store
merging, so anywhere between cd_dce and that.

Richard.


Attached the patch as discussed, put it before store_merging is fine.
Regression tested pass on P8LE, OK for trunk? :)


Thanks,
Xionghu
From 7fcc6ca9ef3b6acbfbcbd3da4be1d1c0eef4be80 Mon Sep 17 00:00:00 2001
From: Xiong Hu Luo <luo...@linux.ibm.com>
Date: Mon, 17 May 2021 20:46:15 -0500
Subject: [PATCH] Run pass_sink_code once more before store_merging

Gimple sink code pass runs quite early, there may be some new
oppertunities exposed by later gimple optmization passes, this patch
runs the sink code pass once more before store_merging.  For detailed
discussion, please refer to:
https://gcc.gnu.org/pipermail/gcc-patches/2020-December/562352.html

Tested the SPEC2017 performance on P8LE, 544.nab_r is improved
by 2.43%, but no big changes to other cases, GEOMEAN is improved quite
small with 0.25%.

gcc/ChangeLog:

        * passes.def: Add sink_code before store_merging.
        * tree-ssa-sink.c (pass_sink_code:clone): New.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/ssa-sink-1.c: Adjust.
        * gcc.dg/tree-ssa/ssa-sink-2.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-3.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-4.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-5.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-6.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-7.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-8.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-9.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-10.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-13.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-14.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-16.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-17.c: Ditto.
        * gcc.dg/tree-ssa/ssa-sink-18.c: New.
---
 gcc/passes.def                              |   1 +
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-1.c  |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-10.c |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-13.c |   4 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-14.c |   4 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-16.c |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-17.c |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-18.c | 196 ++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-2.c  |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c  |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-4.c  |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-5.c  |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-6.c  |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-7.c  |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-8.c  |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-9.c  |   2 +-
 gcc/tree-ssa-sink.c                         |   1 +
 17 files changed, 214 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-18.c

diff --git a/gcc/passes.def b/gcc/passes.def
index de39fa48b3d..945d2bc797c 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -348,6 +348,7 @@ along with GCC; see the file COPYING3.  If not see
       NEXT_PASS (pass_phiopt, false /* early_p */);
       NEXT_PASS (pass_fold_builtins);
       NEXT_PASS (pass_optimize_widening_mul);
+      NEXT_PASS (pass_sink_code);
       NEXT_PASS (pass_store_merging);
       NEXT_PASS (pass_tail_calls);
       /* If DCE is not run before checking for uninitialized uses,
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-1.c
index 411585a6dc4..57b501681f3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-1.c
@@ -7,4 +7,4 @@ foo (int a, int b, int c)
   return c ? x : a;
 }
 /* We should sink the x = a * b calculation into the branch that returns x. */
-/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink" } } */
+/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-10.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-10.c
index 37e4d2fe687..535cb3208f5 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-10.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-10.c
@@ -16,4 +16,4 @@ void foo (void)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "Sinking # VUSE" 4 "sink" } } */
+/* { dg-final { scan-tree-dump-times "Sinking # VUSE" 4 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-13.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-13.c
index a65ba35d4ba..584fd91f43a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-13.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-13.c
@@ -21,5 +21,5 @@ void test ()
 
 /* We should sink/merge all stores and end up with a single BB.  */
 
-/* { dg-final { scan-tree-dump-times "MEM\[^\n\r\]* = 0;" 3 "sink" } } */
-/* { dg-final { scan-tree-dump-times "<bb " 1 "sink" } } */
+/* { dg-final { scan-tree-dump-times "MEM\[^\n\r\]* = 0;" 3 "sink1" } } */
+/* { dg-final { scan-tree-dump-times "<bb " 1 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-14.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-14.c
index 771cd4420c4..f5418b06deb 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-14.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-14.c
@@ -13,5 +13,5 @@ void foo (int b)
 /* We should have sunk the store and inserted a PHI to merge the
    stored values.  */
 
-/* { dg-final { scan-tree-dump-times " = PHI" 1 "sink" } } */
-/* { dg-final { scan-tree-dump-times "x = " 1 "sink" } } */
+/* { dg-final { scan-tree-dump-times " = PHI" 1 "sink1" } } */
+/* { dg-final { scan-tree-dump-times "x = " 1 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-16.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-16.c
index 610c8d60ebe..012b165fbab 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-16.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-16.c
@@ -10,5 +10,5 @@ int f(int n)
   return j;
 }
 
-/* { dg-final { scan-tree-dump "Sinking j_. = __builtin_ffs" "sink" } } */
+/* { dg-final { scan-tree-dump "Sinking j_. = __builtin_ffs" "sink1" } } */
 /* { dg-final { scan-tree-dump "return 2;" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-17.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-17.c
index cf2e2a0f766..d0aeeb312cc 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-17.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-17.c
@@ -12,4 +12,4 @@ int my_f(int a, int b)
 }
 
 /* We should sink the call to pure_f to the if block.  */
-/* { dg-final { scan-tree-dump "Sinking # VUSE" "sink" } } */
+/* { dg-final { scan-tree-dump "Sinking # VUSE" "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-18.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-18.c
new file mode 100644
index 00000000000..b2f5ca9c847
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-18.c
@@ -0,0 +1,196 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-sink-stats" } */
+
+#include <stdint.h>
+
+#define HLOG 16
+#define        MAX_LIT        (1 <<  5)
+typedef const uint8_t *LZF_HSLOT;
+typedef LZF_HSLOT LZF_STATE[1 << (HLOG)];
+
+int
+compute_on_bytes (uint8_t *in_data, int in_len, uint8_t *out_data, int out_len)
+{
+  LZF_STATE htab;
+
+  uint8_t *ip = in_data;
+  uint8_t *op = out_data;
+  uint8_t *in_end = ip + in_len;
+  uint8_t *out_end = op + out_len;
+  uint8_t *ref;
+
+  unsigned long off;
+  unsigned int hval;
+  int lit;
+
+  if (!in_len || !out_len)
+    return 0;
+
+  lit = 0;
+  op++;
+  hval = (((ip[0]) << 8) | ip[1]);
+
+  while (ip < in_end - 2)
+    {
+      uint8_t *hslot;
+
+      hval = (((hval) << 8) | ip[2]);
+      hslot = (uint8_t*)(htab + (((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << 
(16)) - 1)));
+
+      ref = *hslot + in_data;
+      *hslot = ip - in_data;
+
+      if (1 && (off = ip - ref - 1) < (1 << 13) && ref > in_data
+         && ref[2] == ip[2]
+         && ((ref[1] << 8) | ref[0]) == ((ip[1] << 8) | ip[0]))
+       {
+         unsigned int len = 2;
+         unsigned int maxlen = in_end - ip - len;
+         maxlen
+           = maxlen > ((1 << 8) + (1 << 3)) ? ((1 << 8) + (1 << 3)) : maxlen;
+
+         if ((op + 3 + 1 >= out_end) != 0)
+           if (op - !lit + 3 + 1 >= out_end)
+             return 0;
+
+         op[-lit - 1] = lit - 1;
+         op -= !lit;
+
+         for (;;)
+           {
+             if (maxlen > 16)
+               {
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+                 len++;
+                 if (ref[len] != ip[len])
+                   break;
+               }
+
+             do
+               {
+                 len++;
+               }
+             while (len < maxlen && ip[len] == ref[len]);
+
+             break;
+           }
+
+         len -= 2;
+         ip++;
+
+         if (len < 7)
+           {
+             *op++ = (off >> 8) + (len << 5);
+           }
+         else
+           {
+             *op++ = (off >> 8) + (7 << 5);
+             *op++ = len - 7;
+           }
+         *op++ = off;
+         lit = 0;
+         op++;
+         ip += len + 1;
+
+         if (ip >= in_end - 2)
+           break;
+
+         --ip;
+         --ip;
+
+         hval = (((ip[0]) << 8) | ip[1]);
+         hval = (((hval) << 8) | ip[2]);
+         htab[(((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1))]
+           = (LZF_HSLOT)(ip - in_data);
+         ip++;
+
+         hval = (((hval) << 8) | ip[2]);
+         htab[(((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1))]
+           = (LZF_HSLOT)(ip - in_data);
+         ip++;
+       }
+      else
+       {
+         if (op >= out_end)
+           return 0;
+
+         lit++;
+         *op++ = *ip++;
+
+         if (lit == (1 << 5))
+           {
+             op[-lit - 1] = lit - 1;
+             lit = 0;
+             op++;
+           }
+       }
+    }
+  if (op + 3 > out_end) /* at most 3 bytes can be missing here */
+    return 0;
+
+  while (ip < in_end)
+    {
+      lit++;
+      *op++ = *ip++;
+      if (lit == MAX_LIT)
+       {
+         op[-lit - 1] = lit - 1; /* stop run */
+         lit = 0;
+         op++; /* start run */
+       }
+    }
+
+  op[-lit - 1] = lit - 1; /* end run */
+  op -= !lit;            /* undo run if length is zero */
+
+  return op - out_data;
+ }
+
+/* { dg-final { scan-tree-dump-times "Sunk statements: 4" 1 "sink2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-2.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-2.c
index 6aa5a182a3a..a0b4734b1e0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-2.c
@@ -9,4 +9,4 @@ bar (int a, int b, int c)
   return y;
 }
 /* We should sink the x = a * b calculation into the else branch  */
-/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink" } } */
+/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c
index 599997e0e6b..ad88ccc4f5b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c
@@ -12,4 +12,4 @@ main (int argc)
     }
 }
 /* We should sink the a = argc + 1 calculation into the if branch  */
-/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink" } } */
+/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-4.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-4.c
index 784edd2fc87..1e3cfa93fa8 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-4.c
@@ -17,4 +17,4 @@ main (int argc)
   foo2 (a);
 }
 /* We should sink the first a = b + c calculation into the else branch  */
-/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink" } } */
+/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-5.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-5.c
index dbdde39add6..f04da5da9b0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-5.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-5.c
@@ -44,4 +44,4 @@ void foo(int16_t runs[], uint8_t alpha[], int x, int count)
 }
 
 /* We should not sink the next_runs = runs + x calculation after the loop.  */
-/* { dg-final { scan-tree-dump-times "Sunk statements:" 0 "sink" } } */
+/* { dg-final { scan-tree-dump-times "Sunk statements:" 0 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-6.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-6.c
index 1abae9f7943..31f5af330f9 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-6.c
@@ -14,4 +14,4 @@ int foo(int *a, int r)
 
 /* *a = 1 should be sunk to the else block.  */
 
-/* { dg-final { scan-tree-dump-times "Sinking" 1 "sink" } } */
+/* { dg-final { scan-tree-dump-times "Sinking" 1 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-7.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-7.c
index ec3288f4e69..bd748442edc 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-7.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-7.c
@@ -15,4 +15,4 @@ int foo(int *a, int r, short *b)
 
 /* *a = 1 should be sunk to the else block.  */
 
-/* { dg-final { scan-tree-dump-times "Sinking" 1 "sink" } } */
+/* { dg-final { scan-tree-dump-times "Sinking" 1 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-8.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-8.c
index 48af4218fc0..4b23b567fd0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-8.c
@@ -24,4 +24,4 @@ int foo(int *a, int r, short *b)
 
 /* *a = 1 should be sunk into the default case.  */
 
-/* { dg-final { scan-tree-dump-times "Sinking" 1 "sink" } } */
+/* { dg-final { scan-tree-dump-times "Sinking" 1 "sink1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-9.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-9.c
index 509a76330a4..32bfc81741a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-9.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-9.c
@@ -15,4 +15,4 @@ int foo(int *a, int r, int *b)
 
 /* *a = 1 should be sunk to the else block.  */
 
-/* { dg-final { scan-tree-dump-times "Sinking" 1 "sink" } } */
+/* { dg-final { scan-tree-dump-times "Sinking" 1 "sink1" } } */
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index d33e56ef915..d252cbb5c51 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -819,6 +819,7 @@ public:
   /* opt_pass methods: */
   virtual bool gate (function *) { return flag_tree_sink != 0; }
   virtual unsigned int execute (function *);
+  opt_pass *clone (void) { return new pass_sink_code (m_ctxt); }
 
 }; // class pass_sink_code
 
-- 
2.27.0.90.geebb51ba8c

Reply via email to