Hi!

The following testcase is miscompiled since r16-3301 but the problem is much
older.
The *brx_stage1_<GPR:mode> define_insn_and_split pattern doesn't describe
that it clobbers CC_REGNUM, but splits (before reload) into something which
does clobber CC_REGNUM unconditionally.
Since r16-3301 on this testcase the late_combine1 pass figures it can extend
the lifetime of CC_REGNUM across such an instruction, but when it is in
split1 pass split into something that does clobber CC_REGNUM, the value from
earlier comparison till later use is not preserved anymore.

The following patch fixes it by adding clobber for CC_REGNUM even to the
*brx_stage1_<GPR:mode> pattern, so that df/late_combine etc. know that it is
CC_REGNUM is clobbered by it.
I had to put the clobber before the match_scratch clobber, otherwise there
is endless loop trying to split this insn in split1 pass, the insn it is
split into matches the pattern again and is split again etc. forever.
Even with this patch combine can match this insn, we have code to add the
missing clobbers if the register isn't live across it.

Bootstrapped/regtested on s390x-linux, also tested on the veusz package
which now passes its testsuite (and didn't before).  Ok for trunk/16
and perhaps even older release branches (where it is just latent)?

2026-06-27  Jakub Jelinek  <[email protected]>

        PR target/125992
        * config/s390/s390.md (*brx_stage1_<GPR:mode>): Add CC_REGNUM clobber.

        * gcc.target/s390/pr125992.c: New test.

--- gcc/config/s390/s390.md.jj  2026-06-02 08:15:04.576141861 +0200
+++ gcc/config/s390/s390.md     2026-06-26 01:23:35.038623318 +0200
@@ -10256,6 +10256,7 @@ (define_insn_and_split "*brx_stage1_<GPR
         (pc)))
    (set (match_operand:GPR 4 "nonimmediate_operand" "")
         (plus:GPR (match_dup 1) (match_dup 2)))
+   (clobber (reg:CC CC_REGNUM))
    (clobber (match_scratch:GPR 5 ""))]
   ""
   "#"
--- gcc/testsuite/gcc.target/s390/pr125992.c.jj 2026-06-26 08:58:11.720734276 
+0200
+++ gcc/testsuite/gcc.target/s390/pr125992.c    2026-06-26 08:57:45.265070843 
+0200
@@ -0,0 +1,41 @@
+/* PR target/125992 */
+/* { dg-do run { target s390_useable_hw } } */
+/* { dg-options "-O2 -march=z13" } */
+
+long a, b, c, d[4];
+
+[[gnu::noipa]] long
+foo ()
+{
+  return d[c++];
+}
+
+[[gnu::noipa]] void
+bar ()
+{
+  long e = 0;
+  for (;;)
+    {
+      e += a;
+      a = foo ();
+      if (b + a > e)
+       return;
+      if (a == 0)
+       break;
+      if (a > 0)
+       b += a;
+    }
+}
+
+int
+main ()
+{
+  a = 16;
+  b = -64;
+  c = 0;
+  d[0] = 64;
+  d[1] = 128;
+  bar ();
+  if (b != 0)
+    __builtin_abort ();
+}

        Jakub

Reply via email to