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? 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);