pr26026: udiv and umod optimization
Alan Modra
amodra@bigpond.net.au
Sat Feb 11 05:53:00 GMT 2006
On Thu, Feb 09, 2006 at 08:35:20AM -0700, Jeffrey A Law wrote:
> The second alternative would be to walk the def-use chain back one
> step for the divisor and see if the divisor is set from a 1 << X
> style operation. This would be trivial to implement inside the
> existing simplification code.
Like so? My first foray into tree-ssa, so I won't be surprised if
there is a better way to do this.. Bootstrapped and regression tested
powerpc64-linux.
PR tree-optimization/26026
* tree-vrp.c (simplify_div_or_mod_using_ranges): Replace rhs_code
param with is_div. Support optimisation of div and mod by
power of two shifted left a variable amout. Tidy.
(simplify_stmt_using_ranges): Similarly. Also support FLOOR_DIV_EXPR
and FLOOR_MOD_EXPR.
Index: tree-vrp.c
===================================================================
--- tree-vrp.c (revision 110783)
+++ tree-vrp.c (working copy)
@@ -3962,37 +3962,68 @@ varying:
than zero and the second operand is an exact power of two. */
static void
-simplify_div_or_mod_using_ranges (tree stmt, tree rhs, enum tree_code rhs_code)
+simplify_div_or_mod_using_ranges (tree stmt, tree rhs, bool is_div)
{
- tree val = NULL;
- tree op = TREE_OPERAND (rhs, 0);
- value_range_t *vr = get_value_range (TREE_OPERAND (rhs, 0));
+ tree op0 = TREE_OPERAND (rhs, 0);
+ bool ok;
- if (TYPE_UNSIGNED (TREE_TYPE (op)))
+ if (TYPE_UNSIGNED (TREE_TYPE (op0)))
{
- val = integer_one_node;
+ ok = true;
}
else
{
+ tree val;
+ value_range_t *vr = get_value_range (op0);
+
val = compare_range_with_value (GT_EXPR, vr, integer_zero_node);
+ ok = val && integer_onep (val);
}
- if (val && integer_onep (val))
+ if (ok)
{
tree t;
- tree op0 = TREE_OPERAND (rhs, 0);
tree op1 = TREE_OPERAND (rhs, 1);
- if (rhs_code == TRUNC_DIV_EXPR)
+ if (is_div)
{
- t = build_int_cst (NULL_TREE, tree_log2 (op1));
+ if (TREE_CODE (op1) == SSA_NAME)
+ {
+ /* op1 = C << N, C a power of two. */
+ tree defexp = TREE_OPERAND (SSA_NAME_DEF_STMT (op1), 1);
+ int pow2 = tree_log2 (TREE_OPERAND (defexp, 0));
+
+ t = TREE_OPERAND (defexp, 1);
+ if (pow2 != 0)
+ {
+ /* tmp = N + log2(C). */
+ block_stmt_iterator bsi = bsi_for_stmt (stmt);
+
+ t = gimplify_build2 (&bsi, PLUS_EXPR, TREE_TYPE (t),
+ t, build_int_cst (NULL_TREE, pow2));
+ }
+ }
+ else
+ t = build_int_cst (NULL_TREE, tree_log2 (op1));
+
t = build2 (RSHIFT_EXPR, TREE_TYPE (op0), op0, t);
}
else
{
- t = build_int_cst (TREE_TYPE (op1), 1);
- t = int_const_binop (MINUS_EXPR, op1, t, 0);
- t = fold_convert (TREE_TYPE (op0), t);
+ if (TREE_CODE (op1) == SSA_NAME)
+ {
+ block_stmt_iterator bsi = bsi_for_stmt (stmt);
+
+ t = TREE_OPERAND (SSA_NAME_DEF_STMT (op1), 0);
+ t = build2 (MINUS_EXPR, TREE_TYPE (t), t, integer_one_node);
+ t = fold_convert (TREE_TYPE (op0), t);
+ t = gimplify_val (&bsi, TREE_TYPE (op0), t);
+ }
+ else
+ {
+ t = int_const_binop (MINUS_EXPR, op1, integer_one_node, 0);
+ t = fold_convert (TREE_TYPE (op0), t);
+ }
t = build2 (BIT_AND_EXPR, TREE_TYPE (op0), op0, t);
}
@@ -4202,9 +4233,29 @@ simplify_stmt_using_ranges (tree stmt)
and BIT_AND_EXPR respectively if the first operand is greater
than zero and the second operand is an exact power of two. */
if ((rhs_code == TRUNC_DIV_EXPR || rhs_code == TRUNC_MOD_EXPR)
- && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (rhs, 0)))
- && integer_pow2p (TREE_OPERAND (rhs, 1)))
- simplify_div_or_mod_using_ranges (stmt, rhs, rhs_code);
+ && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (rhs, 0))))
+ {
+ tree t = TREE_OPERAND (rhs, 1);
+
+ /* Also handle an exact power of two shifted left a variable
+ amount. */
+ if (TREE_CODE (t) == SSA_NAME)
+ {
+ t = SSA_NAME_DEF_STMT (t);
+ if (TREE_CODE (t) != MODIFY_EXPR)
+ return;
+
+ t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) != LSHIFT_EXPR)
+ return;
+
+ t = TREE_OPERAND (t, 0);
+ }
+
+ if (integer_pow2p (t))
+ simplify_div_or_mod_using_ranges (stmt, rhs,
+ rhs_code == TRUNC_DIV_EXPR);
+ }
/* Transform ABS (X) into X or -X as appropriate. */
if (rhs_code == ABS_EXPR
--
Alan Modra
IBM OzLabs - Linux Technology Centre
More information about the Gcc-patches
mailing list