double-int.c (mpz_set_double_int): Moved from tree-ssa-loop-niter.c.
* double-int.c (mpz_set_double_int): Moved from tree-ssa-loop-niter.c. (mpz_get_double_int): Likewise; also, add option to wrap out-of-range integers. * double-int.h: New prototypes for above. * tree.c (get_static_type_bounds): Moved from tree-ssa-loop-niter.c; now returns TYPE_MIN_VALUE and TYPE_MAX_VALUE if they exist.. * tree.h: New prototype for above. * tree-ssa-loop-niter.c: Adjust mpz_to_double_int and get_type_bounds calls. (mpz_set_double_int): Move to double-int.c. (get_type_bounds): Move to tree.c, rename to get_static_type_bounds. (mpz_to_double_int): Move to double-int.c, rename to mpz_get_double_int. From-SVN: r124304
This commit is contained in:
parent
0a21c1d2ba
commit
e4fd22c6d5
6 changed files with 152 additions and 90 deletions
|
@ -1,3 +1,22 @@
|
|||
2007-04-30 Brooks Moses <brooks.moses@codesourcery.com>
|
||||
|
||||
* double-int.c (mpz_set_double_int): Moved from
|
||||
tree-ssa-loop-niter.c.
|
||||
(mpz_get_double_int): Likewise; also, add option to wrap
|
||||
out-of-range integers.
|
||||
* double-int.h: New prototypes for above.
|
||||
* tree.c (get_static_type_bounds): Moved from
|
||||
tree-ssa-loop-niter.c; now returns TYPE_MIN_VALUE and
|
||||
TYPE_MAX_VALUE if they exist..
|
||||
* tree.h: New prototype for above.
|
||||
* tree-ssa-loop-niter.c: Adjust mpz_to_double_int and
|
||||
get_type_bounds calls.
|
||||
(mpz_set_double_int): Move to double-int.c.
|
||||
(get_type_bounds): Move to tree.c, rename to
|
||||
get_static_type_bounds.
|
||||
(mpz_to_double_int): Move to double-int.c, rename to
|
||||
mpz_get_double_int.
|
||||
|
||||
2007-04-30 Bob Wilson <bob.wilson@acm.org>
|
||||
|
||||
* config/xtensa/lib1funcs.asm (__umodsi3, __modsi3): Rearrange so that
|
||||
|
|
|
@ -413,3 +413,81 @@ dump_double_int (FILE *file, double_int cst, bool uns)
|
|||
for (i = n - 1; i >= 0; i--)
|
||||
fprintf (file, "%u", digits[i]);
|
||||
}
|
||||
|
||||
|
||||
/* Sets RESULT to VAL, taken unsigned if UNS is true and as signed
|
||||
otherwise. */
|
||||
|
||||
void
|
||||
mpz_set_double_int (mpz_t result, double_int val, bool uns)
|
||||
{
|
||||
bool negate = false;
|
||||
unsigned HOST_WIDE_INT vp[2];
|
||||
|
||||
if (!uns && double_int_negative_p (val))
|
||||
{
|
||||
negate = true;
|
||||
val = double_int_neg (val);
|
||||
}
|
||||
|
||||
vp[0] = val.low;
|
||||
vp[1] = (unsigned HOST_WIDE_INT) val.high;
|
||||
mpz_import (result, 2, -1, sizeof (HOST_WIDE_INT), 0, 0, vp);
|
||||
|
||||
if (negate)
|
||||
mpz_neg (result, result);
|
||||
}
|
||||
|
||||
/* Returns VAL converted to TYPE. If WRAP is true, then out-of-range
|
||||
values of VAL will be wrapped; otherwise, they will be set to the
|
||||
appropriate minimum or maximum TYPE bound. */
|
||||
|
||||
double_int
|
||||
mpz_get_double_int (tree type, mpz_t val, bool wrap)
|
||||
{
|
||||
unsigned HOST_WIDE_INT *vp;
|
||||
size_t count, numb;
|
||||
double_int res;
|
||||
|
||||
if (!wrap)
|
||||
{
|
||||
mpz_t min, max;
|
||||
|
||||
mpz_init (min);
|
||||
mpz_init (max);
|
||||
get_type_static_bounds (type, min, max);
|
||||
|
||||
if (mpz_cmp (val, min) < 0)
|
||||
mpz_set (val, min);
|
||||
else if (mpz_cmp (val, max) > 0)
|
||||
mpz_set (val, max);
|
||||
|
||||
mpz_clear (min);
|
||||
mpz_clear (max);
|
||||
}
|
||||
|
||||
/* Determine the number of unsigned HOST_WIDE_INT that are required
|
||||
for representing the value. The code to calculate count is
|
||||
extracted from the GMP manual, section "Integer Import and Export":
|
||||
http://gmplib.org/manual/Integer-Import-and-Export.html */
|
||||
numb = 8*sizeof(HOST_WIDE_INT);
|
||||
count = (mpz_sizeinbase (val, 2) + numb-1) / numb;
|
||||
if (count < 2)
|
||||
count = 2;
|
||||
vp = (unsigned HOST_WIDE_INT *) alloca (count * sizeof(HOST_WIDE_INT));
|
||||
|
||||
vp[0] = 0;
|
||||
vp[1] = 0;
|
||||
mpz_export (vp, &count, -1, sizeof (HOST_WIDE_INT), 0, 0, val);
|
||||
|
||||
gcc_assert (wrap || count <= 2);
|
||||
|
||||
res.low = vp[0];
|
||||
res.high = (HOST_WIDE_INT) vp[1];
|
||||
|
||||
res = double_int_ext (res, TYPE_PRECISION (type), TYPE_UNSIGNED (type));
|
||||
if (mpz_sgn (val) < 0)
|
||||
res = double_int_neg (res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
|||
#ifndef DOUBLE_INT_H
|
||||
#define DOUBLE_INT_H
|
||||
|
||||
#include <gmp.h>
|
||||
#include "coretypes.h"
|
||||
|
||||
/* A large integer is currently represented as a pair of HOST_WIDE_INTs.
|
||||
It therefore represents a number with precision of
|
||||
2 * HOST_BITS_PER_WIDE_INT bits (it is however possible that the
|
||||
|
@ -174,4 +177,10 @@ double_int_equal_p (double_int cst1, double_int cst2)
|
|||
return cst1.low == cst2.low && cst1.high == cst2.high;
|
||||
}
|
||||
|
||||
/* Conversion to and from GMP integer representations. */
|
||||
|
||||
void mpz_set_double_int (mpz_t, double_int, bool);
|
||||
double_int mpz_get_double_int (tree, mpz_t, bool);
|
||||
|
||||
|
||||
#endif /* DOUBLE_INT_H */
|
||||
|
|
|
@ -64,92 +64,6 @@ typedef struct
|
|||
mpz_t below, up;
|
||||
} bounds;
|
||||
|
||||
/* Sets RESULT to VAL, taken unsigned if UNS is true and as signed
|
||||
otherwise. */
|
||||
|
||||
static void
|
||||
mpz_set_double_int (mpz_t result, double_int val, bool uns)
|
||||
{
|
||||
bool negate = false;
|
||||
unsigned HOST_WIDE_INT vp[2];
|
||||
|
||||
if (!uns && double_int_negative_p (val))
|
||||
{
|
||||
negate = true;
|
||||
val = double_int_neg (val);
|
||||
}
|
||||
|
||||
vp[0] = val.low;
|
||||
vp[1] = (unsigned HOST_WIDE_INT) val.high;
|
||||
mpz_import (result, 2, -1, sizeof (HOST_WIDE_INT), 0, 0, vp);
|
||||
|
||||
if (negate)
|
||||
mpz_neg (result, result);
|
||||
}
|
||||
|
||||
/* Stores bounds of TYPE to MIN and MAX. */
|
||||
|
||||
static void
|
||||
get_type_bounds (tree type, mpz_t min, mpz_t max)
|
||||
{
|
||||
if (TYPE_UNSIGNED (type))
|
||||
{
|
||||
mpz_set_ui (min, 0);
|
||||
mpz_set_double_int (max, double_int_mask (TYPE_PRECISION (type)), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
double_int mx, mn;
|
||||
|
||||
mx = double_int_mask (TYPE_PRECISION (type) - 1);
|
||||
mn = double_int_sext (double_int_add (mx, double_int_one),
|
||||
TYPE_PRECISION (type));
|
||||
mpz_set_double_int (max, mx, true);
|
||||
mpz_set_double_int (min, mn, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns VAL converted to TYPE. If VAL does not fit in TYPE,
|
||||
the minimum or maximum value of the type is returned instead. */
|
||||
|
||||
static double_int
|
||||
mpz_to_double_int (tree type, mpz_t val)
|
||||
{
|
||||
mpz_t min, max;
|
||||
unsigned HOST_WIDE_INT vp[2];
|
||||
bool negate = false;
|
||||
size_t count;
|
||||
double_int res;
|
||||
|
||||
mpz_init (min);
|
||||
mpz_init (max);
|
||||
get_type_bounds (type, min, max);
|
||||
|
||||
if (mpz_cmp (val, min) < 0)
|
||||
mpz_set (val, min);
|
||||
else if (mpz_cmp (val, max) > 0)
|
||||
mpz_set (val, max);
|
||||
|
||||
if (mpz_sgn (val) < 0)
|
||||
negate = true;
|
||||
|
||||
vp[0] = 0;
|
||||
vp[1] = 0;
|
||||
mpz_export (vp, &count, -1, sizeof (HOST_WIDE_INT), 0, 0, val);
|
||||
gcc_assert (count <= 2);
|
||||
|
||||
mpz_clear (min);
|
||||
mpz_clear (max);
|
||||
|
||||
res.low = vp[0];
|
||||
res.high = (HOST_WIDE_INT) vp[1];
|
||||
|
||||
res = double_int_ext (res, TYPE_PRECISION (type), TYPE_UNSIGNED (type));
|
||||
if (negate)
|
||||
res = double_int_neg (res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Splits expression EXPR to a variable part VAR and constant OFFSET. */
|
||||
|
||||
|
@ -212,7 +126,7 @@ determine_value_range (tree type, tree var, mpz_t off,
|
|||
|
||||
/* If the computation may wrap, we know nothing about the value, except for
|
||||
the range of the type. */
|
||||
get_type_bounds (type, min, max);
|
||||
get_type_static_bounds (type, min, max);
|
||||
if (!nowrap_type_p (type))
|
||||
return;
|
||||
|
||||
|
@ -703,7 +617,7 @@ number_of_iterations_ne (tree type, affine_iv *iv, tree final,
|
|||
|
||||
mpz_init (max);
|
||||
number_of_iterations_ne_max (max, iv->no_overflow, c, s, bnds);
|
||||
niter->max = mpz_to_double_int (niter_type, max);
|
||||
niter->max = mpz_get_double_int (niter_type, max, false);
|
||||
mpz_clear (max);
|
||||
|
||||
/* First the trivial cases -- when the step is 1. */
|
||||
|
@ -1081,7 +995,7 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
|
|||
niter->may_be_zero = fold_build2 (LT_EXPR, boolean_type_node,
|
||||
iv1->base, iv0->base);
|
||||
niter->niter = delta;
|
||||
niter->max = mpz_to_double_int (niter_type, bnds->up);
|
||||
niter->max = mpz_get_double_int (niter_type, bnds->up, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1128,7 +1042,7 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
|
|||
mpz_add (tmp, bnds->up, mstep);
|
||||
mpz_sub_ui (tmp, tmp, 1);
|
||||
mpz_fdiv_q (tmp, tmp, mstep);
|
||||
niter->max = mpz_to_double_int (niter_type, tmp);
|
||||
niter->max = mpz_get_double_int (niter_type, tmp, false);
|
||||
mpz_clear (mstep);
|
||||
mpz_clear (tmp);
|
||||
|
||||
|
|
41
gcc/tree.c
41
gcc/tree.c
|
@ -6138,6 +6138,47 @@ int_fits_type_p (tree c, tree type)
|
|||
return !fit_double_type (low, high, &low, &high, type);
|
||||
}
|
||||
|
||||
/* Stores bounds of an integer TYPE in MIN and MAX. If TYPE has non-constant
|
||||
bounds or is a POINTER_TYPE, the maximum and/or minimum values that can be
|
||||
represented (assuming two's-complement arithmetic) within the bit
|
||||
precision of the type are returned instead. */
|
||||
|
||||
void
|
||||
get_type_static_bounds (tree type, mpz_t min, mpz_t max)
|
||||
{
|
||||
if (!POINTER_TYPE_P (type) && TYPE_MIN_VALUE (type)
|
||||
&& TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
|
||||
mpz_set_double_int (min, tree_to_double_int (TYPE_MIN_VALUE (type)),
|
||||
TYPE_UNSIGNED (type));
|
||||
else
|
||||
{
|
||||
if (TYPE_UNSIGNED (type))
|
||||
mpz_set_ui (min, 0);
|
||||
else
|
||||
{
|
||||
double_int mn;
|
||||
mn = double_int_mask (TYPE_PRECISION (type) - 1);
|
||||
mn = double_int_sext (double_int_add (mn, double_int_one),
|
||||
TYPE_PRECISION (type));
|
||||
mpz_set_double_int (min, mn, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!POINTER_TYPE_P (type) && TYPE_MAX_VALUE (type)
|
||||
&& TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST)
|
||||
mpz_set_double_int (max, tree_to_double_int (TYPE_MAX_VALUE (type)),
|
||||
TYPE_UNSIGNED (type));
|
||||
else
|
||||
{
|
||||
if (TYPE_UNSIGNED (type))
|
||||
mpz_set_double_int (max, double_int_mask (TYPE_PRECISION (type)),
|
||||
true);
|
||||
else
|
||||
mpz_set_double_int (max, double_int_mask (TYPE_PRECISION (type) - 1),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Subprogram of following function. Called by walk_tree.
|
||||
|
||||
Return *TP if it is an automatic variable or parameter of the
|
||||
|
|
|
@ -4539,6 +4539,7 @@ extern int objects_must_conflict_p (tree, tree);
|
|||
/* In tree.c */
|
||||
extern int really_constant_p (tree);
|
||||
extern int int_fits_type_p (tree, tree);
|
||||
extern void get_type_static_bounds (tree, mpz_t, mpz_t);
|
||||
extern bool variably_modified_type_p (tree, tree);
|
||||
extern int tree_log2 (tree);
|
||||
extern int tree_floor_log2 (tree);
|
||||
|
|
Loading…
Add table
Reference in a new issue