diff options
author | brooks <brooks@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-04-30 19:14:04 +0000 |
---|---|---|
committer | brooks <brooks@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-04-30 19:14:04 +0000 |
commit | 612a17fc003aefd310cd106ca3bab69b7f855956 (patch) | |
tree | 6479ca4b9aae9944979b25e103b6a70c19c8e7fe /gcc/double-int.c | |
parent | 2751c7d48f654df48925752bdbe179096104ca91 (diff) | |
download | gcc-612a17fc003aefd310cd106ca3bab69b7f855956.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@124304 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/double-int.c')
-rw-r--r-- | gcc/double-int.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/gcc/double-int.c b/gcc/double-int.c index 45a833a0654..8cbd3abc653 100644 --- a/gcc/double-int.c +++ b/gcc/double-int.c @@ -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; +} |