This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

pr26026: udiv and umod optimization


This patch optimizes code in a hot loop of a certain well known
benchmark.  Sorry for being mysterious, but I'm not sure I'm allowed
to publish numbers or even mention the benchmark by name since the
2006 version (where this optimization triggers) hasn't been released
yet.

Bootstrapped and regression tested powerpc64-linux.  OK for mainline?

	PR rtl-optimization/26026
	* expr.c (expand_expr_real_1): Optimize div and mod where the divisor
	is a known power of two shifted left a variable amount.

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 110484)
+++ gcc/expr.c	(working copy)
@@ -7999,6 +7999,32 @@ expand_expr_real_1 (tree exp, rtx target
       return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
 
     case TRUNC_DIV_EXPR:
+      /* Simplify A / (B << N)  where B is a power of 2,
+	 to A >> (N + log2(B)).  */
+      if (unsignedp && TREE_CODE (TREE_OPERAND (exp, 1)) == LSHIFT_EXPR)
+	{
+	  tree sval = TREE_OPERAND (TREE_OPERAND (exp, 1), 0);
+	  if (TREE_CODE (sval) == INTEGER_CST
+	      && !TREE_CONSTANT_OVERFLOW (sval)
+	      && TREE_INT_CST_HIGH (sval) == 0
+	      && TREE_INT_CST_LOW (sval) != 0
+	      && ((TREE_INT_CST_LOW (sval) & -TREE_INT_CST_LOW (sval))
+		  == TREE_INT_CST_LOW (sval)))
+	    {
+	      tree sh_cnt = TREE_OPERAND (TREE_OPERAND (exp, 1), 1);
+	      if (TREE_INT_CST_LOW (sval) != 1)
+		{
+		  unsigned long pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
+		  sh_cnt = fold_build2 (PLUS_EXPR, TREE_TYPE (sh_cnt),
+					sh_cnt, build_int_cst (NULL_TREE, pow2));
+		}
+	      exp = build2 (RSHIFT_EXPR, TREE_TYPE (TREE_OPERAND (exp, 0)),
+			    TREE_OPERAND (exp, 0), sh_cnt);
+	      return expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
+	    }
+	}
+      /* Fall thru */
+
     case FLOOR_DIV_EXPR:
     case CEIL_DIV_EXPR:
     case ROUND_DIV_EXPR:
@@ -8016,6 +8042,27 @@ expand_expr_real_1 (tree exp, rtx target
       goto binop;
 
     case TRUNC_MOD_EXPR:
+      /* Simplify A % (B << N)  where B is a power of 2,
+	 to A & ((B << N) - 1).  */
+      if (unsignedp && TREE_CODE (TREE_OPERAND (exp, 1)) == LSHIFT_EXPR)
+	{
+	  tree sval = TREE_OPERAND (TREE_OPERAND (exp, 1), 0);
+	  if (TREE_CODE (sval) == INTEGER_CST
+	      && !TREE_CONSTANT_OVERFLOW (sval)
+	      && TREE_INT_CST_HIGH (sval) == 0
+	      && TREE_INT_CST_LOW (sval) != 0
+	      && ((TREE_INT_CST_LOW (sval) & -TREE_INT_CST_LOW (sval))
+		  == TREE_INT_CST_LOW (sval)))
+	    {
+	      tree mask = build2 (MINUS_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)),
+				  TREE_OPERAND (exp, 1), integer_one_node);
+	      exp = build2 (BIT_AND_EXPR, TREE_TYPE (TREE_OPERAND (exp, 0)),
+			    TREE_OPERAND (exp, 0), mask);
+	      return expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
+	    }
+	}
+      /* Fall thru */
+
     case FLOOR_MOD_EXPR:
     case CEIL_MOD_EXPR:
     case ROUND_MOD_EXPR:

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]