There are a couple of things wrong with this pattern which
I missed during the review. First each nop_convert should
be nop_convert1 or nop_convert2.
Second is we need to the minus in the same type as the minus
was originally so we don't introduce extra undefined behavior
(signed integer overflow). And we need a convert into the new
type too.

pr117363-1.c tests not introducing extra undefined behavior.
pr117363-2.c tests the casting to the correct final type, ldist
introduces the cond_expr here.

Bootstraped and tested on x86_64-linux-gnu.

        PR tree-optimization/117363

gcc/ChangeLog:

        * match.pd (`a != 0 ? a - 1 : 0`): Fix type handling
        and nop_convert handling.

gcc/testsuite/ChangeLog:

        * gcc.dg/torture/pr117363-1.c: New test.
        * gcc.dg/torture/pr117363-2.c: New test.

Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
---
 gcc/match.pd                              |  5 +--
 gcc/testsuite/gcc.dg/torture/pr117363-1.c | 41 +++++++++++++++++++++++
 gcc/testsuite/gcc.dg/torture/pr117363-2.c | 12 +++++++
 3 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117363-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117363-2.c

diff --git a/gcc/match.pd b/gcc/match.pd
index c851ac56e37..9107e6a95ca 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3396,10 +3396,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    simplify (X != 0 ? X + ~0 : 0) to (X - X != 0).  */
 (simplify
  (cond (ne@1 @0 integer_zerop)
-       (nop_convert? (plus (nop_convert? @0) integer_all_onesp))
+       (nop_convert1? (plus (nop_convert2?@2 @0) integer_all_onesp))
        integer_zerop)
  (if (INTEGRAL_TYPE_P (type))
-   (minus @0 (convert @1))))
+   (with { tree itype = TREE_TYPE (@2); }
+    (convert (minus @2 (convert:itype @1))))))
 
 /* Signed saturation sub, case 1:
    T minus = (T)((UT)X - (UT)Y);
diff --git a/gcc/testsuite/gcc.dg/torture/pr117363-1.c 
b/gcc/testsuite/gcc.dg/torture/pr117363-1.c
new file mode 100644
index 00000000000..b8b5bea76f8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr117363-1.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fgimple" } */
+
+/* PR tree-optimization/117363 */
+
+/* a != 0 ? (signed)(((unsigned)a) - 1) : 0
+   Should not be transformed into doing the
+   plus in a signed type which could cause an overflow.` */
+
+__attribute__((noinline))
+signed __GIMPLE ()
+test2 (int n)
+{
+  unsigned t;
+  _Bool _4;
+  if (n_1(D) > 0) goto unreachable;
+  else goto normal;
+normal:
+  t_2 = (unsigned)n_1(D);
+  t_3 = t_2 - 1u;
+  n_5 = (signed) t_3;
+  _4 = n_1(D) != 0;
+  n_6 = _4 ? n_5 : 0;
+  if (n_6 > 0) goto return1;
+  else goto trap;
+
+return1:
+  return n_6;
+
+unreachable:
+  __builtin_unreachable();
+
+trap:
+  __builtin_trap ();
+}
+
+int main()
+{
+  unsigned t = -__INT_MAX__ - 1;
+  test2(t);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr117363-2.c 
b/gcc/testsuite/gcc.dg/torture/pr117363-2.c
new file mode 100644
index 00000000000..f608380e62f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr117363-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+/* PR tree-optimization/117363 */
+/* ldist produces `s != 0 ? s - 1 : 0`  (with casts) and that
+   the match pattern which messed up the converts. */
+
+void f(int *array, long t) {
+  if (!t) return;
+  unsigned long s = ~t;
+  for (long i = 0; i < s; i++)
+    array[i] = 0;
+}
-- 
2.43.0

Reply via email to