Hi!

The following testcase ICEs on x86_64-linux since the PR52345
(ne (ior (ne x 0) y) 0) simplification was (slightly) fixed.
It wants to optimize
    (set (reg/i:DI 10 a0)
        (ne:DI (ior:DI (ne:DI (reg:DI 151 [ a ])
                    (const_int 0 [0]))
                (reg:DI 152 [ b ]))
            (const_int 0 [0])))
but doesn't check important property of that, in particular
that the mode of the inner NE operand is the same as the
mode of the inner NE.
The following testcase has
(set (reg:CCZ 17 flags)
    (compare:CCZ (ior:QI (ne:QI (reg/v:SI 104 [ c ])
                (const_int 0 [0]))
            (reg:QI 98 [ _5 ]))
        (const_int 0 [0])))
where cmp_mode is QImode, but the mode of the inner NE operand
is SImode instead, and it attempts to create
  (ne:CCZ (ior:QI (reg/v:SI 104 [ c ]) (reg:QI 98 [ _5 ])) (const_int 0))
which obviously crashes later on.

The following patch fixes it by checking the mode of the inner NE operand
and also by using CONST0_RTX (cmp_mode) instead of CONST0_RTX (mode)
because that is the mode of the other operand, not mode which is the
mode of the outer comparison (though, guess for most modes it will still
be const0_rtx).

I guess for mode mismatches we could arbitrarily choose some extension (zero
or sign) and extend the narrower mode to the wider mode, but I doubt that it
would ever match on any target.  But even then we'd need to limit it, we
wouldn't want to deal with another mode class (say floating point
comparisons), and dunno about vector modes etc.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2025-12-13  Jakub Jelinek  <[email protected]>

        PR rtl-optimization/123114
        * simplify-rtx.cc (simplify_context::simplify_relational_operation):
        Verify XEXP (XEXP (op0, 0), 0) mode and use CONST0_RTX (cmp_mode)
        instead of CONST0_RTX (mode).

        * gcc.dg/pr123114.c: New test.

--- gcc/simplify-rtx.cc.jj      2025-12-09 10:18:55.437229339 +0100
+++ gcc/simplify-rtx.cc 2025-12-13 23:04:14.672186706 +0100
@@ -6509,8 +6509,9 @@ simplify_context::simplify_relational_op
          /* only enters if op1 is 0 */
          /* Verify IOR operand is NE */
          && GET_CODE (XEXP (op0, 0)) == NE
+         && GET_MODE (XEXP (XEXP (op0, 0), 0)) == cmp_mode
          /* Verify second NE operand is 0 */
-         && XEXP (XEXP (op0, 0), 1) == CONST0_RTX (mode))
+         && XEXP (XEXP (op0, 0), 1) == CONST0_RTX (cmp_mode))
        {
          rtx t = gen_rtx_IOR (cmp_mode, XEXP (XEXP (op0, 0), 0), XEXP (op0, 
1));
          t = gen_rtx_fmt_ee (code, mode, t, CONST0_RTX (mode));
--- gcc/testsuite/gcc.dg/pr123114.c.jj  2025-12-13 23:13:53.528178273 +0100
+++ gcc/testsuite/gcc.dg/pr123114.c     2025-12-13 23:13:25.964657498 +0100
@@ -0,0 +1,21 @@
+/* PR rtl-optimization/123114 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-tree-vrp" } */
+
+volatile int a, b, g;
+unsigned short e;
+int f;
+
+int
+main ()
+{
+  int c, d;
+  while (a)
+    {
+      c = e = b << 2;
+      d = f;
+      g = (c <= 0 && d) || c ? 0 : d;
+      a = g;
+    }
+  return 0;
+}

        Jakub

Reply via email to