This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
pr26026: udiv and umod optimization
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 3 Feb 2006 22:59:32 +1030
- Subject: 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