[PATCH] s390: Fix ICE in usubc5 [PR126667]

Jakub Jelinek <[email protected]> Thu, 6 Aug 2026 22:14:10 +0200
Newsgroups gmane.comp.gcc.patches
Message-ID <anTrEiEYq-eb5OZv@tucnak>
Hi!

The following testcase ICEs on s390x-linux I believe since r15-6791
when usubc<mode>5 named pattern has been introduced.
It intentionally uses general_operand predicate for operands[4],
so that it can test it against const0_rtx and handle that differently,
but otherwise it uses xor<mode>3 insn with operands[4] as first input,
which has nonimmediate_operand.  So we emit (xor:DI (const1_rtx) (const1_rtx))
and then fail to recognize it.

The following patch just forces it into a register in that case, cse or
combine can then simplify it.  The other option would be
to check for CONSTANT_P, force into REG unless it is CONST_INT and if it
is CONST_INT, perform the xor at compile time, but then the compare
too and unsure what to pass to the subsequent insn.

The testcase is simplified from a larger botan real-world testcase (though
there isn't usubc with a constant 1 carry in visible in the source).

Bootstrapped/regtested on s390x-linux, ok for trunk, 16.2.1 (after 16.2
is released) and 15.4?

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

	PR target/126667
	* config/s390/s390.md (usubc<mode>5): If operands[4] is
	an immediate operand other than const0_rtx, force it into reg
	before using it in xor<mode>3 insn.

	* gcc.dg/pr126667.c: New test.
	* gcc.target/s390/pr126667.c: New test.

--- gcc/config/s390/s390.md.jj	2026-08-06 10:24:00.121415450 +0200
+++ gcc/config/s390/s390.md	2026-08-06 13:36:37.344210259 +0200
@@ -6745,7 +6745,9 @@ (define_expand "usubc<mode>5"
   else
     {
       rtx tmp = gen_reg_rtx (<MODE>mode);
-      emit_insn (gen_xor<mode>3 (tmp, operands[4], const1_rtx));
+      emit_insn (gen_xor<mode>3 (tmp, CONSTANT_P (operands[4])
+				      ? force_reg (<MODE>mode, operands[4])
+				      : operands[4], const1_rtx));
       rtx slb_cond = s390_emit_compare (<MODE>mode, LEU, tmp, const0_rtx);
       emit_insn (gen_sub<mode>3_slb_borrow1_cc (operands[0], operands[2], operands[3], slb_cond));
     }
--- gcc/testsuite/gcc.dg/pr126667.c.jj	2026-08-06 13:37:24.743970575 +0200
+++ gcc/testsuite/gcc.dg/pr126667.c	2026-08-06 13:37:18.352048196 +0200
@@ -0,0 +1,9 @@
+/* PR target/126667 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long
+foo (unsigned long x, unsigned long y, unsigned long *p)
+{
+  return __builtin_subcl (x, y, 1UL, p);
+}
--- gcc/testsuite/gcc.target/s390/pr126667.c.jj	2026-08-06 13:37:50.592656684 +0200
+++ gcc/testsuite/gcc.target/s390/pr126667.c	2026-08-06 13:38:11.096407697 +0200
@@ -0,0 +1,9 @@
+/* PR target/126667 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=z14" } */
+
+unsigned long
+foo (unsigned long x, unsigned long y, unsigned long *p)
+{
+  return __builtin_subcl (x, y, 1UL, p);
+}

	Jakub