match.pd: Canonicalize (X + (X >> (prec - 1))) ^ (X >> (prec - 1)) to abs (X) [PR94783]
authorJakub Jelinek <jakub@redhat.com>
Fri, 8 May 2020 07:35:41 +0000 (09:35 +0200)
committerJakub Jelinek <jakub@redhat.com>
Fri, 8 May 2020 07:35:41 +0000 (09:35 +0200)
The following patch canonicalizes M = X >> (prec - 1); (X + M) ^ M
for signed integral types into ABS_EXPR (X).  For X == min it is already
UB because M is -1 and min + -1 is UB, so we can use ABS_EXPR rather than
say ABSU_EXPR + cast.

The backend might then emit the abs code back using the shift and addition
and xor if it is the best sequence for the target, but could do something
different that is better.

2020-05-08  Jakub Jelinek  <jakub@redhat.com>

PR tree-optimization/94783
* match.pd ((X + (X >> (prec - 1))) ^ (X >> (prec - 1)) to abs (X)):
New simplification.

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

gcc/ChangeLog
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr94783.c [new file with mode: 0644]

index 5bad3ff924b27004db2679ba3d866c53df7207f5..75b0ed1542f922e5f71a0ef6c8930ca3886d451d 100644 (file)
@@ -1,5 +1,9 @@
 2020-05-08  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/94783
+       * match.pd ((X + (X >> (prec - 1))) ^ (X >> (prec - 1)) to abs (X)):
+       New simplification.
+
        PR tree-optimization/94956
        * match.pd (FFS): Optimize __builtin_ffs* of non-zero argument into
        __builtin_ctz* + 1 if direct IFN_CTZ is supported.
index 892df1ec3d39ee715d088ae9975c822460d48621..e8c53e347f4d7941901c5b99f59beabe9755d631 100644 (file)
@@ -120,6 +120,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
    (convert (absu:utype @0)))))
 
+#if GIMPLE
+/* Optimize (X + (X >> (prec - 1))) ^ (X >> (prec - 1)) into abs (X).  */
+(simplify
+ (bit_xor:c (plus:c @0 (rshift@2 @0 INTEGER_CST@1)) @2)
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+      && !TYPE_UNSIGNED (TREE_TYPE (@0))
+      && wi::to_widest (@1) == element_precision (TREE_TYPE (@0)) - 1)
+  (abs @0)))
+#endif
 
 /* Simplifications of operations with one constant operand and
    simplifications to constants or single values.  */
index e8c54c7cd67764d88d6cb362b59ab8f8c624ab28..174198fdbe49c3acfa3040374bc61b83ea1d1497 100644 (file)
@@ -1,5 +1,8 @@
 2020-05-08  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/94783
+       * gcc.dg/tree-ssa/pr94783.c: New test.
+
        PR tree-optimization/94956
        * gcc.target/i386/pr94956.c: New test.
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94783.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94783.c
new file mode 100644 (file)
index 0000000..c52f657
--- /dev/null
@@ -0,0 +1,12 @@
+/* PR tree-optimization/94783 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump "ABS_EXPR" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " >> 31" "optimized" } } */
+
+int
+foo (int v)
+{
+  int mask = v >> (__SIZEOF_INT__ * __CHAR_BIT__ - 1);
+  return (v + mask) ^ mask;
+}