https://gcc.gnu.org/g:9f3f376a5c6baa7e3d627d6e98e538622e6d53dd

commit r14-12711-g9f3f376a5c6baa7e3d627d6e98e538622e6d53dd
Author: Jakub Jelinek <[email protected]>
Date:   Sat Jun 27 21:33:00 2026 +0200

    s390: Fix up *brx_stage1_<GPR:mode> [PR125992]
    
    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.
    
    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.
    
    Reviewed-by: Stefan Schulze Frielinghaus <[email protected]>
    (cherry picked from commit 13529401b15fe82c0b1d44b0b0a8bf5d2d72a1b3)

Diff:
---
 gcc/config/s390/s390.md                  |  1 +
 gcc/testsuite/gcc.target/s390/pr125992.c | 41 ++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index c364880af0ae..2e24836d40a9 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -9678,6 +9678,7 @@
         (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 ""))]
   ""
   "#"
diff --git a/gcc/testsuite/gcc.target/s390/pr125992.c 
b/gcc/testsuite/gcc.target/s390/pr125992.c
new file mode 100644
index 000000000000..a7d4b799ebee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr125992.c
@@ -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 ();
+}

Reply via email to