match.pd: Optimize (((type)A * B) >> prec) != 0 into __imag__ .MUL_OVERFLOW [PR94914]
authorJakub Jelinek <jakub@redhat.com>
Tue, 5 May 2020 09:31:43 +0000 (11:31 +0200)
committerJakub Jelinek <jakub@redhat.com>
Tue, 5 May 2020 09:34:45 +0000 (11:34 +0200)
On x86 (the only target with umulv4_optab) one can use mull; seto to check
for overflow instead of performing wider multiplication and performing
comparison on the high bits.

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

PR tree-optimization/94914
* match.pd ((((type)A * B) >> prec) != 0 to .MUL_OVERFLOW(A, B) != 0):
New simplification.

* gcc.target/i386/pr94914.c: New test.

gcc/ChangeLog
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr94914.c [new file with mode: 0644]

index 8c46dcd92c3fcd26c85f112c9a4729436401888b..e51c0e097228a4f8ac57441f37bb9bb025c47f87 100644 (file)
@@ -1,3 +1,9 @@
+2020-05-05  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/94914
+       * match.pd ((((type)A * B) >> prec) != 0 to .MUL_OVERFLOW(A, B) != 0):
+       New simplification.
+
 2020-05-05  Uroš Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (*testqi_ext_3): Use
index 9c1e23984d600089370ca59880bf0889383a3278..c45e94c0c6a99b59cdbea41cd02ada430e74f5f0 100644 (file)
@@ -4776,6 +4776,27 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (with { tree t = TREE_TYPE (@0), cpx = build_complex_type (t); }
     (out (imagpart (IFN_MUL_OVERFLOW:cpx @0 @1)) { build_zero_cst (t); })))))
 
+/* Similarly, for unsigned operands, (((type) A * B) >> prec) != 0 where type
+   is at least twice as wide as type of A and B, simplify to
+   __builtin_mul_overflow (A, B, <unused>).  */
+(for cmp (eq ne)
+ (simplify
+  (cmp (rshift (mult:s (convert@3 @0) (convert @1)) INTEGER_CST@2)
+       integer_zerop)
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       && INTEGRAL_TYPE_P (TREE_TYPE (@3))
+       && TYPE_UNSIGNED (TREE_TYPE (@0))
+       && (TYPE_PRECISION (TREE_TYPE (@3))
+          >= 2 * TYPE_PRECISION (TREE_TYPE (@0)))
+       && tree_fits_uhwi_p (@2)
+       && tree_to_uhwi (@2) == TYPE_PRECISION (TREE_TYPE (@0))
+       && types_match (@0, @1)
+       && type_has_mode_precision_p (TREE_TYPE (@0))
+       && (optab_handler (umulv4_optab, TYPE_MODE (TREE_TYPE (@0)))
+          != CODE_FOR_nothing))
+   (with { tree t = TREE_TYPE (@0), cpx = build_complex_type (t); }
+    (cmp (imagpart (IFN_MUL_OVERFLOW:cpx @0 @1)) { build_zero_cst (t); })))))
+
 /* Simplification of math builtins.  These rules must all be optimizations
    as well as IL simplifications.  If there is a possibility that the new
    form could be a pessimization, the rule should go in the canonicalization
index 09f89951042f0ee8e4506274162320c81bd6780f..2a44c70a777b60b4c84f06519419cb60ac7cbe46 100644 (file)
@@ -1,3 +1,8 @@
+2020-05-05  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/94914
+       * gcc.target/i386/pr94914.c: New test.
+
 2020-05-04  Patrick Palka  <ppalka@redhat.com>
 
        PR c++/94038
diff --git a/gcc/testsuite/gcc.target/i386/pr94914.c b/gcc/testsuite/gcc.target/i386/pr94914.c
new file mode 100644 (file)
index 0000000..932bd21
--- /dev/null
@@ -0,0 +1,17 @@
+/* PR tree-optimization/94914 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "\tseto\t" } } */
+/* { dg-final { scan-assembler "\tsetno\t" } } */
+
+int
+foo (unsigned int x, unsigned int y)
+{
+  return (((unsigned long long)x * y) >> 32) != 0;
+}
+
+int
+bar (unsigned int x, unsigned int y)
+{
+  return (((unsigned long long)x * y) >> 32) == 0;
+}