diff mbox

More Division optimization using match and simplify

Message ID SN2PR0701MB10242E35845F2C5C3BA1BD568E1D0@SN2PR0701MB1024.namprd07.prod.outlook.com
State New
Headers show

Commit Message

Hurugalawadi, Naveen Nov. 17, 2015, 6:22 a.m. UTC
Hi,  

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

Please review the patch and let me know if any modifications are required.
Hopefully got the converts right this time :-)  

Regression tested the patch on X86 without any issues.  

Thanks, 
Naveen  

ChangeLog

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

	* fold-const.c (fold_binary_loc) : Move Simplify A / (B << N) where A
	and B are positive and B is a power of 2, to A >> (N + log2(B)) 
	to match.pd.
	Move If arg0 is a multiple of arg1, then rewrite to the fastest div
	operation, EXACT_DIV_EXPR to match.pd.

	* match.pd (floor_div (convert? @0) (lshift @1 INTEGER_CST@2)):
	New simplifier.
	(div (convert? @0) (convert? @1)): New simplifier.

Comments

Marc Glisse Nov. 21, 2015, 6:50 p.m. UTC | #1
On Tue, 17 Nov 2015, Hurugalawadi, Naveen wrote:

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

First, note that we are in stage 3, so this all may have to wait until 
sometime around March or April next year unless it is fixing some bug.

+/* Simplify A / (B << N) where A and B are positive and B is a power of 2,
+   to A >> (N + log2(B)).  */
+(simplify
+ (floor_div (convert? @0) (lshift @1 INTEGER_CST@2))

I don't think the fold-const code was asking for @2 to be a constant. You 
will never see (lshift cst1 cst2) in match.pd, it has already been folded 
to a constant.

+ (if ((TYPE_UNSIGNED (type)
+       || tree_expr_nonnegative_warnv_p (@0, NULL))
+      && integer_pow2p (@1)

Note that you can write integer_pow2p@1 in the pattern directly if you 
want.

+      && tree_int_cst_sgn (@1) > 0
+      && tree_nop_conversion_p (type, TREE_TYPE (@0)))
+  (with
+   { tree pow2 = build_int_cst (TREE_TYPE (@2), wi::exact_log2 (@1));
+     tree temp = const_binop (PLUS_EXPR, TREE_TYPE (@2), @2, pow2); }

Hmm, maybe you could do the log and plus using wi and only build a single 
tree at the end, for a slight economy?

+   (rshift (convert @0) { temp; }))))
+
+/* Convert A/B to A/B  */
+(for div (CEIL_DIV_EXPR FLOOR_DIV_EXPR)
+ (simplify
+  (div (convert? @0) (convert? @1))
+  (if (wi::multiple_of_p (@0, @1, TYPE_SIGN (type)))
+   (exact_div (convert @0) (convert @1)))))

Sorry, using wi::multiple_of_p makes no sense here. It can only work on 
constants, but for constants we have constant propagation.
diff mbox

Patch

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index ce59c48..0c72a75 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -10220,32 +10220,6 @@  fold_binary_loc (location_t loc,
       /* Fall through */
       
     case FLOOR_DIV_EXPR:
-      /* Simplify A / (B << N) where A and B are positive and B is
-	 a power of 2, to A >> (N + log2(B)).  */
-      strict_overflow_p = false;
-      if (TREE_CODE (arg1) == LSHIFT_EXPR
-	  && (TYPE_UNSIGNED (type)
-	      || tree_expr_nonnegative_warnv_p (op0, &strict_overflow_p)))
-	{
-	  tree sval = TREE_OPERAND (arg1, 0);
-	  if (integer_pow2p (sval) && tree_int_cst_sgn (sval) > 0)
-	    {
-	      tree sh_cnt = TREE_OPERAND (arg1, 1);
-	      tree pow2 = build_int_cst (TREE_TYPE (sh_cnt),
-					 wi::exact_log2 (sval));
-
-	      if (strict_overflow_p)
-		fold_overflow_warning (("assuming signed overflow does not "
-					"occur when simplifying A / (B << N)"),
-				       WARN_STRICT_OVERFLOW_MISC);
-
-	      sh_cnt = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (sh_cnt),
-					sh_cnt, pow2);
-	      return fold_build2_loc (loc, RSHIFT_EXPR, type,
-				      fold_convert_loc (loc, type, arg0), sh_cnt);
-	    }
-	}
-
       /* Fall through */
 
     case ROUND_DIV_EXPR:
@@ -10287,18 +10261,6 @@  fold_binary_loc (location_t loc,
 						TREE_OPERAND (arg1, 0)));
 	}
 
-      /* If arg0 is a multiple of arg1, then rewrite to the fastest div
-	 operation, EXACT_DIV_EXPR.
-
-	 Note that only CEIL_DIV_EXPR and FLOOR_DIV_EXPR are rewritten now.
-	 At one time others generated faster code, it's not clear if they do
-	 after the last round to changes to the DIV code in expmed.c.  */
-      if ((code == CEIL_DIV_EXPR || code == FLOOR_DIV_EXPR)
-	  && multiple_of_p (type, arg0, arg1))
-	return fold_build2_loc (loc, EXACT_DIV_EXPR, type,
-				fold_convert (type, arg0),
-				fold_convert (type, arg1));
-
       strict_overflow_p = false;
       if (TREE_CODE (arg1) == INTEGER_CST
 	  && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE,
diff --git a/gcc/match.pd b/gcc/match.pd
index d552beb..5ca2778 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -269,6 +269,27 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (rshift (convert @0) { build_int_cst (integer_type_node,
 					 wi::exact_log2 (@2)); }))))
 
+/* Simplify A / (B << N) where A and B are positive and B is a power of 2,
+   to A >> (N + log2(B)).  */
+(simplify
+ (floor_div (convert? @0) (lshift @1 INTEGER_CST@2))
+ (if ((TYPE_UNSIGNED (type)
+       || tree_expr_nonnegative_warnv_p (@0, NULL))
+      && integer_pow2p (@1)
+      && tree_int_cst_sgn (@1) > 0
+      && tree_nop_conversion_p (type, TREE_TYPE (@0)))
+  (with
+   { tree pow2 = build_int_cst (TREE_TYPE (@2), wi::exact_log2 (@1));
+     tree temp = const_binop (PLUS_EXPR, TREE_TYPE (@2), @2, pow2); }
+   (rshift (convert @0) { temp; }))))
+
+/* Convert A/B to A/B  */
+(for div (CEIL_DIV_EXPR FLOOR_DIV_EXPR)
+ (simplify
+  (div (convert? @0) (convert? @1))
+  (if (wi::multiple_of_p (@0, @1, TYPE_SIGN (type)))
+   (exact_div (convert @0) (convert @1)))))
+
 /* 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