This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [wide-int] Turn lts_p & co. back into template functions
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: Richard Sandiford <rdsandiford at googlemail dot com>,zadeck at naturalbridge dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Sun, 20 Oct 2013 14:47:17 +0200
- Subject: Re: [wide-int] Turn lts_p & co. back into template functions
- Authentication-results: sourceware.org; auth=none
- References: <871u3g5j92 dot fsf at talisman dot default>
Richard Sandiford <rdsandiford@googlemail.com> wrote:
>This patch just converts some functions back to template functions,
>for the benefit of the upcoming ::is_sign_extended patch. There's no
>behavioural change.
>
>Tested on x86_64-linux-gnu. OK for wide-int?
Ok.
Thanks,
Richard.
>Thanks,
>Richard
>
>
>Index: gcc/gcc/wide-int.h
>===================================================================
>--- gcc.orig/gcc/wide-int.h
>+++ gcc/gcc/wide-int.h
>@@ -347,42 +347,48 @@ namespace wi
> template <typename T1, typename T2>
> unsigned int get_binary_precision (const T1 &, const T2 &);
>
>- bool fits_shwi_p (const wide_int_ref &);
>- bool fits_uhwi_p (const wide_int_ref &);
>- bool neg_p (const wide_int_ref &, signop = SIGNED);
>- bool only_sign_bit_p (const wide_int_ref &, unsigned int);
>- bool only_sign_bit_p (const wide_int_ref &);
>- HOST_WIDE_INT sign_mask (const wide_int_ref &);
>-
>- template <typename T1, typename T2>
>- bool eq_p (const T1 &, const T2 &);
>-
>- template <typename T1, typename T2>
>- bool ne_p (const T1 &, const T2 &);
>-
>- bool lt_p (const wide_int_ref &, const wide_int_ref &, signop);
>- bool lts_p (const wide_int_ref &, const wide_int_ref &);
>- bool ltu_p (const wide_int_ref &, const wide_int_ref &);
>- bool le_p (const wide_int_ref &, const wide_int_ref &, signop);
>- bool les_p (const wide_int_ref &, const wide_int_ref &);
>- bool leu_p (const wide_int_ref &, const wide_int_ref &);
>- bool gt_p (const wide_int_ref &, const wide_int_ref &, signop);
>- bool gts_p (const wide_int_ref &, const wide_int_ref &);
>- bool gtu_p (const wide_int_ref &, const wide_int_ref &);
>- bool ge_p (const wide_int_ref &, const wide_int_ref &, signop);
>- bool ges_p (const wide_int_ref &, const wide_int_ref &);
>- bool geu_p (const wide_int_ref &, const wide_int_ref &);
>- int cmp (const wide_int_ref &, const wide_int_ref &, signop);
>- int cmps (const wide_int_ref &, const wide_int_ref &);
>- int cmpu (const wide_int_ref &, const wide_int_ref &);
>-
>+#define UNARY_PREDICATE \
>+ template <typename T> bool
> #define UNARY_FUNCTION \
> template <typename T> WI_UNARY_RESULT (T)
>+#define BINARY_PREDICATE \
>+ template <typename T1, typename T2> bool
> #define BINARY_FUNCTION \
> template <typename T1, typename T2> WI_BINARY_RESULT (T1, T2)
> #define SHIFT_FUNCTION \
> template <typename T> WI_UNARY_RESULT (T)
>
>+ UNARY_PREDICATE fits_shwi_p (const T &);
>+ UNARY_PREDICATE fits_uhwi_p (const T &);
>+ UNARY_PREDICATE neg_p (const T &, signop = SIGNED);
>+
>+ template <typename T>
>+ HOST_WIDE_INT sign_mask (const T &);
>+
>+ BINARY_PREDICATE eq_p (const T1 &, const T2 &);
>+ BINARY_PREDICATE ne_p (const T1 &, const T2 &);
>+ BINARY_PREDICATE lt_p (const T1 &, const T2 &, signop);
>+ BINARY_PREDICATE lts_p (const T1 &, const T2 &);
>+ BINARY_PREDICATE ltu_p (const T1 &, const T2 &);
>+ BINARY_PREDICATE le_p (const T1 &, const T2 &, signop);
>+ BINARY_PREDICATE les_p (const T1 &, const T2 &);
>+ BINARY_PREDICATE leu_p (const T1 &, const T2 &);
>+ BINARY_PREDICATE gt_p (const T1 &, const T2 &, signop);
>+ BINARY_PREDICATE gts_p (const T1 &, const T2 &);
>+ BINARY_PREDICATE gtu_p (const T1 &, const T2 &);
>+ BINARY_PREDICATE ge_p (const T1 &, const T2 &, signop);
>+ BINARY_PREDICATE ges_p (const T1 &, const T2 &);
>+ BINARY_PREDICATE geu_p (const T1 &, const T2 &);
>+
>+ template <typename T1, typename T2>
>+ int cmp (const T1 &, const T2 &, signop);
>+
>+ template <typename T1, typename T2>
>+ int cmps (const T1 &, const T2 &);
>+
>+ template <typename T1, typename T2>
>+ int cmpu (const T1 &, const T2 &);
>+
> UNARY_FUNCTION bit_not (const T &);
> UNARY_FUNCTION neg (const T &);
> UNARY_FUNCTION neg (const T &, bool *);
>@@ -446,9 +452,13 @@ namespace wi
>SHIFT_FUNCTION rrotate (const T &, const wide_int_ref &, unsigned int =
>0);
>
> #undef SHIFT_FUNCTION
>+#undef BINARY_PREDICATE
> #undef BINARY_FUNCTION
>+#undef UNARY_PREDICATE
> #undef UNARY_FUNCTION
>
>+ bool only_sign_bit_p (const wide_int_ref &, unsigned int);
>+ bool only_sign_bit_p (const wide_int_ref &);
> int clz (const wide_int_ref &);
> int clrsb (const wide_int_ref &);
> int ctz (const wide_int_ref &);
>@@ -1401,40 +1411,48 @@ wi::get_binary_precision (const T1 &x, c
>
> /* Return true if X fits in a HOST_WIDE_INT with no loss of
> precision. */
>+template <typename T>
> inline bool
>-wi::fits_shwi_p (const wide_int_ref &x)
>+wi::fits_shwi_p (const T &x)
> {
>- return x.len == 1;
>+ wide_int_ref xi (x);
>+ return xi.len == 1;
> }
>
> /* Return true if X fits in an unsigned HOST_WIDE_INT with no loss of
> precision. */
>+template <typename T>
> inline bool
>-wi::fits_uhwi_p (const wide_int_ref &x)
>+wi::fits_uhwi_p (const T &x)
> {
>- if (x.precision <= HOST_BITS_PER_WIDE_INT)
>+ wide_int_ref xi (x);
>+ if (xi.precision <= HOST_BITS_PER_WIDE_INT)
> return true;
>- if (x.len == 1)
>- return x.slow () >= 0;
>- return x.len == 2 && x.uhigh () == 0;
>+ if (xi.len == 1)
>+ return xi.slow () >= 0;
>+ return xi.len == 2 && xi.uhigh () == 0;
> }
>
> /* Return true if X is negative based on the interpretation of SGN.
> For UNSIGNED, this is always false. */
>+template <typename T>
> inline bool
>-wi::neg_p (const wide_int_ref &x, signop sgn)
>+wi::neg_p (const T &x, signop sgn)
> {
>+ wide_int_ref xi (x);
> if (sgn == UNSIGNED)
> return false;
>- return x.sign_mask () < 0;
>+ return xi.sign_mask () < 0;
> }
>
> /* Return -1 if the top bit of X is set and 0 if the top bit is
> clear. */
>+template <typename T>
> inline HOST_WIDE_INT
>-wi::sign_mask (const wide_int_ref &x)
>+wi::sign_mask (const T &x)
> {
>- return x.sign_mask ();
>+ wide_int_ref xi (x);
>+ return xi.sign_mask ();
> }
>
> /* Return true if X == Y. X and Y must be binary-compatible. */
>@@ -1464,19 +1482,22 @@ wi::ne_p (const T1 &x, const T2 &y)
> }
>
> /* Return true if X < Y when both are treated as signed values. */
>+template <typename T1, typename T2>
> inline bool
>-wi::lts_p (const wide_int_ref &x, const wide_int_ref &y)
>+wi::lts_p (const T1 &x, const T2 &y)
> {
> // We optimize x < y, where y is 64 or fewer bits.
> // We have to be careful to not allow comparison to a large positive
> // unsigned value like 0x8000000000000000, those would be encoded
> // with a y.len == 2.
>- if (y.precision <= HOST_BITS_PER_WIDE_INT
>- && y.len == 1)
>+ wide_int_ref xi (x);
>+ wide_int_ref yi (y);
>+ if (yi.precision <= HOST_BITS_PER_WIDE_INT
>+ && yi.len == 1)
> {
> // If x fits directly into a shwi, we can compare directly.
> if (wi::fits_shwi_p (x))
>- return x.to_shwi () < y.to_shwi ();
>+ return xi.to_shwi () < yi.to_shwi ();
> // If x doesn't fit and is negative, then it must be more
> // negative than any value in y, and hence smaller than y.
> if (neg_p (x, SIGNED))
>@@ -1485,29 +1506,33 @@ wi::lts_p (const wide_int_ref &x, const
> // and hence greater than y.
> return false;
> }
>- return lts_p_large (x.val, x.len, x.precision, y.val, y.len,
>- y.precision);
>+ return lts_p_large (xi.val, xi.len, xi.precision, yi.val, yi.len,
>+ yi.precision);
> }
>
> /* Return true if X < Y when both are treated as unsigned values. */
>+template <typename T1, typename T2>
> inline bool
>-wi::ltu_p (const wide_int_ref &x, const wide_int_ref &y)
>+wi::ltu_p (const T1 &x, const T2 &y)
> {
>- if (x.precision <= HOST_BITS_PER_WIDE_INT
>- && y.precision <= HOST_BITS_PER_WIDE_INT)
>+ wide_int_ref xi (x);
>+ wide_int_ref yi (y);
>+ if (xi.precision <= HOST_BITS_PER_WIDE_INT
>+ && yi.precision <= HOST_BITS_PER_WIDE_INT)
> {
>- unsigned HOST_WIDE_INT xl = x.to_uhwi ();
>- unsigned HOST_WIDE_INT yl = y.to_uhwi ();
>+ unsigned HOST_WIDE_INT xl = xi.to_uhwi ();
>+ unsigned HOST_WIDE_INT yl = yi.to_uhwi ();
> return xl < yl;
> }
> else
>- return ltu_p_large (x.val, x.len, x.precision,
>- y.val, y.len, y.precision);
>+ return ltu_p_large (xi.val, xi.len, xi.precision,
>+ yi.val, yi.len, yi.precision);
> }
>
>/* Return true if X < Y. Signedness of X and Y is indicated by SGN.
>*/
>+template <typename T1, typename T2>
> inline bool
>-wi::lt_p (const wide_int_ref &x, const wide_int_ref &y, signop sgn)
>+wi::lt_p (const T1 &x, const T2 &y, signop sgn)
> {
> if (sgn == SIGNED)
> return lts_p (x, y);
>@@ -1516,22 +1541,25 @@ wi::lt_p (const wide_int_ref &x, const w
> }
>
> /* Return true if X <= Y when both are treated as signed values. */
>+template <typename T1, typename T2>
> inline bool
>-wi::les_p (const wide_int_ref &x, const wide_int_ref &y)
>+wi::les_p (const T1 &x, const T2 &y)
> {
> return !lts_p (y, x);
> }
>
> /* Return true if X <= Y when both are treated as unsigned values. */
>+template <typename T1, typename T2>
> inline bool
>-wi::leu_p (const wide_int_ref &x, const wide_int_ref &y)
>+wi::leu_p (const T1 &x, const T2 &y)
> {
> return !ltu_p (y, x);
> }
>
>/* Return true if X <= Y. Signedness of X and Y is indicated by SGN.
>*/
>+template <typename T1, typename T2>
> inline bool
>-wi::le_p (const wide_int_ref &x, const wide_int_ref &y, signop sgn)
>+wi::le_p (const T1 &x, const T2 &y, signop sgn)
> {
> if (sgn == SIGNED)
> return les_p (x, y);
>@@ -1540,22 +1568,25 @@ wi::le_p (const wide_int_ref &x, const w
> }
>
> /* Return true if X > Y when both are treated as signed values. */
>+template <typename T1, typename T2>
> inline bool
>-wi::gts_p (const wide_int_ref &x, const wide_int_ref &y)
>+wi::gts_p (const T1 &x, const T2 &y)
> {
> return lts_p (y, x);
> }
>
> /* Return true if X > Y when both are treated as unsigned values. */
>+template <typename T1, typename T2>
> inline bool
>-wi::gtu_p (const wide_int_ref &x, const wide_int_ref &y)
>+wi::gtu_p (const T1 &x, const T2 &y)
> {
> return ltu_p (y, x);
> }
>
>/* Return true if X > Y. Signedness of X and Y is indicated by SGN.
>*/
>+template <typename T1, typename T2>
> inline bool
>-wi::gt_p (const wide_int_ref &x, const wide_int_ref &y, signop sgn)
>+wi::gt_p (const T1 &x, const T2 &y, signop sgn)
> {
> if (sgn == SIGNED)
> return gts_p (x, y);
>@@ -1564,22 +1595,25 @@ wi::gt_p (const wide_int_ref &x, const w
> }
>
> /* Return true if X >= Y when both are treated as signed values. */
>+template <typename T1, typename T2>
> inline bool
>-wi::ges_p (const wide_int_ref &x, const wide_int_ref &y)
>+wi::ges_p (const T1 &x, const T2 &y)
> {
> return !lts_p (x, y);
> }
>
> /* Return true if X >= Y when both are treated as unsigned values. */
>+template <typename T1, typename T2>
> inline bool
>-wi::geu_p (const wide_int_ref &x, const wide_int_ref &y)
>+wi::geu_p (const T1 &x, const T2 &y)
> {
> return !ltu_p (x, y);
> }
>
>/* Return true if X >= Y. Signedness of X and Y is indicated by SGN.
>*/
>+template <typename T1, typename T2>
> inline bool
>-wi::ge_p (const wide_int_ref &x, const wide_int_ref &y, signop sgn)
>+wi::ge_p (const T1 &x, const T2 &y, signop sgn)
> {
> if (sgn == SIGNED)
> return ges_p (x, y);
>@@ -1589,14 +1623,17 @@ wi::ge_p (const wide_int_ref &x, const w
>
> /* Return -1 if X < Y, 0 if X == Y and 1 if X > Y. Treat both X and Y
> as signed values. */
>+template <typename T1, typename T2>
> inline int
>-wi::cmps (const wide_int_ref &x, const wide_int_ref &y)
>+wi::cmps (const T1 &x, const T2 &y)
> {
>- if (x.precision <= HOST_BITS_PER_WIDE_INT
>- && y.precision <= HOST_BITS_PER_WIDE_INT)
>+ wide_int_ref xi (x);
>+ wide_int_ref yi (y);
>+ if (xi.precision <= HOST_BITS_PER_WIDE_INT
>+ && yi.precision <= HOST_BITS_PER_WIDE_INT)
> {
>- HOST_WIDE_INT xl = x.to_shwi ();
>- HOST_WIDE_INT yl = y.to_shwi ();
>+ HOST_WIDE_INT xl = xi.to_shwi ();
>+ HOST_WIDE_INT yl = yi.to_shwi ();
> if (xl < yl)
> return -1;
> else if (xl > yl)
>@@ -1604,20 +1641,23 @@ wi::cmps (const wide_int_ref &x, const w
> else
> return 0;
> }
>- return cmps_large (x.val, x.len, x.precision, y.val, y.len,
>- y.precision);
>+ return cmps_large (xi.val, xi.len, xi.precision, yi.val, yi.len,
>+ yi.precision);
> }
>
> /* Return -1 if X < Y, 0 if X == Y and 1 if X > Y. Treat both X and Y
> as unsigned values. */
>+template <typename T1, typename T2>
> inline int
>-wi::cmpu (const wide_int_ref &x, const wide_int_ref &y)
>+wi::cmpu (const T1 &x, const T2 &y)
> {
>- if (x.precision <= HOST_BITS_PER_WIDE_INT
>- && y.precision <= HOST_BITS_PER_WIDE_INT)
>+ wide_int_ref xi (x);
>+ wide_int_ref yi (y);
>+ if (xi.precision <= HOST_BITS_PER_WIDE_INT
>+ && yi.precision <= HOST_BITS_PER_WIDE_INT)
> {
>- unsigned HOST_WIDE_INT xl = x.to_uhwi ();
>- unsigned HOST_WIDE_INT yl = y.to_uhwi ();
>+ unsigned HOST_WIDE_INT xl = xi.to_uhwi ();
>+ unsigned HOST_WIDE_INT yl = yi.to_uhwi ();
> if (xl < yl)
> return -1;
> else if (xl == yl)
>@@ -1625,14 +1665,15 @@ wi::cmpu (const wide_int_ref &x, const w
> else
> return 1;
> }
>- return cmpu_large (x.val, x.len, x.precision, y.val, y.len,
>- y.precision);
>+ return cmpu_large (xi.val, xi.len, xi.precision, yi.val, yi.len,
>+ yi.precision);
> }
>
> /* Return -1 if X < Y, 0 if X == Y and 1 if X > Y. Signedness of
> X and Y indicated by SGN. */
>+template <typename T1, typename T2>
> inline int
>-wi::cmp (const wide_int_ref &x, const wide_int_ref &y, signop sgn)
>+wi::cmp (const T1 &x, const T2 &y, signop sgn)
> {
> if (sgn == SIGNED)
> return cmps (x, y);