From 58f43b9022418d659bfa7c3600662fdecd313774 Mon Sep 17 00:00:00 2001 From: rakdver Date: Mon, 28 Aug 2006 21:15:19 +0000 Subject: [PATCH] PR tree-optimization/28411 * double-int.c (double_int_div): Use double_int_divmod. (double_int_divmod, double_int_sdivmod, double_int_udivmod, double_int_mod, double_int_smod, double_int_umod): New functions. * double-int.h (double_int_divmod, double_int_sdivmod, double_int_udivmod, double_int_mod, double_int_smod, double_int_umod): Declare. * tree-ssa-loop-ivopts.c (constant_multiple_of): Returns the result in double_int. (get_computation_aff, get_computation_cost_at): Handle double_int return type of constant_multiple_of. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116529 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 14 ++++++ gcc/double-int.c | 67 +++++++++++++++++++++++-- gcc/double-int.h | 6 +++ gcc/tree-ssa-loop-ivopts.c | 119 ++++++++++++++++++--------------------------- 4 files changed, 129 insertions(+), 77 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 733fa47e7f4..b333fe2b1f4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2006-08-28 Zdenek Dvorak + + PR tree-optimization/28411 + * double-int.c (double_int_div): Use double_int_divmod. + (double_int_divmod, double_int_sdivmod, double_int_udivmod, + double_int_mod, double_int_smod, double_int_umod): New functions. + * double-int.h (double_int_divmod, double_int_sdivmod, + double_int_udivmod, double_int_mod, double_int_smod, double_int_umod): + Declare. + * tree-ssa-loop-ivopts.c (constant_multiple_of): Returns the result + in double_int. + (get_computation_aff, get_computation_cost_at): Handle double_int + return type of constant_multiple_of. + 2006-08-28 Kazu Hirata PR middle-end/26632 diff --git a/gcc/double-int.c b/gcc/double-int.c index 5a7b51dbe31..3be0abf4f3a 100644 --- a/gcc/double-int.c +++ b/gcc/double-int.c @@ -203,20 +203,48 @@ double_int_neg (double_int a) /* Returns A / B (computed as unsigned depending on UNS, and rounded as specified by CODE). CODE is enum tree_code in fact, but double_int.h - must be included before tree.h. */ + must be included before tree.h. The remainder after the division is + stored to MOD. */ double_int -double_int_div (double_int a, double_int b, bool uns, unsigned code) +double_int_divmod (double_int a, double_int b, bool uns, unsigned code, + double_int *mod) { - unsigned HOST_WIDE_INT rem_lo; - HOST_WIDE_INT rem_hi; double_int ret; div_and_round_double (code, uns, a.low, a.high, b.low, b.high, - &ret.low, &ret.high, &rem_lo, &rem_hi); + &ret.low, &ret.high, &mod->low, &mod->high); return ret; } +/* The same as double_int_divmod with UNS = false. */ + +double_int +double_int_sdivmod (double_int a, double_int b, unsigned code, double_int *mod) +{ + return double_int_divmod (a, b, false, code, mod); +} + +/* The same as double_int_divmod with UNS = true. */ + +double_int +double_int_udivmod (double_int a, double_int b, unsigned code, double_int *mod) +{ + return double_int_divmod (a, b, true, code, mod); +} + +/* Returns A / B (computed as unsigned depending on UNS, and rounded as + specified by CODE). CODE is enum tree_code in fact, but double_int.h + must be included before tree.h. */ + +double_int +double_int_div (double_int a, double_int b, bool uns, unsigned code) +{ + double_int mod; + + return double_int_divmod (a, b, uns, code, &mod); +} + /* The same as double_int_div with UNS = false. */ double_int @@ -233,6 +261,35 @@ double_int_udiv (double_int a, double_int b, unsigned code) return double_int_div (a, b, true, code); } +/* Returns A % B (computed as unsigned depending on UNS, and rounded as + specified by CODE). CODE is enum tree_code in fact, but double_int.h + must be included before tree.h. */ + +double_int +double_int_mod (double_int a, double_int b, bool uns, unsigned code) +{ + double_int mod; + + double_int_divmod (a, b, uns, code, &mod); + return mod; +} + +/* The same as double_int_mod with UNS = false. */ + +double_int +double_int_smod (double_int a, double_int b, unsigned code) +{ + return double_int_mod (a, b, false, code); +} + +/* The same as double_int_mod with UNS = true. */ + +double_int +double_int_umod (double_int a, double_int b, unsigned code) +{ + return double_int_mod (a, b, true, code); +} + /* Constructs tree in type TYPE from with value given by CST. */ tree diff --git a/gcc/double-int.h b/gcc/double-int.h index f37bcb2f299..eddd7b7e2fe 100644 --- a/gcc/double-int.h +++ b/gcc/double-int.h @@ -116,6 +116,12 @@ unsigned HOST_WIDE_INT double_int_to_uhwi (double_int); double_int double_int_div (double_int, double_int, bool, unsigned); double_int double_int_sdiv (double_int, double_int, unsigned); double_int double_int_udiv (double_int, double_int, unsigned); +double_int double_int_mod (double_int, double_int, bool, unsigned); +double_int double_int_smod (double_int, double_int, unsigned); +double_int double_int_umod (double_int, double_int, unsigned); +double_int double_int_divmod (double_int, double_int, bool, unsigned, double_int *); +double_int double_int_sdivmod (double_int, double_int, unsigned, double_int *); +double_int double_int_udivmod (double_int, double_int, unsigned, double_int *); bool double_int_negative_p (double_int); int double_int_cmp (double_int, double_int, bool); int double_int_scmp (double_int, double_int); diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 2ead5495b7e..ae1905d05de 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -2554,21 +2554,27 @@ tree_int_cst_sign_bit (tree t) return (w >> bitno) & 1; } -/* If we can prove that TOP = cst * BOT for some constant cst in TYPE, - return cst. Otherwise return NULL_TREE. */ +/* If we can prove that TOP = cst * BOT for some constant cst, + store cst to MUL and return true. Otherwise return false. + The returned value is always sign-extended, regardless of the + signedness of TOP and BOT. */ -static tree -constant_multiple_of (tree type, tree top, tree bot) +static bool +constant_multiple_of (tree top, tree bot, double_int *mul) { - tree res, mby, p0, p1; + tree mby; enum tree_code code; - bool negate; + double_int res, p0, p1; + unsigned precision = TYPE_PRECISION (TREE_TYPE (top)); STRIP_NOPS (top); STRIP_NOPS (bot); if (operand_equal_p (top, bot, 0)) - return build_int_cst (type, 1); + { + *mul = double_int_one; + return true; + } code = TREE_CODE (top); switch (code) @@ -2576,60 +2582,40 @@ constant_multiple_of (tree type, tree top, tree bot) case MULT_EXPR: mby = TREE_OPERAND (top, 1); if (TREE_CODE (mby) != INTEGER_CST) - return NULL_TREE; + return false; - res = constant_multiple_of (type, TREE_OPERAND (top, 0), bot); - if (!res) - return NULL_TREE; + if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &res)) + return false; - return fold_binary_to_constant (MULT_EXPR, type, res, - fold_convert (type, mby)); + *mul = double_int_sext (double_int_mul (res, tree_to_double_int (mby)), + precision); + return true; case PLUS_EXPR: case MINUS_EXPR: - p0 = constant_multiple_of (type, TREE_OPERAND (top, 0), bot); - if (!p0) - return NULL_TREE; - p1 = constant_multiple_of (type, TREE_OPERAND (top, 1), bot); - if (!p1) - return NULL_TREE; + if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &p0) + || !constant_multiple_of (TREE_OPERAND (top, 1), bot, &p1)) + return false; - return fold_binary_to_constant (code, type, p0, p1); + if (code == MINUS_EXPR) + p1 = double_int_neg (p1); + *mul = double_int_sext (double_int_add (p0, p1), precision); + return true; case INTEGER_CST: if (TREE_CODE (bot) != INTEGER_CST) - return NULL_TREE; - - bot = fold_convert (type, bot); - top = fold_convert (type, top); - - /* If BOT seems to be negative, try dividing by -BOT instead, and negate - the result afterwards. */ - if (tree_int_cst_sign_bit (bot)) - { - negate = true; - bot = fold_unary_to_constant (NEGATE_EXPR, type, bot); - } - else - negate = false; - - /* Ditto for TOP. */ - if (tree_int_cst_sign_bit (top)) - { - negate = !negate; - top = fold_unary_to_constant (NEGATE_EXPR, type, top); - } - - if (!zero_p (fold_binary_to_constant (TRUNC_MOD_EXPR, type, top, bot))) - return NULL_TREE; + return false; - res = fold_binary_to_constant (EXACT_DIV_EXPR, type, top, bot); - if (negate) - res = fold_unary_to_constant (NEGATE_EXPR, type, res); - return res; + p0 = double_int_sext (tree_to_double_int (bot), precision); + p1 = double_int_sext (tree_to_double_int (top), precision); + if (double_int_zero_p (p1)) + return false; + *mul = double_int_sext (double_int_sdivmod (p0, p1, FLOOR_DIV_EXPR, &res), + precision); + return double_int_zero_p (res); default: - return NULL_TREE; + return false; } } @@ -2986,6 +2972,7 @@ get_computation_aff (struct loop *loop, HOST_WIDE_INT ratioi; struct affine_tree_combination cbase_aff, expr_aff; tree cstep_orig = cstep, ustep_orig = ustep; + double_int rat; if (TYPE_PRECISION (utype) > TYPE_PRECISION (ctype)) { @@ -3040,21 +3027,15 @@ get_computation_aff (struct loop *loop, } else { - ratio = constant_multiple_of (uutype, ustep_orig, cstep_orig); - if (!ratio) + if (!constant_multiple_of (ustep_orig, cstep_orig, &rat)) return false; + ratio = double_int_to_tree (uutype, rat); /* Ratioi is only used to detect special cases when the multiplicative - factor is 1 or -1, so if we cannot convert ratio to HOST_WIDE_INT, - we may set it to 0. We prefer cst_and_fits_in_hwi/int_cst_value - to integer_onep/integer_all_onesp, since the former ignores - TREE_OVERFLOW. */ - if (cst_and_fits_in_hwi (ratio)) - ratioi = int_cst_value (ratio); - else if (integer_onep (ratio)) - ratioi = 1; - else if (integer_all_onesp (ratio)) - ratioi = -1; + factor is 1 or -1, so if rat does not fit to HOST_WIDE_INT, we may + set it to 0. */ + if (double_int_fits_in_shwi_p (rat)) + ratioi = double_int_to_shwi (rat); else ratioi = 0; } @@ -3775,19 +3756,13 @@ get_computation_cost_at (struct ivopts_data *data, } else { - tree rat; + double_int rat; - rat = constant_multiple_of (utype, ustep, cstep); - - if (!rat) + if (!constant_multiple_of (ustep, cstep, &rat)) return INFTY; - - if (cst_and_fits_in_hwi (rat)) - ratio = int_cst_value (rat); - else if (integer_onep (rat)) - ratio = 1; - else if (integer_all_onesp (rat)) - ratio = -1; + + if (double_int_fits_in_shwi_p (rat)) + ratio = double_int_to_shwi (rat); else return INFTY; } -- 2.11.4.GIT