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 <[email protected]>
---
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