]> git.feebdaed.xyz Git - 0xmirror/gcc.git/commitdiff
simplify-rtx: Fix up (ne (ior (ne x 0) y) 0) simplification [PR123114]
authorJakub Jelinek <jakub@redhat.com>
Sat, 27 Dec 2025 10:45:18 +0000 (11:45 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 27 Dec 2025 10:45:18 +0000 (11:45 +0100)
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.

2025-12-27  Jakub Jelinek  <jakub@redhat.com>

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
gcc/testsuite/gcc.dg/pr123114.c [new file with mode: 0644]

index 8016e02e9253a8cf3fa8852043927a586f5dbf67..38d366622b5a65420f1738b1cc70e758ac05ec96 100644 (file)
@@ -6509,8 +6509,9 @@ simplify_context::simplify_relational_operation_1 (rtx_code code,
          /* 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));
diff --git a/gcc/testsuite/gcc.dg/pr123114.c b/gcc/testsuite/gcc.dg/pr123114.c
new file mode 100644 (file)
index 0000000..3d36305
--- /dev/null
@@ -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;
+}