MATCH: `(nop_convert)-(convert)a` into -(convert)a if we are converting from something smaller

Message ID 20230902070005.824764-1-apinski@marvell.com
State Accepted
Headers
Series MATCH: `(nop_convert)-(convert)a` into -(convert)a if we are converting from something smaller |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Andrew Pinski Sept. 2, 2023, 7 a.m. UTC
  This allows removal of one conversion and in the case of booleans, might be able to remove
the negate and the other conversion later on.

OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.

	PR tree-optimization/107137

gcc/ChangeLog:

	* match.pd (`(nop_convert)-(convert)a`): New pattern.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/neg-cast-2.c: New test.
	* gcc.dg/tree-ssa/neg-cast-3.c: New test.
---
 gcc/match.pd                               | 11 +++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/neg-cast-2.c | 20 ++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/neg-cast-3.c | 15 +++++++++++++++
 3 files changed, 46 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/neg-cast-2.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/neg-cast-3.c
  

Comments

Jeff Law Sept. 5, 2023, 7:25 a.m. UTC | #1
On 9/2/23 01:00, Andrew Pinski via Gcc-patches wrote:
> This allows removal of one conversion and in the case of booleans, might be able to remove
> the negate and the other conversion later on.
> 
> OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.
> 
> 	PR tree-optimization/107137
> 
> gcc/ChangeLog:
> 
> 	* match.pd (`(nop_convert)-(convert)a`): New pattern.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.dg/tree-ssa/neg-cast-2.c: New test.
> 	* gcc.dg/tree-ssa/neg-cast-3.c: New test.
OK.
jeff
  

Patch

diff --git a/gcc/match.pd b/gcc/match.pd
index 487a7e38719..3efc971f7f6 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -959,6 +959,17 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 #endif
    ))))
 
+/* (nop_outer_cast)-(inner_cast)var -> -(outer_cast)(var)
+   if var is smaller in precision.
+   This is always safe for both doing the negative in signed or unsigned
+   as the value for undefined will not show up.  */
+(simplify
+ (convert (negate:s@1 (convert:s @0)))
+ (if (INTEGRAL_TYPE_P (type)
+      && tree_nop_conversion_p (type, TREE_TYPE (@1))
+      && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0)))
+    (negate (convert @0))))
+
 (for op (negate abs)
  /* Simplify cos(-x) and cos(|x|) -> cos(x).  Similarly for cosh.  */
  (for coss (COS COSH)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-2.c b/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-2.c
new file mode 100644
index 00000000000..c1d5066cd4a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-2.c
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-fre1 -fdump-tree-optimized" } */
+/* part of PR tree-optimization/108397 */
+
+long long
+foo (unsigned char o)
+{
+  unsigned long long t1 = -(long long) (o == 0);
+  unsigned long long t2 = -(long long) (t1 != 0);
+  unsigned long long t3 = -(long long) (t1 <= t2);
+  return t3;
+}
+
+/* Should be able to optimize this down to just `return -1;` during fre1. */
+/* { dg-final { scan-tree-dump "return -1;" "fre1" } } */
+/* FRE does not remove all dead statements so a few negate expressions are left behind. */
+/* { dg-final { scan-tree-dump-not " -\[^1\]" "fre1" { xfail *-*-* } } } */
+
+/* { dg-final { scan-tree-dump "return -1;" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " - " "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-3.c b/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-3.c
new file mode 100644
index 00000000000..7b23ca85d1f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-3.c
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-forwprop1 -fdump-tree-optimized" } */
+/* PR tree-optimization/107137 */
+
+unsigned f(_Bool a)
+{
+  int t = a;
+  t = -t;
+  return t;
+}
+
+/* There should be no cast to int at all. */
+/* Forwprop1 does not remove all of the statements. */
+/* { dg-final { scan-tree-dump-not "\\\(int\\\)" "forwprop1" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-not "\\\(int\\\)" "optimized" } } */