[PATCH] match.pd: Optimize (((type)A * B) >> prec) != 0 into __imag__ .MUL_OVERFLOW [PR94914]

Jakub Jelinek jakub@redhat.com
Tue May 5 07:07:08 GMT 2020


Hi!

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.

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

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/match.pd.jj	2020-05-04 11:02:14.288865592 +0200
+++ gcc/match.pd	2020-05-04 12:15:33.220799388 +0200
@@ -4776,6 +4776,27 @@ (define_operator_list COND_TERNARY
    (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
--- gcc/testsuite/gcc.target/i386/pr94914.c.jj	2020-05-04 12:58:04.435775670 +0200
+++ gcc/testsuite/gcc.target/i386/pr94914.c	2020-05-04 12:57:39.307152707 +0200
@@ -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;
+}

	Jakub



More information about the Gcc-patches mailing list