mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-31 15:11:04 +08:00
re PR tree-optimization/28411 ("Illegal instruction" error with -ftrapv)
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. From-SVN: r116529
This commit is contained in:
parent
689e7ddada
commit
f414f2f35e
@ -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
|
||||
|
@ -201,6 +201,38 @@ double_int_neg (double_int a)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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. The remainder after the division is
|
||||
stored to MOD. */
|
||||
|
||||
double_int
|
||||
double_int_divmod (double_int a, double_int b, bool uns, unsigned code,
|
||||
double_int *mod)
|
||||
{
|
||||
double_int ret;
|
||||
|
||||
div_and_round_double (code, uns, a.low, a.high, b.low, b.high,
|
||||
&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. */
|
||||
@ -208,13 +240,9 @@ double_int_neg (double_int a)
|
||||
double_int
|
||||
double_int_div (double_int a, double_int b, bool uns, unsigned code)
|
||||
{
|
||||
unsigned HOST_WIDE_INT rem_lo;
|
||||
HOST_WIDE_INT rem_hi;
|
||||
double_int ret;
|
||||
double_int mod;
|
||||
|
||||
div_and_round_double (code, uns, a.low, a.high, b.low, b.high,
|
||||
&ret.low, &ret.high, &rem_lo, &rem_hi);
|
||||
return ret;
|
||||
return double_int_divmod (a, b, uns, code, &mod);
|
||||
}
|
||||
|
||||
/* The same as double_int_div with UNS = false. */
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
return false;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user