Improve (CST1 - A) +- CST2 -> CST3 - A and CST1 - (CST2 - A) -> CST3 + A match.pd opt (PR tree-optimization/92734)

Message ID 20191203084754.GC10088@tucnak
State New
Headers show
Series
  • Improve (CST1 - A) +- CST2 -> CST3 - A and CST1 - (CST2 - A) -> CST3 + A match.pd opt (PR tree-optimization/92734)
Related show

Commit Message

Jakub Jelinek Dec. 3, 2019, 8:47 a.m.
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  <jakub@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.


	Jakub

Comments

Richard Biener Dec. 3, 2019, 8:58 a.m. | #1
On Tue, 3 Dec 2019, Jakub Jelinek wrote:

> 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?


OK.

Thanks,
Richard.

> 2019-12-03  Jakub Jelinek  <jakub@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

> 

> 


-- 
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

Patch

--- 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);
+}