Hi!

The following patch extends the improvements Marc did to the
(A +- CST1) +- CST2 -> A +- CST3
match.pd simplification some time ago to the other two patterns,
in particular handle the case when the inner subtraction is done in a
different, but nop_convert compatible, type from the outer +/-.

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

2019-12-03  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/92734
        * match.pd ((CST1 - A) +- CST2 -> CST3 - A,
        CST1 - (CST2 - A) -> CST3 + A): Handle nop casts around
        inner subtraction.

        * gcc.dg/tree-ssa/pr92734.c: New test.

--- gcc/match.pd.jj     2019-12-02 09:50:27.000000000 +0100
+++ gcc/match.pd        2019-12-02 16:23:43.825040429 +0100
@@ -2237,17 +2237,39 @@ (define_operator_list COND_TERNARY
   /* (CST1 - A) +- CST2 -> CST3 - A  */
   (for outer_op (plus minus)
    (simplify
-    (outer_op (minus CONSTANT_CLASS_P@1 @0) CONSTANT_CLASS_P@2)
-    (with { tree cst = const_binop (outer_op, type, @1, @2); }
-     (if (cst && !TREE_OVERFLOW (cst))
-      (minus { cst; } @0)))))
+    (outer_op (nop_convert (minus CONSTANT_CLASS_P@1 @0)) CONSTANT_CLASS_P@2)
+    /* If one of the types wraps, use that one.  */
+    (if (!ANY_INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type))
+     /* If all 3 captures are CONSTANT_CLASS_P, punt, as we might recurse
+       forever if something doesn't simplify into a constant.  */
+     (if (!CONSTANT_CLASS_P (@0))
+      (minus (outer_op (view_convert @1) @2) (view_convert @0)))
+     (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+         || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+      (view_convert (minus (outer_op @1 (view_convert @2)) @0))
+      (if (types_match (type, @0))
+       (with { tree cst = const_binop (outer_op, type, @1, @2); }
+       (if (cst && !TREE_OVERFLOW (cst))
+        (minus { cst; } @0))))))))
 
-  /* CST1 - (CST2 - A) -> CST3 + A  */
+  /* CST1 - (CST2 - A) -> CST3 + A
+     Use view_convert because it is safe for vectors and equivalent for
+     scalars.  */
   (simplify
-   (minus CONSTANT_CLASS_P@1 (minus CONSTANT_CLASS_P@2 @0))
-   (with { tree cst = const_binop (MINUS_EXPR, type, @1, @2); }
-    (if (cst && !TREE_OVERFLOW (cst))
-     (plus { cst; } @0))))
+   (minus CONSTANT_CLASS_P@1 (nop_convert (minus CONSTANT_CLASS_P@2 @0)))
+   /* If one of the types wraps, use that one.  */
+   (if (!ANY_INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type))
+    /* If all 3 captures are CONSTANT_CLASS_P, punt, as we might recurse
+      forever if something doesn't simplify into a constant.  */
+    (if (!CONSTANT_CLASS_P (@0))
+     (plus (view_convert @0) (minus @1 (view_convert @2))))
+    (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+        || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+     (view_convert (plus @0 (minus (view_convert @1) @2)))
+     (if (types_match (type, @0))
+      (with { tree cst = const_binop (MINUS_EXPR, type, @1, @2); }
+       (if (cst && !TREE_OVERFLOW (cst))
+       (plus { cst; } @0)))))))
 
 /* ((T)(A)) + CST -> (T)(A + CST)  */
 #if GIMPLE
--- gcc/testsuite/gcc.dg/tree-ssa/pr92734.c.jj  2019-12-02 16:26:55.771057273 
+0100
+++ gcc/testsuite/gcc.dg/tree-ssa/pr92734.c     2019-12-02 16:29:59.922195268 
+0100
@@ -0,0 +1,31 @@
+/* PR tree-optimization/92734 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-forwprop1" } */
+/* { dg-final { scan-tree-dump-times "return t_\[0-9]*\\\(D\\\);" 4 
"forwprop1" } } */
+
+int
+f1 (int t)
+{
+  return 1 - (int) (1U - t);
+}
+
+int
+f2 (int t)
+{
+  int a = 7U - t;
+  return 7 - a;
+}
+
+int
+f3 (int t)
+{
+  int a = 32U - t;
+  return 32 - a;
+}
+
+int
+f4 (int t)
+{
+  int a = 32 - t;
+  return (int) (32 - (unsigned) a);
+}

        Jakub

Reply via email to