summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2006-08-28 21:15:19 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2006-08-28 21:15:19 +0000
commit58f43b9022418d659bfa7c3600662fdecd313774 (patch)
tree30bc9b33718fe7a8c347a8df8410345bef4030ee
parentab71f27487869cae781c73d50eef9d1c6732a830 (diff)
downloadgcc-58f43b9022418d659bfa7c3600662fdecd313774.tar.gz
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
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/double-int.c67
-rw-r--r--gcc/double-int.h6
-rw-r--r--gcc/tree-ssa-loop-ivopts.c119
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 <dvorakz@suse.cz>
+
+ 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 <kazu@codesourcery.com>
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;
}