diff options
-rw-r--r-- | gcc/ChangeLog.wide-int | 17 | ||||
-rw-r--r-- | gcc/builtins.c | 7 | ||||
-rw-r--r-- | gcc/gimple-pretty-print.c | 6 | ||||
-rw-r--r-- | gcc/tree-ssa-ccp.c | 37 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 17 | ||||
-rw-r--r-- | gcc/tree-ssanames.c | 69 | ||||
-rw-r--r-- | gcc/tree-ssanames.h | 25 | ||||
-rw-r--r-- | gcc/tree-vect-patterns.c | 6 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 12 | ||||
-rw-r--r-- | gcc/wide-int.h | 183 |
10 files changed, 279 insertions, 100 deletions
diff --git a/gcc/ChangeLog.wide-int b/gcc/ChangeLog.wide-int index eedd8a7298e..856fca13881 100644 --- a/gcc/ChangeLog.wide-int +++ b/gcc/ChangeLog.wide-int @@ -677,6 +677,7 @@ * tree-ssa-ccp.c: Update comment at top of file. Include wide-int-print.h. (struct prop_value_d): Change type of mask to widest_int. + (extend_mask): New function. (dump_lattice_value): Use wide-int interfaces. (get_default_value): Likewise. (set_constant_value): Likewise. @@ -768,16 +769,20 @@ * tree-ssa-math-opts.c (gimple_expand_builtin_pow): Update calls to real_to_integer. * tree-ssanames.c - (set_range_info): Use widest_ints rather than double_ints. - (get_range_info): Likewise. + (set_range_info): Use wide_int_refs rather than double_ints. + Adjust for trailing_wide_ints <3> representation. (set_nonzero_bits): Likewise. + (get_range_info): Return wide_ints rather than double_ints. + Adjust for trailing_wide_ints <3> representation. (get_nonzero_bits): Likewise. + (duplicate_ssa_name_range_info): Adjust for trailing_wide_ints <3> + representation. * tree-ssanames.h - (struct range_info_def): Change type of min, max and nonzero_bits - to widest_int. - (set_range_info): Use widest_ints rather than double_ints. - (get_range_info): Likewise. + (struct range_info_def): Replace min, max and nonzero_bits with + a trailing_wide_ints <3>. + (set_range_info): Use wide_int_refs rather than double_ints. (set_nonzero_bits): Likewise. + (get_range_info): Return wide_ints rather than double_ints. (get_nonzero_bits): Likewise. * tree-ssa-phiopt.c (jump_function_from_stmt): Use wide-int interfaces. diff --git a/gcc/builtins.c b/gcc/builtins.c index 13fd0ffe57e..ddca5471810 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3125,7 +3125,7 @@ determine_block_size (tree len, rtx len_rtx, } else { - widest_int min, max; + wide_int min, max; enum value_range_type range_type = VR_UNDEFINED; /* Determine bounds from the type. */ @@ -3152,9 +3152,8 @@ determine_block_size (tree len, rtx len_rtx, /* Anti range 0...N lets us to determine minmal size to N+1. */ if (min == 0) { - widest_int max_plus_one = max + 1; - if (wi::fits_uhwi_p (max_plus_one)) - *min_size = max_plus_one.to_uhwi (); + if (wi::fits_uhwi_p (max) && max.to_uhwi () + 1 != 0) + *min_size = max.to_uhwi () + 1; } /* Code like diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index e0786342f69..7458647057a 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1754,7 +1754,7 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc) if (!POINTER_TYPE_P (TREE_TYPE (node)) && SSA_NAME_RANGE_INFO (node)) { - widest_int min, max, nonzero_bits; + wide_int min, max, nonzero_bits; value_range_type range_type = get_range_info (node, &min, &max); if (range_type == VR_VARYING) @@ -1769,9 +1769,7 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc) pp_printf (buffer, "]"); } nonzero_bits = get_nonzero_bits (node); - if (nonzero_bits != -1 - && (nonzero_bits - != wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (node)), false))) + if (nonzero_bits != -1) { pp_string (buffer, " NONZERO "); pp_wide_int (buffer, nonzero_bits, UNSIGNED); diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index c836f53defe..bad969648a7 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -237,6 +237,14 @@ debug_lattice_value (prop_value_t val) fprintf (stderr, "\n"); } +/* Extend NONZERO_BITS to a full mask, with the upper bits being set. */ + +static widest_int +extend_mask (const wide_int &nonzero_bits) +{ + return (wi::mask <widest_int> (wi::get_precision (nonzero_bits), true) + | widest_int::from (nonzero_bits, UNSIGNED)); +} /* Compute a default value for variable VAR and store it in the CONST_VAL array. The following rules are used to get default @@ -279,15 +287,12 @@ get_default_value (tree var) val.mask = -1; if (flag_tree_bit_ccp) { - widest_int nonzero_bits = get_nonzero_bits (var); - widest_int mask - = wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (var)), false); - if (nonzero_bits != -1 && nonzero_bits != mask) + wide_int nonzero_bits = get_nonzero_bits (var); + if (nonzero_bits != -1) { val.lattice_val = CONSTANT; val.value = build_zero_cst (TREE_TYPE (var)); - /* CCP wants the bits above precision set. */ - val.mask = nonzero_bits | ~mask; + val.mask = extend_mask (nonzero_bits); } } } @@ -895,7 +900,9 @@ ccp_finalize (void) } else { - widest_int nonzero_bits = val->mask | wi::to_widest (val->value); + unsigned int precision = TYPE_PRECISION (TREE_TYPE (val->value)); + wide_int nonzero_bits = wide_int::from (val->mask, precision, + UNSIGNED) | val->value; nonzero_bits &= get_nonzero_bits (name); set_nonzero_bits (name, nonzero_bits); } @@ -1758,29 +1765,25 @@ evaluate_stmt (gimple stmt) && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME) { tree lhs = gimple_get_lhs (stmt); - widest_int nonzero_bits = get_nonzero_bits (lhs); - widest_int mask - = wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (lhs)), false); - if (nonzero_bits != -1 && nonzero_bits != mask) + wide_int nonzero_bits = get_nonzero_bits (lhs); + if (nonzero_bits != -1) { if (!is_constant) { val.lattice_val = CONSTANT; val.value = build_zero_cst (TREE_TYPE (lhs)); - /* CCP wants the bits above precision set. */ - val.mask = nonzero_bits | ~mask; + val.mask = extend_mask (nonzero_bits); is_constant = true; } else { - widest_int valv = wi::to_widest (val.value); - if ((valv & ~nonzero_bits & mask) != 0) + if (wi::bit_and_not (val.value, nonzero_bits) != 0) val.value = wide_int_to_tree (TREE_TYPE (lhs), - valv & nonzero_bits); + nonzero_bits & val.value); if (nonzero_bits == 0) val.mask = 0; else - val.mask = val.mask & (nonzero_bits | ~mask); + val.mask = extend_mask (nonzero_bits); } } } diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index f912a0d813e..a50b9e37dcf 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -125,7 +125,7 @@ static void determine_value_range (struct loop *loop, tree type, tree var, mpz_t off, mpz_t min, mpz_t max) { - widest_int minv, maxv; + wide_int minv, maxv; enum value_range_type rtype = VR_VARYING; /* If the expression is a constant, we know its value exactly. */ @@ -142,6 +142,7 @@ determine_value_range (struct loop *loop, tree type, tree var, mpz_t off, if (TREE_CODE (var) == SSA_NAME && INTEGRAL_TYPE_P (type)) { edge e = loop_preheader_edge (loop); + signop sgn = TYPE_SIGN (type); gimple_stmt_iterator gsi; /* Either for VAR itself... */ @@ -151,7 +152,7 @@ determine_value_range (struct loop *loop, tree type, tree var, mpz_t off, for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple phi = gsi_stmt (gsi); - widest_int minc, maxc; + wide_int minc, maxc; if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var && (get_range_info (gimple_phi_result (phi), &minc, &maxc) == VR_RANGE)) @@ -164,20 +165,20 @@ determine_value_range (struct loop *loop, tree type, tree var, mpz_t off, } else { - minv = wi::smax (minv, minc); - maxv = wi::smin (maxv, maxc); - gcc_assert (wi::les_p (minv, maxv)); + minv = wi::max (minv, minc, sgn); + maxv = wi::min (maxv, maxc, sgn); + gcc_assert (wi::le_p (minv, maxv, sgn)); } } } if (rtype == VR_RANGE) { mpz_t minm, maxm; - gcc_assert (wi::les_p (minv, maxv)); + gcc_assert (wi::le_p (minv, maxv, sgn)); mpz_init (minm); mpz_init (maxm); - wi::to_mpz (minv, minm, SIGNED); - wi::to_mpz (maxv, maxm, SIGNED); + wi::to_mpz (minv, minm, sgn); + wi::to_mpz (maxv, maxm, sgn); mpz_add (minm, minm, off); mpz_add (maxm, maxm, off); /* If the computation may not wrap or off is zero, then this diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 4141cc4a127..4c04a8c8af5 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -182,19 +182,22 @@ make_ssa_name_fn (struct function *fn, tree var, gimple stmt) void set_range_info (tree name, enum value_range_type range_type, - const widest_int &min, const widest_int &max) + const wide_int_ref &min, const wide_int_ref &max) { gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE); range_info_def *ri = SSA_NAME_RANGE_INFO (name); + unsigned int precision = TYPE_PRECISION (TREE_TYPE (name)); /* Allocate if not available. */ if (ri == NULL) { - ri = ggc_alloc_cleared_range_info_def (); + size_t size = (sizeof (range_info_def) + + trailing_wide_ints <3>::extra_size (precision)); + ri = ggc_alloc_range_info_def (size); + ri->ints.set_precision (precision); SSA_NAME_RANGE_INFO (name) = ri; - ri->nonzero_bits = wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)), - false); + ri->set_nonzero_bits (wi::shwi (-1, precision)); } /* Record the range type. */ @@ -202,22 +205,16 @@ set_range_info (tree name, enum value_range_type range_type, SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE); /* Set the values. */ - ri->min = min; - ri->max = max; + ri->set_min (min); + ri->set_max (max); /* If it is a range, try to improve nonzero_bits from the min/max. */ if (range_type == VR_RANGE) { - int prec = TYPE_PRECISION (TREE_TYPE (name)); - - widest_int ext_min = wi::zext (min, prec); - widest_int ext_max = wi::zext (max, prec); - widest_int xorv = ext_min ^ ext_max; + wide_int xorv = ri->get_min () ^ ri->get_max (); if (xorv != 0) - xorv = wi::mask <widest_int> (MAX_BITSIZE_MODE_ANY_INT - - wi::clz (xorv), - false); - ri->nonzero_bits = ri->nonzero_bits & (ext_min | xorv); + xorv = wi::mask (precision - wi::clz (xorv), false, precision); + ri->set_nonzero_bits (ri->get_nonzero_bits () & (ri->get_min () | xorv)); } } @@ -227,7 +224,7 @@ set_range_info (tree name, enum value_range_type range_type, is used to determine if MIN and MAX are valid values. */ enum value_range_type -get_range_info (const_tree name, widest_int *min, widest_int *max) +get_range_info (const_tree name, wide_int *min, wide_int *max) { gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); gcc_assert (min && max); @@ -239,52 +236,45 @@ get_range_info (const_tree name, widest_int *min, widest_int *max) > 2 * HOST_BITS_PER_WIDE_INT)) return VR_VARYING; - *min = ri->min; - *max = ri->max; + *min = ri->get_min (); + *max = ri->get_max (); return SSA_NAME_RANGE_TYPE (name); } /* Change non-zero bits bitmask of NAME. */ void -set_nonzero_bits (tree name, const widest_int &mask) +set_nonzero_bits (tree name, const wide_int_ref &mask) { gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); if (SSA_NAME_RANGE_INFO (name) == NULL) set_range_info (name, VR_RANGE, - wi::to_widest (TYPE_MIN_VALUE (TREE_TYPE (name))), - wi::to_widest (TYPE_MAX_VALUE (TREE_TYPE (name)))); + TYPE_MIN_VALUE (TREE_TYPE (name)), + TYPE_MAX_VALUE (TREE_TYPE (name))); range_info_def *ri = SSA_NAME_RANGE_INFO (name); - ri->nonzero_bits - = mask & wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)), - false); + ri->set_nonzero_bits (mask); } /* Return a widest_int with potentially non-zero bits in SSA_NAME NAME, or -1 if unknown. */ -widest_int +wide_int get_nonzero_bits (const_tree name) { + unsigned int precision = TYPE_PRECISION (TREE_TYPE (name)); if (POINTER_TYPE_P (TREE_TYPE (name))) { struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name); if (pi && pi->align) - { - widest_int al = pi->align - 1; - return ((wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)), - false) & ~al) - | pi->misalign); - } - return -1; + return wi::shwi (-(int) pi->align | pi->misalign, precision); + return wi::shwi (-1, precision); } range_info_def *ri = SSA_NAME_RANGE_INFO (name); - if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name))) - > 2 * HOST_BITS_PER_WIDE_INT)) - return -1; + if (!ri) + return wi::shwi (-1, precision); - return ri->nonzero_bits; + return ri->get_nonzero_bits (); } /* We no longer need the SSA_NAME expression VAR, release it so that @@ -497,8 +487,11 @@ duplicate_ssa_name_range_info (tree name, enum value_range_type range_type, if (!range_info) return; - new_range_info = ggc_alloc_range_info_def (); - *new_range_info = *range_info; + unsigned int precision = TYPE_PRECISION (TREE_TYPE (name)); + size_t size = (sizeof (range_info_def) + + trailing_wide_ints <3>::extra_size (precision)); + new_range_info = ggc_alloc_range_info_def (size); + memcpy (new_range_info, range_info, size); gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE); SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE); diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h index ff4f85adf26..23c988cb2a2 100644 --- a/gcc/tree-ssanames.h +++ b/gcc/tree-ssanames.h @@ -47,13 +47,12 @@ struct GTY(()) ptr_info_def /* Value range information for SSA_NAMEs representing non-pointer variables. */ -struct GTY (()) range_info_def { - /* Minimum for value range. */ - widest_int min; - /* Maximum for value range. */ - widest_int max; - /* Non-zero bits - bits not set are guaranteed to be always zero. */ - widest_int nonzero_bits; +struct GTY ((variable_size)) range_info_def { + /* Minimum, maximum and nonzero bits. */ + TRAILING_WIDE_INT_ACCESSOR (min, ints, 0) + TRAILING_WIDE_INT_ACCESSOR (max, ints, 1) + TRAILING_WIDE_INT_ACCESSOR (nonzero_bits, ints, 2) + trailing_wide_ints <3> ints; }; @@ -70,13 +69,13 @@ struct GTY (()) range_info_def { enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING }; /* Sets the value range to SSA. */ -extern void set_range_info (tree, enum value_range_type, const widest_int &, - const widest_int &); +extern void set_range_info (tree, enum value_range_type, const wide_int_ref &, + const wide_int_ref &); /* Gets the value range from SSA. */ -extern enum value_range_type get_range_info (const_tree, widest_int *, - widest_int *); -extern void set_nonzero_bits (tree, const widest_int &); -extern widest_int get_nonzero_bits (const_tree); +extern enum value_range_type get_range_info (const_tree, wide_int *, + wide_int *); +extern void set_nonzero_bits (tree, const wide_int_ref &); +extern wide_int get_nonzero_bits (const_tree); extern void init_ssanames (struct function *, int); extern void fini_ssanames (void); extern void ssanames_print_statistics (void); diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index da4cc94f7b7..ebfe10ee321 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -2261,13 +2261,13 @@ vect_recog_divmod_pattern (vec<gimple> *stmts, else t3 = t2; - widest_int oprnd0_min, oprnd0_max; + wide_int oprnd0_min, oprnd0_max; int msb = 1; if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE) { - if (!wi::neg_p (oprnd0_min)) + if (!wi::neg_p (oprnd0_min, TYPE_SIGN (itype))) msb = 0; - else if (wi::neg_p (oprnd0_max)) + else if (wi::neg_p (oprnd0_max, TYPE_SIGN (itype))) msb = -1; } diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index a7475ffcbfa..96e345726f2 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -6422,8 +6422,7 @@ maybe_set_nonzero_bits (basic_block bb, tree var) return; } cst = gimple_assign_rhs2 (stmt); - set_nonzero_bits (var, (get_nonzero_bits (var) - & ~wi::to_widest (cst))); + set_nonzero_bits (var, wi::bit_and_not (get_nonzero_bits (var), cst)); } /* Convert range assertion expressions into the implied copies and @@ -6508,8 +6507,8 @@ remove_range_assertions (void) single_pred (bb))) { set_range_info (var, SSA_NAME_RANGE_TYPE (lhs), - SSA_NAME_RANGE_INFO (lhs)->min, - SSA_NAME_RANGE_INFO (lhs)->max); + SSA_NAME_RANGE_INFO (lhs)->get_min (), + SSA_NAME_RANGE_INFO (lhs)->get_max ()); maybe_set_nonzero_bits (bb, var); } } @@ -9534,9 +9533,8 @@ vrp_finalize (void) && (TREE_CODE (vr_value[i]->max) == INTEGER_CST) && (vr_value[i]->type == VR_RANGE || vr_value[i]->type == VR_ANTI_RANGE)) - set_range_info (name, vr_value[i]->type, - wi::to_widest (vr_value[i]->min), - wi::to_widest (vr_value[i]->max)); + set_range_info (name, vr_value[i]->type, vr_value[i]->min, + vr_value[i]->max); } /* Free allocated memory. */ diff --git a/gcc/wide-int.h b/gcc/wide-int.h index a60389f6620..9be21021259 100644 --- a/gcc/wide-int.h +++ b/gcc/wide-int.h @@ -653,6 +653,9 @@ public: HOST_WIDE_INT slow () const; HOST_WIDE_INT shigh () const; + template <typename T> + generic_wide_int &operator = (const T &); + #define BINARY_PREDICATE(OP, F) \ template <typename T> \ bool OP (const T &c) const { return wi::F (*this, c); } @@ -831,6 +834,15 @@ generic_wide_int <storage>::elt (unsigned int i) const return this->get_val ()[i]; } +template <typename storage> +template <typename T> +generic_wide_int <storage> & +generic_wide_int <storage>::operator = (const T &x) +{ + storage::operator = (x); + return *this; +} + namespace wi { template <> @@ -1188,6 +1200,159 @@ get_binary_result (const T1 &, const T2 &) return FIXED_WIDE_INT (N) (); } +/* A reference to one element of a trailing_wide_ints structure. */ +class trailing_wide_int_storage +{ +private: + /* The precision of the integer, which is a fixed property of the + parent trailing_wide_ints. */ + unsigned int m_precision; + + /* A pointer to the length field. */ + unsigned char *m_len; + + /* A pointer to the HWI array. There are enough elements to hold all + values of precision M_PRECISION. */ + HOST_WIDE_INT *m_val; + +public: + trailing_wide_int_storage (unsigned int, unsigned char *, HOST_WIDE_INT *); + + /* The standard generic_wide_int storage methods. */ + unsigned int get_len () const; + unsigned int get_precision () const; + const HOST_WIDE_INT *get_val () const; + HOST_WIDE_INT *write_val (); + void set_len (unsigned int, bool = false); + + template <typename T> + trailing_wide_int_storage &operator = (const T &); +}; + +typedef generic_wide_int <trailing_wide_int_storage> trailing_wide_int; + +/* trailing_wide_int behaves like a wide_int. */ +namespace wi +{ + template <> + struct int_traits <trailing_wide_int_storage> + : public int_traits <wide_int_storage> {}; +} + +/* An array of N wide_int-like objects that can be put at the end of + a variable-sized structure. Use extra_size to calculate how many + bytes beyond the sizeof need to be allocated. Use set_precision + to initialize the structure. */ +template <int N> +class GTY(()) trailing_wide_ints +{ +private: + /* The shared precision of each number. */ + unsigned short m_precision; + + /* The shared maximum length of each number. */ + unsigned char m_max_len; + + /* The current length of each number. */ + unsigned char m_len[N]; + + /* The variable-length part of the structure, which always contains + at least one HWI. Element I starts at index I * M_MAX_LEN. */ + HOST_WIDE_INT m_val[1]; + +public: + void set_precision (unsigned int); + trailing_wide_int operator [] (unsigned int); + static size_t extra_size (unsigned int); +}; + +inline trailing_wide_int_storage:: +trailing_wide_int_storage (unsigned int precision, unsigned char *len, + HOST_WIDE_INT *val) + : m_precision (precision), m_len (len), m_val (val) +{ +} + +inline unsigned int +trailing_wide_int_storage::get_len () const +{ + return *m_len; +} + +inline unsigned int +trailing_wide_int_storage::get_precision () const +{ + return m_precision; +} + +inline const HOST_WIDE_INT * +trailing_wide_int_storage::get_val () const +{ + return m_val; +} + +inline HOST_WIDE_INT * +trailing_wide_int_storage::write_val () +{ + return m_val; +} + +inline void +trailing_wide_int_storage::set_len (unsigned int len, bool is_sign_extended) +{ + *m_len = len; + if (!is_sign_extended && len * HOST_BITS_PER_WIDE_INT > m_precision) + m_val[len - 1] = sext_hwi (m_val[len - 1], + m_precision % HOST_BITS_PER_WIDE_INT); +} + +template <typename T> +inline trailing_wide_int_storage & +trailing_wide_int_storage::operator = (const T &x) +{ + WIDE_INT_REF_FOR (T) xi (x, m_precision); + wi::copy (*this, xi); + return *this; +} + +/* Initialize the structure and record that all elements have precision + PRECISION. */ +template <int N> +inline void +trailing_wide_ints <N>::set_precision (unsigned int precision) +{ + m_precision = precision; + m_max_len = ((precision + HOST_BITS_PER_WIDE_INT - 1) + / HOST_BITS_PER_WIDE_INT); +} + +/* Return a reference to element INDEX. */ +template <int N> +inline trailing_wide_int +trailing_wide_ints <N>::operator [] (unsigned int index) +{ + return trailing_wide_int_storage (m_precision, &m_len[index], + &m_val[index * m_max_len]); +} + +/* Return how many extra bytes need to be added to the end of the structure + in order to handle N wide_ints of precision PRECISION. */ +template <int N> +inline size_t +trailing_wide_ints <N>::extra_size (unsigned int precision) +{ + unsigned int max_len = ((precision + HOST_BITS_PER_WIDE_INT - 1) + / HOST_BITS_PER_WIDE_INT); + return (N * max_len - 1) * sizeof (HOST_WIDE_INT); +} + +/* This macro is used in structures that end with a trailing_wide_ints field + called FIELD. It declares get_NAME() and set_NAME() methods to access + element I of FIELD. */ +#define TRAILING_WIDE_INT_ACCESSOR(NAME, FIELD, I) \ + trailing_wide_int get_##NAME () { return FIELD[I]; } \ + template <typename T> void set_##NAME (const T &x) { FIELD[I] = x; } + namespace wi { /* Implementation of int_traits for primitive integer types like "int". */ @@ -2726,6 +2891,24 @@ gt_pch_nx (generic_wide_int <T> *, void (*) (void *, void *), void *) { } +template<int N> +void +gt_ggc_mx (trailing_wide_ints <N> *) +{ +} + +template<int N> +void +gt_pch_nx (trailing_wide_ints <N> *) +{ +} + +template<int N> +void +gt_pch_nx (trailing_wide_ints <N> *, void (*) (void *, void *), void *) +{ +} + namespace wi { /* Used for overloaded functions in which the only other acceptable |