diff mbox

Division Optimization in match and simplify

Message ID BLUPR0701MB10112FDAF6046909BE252FFB8E2A0@BLUPR0701MB1011.namprd07.prod.outlook.com
State New
Headers show

Commit Message

Hurugalawadi, Naveen Nov. 4, 2015, 5:28 a.m. UTC
Hi,

Please find attached the patch that moves some division optimizations
from fold-const using match and simplify.

Please review the patch and let me know if any modifications are required.

Regression tested the patch on X86 without any issues.

Thanks,
Naveen

ChangeLog

2015-11-04  Naveen H.S  <Naveen.Hurugalawadi@caviumnetworks.com>

        * fold-const.c (fold_binary_loc) : Move Convert A/B/C to A/(B*C)
	to match.pd.
        Move Convert A/(B/C) to (A/B)*C to match.pd.
        Move Convert C1/(X*C2) into (C1/C2)/X to match.pd.
        Move Optimize (X & (-A)) / A where A is a power of 2, to
	X >> log2(A) to match.pd.
        
        * match.pd (rdiv (convert? (rdiv @0 @1)) (convert? @2)):
	New simplifier.
	(rdiv (convert? @0) (convert? (rdiv @1 @2))): New simplifier.
	(trunc_div (bit_and (convert? @0) @1) INTEGER_CST@2): New simplifier.
	(rdiv (REAL_CST@0) (mult (convert? @1) REAL_CST@2)): New simplifier.

Comments

Marc Glisse Nov. 4, 2015, 8:32 a.m. UTC | #1
(I didn't read everything)

+/* Convert (A/B)/C to A/(B*C)  */
+(simplify
+ (rdiv (convert? (rdiv @0 @1)) (convert? @2))
+  (if (flag_reciprocal_math
+       && tree_nop_conversion_p (type, TREE_TYPE (@0))
+       && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+   (rdiv (convert @0) (convert (mult @1 @2)))))

I thought we were mostly using the 'convert?' and tree_nop_conversion_p on 
integers, but I could be wrong. For floats, it seems limited to cases 
where long double has the same size as double? In any case, the 'convert?' 
on @2 seems strange, either useless or not sufficient.

+ (rdiv (REAL_CST@0) (mult (convert? @1) REAL_CST@2))

Here again, the 'convert?' seems useless, (mult @1 REAL_CST@2) would match 
just as well.

+(simplify
+ (trunc_div (bit_and (convert? @0) @1) INTEGER_CST@2)

That would probably also work for exact_div.
Again, I don't see the point of this 'convert?'.

+ (if (!TYPE_UNSIGNED (type) && integer_pow2p (@2)
+      && tree_int_cst_sgn (@2) > 0
+      && tree_nop_conversion_p (type, TREE_TYPE (@0)))
+  (with
+   { tree sum = fold_binary (PLUS_EXPR, TREE_TYPE (@2), @2, @1); }

Don't you want to require that @1 is INTEGER_CST? And then you could use 
const_binop, or even wi::add.

+   (if (sum && integer_zerop (sum))
+    (rshift (convert @0) { build_int_cst (integer_type_node,
+					  wi::exact_log2 (@2)); })))))
diff mbox

Patch

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index ee9b349..88dbbdd 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -10163,54 +10163,9 @@  fold_binary_loc (location_t loc,
 	return fold_build2_loc (loc, RDIV_EXPR, type,
 			    negate_expr (arg0),
 			    TREE_OPERAND (arg1, 0));
-
-      /* Convert A/B/C to A/(B*C).  */
-      if (flag_reciprocal_math
-	  && TREE_CODE (arg0) == RDIV_EXPR)
-	return fold_build2_loc (loc, RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
-			    fold_build2_loc (loc, MULT_EXPR, type,
-					 TREE_OPERAND (arg0, 1), arg1));
-
-      /* Convert A/(B/C) to (A/B)*C.  */
-      if (flag_reciprocal_math
-	  && TREE_CODE (arg1) == RDIV_EXPR)
-	return fold_build2_loc (loc, MULT_EXPR, type,
-			    fold_build2_loc (loc, RDIV_EXPR, type, arg0,
-					 TREE_OPERAND (arg1, 0)),
-			    TREE_OPERAND (arg1, 1));
-
-      /* Convert C1/(X*C2) into (C1/C2)/X.  */
-      if (flag_reciprocal_math
-	  && TREE_CODE (arg1) == MULT_EXPR
-	  && TREE_CODE (arg0) == REAL_CST
-	  && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST)
-	{
-	  tree tem = const_binop (RDIV_EXPR, arg0,
-				  TREE_OPERAND (arg1, 1));
-	  if (tem)
-	    return fold_build2_loc (loc, RDIV_EXPR, type, tem,
-				TREE_OPERAND (arg1, 0));
-	}
-
       return NULL_TREE;
 
     case TRUNC_DIV_EXPR:
-      /* Optimize (X & (-A)) / A where A is a power of 2,
-	 to X >> log2(A) */
-      if (TREE_CODE (arg0) == BIT_AND_EXPR
-	  && !TYPE_UNSIGNED (type) && TREE_CODE (arg1) == INTEGER_CST
-	  && integer_pow2p (arg1) && tree_int_cst_sgn (arg1) > 0)
-	{
-	  tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (arg1),
-				      arg1, TREE_OPERAND (arg0, 1));
-	  if (sum && integer_zerop (sum)) {
-	    tree pow2 = build_int_cst (integer_type_node,
-				       wi::exact_log2 (arg1));
-	    return fold_build2_loc (loc, RSHIFT_EXPR, type,
-				    TREE_OPERAND (arg0, 0), pow2);
-	  }
-	}
-
       /* Fall through */
       
     case FLOOR_DIV_EXPR:
diff --git a/gcc/match.pd b/gcc/match.pd
index f6c5c07..04f384c 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -247,6 +247,34 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (if (!HONOR_SNANS (type))
   (negate @0)))
 
+/* Convert (A/B)/C to A/(B*C)  */
+(simplify
+ (rdiv (convert? (rdiv @0 @1)) (convert? @2))
+  (if (flag_reciprocal_math
+       && tree_nop_conversion_p (type, TREE_TYPE (@0))
+       && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+   (rdiv (convert @0) (convert (mult @1 @2)))))
+
+/* Convert A/(B/C) to (A/B)*C  */
+(simplify
+ (rdiv (convert? @0) (convert? (rdiv @1 @2)))
+  (if (flag_reciprocal_math
+       && tree_nop_conversion_p (type, TREE_TYPE (@0))
+       && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+   (mult (convert (rdiv @0 @1)) (convert @2))))
+
+/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */
+(simplify
+ (trunc_div (bit_and (convert? @0) @1) INTEGER_CST@2)
+ (if (!TYPE_UNSIGNED (type) && integer_pow2p (@2)
+      && tree_int_cst_sgn (@2) > 0
+      && tree_nop_conversion_p (type, TREE_TYPE (@0)))
+  (with
+   { tree sum = fold_binary (PLUS_EXPR, TREE_TYPE (@2), @2, @1); }
+   (if (sum && integer_zerop (sum))
+    (rshift (convert @0) { build_int_cst (integer_type_node,
+					  wi::exact_log2 (@2)); })))))
+
 /* If ARG1 is a constant, we can convert this to a multiply by the
    reciprocal.  This does not have the same rounding properties,
    so only do this if -freciprocal-math.  We can actually
@@ -464,6 +492,15 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (if (tem)
      (rdiv { tem; } @1)))))
 
+/* Convert C1/(X*C2) into (C1/C2)/X  */
+(simplify
+ (rdiv (REAL_CST@0) (mult (convert? @1) REAL_CST@2))
+  (if (flag_reciprocal_math)
+   (with
+    { tree tem = const_binop (RDIV_EXPR, type, @0, @2); }
+    (if (tem && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+     (rdiv { tem; } @1)))))
+
 /* Simplify ~X & X as zero.  */
 (simplify
  (bit_and:c (convert? @0) (convert? (bit_not @0)))