aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-10-12 16:01:12 +0200
committerJakub Jelinek <jakub@redhat.com>2023-10-12 16:01:12 +0200
commit0d00385eaf72ccacff17935b0d214a26773e095f (patch)
tree8dd6bddfc6220b8e8140085bb0d8b805b4ca1207 /gcc
parentcd0185b8d155887a7d3a78d0c186289140b44e47 (diff)
downloadgcc-0d00385eaf72ccacff17935b0d214a26773e095f.zip
gcc-0d00385eaf72ccacff17935b0d214a26773e095f.tar.gz
gcc-0d00385eaf72ccacff17935b0d214a26773e095f.tar.bz2
wide-int: Allow up to 16320 bits wide_int and change widest_int precision to 32640 bits [PR102989]
As mentioned in the _BitInt support thread, _BitInt(N) is currently limited by the wide_int/widest_int maximum precision limitation, which is depending on target 191, 319, 575 or 703 bits (one less than WIDE_INT_MAX_PRECISION). That is fairly low limit for _BitInt, especially on the targets with the 191 bit limitation. The following patch bumps that limit to 16319 bits on all arches (which support _BitInt at all), which is the limit imposed by INTEGER_CST representation (unsigned char members holding number of HOST_WIDE_INT limbs). In order to achieve that, wide_int is changed from a trivially copyable type which contained just an inline array of WIDE_INT_MAX_ELTS (3, 5, 9 or 11 limbs depending on target) limbs into a non-trivially copy constructible, copy assignable and destructible type which for the usual small cases (up to WIDE_INT_MAX_INL_ELTS which is the former WIDE_INT_MAX_ELTS) still uses an inline array of limbs, but for larger precisions uses heap allocated limb array. This makes wide_int unusable in GC structures, so for dwarf2out which was the only place which needed it there is a new rwide_int type (restricted wide_int) which supports only up to RWIDE_INT_MAX_ELTS limbs inline and is trivially copyable (dwarf2out should never deal with large _BitInt constants, those should have been lowered earlier). Similarly, widest_int has been changed from a trivially copyable type which contained also an inline array of WIDE_INT_MAX_ELTS limbs (but unlike wide_int didn't contain precision and assumed that to be WIDE_INT_MAX_PRECISION) into a non-trivially copy constructible, copy assignable and destructible type which has always WIDEST_INT_MAX_PRECISION precision (32640 bits currently, twice as much as INTEGER_CST limitation allows) and unlike wide_int decides depending on get_len () value whether it uses an inline array (again, up to WIDE_INT_MAX_INL_ELTS) or heap allocated one. In wide-int.h this means we need to estimate an upper bound on how many limbs will wide-int.cc (usually, sometimes wide-int.h) need to write, heap allocate if needed based on that estimation and upon set_len which is done at the end if we guessed over WIDE_INT_MAX_INL_ELTS and allocated dynamically, while we actually need less than that copy/deallocate. The unexact guesses are needed because the exact computation of the length in wide-int.cc is sometimes quite complex and especially canonicalize at the end can decrease it. widest_int is again because of this not usable in GC structures, so cfgloop.h has been changed to use fixed_wide_int_storage <WIDE_INT_MAX_INL_PRECISION> and punt if we'd have larger _BitInt based iterators, programs having more than 128-bit iterators will be hopefully rare and I think it is fine to treat loops with more than 2^127 iterations as effectively possibly infinite, omp-general.cc is changed to use fixed_wide_int_storage <1024>, as it better should support scores with the same precision on all arches. Code which used WIDE_INT_PRINT_BUFFER_SIZE sized buffers for printing wide_int/widest_int into buffer had to be changed to use XALLOCAVEC for larger lengths. On x86_64, the patch in --enable-checking=yes,rtl,extra configured bootstrapped cc1plus enlarges the .text section by 1.01% - from 0x25725a5 to 0x25e5555 and similarly at least when compiling insn-recog.cc with the usual bootstrap option slows compilation down by 1.01%, user 4m22.046s and 4m22.384s on vanilla trunk vs. 4m25.947s and 4m25.581s on patched trunk. I'm afraid some code size growth and compile time slowdown is unavoidable in this case, we use wide_int and widest_int everywhere, and while the rare cases are marked with UNLIKELY macros, it still means extra checks for it. The patch also regresses +FAIL: gm2/pim/fail/largeconst.mod, -O +FAIL: gm2/pim/fail/largeconst.mod, -O -g +FAIL: gm2/pim/fail/largeconst.mod, -O3 -fomit-frame-pointer +FAIL: gm2/pim/fail/largeconst.mod, -O3 -fomit-frame-pointer -finline-functions +FAIL: gm2/pim/fail/largeconst.mod, -Os +FAIL: gm2/pim/fail/largeconst.mod, -g +FAIL: gm2/pim/fail/largeconst2.mod, -O +FAIL: gm2/pim/fail/largeconst2.mod, -O -g +FAIL: gm2/pim/fail/largeconst2.mod, -O3 -fomit-frame-pointer +FAIL: gm2/pim/fail/largeconst2.mod, -O3 -fomit-frame-pointer -finline-functions +FAIL: gm2/pim/fail/largeconst2.mod, -Os +FAIL: gm2/pim/fail/largeconst2.mod, -g tests, which previously were rejected with error: constant literal ‘12345678912345678912345679123456789123456789123456789123456789123456791234567891234567891234567891234567891234567912345678912345678912345678912345678912345679123456789123456789’ exceeds internal ZTYPE range kind of errors, but now are accepted. Seems the FE tries to parse constants into widest_int in that case and only diagnoses if widest_int overflows, that seems wrong, it should at least punt if stuff doesn't fit into WIDE_INT_MAX_PRECISION, but perhaps far less than that, if it wants support for middle-end for precisions above 128-bit, it better should be using BITINT_TYPE. Will file a PR and defer to Modula2 maintainer. 2023-10-12 Jakub Jelinek <jakub@redhat.com> PR c/102989 * wide-int.h: Adjust file comment. (WIDE_INT_MAX_INL_ELTS): Define to former value of WIDE_INT_MAX_ELTS. (WIDE_INT_MAX_INL_PRECISION): Define. (WIDE_INT_MAX_ELTS): Change to 255. Assert that WIDE_INT_MAX_INL_ELTS is smaller than WIDE_INT_MAX_ELTS. (RWIDE_INT_MAX_ELTS, RWIDE_INT_MAX_PRECISION, WIDEST_INT_MAX_ELTS, WIDEST_INT_MAX_PRECISION): Define. (WI_BINARY_RESULT_VAR, WI_UNARY_RESULT_VAR): Change write_val callers to pass 0 as a new argument. (class widest_int_storage): Likewise. (widest_int, widest2_int): Change typedefs to use widest_int_storage rather than fixed_wide_int_storage. (enum wi::precision_type): Add INL_CONST_PRECISION enumerator. (struct binary_traits): Add partial specializations for INL_CONST_PRECISION. (generic_wide_int): Add needs_write_val_arg static data member. (int_traits): Likewise. (wide_int_storage): Replace val non-static data member with a union u of it and HOST_WIDE_INT *valp. Declare copy constructor, copy assignment operator and destructor. Add unsigned int argument to write_val. (wide_int_storage::wide_int_storage): Initialize precision to 0 in the default ctor. Remove unnecessary {}s around STATIC_ASSERTs. Assert in non-default ctor T's precision_type is not INL_CONST_PRECISION and allocate u.valp for large precision. Add copy constructor. (wide_int_storage::~wide_int_storage): New. (wide_int_storage::operator=): Add copy assignment operator. In assignment operator remove unnecessary {}s around STATIC_ASSERTs, assert ctor T's precision_type is not INL_CONST_PRECISION and if precision changes, deallocate and/or allocate u.valp. (wide_int_storage::get_val): Return u.valp rather than u.val for large precision. (wide_int_storage::write_val): Likewise. Add an unused unsigned int argument. (wide_int_storage::set_len): Use write_val instead of writing val directly. (wide_int_storage::from, wide_int_storage::from_array): Adjust write_val callers. (wide_int_storage::create): Allocate u.valp for large precisions. (wi::int_traits <wide_int_storage>::get_binary_precision): New. (fixed_wide_int_storage::fixed_wide_int_storage): Make default ctor defaulted. (fixed_wide_int_storage::write_val): Add unused unsigned int argument. (fixed_wide_int_storage::from, fixed_wide_int_storage::from_array): Adjust write_val callers. (wi::int_traits <fixed_wide_int_storage>::get_binary_precision): New. (WIDEST_INT): Define. (widest_int_storage): New template class. (wi::int_traits <widest_int_storage>): New. (trailing_wide_int_storage::write_val): Add unused unsigned int argument. (wi::get_binary_precision): Use wi::int_traits <WI_BINARY_RESULT (T1, T2)>::get_binary_precision rather than get_precision on get_binary_result. (wi::copy): Adjust write_val callers. Don't call set_len if needs_write_val_arg. (wi::bit_not): If result.needs_write_val_arg, call write_val again with upper bound estimate of len. (wi::sext, wi::zext, wi::set_bit): Likewise. (wi::bit_and, wi::bit_and_not, wi::bit_or, wi::bit_or_not, wi::bit_xor, wi::add, wi::sub, wi::mul, wi::mul_high, wi::div_trunc, wi::div_floor, wi::div_ceil, wi::div_round, wi::divmod_trunc, wi::mod_trunc, wi::mod_floor, wi::mod_ceil, wi::mod_round, wi::lshift, wi::lrshift, wi::arshift): Likewise. (wi::bswap, wi::bitreverse): Assert result.needs_write_val_arg is false. (gt_ggc_mx, gt_pch_nx): Remove generic template for all generic_wide_int, instead add functions and templates for each storage of generic_wide_int. Make functions for generic_wide_int <wide_int_storage> and templates for generic_wide_int <widest_int_storage <N>> deleted. (wi::mask, wi::shifted_mask): Adjust write_val calls. * wide-int.cc (zeros): Decrease array size to 1. (BLOCKS_NEEDED): Use CEIL. (canonize): Use HOST_WIDE_INT_M1. (wi::from_buffer): Pass 0 to write_val. (wi::to_mpz): Use CEIL. (wi::from_mpz): Likewise. Pass 0 to write_val. Use WIDE_INT_MAX_INL_ELTS instead of WIDE_INT_MAX_ELTS. (wi::mul_internal): Use WIDE_INT_MAX_INL_PRECISION instead of MAX_BITSIZE_MODE_ANY_INT in automatic array sizes, for prec above WIDE_INT_MAX_INL_PRECISION estimate precision from lengths of operands. Use XALLOCAVEC allocated buffers for prec above WIDE_INT_MAX_INL_PRECISION. (wi::divmod_internal): Likewise. (wi::lshift_large): For len > WIDE_INT_MAX_INL_ELTS estimate it from xlen and skip. (rshift_large_common): Remove xprecision argument, add len argument with len computed in caller. Don't return anything. (wi::lrshift_large, wi::arshift_large): Compute len here and pass it to rshift_large_common, for lengths above WIDE_INT_MAX_INL_ELTS using estimations from xlen if possible. (assert_deceq, assert_hexeq): For lengths above WIDE_INT_MAX_INL_ELTS use XALLOCAVEC allocated buffer. (test_printing): Use WIDE_INT_MAX_INL_PRECISION instead of WIDE_INT_MAX_PRECISION. * wide-int-print.h (WIDE_INT_PRINT_BUFFER_SIZE): Use WIDE_INT_MAX_INL_PRECISION instead of WIDE_INT_MAX_PRECISION. * wide-int-print.cc (print_decs, print_decu, print_hex): For lengths above WIDE_INT_MAX_INL_ELTS use XALLOCAVEC allocated buffer. * tree.h (wi::int_traits<extended_tree <N>>): Change precision_type to INL_CONST_PRECISION for N == ADDR_MAX_PRECISION. (widest_extended_tree): Use WIDEST_INT_MAX_PRECISION instead of WIDE_INT_MAX_PRECISION. (wi::ints_for): Use int_traits <extended_tree <N> >::precision_type instead of hard coded CONST_PRECISION. (widest2_int_cst): Use WIDEST_INT_MAX_PRECISION instead of WIDE_INT_MAX_PRECISION. (wi::extended_tree <N>::get_len): Use WIDEST_INT_MAX_PRECISION rather than WIDE_INT_MAX_PRECISION. (wi::ints_for::zero): Use wi::int_traits <wi::extended_tree <N> >::precision_type instead of wi::CONST_PRECISION. * tree.cc (build_replicated_int_cst): Formatting fix. Use WIDE_INT_MAX_INL_ELTS rather than WIDE_INT_MAX_ELTS. * print-tree.cc (print_node): Don't print TREE_UNAVAILABLE on INTEGER_CSTs, TREE_VECs or SSA_NAMEs. * double-int.h (wi::int_traits <double_int>::precision_type): Change to INL_CONST_PRECISION from CONST_PRECISION. * poly-int.h (struct poly_coeff_traits): Add partial specialization for wi::INL_CONST_PRECISION. * cfgloop.h (bound_wide_int): New typedef. (struct nb_iter_bound): Change bound type from widest_int to bound_wide_int. (struct loop): Change nb_iterations_upper_bound, nb_iterations_likely_upper_bound and nb_iterations_estimate type from widest_int to bound_wide_int. * cfgloop.cc (record_niter_bound): Return early if wi::min_precision of i_bound is too large for bound_wide_int. Adjustments for the widest_int to bound_wide_int type change in non-static data members. (get_estimated_loop_iterations, get_max_loop_iterations, get_likely_max_loop_iterations): Adjustments for the widest_int to bound_wide_int type change in non-static data members. * tree-vect-loop.cc (vect_transform_loop): Likewise. * tree-ssa-loop-niter.cc (do_warn_aggressive_loop_optimizations): Use XALLOCAVEC allocated buffer for i_bound len above WIDE_INT_MAX_INL_ELTS. (record_estimate): Return early if wi::min_precision of i_bound is too large for bound_wide_int. Adjustments for the widest_int to bound_wide_int type change in non-static data members. (wide_int_cmp): Use bound_wide_int instead of widest_int. (bound_index): Use bound_wide_int instead of widest_int. (discover_iteration_bound_by_body_walk): Likewise. Use widest_int::from to convert it to widest_int when passed to record_niter_bound. (maybe_lower_iteration_bound): Use widest_int::from to convert it to widest_int when passed to record_niter_bound. (estimate_numbers_of_iteration): Don't record upper bound if loop->nb_iterations has too large precision for bound_wide_int. (n_of_executions_at_most): Use widest_int::from. * tree-ssa-loop-ivcanon.cc (remove_redundant_iv_tests): Adjust for the widest_int to bound_wide_int changes. * match.pd (fold_sign_changed_comparison simplification): Use wide_int::from on wi::to_wide instead of wi::to_widest. * value-range.h (irange::maybe_resize): Avoid using memcpy on non-trivially copyable elements. * value-range.cc (irange_bitmask::dump): Use XALLOCAVEC allocated buffer for mask or value len above WIDE_INT_PRINT_BUFFER_SIZE. * fold-const.cc (fold_convert_const_int_from_int, fold_unary_loc): Use wide_int::from on wi::to_wide instead of wi::to_widest. * tree-ssa-ccp.cc (bit_value_binop): Zero extend r1max from width before calling wi::udiv_trunc. * lto-streamer-out.cc (output_cfg): Adjustments for the widest_int to bound_wide_int type change in non-static data members. * lto-streamer-in.cc (input_cfg): Likewise. (lto_input_tree_1): Use WIDE_INT_MAX_INL_ELTS rather than WIDE_INT_MAX_ELTS. For length above WIDE_INT_MAX_INL_ELTS use XALLOCAVEC allocated buffer. Formatting fix. * data-streamer-in.cc (streamer_read_wide_int, streamer_read_widest_int): Likewise. * tree-affine.cc (aff_combination_expand): Use placement new to construct name_expansion. (free_name_expansion): Destruct name_expansion. * gimple-ssa-strength-reduction.cc (struct slsr_cand_d): Change index type from widest_int to offset_int. (class incr_info_d): Change incr type from widest_int to offset_int. (alloc_cand_and_find_basis, backtrace_base_for_ref, restructure_reference, slsr_process_ref, create_mul_ssa_cand, create_mul_imm_cand, create_add_ssa_cand, create_add_imm_cand, slsr_process_add, cand_abs_increment, replace_mult_candidate, replace_unconditional_candidate, incr_vec_index, create_add_on_incoming_edge, create_phi_basis_1, replace_conditional_candidate, record_increment, record_phi_increments_1, phi_incr_cost_1, phi_incr_cost, lowest_cost_path, total_savings, ncd_with_phi, ncd_of_cand_and_phis, nearest_common_dominator_for_cands, insert_initializers, all_phi_incrs_profitable_1, replace_one_candidate, replace_profitable_candidates): Use offset_int rather than widest_int and wi::to_offset rather than wi::to_widest. * real.cc (real_to_integer): Use WIDE_INT_MAX_INL_ELTS rather than 2 * WIDE_INT_MAX_ELTS and for words above that use XALLOCAVEC allocated buffer. * tree-ssa-loop-ivopts.cc (niter_for_exit): Use placement new to construct tree_niter_desc and destruct it on failure. (free_tree_niter_desc): Destruct tree_niter_desc if value is non-NULL. * gengtype.cc (main): Remove widest_int handling. * graphite-isl-ast-to-gimple.cc (widest_int_from_isl_expr_int): Use WIDEST_INT_MAX_ELTS instead of WIDE_INT_MAX_ELTS. * gimple-ssa-warn-alloca.cc (pass_walloca::execute): Use WIDE_INT_MAX_INL_PRECISION instead of WIDE_INT_MAX_PRECISION and assert get_len () fits into it. * value-range-pretty-print.cc (vrange_printer::print_irange_bitmasks): For mask or value lengths above WIDE_INT_MAX_INL_ELTS use XALLOCAVEC allocated buffer. * gimple-ssa-sprintf.cc (adjust_range_for_overflow): Use wide_int::from on wi::to_wide instead of wi::to_widest. * omp-general.cc (score_wide_int): New typedef. (omp_context_compute_score): Use score_wide_int instead of widest_int and adjust for those changes. (struct omp_declare_variant_entry): Change score and score_in_declare_simd_clone non-static data member type from widest_int to score_wide_int. (omp_resolve_late_declare_variant, omp_resolve_declare_variant): Use score_wide_int instead of widest_int and adjust for those changes. (omp_lto_output_declare_variant_alt): Likewise. (omp_lto_input_declare_variant_alt): Likewise. * godump.cc (go_output_typedef): Assert get_len () is smaller than WIDE_INT_MAX_INL_ELTS. gcc/c-family/ * c-warn.cc (match_case_to_enum_1): Use wi::to_wide just once instead of 3 times, assert get_len () is smaller than WIDE_INT_MAX_INL_ELTS. gcc/testsuite/ * gcc.dg/bitint-38.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/c-warn.cc8
-rw-r--r--gcc/cfgloop.cc25
-rw-r--r--gcc/cfgloop.h11
-rw-r--r--gcc/data-streamer-in.cc8
-rw-r--r--gcc/double-int.h2
-rw-r--r--gcc/fold-const.cc14
-rw-r--r--gcc/gengtype.cc1
-rw-r--r--gcc/gimple-ssa-sprintf.cc11
-rw-r--r--gcc/gimple-ssa-strength-reduction.cc108
-rw-r--r--gcc/gimple-ssa-warn-alloca.cc4
-rw-r--r--gcc/godump.cc6
-rw-r--r--gcc/graphite-isl-ast-to-gimple.cc2
-rw-r--r--gcc/lto-streamer-in.cc19
-rw-r--r--gcc/lto-streamer-out.cc19
-rw-r--r--gcc/match.pd8
-rw-r--r--gcc/omp-general.cc54
-rw-r--r--gcc/poly-int.h14
-rw-r--r--gcc/print-tree.cc4
-rw-r--r--gcc/real.cc8
-rw-r--r--gcc/testsuite/gcc.dg/bitint-38.c18
-rw-r--r--gcc/tree-affine.cc2
-rw-r--r--gcc/tree-ssa-ccp.cc3
-rw-r--r--gcc/tree-ssa-loop-ivcanon.cc5
-rw-r--r--gcc/tree-ssa-loop-ivopts.cc8
-rw-r--r--gcc/tree-ssa-loop-niter.cc45
-rw-r--r--gcc/tree-vect-loop.cc2
-rw-r--r--gcc/tree.cc12
-rw-r--r--gcc/tree.h15
-rw-r--r--gcc/value-range-pretty-print.cc17
-rw-r--r--gcc/value-range.cc17
-rw-r--r--gcc/value-range.h4
-rw-r--r--gcc/wide-int-print.cc27
-rw-r--r--gcc/wide-int-print.h2
-rw-r--r--gcc/wide-int.cc168
-rw-r--r--gcc/wide-int.h661
35 files changed, 1035 insertions, 297 deletions
diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index e67dd87..3e38a86 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -1517,13 +1517,15 @@ match_case_to_enum_1 (tree key, tree type, tree label)
return;
char buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ wide_int w = wi::to_wide (key);
+ gcc_assert (w.get_len () <= WIDE_INT_MAX_INL_ELTS);
if (tree_fits_uhwi_p (key))
- print_dec (wi::to_wide (key), buf, UNSIGNED);
+ print_dec (w, buf, UNSIGNED);
else if (tree_fits_shwi_p (key))
- print_dec (wi::to_wide (key), buf, SIGNED);
+ print_dec (w, buf, SIGNED);
else
- print_hex (wi::to_wide (key), buf);
+ print_hex (w, buf);
if (TYPE_NAME (type) == NULL_TREE)
warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
diff --git a/gcc/cfgloop.cc b/gcc/cfgloop.cc
index 6d46b5b..5a05896 100644
--- a/gcc/cfgloop.cc
+++ b/gcc/cfgloop.cc
@@ -1895,33 +1895,38 @@ void
record_niter_bound (class loop *loop, const widest_int &i_bound,
bool realistic, bool upper)
{
+ if (wi::min_precision (i_bound, SIGNED) > bound_wide_int ().get_precision ())
+ return;
+
+ bound_wide_int bound = bound_wide_int::from (i_bound, SIGNED);
+
/* Update the bounds only when there is no previous estimation, or when the
current estimation is smaller. */
if (upper
&& (!loop->any_upper_bound
- || wi::ltu_p (i_bound, loop->nb_iterations_upper_bound)))
+ || wi::ltu_p (bound, loop->nb_iterations_upper_bound)))
{
loop->any_upper_bound = true;
- loop->nb_iterations_upper_bound = i_bound;
+ loop->nb_iterations_upper_bound = bound;
if (!loop->any_likely_upper_bound)
{
loop->any_likely_upper_bound = true;
- loop->nb_iterations_likely_upper_bound = i_bound;
+ loop->nb_iterations_likely_upper_bound = bound;
}
}
if (realistic
&& (!loop->any_estimate
- || wi::ltu_p (i_bound, loop->nb_iterations_estimate)))
+ || wi::ltu_p (bound, loop->nb_iterations_estimate)))
{
loop->any_estimate = true;
- loop->nb_iterations_estimate = i_bound;
+ loop->nb_iterations_estimate = bound;
}
if (!realistic
&& (!loop->any_likely_upper_bound
- || wi::ltu_p (i_bound, loop->nb_iterations_likely_upper_bound)))
+ || wi::ltu_p (bound, loop->nb_iterations_likely_upper_bound)))
{
loop->any_likely_upper_bound = true;
- loop->nb_iterations_likely_upper_bound = i_bound;
+ loop->nb_iterations_likely_upper_bound = bound;
}
/* If an upper bound is smaller than the realistic estimate of the
@@ -2018,7 +2023,7 @@ get_estimated_loop_iterations (class loop *loop, widest_int *nit)
return false;
}
- *nit = loop->nb_iterations_estimate;
+ *nit = widest_int::from (loop->nb_iterations_estimate, SIGNED);
return true;
}
@@ -2032,7 +2037,7 @@ get_max_loop_iterations (const class loop *loop, widest_int *nit)
if (!loop->any_upper_bound)
return false;
- *nit = loop->nb_iterations_upper_bound;
+ *nit = widest_int::from (loop->nb_iterations_upper_bound, SIGNED);
return true;
}
@@ -2066,7 +2071,7 @@ get_likely_max_loop_iterations (class loop *loop, widest_int *nit)
if (!loop->any_likely_upper_bound)
return false;
- *nit = loop->nb_iterations_likely_upper_bound;
+ *nit = widest_int::from (loop->nb_iterations_likely_upper_bound, SIGNED);
return true;
}
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index f28ec70..559d512 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -44,6 +44,9 @@ enum iv_extend_code
IV_UNKNOWN_EXTEND
};
+typedef generic_wide_int <fixed_wide_int_storage <WIDE_INT_MAX_INL_PRECISION> >
+ bound_wide_int;
+
/* The structure describing a bound on number of iterations of a loop. */
class GTY ((chain_next ("%h.next"))) nb_iter_bound {
@@ -58,7 +61,7 @@ public:
overflows (as MAX + 1 is sometimes produced as the estimate on number
of executions of STMT).
b) it is consistent with the result of number_of_iterations_exit. */
- widest_int bound;
+ bound_wide_int bound;
/* True if, after executing the statement BOUND + 1 times, we will
leave the loop; that is, all the statements after it are executed at most
@@ -161,14 +164,14 @@ public:
/* An integer guaranteed to be greater or equal to nb_iterations. Only
valid if any_upper_bound is true. */
- widest_int nb_iterations_upper_bound;
+ bound_wide_int nb_iterations_upper_bound;
- widest_int nb_iterations_likely_upper_bound;
+ bound_wide_int nb_iterations_likely_upper_bound;
/* An integer giving an estimate on nb_iterations. Unlike
nb_iterations_upper_bound, there is no guarantee that it is at least
nb_iterations. */
- widest_int nb_iterations_estimate;
+ bound_wide_int nb_iterations_estimate;
/* If > 0, an integer, where the user asserted that for any
I in [ 0, nb_iterations ) and for any J in
diff --git a/gcc/data-streamer-in.cc b/gcc/data-streamer-in.cc
index 6e36adc..2334298 100644
--- a/gcc/data-streamer-in.cc
+++ b/gcc/data-streamer-in.cc
@@ -277,10 +277,12 @@ streamer_read_value_range (class lto_input_block *ib, data_in *data_in,
wide_int
streamer_read_wide_int (class lto_input_block *ib)
{
- HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
+ HOST_WIDE_INT abuf[WIDE_INT_MAX_INL_ELTS], *a = abuf;
int i;
int prec = streamer_read_uhwi (ib);
int len = streamer_read_uhwi (ib);
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ a = XALLOCAVEC (HOST_WIDE_INT, len);
for (i = 0; i < len; i++)
a[i] = streamer_read_hwi (ib);
return wide_int::from_array (a, len, prec);
@@ -292,10 +294,12 @@ streamer_read_wide_int (class lto_input_block *ib)
widest_int
streamer_read_widest_int (class lto_input_block *ib)
{
- HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
+ HOST_WIDE_INT abuf[WIDE_INT_MAX_INL_ELTS], *a = abuf;
int i;
int prec ATTRIBUTE_UNUSED = streamer_read_uhwi (ib);
int len = streamer_read_uhwi (ib);
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ a = XALLOCAVEC (HOST_WIDE_INT, len);
for (i = 0; i < len; i++)
a[i] = streamer_read_hwi (ib);
return widest_int::from_array (a, len);
diff --git a/gcc/double-int.h b/gcc/double-int.h
index 41abe84..5fe6702 100644
--- a/gcc/double-int.h
+++ b/gcc/double-int.h
@@ -440,7 +440,7 @@ namespace wi
template <>
struct int_traits <double_int>
{
- static const enum precision_type precision_type = CONST_PRECISION;
+ static const enum precision_type precision_type = INL_CONST_PRECISION;
static const bool host_dependent_precision = true;
static const unsigned int precision = HOST_BITS_PER_DOUBLE_INT;
static unsigned int get_precision (const double_int &);
diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 82299bb..0b6bd37 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -2137,7 +2137,10 @@ fold_convert_const_int_from_int (tree type, const_tree arg1)
/* Given an integer constant, make new constant with new type,
appropriately sign-extended or truncated. Use widest_int
so that any extension is done according ARG1's type. */
- return force_fit_type (type, wi::to_widest (arg1),
+ tree arg1_type = TREE_TYPE (arg1);
+ unsigned prec = MAX (TYPE_PRECISION (arg1_type), TYPE_PRECISION (type));
+ return force_fit_type (type, wide_int::from (wi::to_wide (arg1), prec,
+ TYPE_SIGN (arg1_type)),
!POINTER_TYPE_P (TREE_TYPE (arg1)),
TREE_OVERFLOW (arg1));
}
@@ -9565,8 +9568,13 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
}
if (change)
{
- tem = force_fit_type (type, wi::to_widest (and1), 0,
- TREE_OVERFLOW (and1));
+ tree and1_type = TREE_TYPE (and1);
+ unsigned prec = MAX (TYPE_PRECISION (and1_type),
+ TYPE_PRECISION (type));
+ tem = force_fit_type (type,
+ wide_int::from (wi::to_wide (and1), prec,
+ TYPE_SIGN (and1_type)),
+ 0, TREE_OVERFLOW (and1));
return fold_build2_loc (loc, BIT_AND_EXPR, type,
fold_convert_loc (loc, type, and0), tem);
}
diff --git a/gcc/gengtype.cc b/gcc/gengtype.cc
index 517d84e..fc469e4 100644
--- a/gcc/gengtype.cc
+++ b/gcc/gengtype.cc
@@ -5235,7 +5235,6 @@ main (int argc, char **argv)
POS_HERE (do_scalar_typedef ("FIXED_VALUE_TYPE", &pos));
POS_HERE (do_scalar_typedef ("double_int", &pos));
POS_HERE (do_scalar_typedef ("offset_int", &pos));
- POS_HERE (do_scalar_typedef ("widest_int", &pos));
POS_HERE (do_scalar_typedef ("int64_t", &pos));
POS_HERE (do_scalar_typedef ("poly_int64", &pos));
POS_HERE (do_scalar_typedef ("poly_uint64", &pos));
diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc
index 1897570..b01687e 100644
--- a/gcc/gimple-ssa-sprintf.cc
+++ b/gcc/gimple-ssa-sprintf.cc
@@ -1181,8 +1181,15 @@ adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
*argmin),
size_int (dirprec)))))
{
- *argmin = force_fit_type (dirtype, wi::to_widest (*argmin), 0, false);
- *argmax = force_fit_type (dirtype, wi::to_widest (*argmax), 0, false);
+ unsigned int maxprec = MAX (argprec, dirprec);
+ *argmin = force_fit_type (dirtype,
+ wide_int::from (wi::to_wide (*argmin), maxprec,
+ TYPE_SIGN (argtype)),
+ 0, false);
+ *argmax = force_fit_type (dirtype,
+ wide_int::from (wi::to_wide (*argmax), maxprec,
+ TYPE_SIGN (argtype)),
+ 0, false);
/* If *ARGMIN is still less than *ARGMAX the conversion above
is safe. Otherwise, it has overflowed and would be unsafe. */
diff --git a/gcc/gimple-ssa-strength-reduction.cc b/gcc/gimple-ssa-strength-reduction.cc
index 65d6c06..bb4a4f5 100644
--- a/gcc/gimple-ssa-strength-reduction.cc
+++ b/gcc/gimple-ssa-strength-reduction.cc
@@ -238,7 +238,7 @@ public:
tree stride;
/* The index constant i. */
- widest_int index;
+ offset_int index;
/* The type of the candidate. This is normally the type of base_expr,
but casts may have occurred when combining feeding instructions.
@@ -333,7 +333,7 @@ class incr_info_d
{
public:
/* The increment that relates a candidate to its basis. */
- widest_int incr;
+ offset_int incr;
/* How many times the increment occurs in the candidate tree. */
unsigned count;
@@ -677,7 +677,7 @@ record_potential_basis (slsr_cand_t c, tree base)
static slsr_cand_t
alloc_cand_and_find_basis (enum cand_kind kind, gimple *gs, tree base,
- const widest_int &index, tree stride, tree ctype,
+ const offset_int &index, tree stride, tree ctype,
tree stype, unsigned savings)
{
slsr_cand_t c = (slsr_cand_t) obstack_alloc (&cand_obstack,
@@ -893,7 +893,7 @@ slsr_process_phi (gphi *phi, bool speed)
int (i * S).
Otherwise, just return double int zero. */
-static widest_int
+static offset_int
backtrace_base_for_ref (tree *pbase)
{
tree base_in = *pbase;
@@ -922,7 +922,7 @@ backtrace_base_for_ref (tree *pbase)
{
/* X = B + (1 * S), S is integer constant. */
*pbase = base_cand->base_expr;
- return wi::to_widest (base_cand->stride);
+ return wi::to_offset (base_cand->stride);
}
else if (base_cand->kind == CAND_ADD
&& TREE_CODE (base_cand->stride) == INTEGER_CST
@@ -966,13 +966,13 @@ backtrace_base_for_ref (tree *pbase)
*PINDEX: C1 + (C2 * C3) + C4 + (C5 * C3) */
static bool
-restructure_reference (tree *pbase, tree *poffset, widest_int *pindex,
+restructure_reference (tree *pbase, tree *poffset, offset_int *pindex,
tree *ptype)
{
tree base = *pbase, offset = *poffset;
- widest_int index = *pindex;
+ offset_int index = *pindex;
tree mult_op0, t1, t2, type;
- widest_int c1, c2, c3, c4, c5;
+ offset_int c1, c2, c3, c4, c5;
offset_int mem_offset;
if (!base
@@ -985,18 +985,18 @@ restructure_reference (tree *pbase, tree *poffset, widest_int *pindex,
return false;
t1 = TREE_OPERAND (base, 0);
- c1 = widest_int::from (mem_offset, SIGNED);
+ c1 = offset_int::from (mem_offset, SIGNED);
type = TREE_TYPE (TREE_OPERAND (base, 1));
mult_op0 = TREE_OPERAND (offset, 0);
- c3 = wi::to_widest (TREE_OPERAND (offset, 1));
+ c3 = wi::to_offset (TREE_OPERAND (offset, 1));
if (TREE_CODE (mult_op0) == PLUS_EXPR)
if (TREE_CODE (TREE_OPERAND (mult_op0, 1)) == INTEGER_CST)
{
t2 = TREE_OPERAND (mult_op0, 0);
- c2 = wi::to_widest (TREE_OPERAND (mult_op0, 1));
+ c2 = wi::to_offset (TREE_OPERAND (mult_op0, 1));
}
else
return false;
@@ -1006,7 +1006,7 @@ restructure_reference (tree *pbase, tree *poffset, widest_int *pindex,
if (TREE_CODE (TREE_OPERAND (mult_op0, 1)) == INTEGER_CST)
{
t2 = TREE_OPERAND (mult_op0, 0);
- c2 = -wi::to_widest (TREE_OPERAND (mult_op0, 1));
+ c2 = -wi::to_offset (TREE_OPERAND (mult_op0, 1));
}
else
return false;
@@ -1057,7 +1057,7 @@ slsr_process_ref (gimple *gs)
HOST_WIDE_INT cbitpos;
if (reversep || !bitpos.is_constant (&cbitpos))
return;
- widest_int index = cbitpos;
+ offset_int index = cbitpos;
if (!restructure_reference (&base, &offset, &index, &type))
return;
@@ -1079,7 +1079,7 @@ create_mul_ssa_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
{
tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
tree stype = NULL_TREE;
- widest_int index;
+ offset_int index;
unsigned savings = 0;
slsr_cand_t c;
slsr_cand_t base_cand = base_cand_from_table (base_in);
@@ -1112,7 +1112,7 @@ create_mul_ssa_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
============================
X = B + ((i' * S) * Z) */
base = base_cand->base_expr;
- index = base_cand->index * wi::to_widest (base_cand->stride);
+ index = base_cand->index * wi::to_offset (base_cand->stride);
stride = stride_in;
ctype = base_cand->cand_type;
stype = TREE_TYPE (stride_in);
@@ -1149,7 +1149,7 @@ static slsr_cand_t
create_mul_imm_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
{
tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
- widest_int index, temp;
+ offset_int index, temp;
unsigned savings = 0;
slsr_cand_t c;
slsr_cand_t base_cand = base_cand_from_table (base_in);
@@ -1165,7 +1165,7 @@ create_mul_imm_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
X = Y * c
============================
X = (B + i') * (S * c) */
- temp = wi::to_widest (base_cand->stride) * wi::to_widest (stride_in);
+ temp = wi::to_offset (base_cand->stride) * wi::to_offset (stride_in);
if (wi::fits_to_tree_p (temp, TREE_TYPE (stride_in)))
{
base = base_cand->base_expr;
@@ -1200,7 +1200,7 @@ create_mul_imm_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
===========================
X = (B + S) * c */
base = base_cand->base_expr;
- index = wi::to_widest (base_cand->stride);
+ index = wi::to_offset (base_cand->stride);
stride = stride_in;
ctype = base_cand->cand_type;
if (has_single_use (base_in))
@@ -1281,7 +1281,7 @@ create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
{
tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
tree stype = NULL_TREE;
- widest_int index;
+ offset_int index;
unsigned savings = 0;
slsr_cand_t c;
slsr_cand_t base_cand = base_cand_from_table (base_in);
@@ -1300,7 +1300,7 @@ create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
===========================
X = Y + ((+/-1 * S) * B) */
base = base_in;
- index = wi::to_widest (addend_cand->stride);
+ index = wi::to_offset (addend_cand->stride);
if (subtract_p)
index = -index;
stride = addend_cand->base_expr;
@@ -1350,7 +1350,7 @@ create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
===========================
Value: X = Y + ((-1 * S) * B) */
base = base_in;
- index = wi::to_widest (subtrahend_cand->stride);
+ index = wi::to_offset (subtrahend_cand->stride);
index = -index;
stride = subtrahend_cand->base_expr;
ctype = TREE_TYPE (base_in);
@@ -1389,13 +1389,13 @@ create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
about BASE_IN into the new candidate. Return the new candidate. */
static slsr_cand_t
-create_add_imm_cand (gimple *gs, tree base_in, const widest_int &index_in,
+create_add_imm_cand (gimple *gs, tree base_in, const offset_int &index_in,
bool speed)
{
enum cand_kind kind = CAND_ADD;
tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
tree stype = NULL_TREE;
- widest_int index, multiple;
+ offset_int index, multiple;
unsigned savings = 0;
slsr_cand_t c;
slsr_cand_t base_cand = base_cand_from_table (base_in);
@@ -1405,7 +1405,7 @@ create_add_imm_cand (gimple *gs, tree base_in, const widest_int &index_in,
signop sign = TYPE_SIGN (TREE_TYPE (base_cand->stride));
if (TREE_CODE (base_cand->stride) == INTEGER_CST
- && wi::multiple_of_p (index_in, wi::to_widest (base_cand->stride),
+ && wi::multiple_of_p (index_in, wi::to_offset (base_cand->stride),
sign, &multiple))
{
/* Y = (B + i') * S, S constant, c = kS for some integer k
@@ -1494,7 +1494,7 @@ slsr_process_add (gimple *gs, tree rhs1, tree rhs2, bool speed)
else if (TREE_CODE (rhs2) == INTEGER_CST)
{
/* Record an interpretation for the add-immediate. */
- widest_int index = wi::to_widest (rhs2);
+ offset_int index = wi::to_offset (rhs2);
if (subtract_p)
index = -index;
@@ -2079,7 +2079,7 @@ phi_dependent_cand_p (slsr_cand_t c)
/* Calculate the increment required for candidate C relative to
its basis. */
-static widest_int
+static offset_int
cand_increment (slsr_cand_t c)
{
slsr_cand_t basis;
@@ -2102,10 +2102,10 @@ cand_increment (slsr_cand_t c)
for this candidate, return the absolute value of that increment
instead. */
-static inline widest_int
+static inline offset_int
cand_abs_increment (slsr_cand_t c)
{
- widest_int increment = cand_increment (c);
+ offset_int increment = cand_increment (c);
if (!address_arithmetic_p && wi::neg_p (increment))
increment = -increment;
@@ -2126,7 +2126,7 @@ cand_already_replaced (slsr_cand_t c)
replace_conditional_candidate. */
static void
-replace_mult_candidate (slsr_cand_t c, tree basis_name, widest_int bump)
+replace_mult_candidate (slsr_cand_t c, tree basis_name, offset_int bump)
{
tree target_type = TREE_TYPE (gimple_assign_lhs (c->cand_stmt));
enum tree_code cand_code = gimple_assign_rhs_code (c->cand_stmt);
@@ -2245,7 +2245,7 @@ replace_unconditional_candidate (slsr_cand_t c)
return;
basis = lookup_cand (c->basis);
- widest_int bump = cand_increment (c) * wi::to_widest (c->stride);
+ offset_int bump = cand_increment (c) * wi::to_offset (c->stride);
replace_mult_candidate (c, gimple_assign_lhs (basis->cand_stmt), bump);
}
@@ -2255,7 +2255,7 @@ replace_unconditional_candidate (slsr_cand_t c)
MAX_INCR_VEC_LEN increments have been found. */
static inline int
-incr_vec_index (const widest_int &increment)
+incr_vec_index (const offset_int &increment)
{
unsigned i;
@@ -2275,7 +2275,7 @@ incr_vec_index (const widest_int &increment)
static tree
create_add_on_incoming_edge (slsr_cand_t c, tree basis_name,
- widest_int increment, edge e, location_t loc,
+ offset_int increment, edge e, location_t loc,
bool known_stride)
{
tree lhs, basis_type;
@@ -2299,7 +2299,7 @@ create_add_on_incoming_edge (slsr_cand_t c, tree basis_name,
{
tree bump_tree;
enum tree_code code = plus_code;
- widest_int bump = increment * wi::to_widest (c->stride);
+ offset_int bump = increment * wi::to_offset (c->stride);
if (wi::neg_p (bump) && !POINTER_TYPE_P (basis_type))
{
code = MINUS_EXPR;
@@ -2427,7 +2427,7 @@ create_phi_basis_1 (slsr_cand_t c, gimple *from_phi, tree basis_name,
feeding_def = gimple_assign_lhs (basis->cand_stmt);
else
{
- widest_int incr = -basis->index;
+ offset_int incr = -basis->index;
feeding_def = create_add_on_incoming_edge (c, basis_name, incr,
e, loc, known_stride);
}
@@ -2444,7 +2444,7 @@ create_phi_basis_1 (slsr_cand_t c, gimple *from_phi, tree basis_name,
else
{
slsr_cand_t arg_cand = base_cand_from_table (arg);
- widest_int diff = arg_cand->index - basis->index;
+ offset_int diff = arg_cand->index - basis->index;
feeding_def = create_add_on_incoming_edge (c, basis_name, diff,
e, loc, known_stride);
}
@@ -2525,7 +2525,7 @@ replace_conditional_candidate (slsr_cand_t c)
basis_name, loc, KNOWN_STRIDE);
/* Replace C with an add of the new basis phi and a constant. */
- widest_int bump = c->index * wi::to_widest (c->stride);
+ offset_int bump = c->index * wi::to_offset (c->stride);
replace_mult_candidate (c, name, bump);
}
@@ -2614,7 +2614,7 @@ replace_uncond_cands_and_profitable_phis (slsr_cand_t c)
{
/* A multiply candidate with a stride of 1 is just an artifice
of a copy or cast; there is no value in replacing it. */
- if (c->kind == CAND_MULT && wi::to_widest (c->stride) != 1)
+ if (c->kind == CAND_MULT && wi::to_offset (c->stride) != 1)
{
/* A candidate dependent upon a phi will replace a multiply by
a constant with an add, and will insert at most one add for
@@ -2681,7 +2681,7 @@ count_candidates (slsr_cand_t c)
candidates with the same increment, also record T_0 for subsequent use. */
static void
-record_increment (slsr_cand_t c, widest_int increment, bool is_phi_adjust)
+record_increment (slsr_cand_t c, offset_int increment, bool is_phi_adjust)
{
bool found = false;
unsigned i;
@@ -2786,7 +2786,7 @@ record_phi_increments_1 (slsr_cand_t basis, gimple *phi)
record_phi_increments_1 (basis, arg_def);
else
{
- widest_int diff;
+ offset_int diff;
if (operand_equal_p (arg, phi_cand->base_expr, 0))
{
@@ -2856,7 +2856,7 @@ record_increments (slsr_cand_t c)
/* Recursive helper function for phi_incr_cost. */
static int
-phi_incr_cost_1 (slsr_cand_t c, const widest_int &incr, gimple *phi,
+phi_incr_cost_1 (slsr_cand_t c, const offset_int &incr, gimple *phi,
int *savings)
{
unsigned i;
@@ -2883,7 +2883,7 @@ phi_incr_cost_1 (slsr_cand_t c, const widest_int &incr, gimple *phi,
}
else
{
- widest_int diff;
+ offset_int diff;
slsr_cand_t arg_cand;
/* When the PHI argument is just a pass-through to the base
@@ -2925,7 +2925,7 @@ phi_incr_cost_1 (slsr_cand_t c, const widest_int &incr, gimple *phi,
uses. */
static int
-phi_incr_cost (slsr_cand_t c, const widest_int &incr, gimple *phi,
+phi_incr_cost (slsr_cand_t c, const offset_int &incr, gimple *phi,
int *savings)
{
int retval = phi_incr_cost_1 (c, incr, phi, savings);
@@ -2981,10 +2981,10 @@ optimize_cands_for_speed_p (slsr_cand_t c)
static int
lowest_cost_path (int cost_in, int repl_savings, slsr_cand_t c,
- const widest_int &incr, bool count_phis)
+ const offset_int &incr, bool count_phis)
{
int local_cost, sib_cost, savings = 0;
- widest_int cand_incr = cand_abs_increment (c);
+ offset_int cand_incr = cand_abs_increment (c);
if (cand_already_replaced (c))
local_cost = cost_in;
@@ -3027,11 +3027,11 @@ lowest_cost_path (int cost_in, int repl_savings, slsr_cand_t c,
would go dead. */
static int
-total_savings (int repl_savings, slsr_cand_t c, const widest_int &incr,
+total_savings (int repl_savings, slsr_cand_t c, const offset_int &incr,
bool count_phis)
{
int savings = 0;
- widest_int cand_incr = cand_abs_increment (c);
+ offset_int cand_incr = cand_abs_increment (c);
if (incr == cand_incr && !cand_already_replaced (c))
savings += repl_savings + c->dead_savings;
@@ -3239,7 +3239,7 @@ ncd_for_two_cands (basic_block bb1, basic_block bb2,
candidates, return the earliest candidate in the block in *WHERE. */
static basic_block
-ncd_with_phi (slsr_cand_t c, const widest_int &incr, gphi *phi,
+ncd_with_phi (slsr_cand_t c, const offset_int &incr, gphi *phi,
basic_block ncd, slsr_cand_t *where)
{
unsigned i;
@@ -3255,7 +3255,7 @@ ncd_with_phi (slsr_cand_t c, const widest_int &incr, gphi *phi,
ncd = ncd_with_phi (c, incr, as_a <gphi *> (arg_def), ncd, where);
else
{
- widest_int diff;
+ offset_int diff;
if (operand_equal_p (arg, phi_cand->base_expr, 0))
diff = -basis->index;
@@ -3282,7 +3282,7 @@ ncd_with_phi (slsr_cand_t c, const widest_int &incr, gphi *phi,
return the earliest candidate in the block in *WHERE. */
static basic_block
-ncd_of_cand_and_phis (slsr_cand_t c, const widest_int &incr, slsr_cand_t *where)
+ncd_of_cand_and_phis (slsr_cand_t c, const offset_int &incr, slsr_cand_t *where)
{
basic_block ncd = NULL;
@@ -3308,7 +3308,7 @@ ncd_of_cand_and_phis (slsr_cand_t c, const widest_int &incr, slsr_cand_t *where)
*WHERE. */
static basic_block
-nearest_common_dominator_for_cands (slsr_cand_t c, const widest_int &incr,
+nearest_common_dominator_for_cands (slsr_cand_t c, const offset_int &incr,
slsr_cand_t *where)
{
basic_block sib_ncd = NULL, dep_ncd = NULL, this_ncd = NULL, ncd;
@@ -3385,7 +3385,7 @@ insert_initializers (slsr_cand_t c)
gassign *init_stmt;
gassign *cast_stmt = NULL;
tree new_name, incr_tree, init_stride;
- widest_int incr = incr_vec[i].incr;
+ offset_int incr = incr_vec[i].incr;
if (!profitable_increment_p (i)
|| incr == 1
@@ -3550,7 +3550,7 @@ all_phi_incrs_profitable_1 (slsr_cand_t c, gphi *phi, int *spread)
else
{
int j;
- widest_int increment;
+ offset_int increment;
if (operand_equal_p (arg, phi_cand->base_expr, 0))
increment = -basis->index;
@@ -3681,7 +3681,7 @@ replace_one_candidate (slsr_cand_t c, unsigned i, tree basis_name)
tree orig_rhs1, orig_rhs2;
tree rhs2;
enum tree_code orig_code, repl_code;
- widest_int cand_incr;
+ offset_int cand_incr;
orig_code = gimple_assign_rhs_code (c->cand_stmt);
orig_rhs1 = gimple_assign_rhs1 (c->cand_stmt);
@@ -3839,7 +3839,7 @@ replace_profitable_candidates (slsr_cand_t c)
{
if (!cand_already_replaced (c))
{
- widest_int increment = cand_abs_increment (c);
+ offset_int increment = cand_abs_increment (c);
enum tree_code orig_code = gimple_assign_rhs_code (c->cand_stmt);
int i;
diff --git a/gcc/gimple-ssa-warn-alloca.cc b/gcc/gimple-ssa-warn-alloca.cc
index 2d8ab93..4c97434 100644
--- a/gcc/gimple-ssa-warn-alloca.cc
+++ b/gcc/gimple-ssa-warn-alloca.cc
@@ -310,7 +310,7 @@ pass_walloca::execute (function *fun)
enum opt_code wcode
= is_vla ? OPT_Wvla_larger_than_ : OPT_Walloca_larger_than_;
- char buff[WIDE_INT_MAX_PRECISION / 4 + 4];
+ char buff[WIDE_INT_MAX_INL_PRECISION / 4 + 4];
switch (t.type)
{
case ALLOCA_OK:
@@ -329,6 +329,7 @@ pass_walloca::execute (function *fun)
"large")))
&& t.limit != 0)
{
+ gcc_assert (t.limit.get_len () < WIDE_INT_MAX_INL_ELTS);
print_decu (t.limit, buff);
inform (loc, "limit is %wu bytes, but argument "
"may be as large as %s",
@@ -347,6 +348,7 @@ pass_walloca::execute (function *fun)
: G_("argument to %<alloca%> is too large")))
&& t.limit != 0)
{
+ gcc_assert (t.limit.get_len () < WIDE_INT_MAX_INL_ELTS);
print_decu (t.limit, buff);
inform (loc, "limit is %wu bytes, but argument is %s",
is_vla ? warn_vla_limit : adjusted_alloca_limit,
diff --git a/gcc/godump.cc b/gcc/godump.cc
index bdd2d10..c6f547c 100644
--- a/gcc/godump.cc
+++ b/gcc/godump.cc
@@ -1154,7 +1154,11 @@ go_output_typedef (class godump_container *container, tree decl)
snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
tree_to_uhwi (value));
else
- print_hex (wi::to_wide (element), buf);
+ {
+ wide_int w = wi::to_wide (element);
+ gcc_assert (w.get_len () <= WIDE_INT_MAX_INL_ELTS);
+ print_hex (w, buf);
+ }
mhval->value = xstrdup (buf);
*slot = mhval;
diff --git a/gcc/graphite-isl-ast-to-gimple.cc b/gcc/graphite-isl-ast-to-gimple.cc
index 6c0d6f9..f62b0fe 100644
--- a/gcc/graphite-isl-ast-to-gimple.cc
+++ b/gcc/graphite-isl-ast-to-gimple.cc
@@ -274,7 +274,7 @@ widest_int_from_isl_expr_int (__isl_keep isl_ast_expr *expr)
isl_val *val = isl_ast_expr_get_val (expr);
size_t n = isl_val_n_abs_num_chunks (val, sizeof (HOST_WIDE_INT));
HOST_WIDE_INT *chunks = XALLOCAVEC (HOST_WIDE_INT, n);
- if (n > WIDE_INT_MAX_ELTS
+ if (n > WIDEST_INT_MAX_ELTS
|| isl_val_get_abs_num_chunks (val, sizeof (HOST_WIDE_INT), chunks) == -1)
{
isl_val_free (val);
diff --git a/gcc/lto-streamer-in.cc b/gcc/lto-streamer-in.cc
index d3128fc..b257c13 100644
--- a/gcc/lto-streamer-in.cc
+++ b/gcc/lto-streamer-in.cc
@@ -1122,13 +1122,16 @@ input_cfg (class lto_input_block *ib, class data_in *data_in,
loop->estimate_state = streamer_read_enum (ib, loop_estimation, EST_LAST);
loop->any_upper_bound = streamer_read_hwi (ib);
if (loop->any_upper_bound)
- loop->nb_iterations_upper_bound = streamer_read_widest_int (ib);
+ loop->nb_iterations_upper_bound
+ = bound_wide_int::from (streamer_read_widest_int (ib), SIGNED);
loop->any_likely_upper_bound = streamer_read_hwi (ib);
if (loop->any_likely_upper_bound)
- loop->nb_iterations_likely_upper_bound = streamer_read_widest_int (ib);
+ loop->nb_iterations_likely_upper_bound
+ = bound_wide_int::from (streamer_read_widest_int (ib), SIGNED);
loop->any_estimate = streamer_read_hwi (ib);
if (loop->any_estimate)
- loop->nb_iterations_estimate = streamer_read_widest_int (ib);
+ loop->nb_iterations_estimate
+ = bound_wide_int::from (streamer_read_widest_int (ib), SIGNED);
/* Read OMP SIMD related info. */
loop->safelen = streamer_read_hwi (ib);
@@ -1888,13 +1891,17 @@ lto_input_tree_1 (class lto_input_block *ib, class data_in *data_in,
tree type = stream_read_tree_ref (ib, data_in);
unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
unsigned HOST_WIDE_INT i;
- HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
+ HOST_WIDE_INT abuf[WIDE_INT_MAX_INL_ELTS], *a = abuf;
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ a = XALLOCAVEC (HOST_WIDE_INT, len);
for (i = 0; i < len; i++)
a[i] = streamer_read_hwi (ib);
gcc_assert (TYPE_PRECISION (type) <= WIDE_INT_MAX_PRECISION);
- result = wide_int_to_tree (type, wide_int::from_array
- (a, len, TYPE_PRECISION (type)));
+ result
+ = wide_int_to_tree (type,
+ wide_int::from_array (a, len,
+ TYPE_PRECISION (type)));
streamer_tree_cache_append (data_in->reader_cache, result, hash);
}
else if (tag == LTO_tree_scc || tag == LTO_trees)
diff --git a/gcc/lto-streamer-out.cc b/gcc/lto-streamer-out.cc
index 5ffa895..a1bbea8 100644
--- a/gcc/lto-streamer-out.cc
+++ b/gcc/lto-streamer-out.cc
@@ -2173,13 +2173,26 @@ output_cfg (struct output_block *ob, struct function *fn)
loop_estimation, EST_LAST, loop->estimate_state);
streamer_write_hwi (ob, loop->any_upper_bound);
if (loop->any_upper_bound)
- streamer_write_widest_int (ob, loop->nb_iterations_upper_bound);
+ {
+ widest_int w = widest_int::from (loop->nb_iterations_upper_bound,
+ SIGNED);
+ streamer_write_widest_int (ob, w);
+ }
streamer_write_hwi (ob, loop->any_likely_upper_bound);
if (loop->any_likely_upper_bound)
- streamer_write_widest_int (ob, loop->nb_iterations_likely_upper_bound);
+ {
+ widest_int w
+ = widest_int::from (loop->nb_iterations_likely_upper_bound,
+ SIGNED);
+ streamer_write_widest_int (ob, w);
+ }
streamer_write_hwi (ob, loop->any_estimate);
if (loop->any_estimate)
- streamer_write_widest_int (ob, loop->nb_iterations_estimate);
+ {
+ widest_int w = widest_int::from (loop->nb_iterations_estimate,
+ SIGNED);
+ streamer_write_widest_int (ob, w);
+ }
/* Write OMP SIMD related info. */
streamer_write_hwi (ob, loop->safelen);
diff --git a/gcc/match.pd b/gcc/match.pd
index 26b05c1..51e5065 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6464,8 +6464,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
code and here to avoid a spurious overflow flag on the resulting
constant which fold_convert produces. */
(if (TREE_CODE (@1) == INTEGER_CST)
- (cmp @00 { force_fit_type (TREE_TYPE (@00), wi::to_widest (@1), 0,
- TREE_OVERFLOW (@1)); })
+ (cmp @00 { force_fit_type (TREE_TYPE (@00),
+ wide_int::from (wi::to_wide (@1),
+ MAX (TYPE_PRECISION (TREE_TYPE (@1)),
+ TYPE_PRECISION (TREE_TYPE (@00))),
+ TYPE_SIGN (TREE_TYPE (@1))),
+ 0, TREE_OVERFLOW (@1)); })
(cmp @00 (convert @1)))
(if (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE (@00)))
diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc
index 1e31014..b88d593 100644
--- a/gcc/omp-general.cc
+++ b/gcc/omp-general.cc
@@ -1986,13 +1986,17 @@ omp_get_context_selector (tree ctx, const char *set, const char *sel)
return NULL_TREE;
}
+/* Needs to be a GC-friendly widest_int variant, but precision is
+ desirable to be the same on all targets. */
+typedef generic_wide_int <fixed_wide_int_storage <1024> > score_wide_int;
+
/* Compute *SCORE for context selector CTX. Return true if the score
would be different depending on whether it is a declare simd clone or
not. DECLARE_SIMD should be true for the case when it would be
a declare simd clone. */
static bool
-omp_context_compute_score (tree ctx, widest_int *score, bool declare_simd)
+omp_context_compute_score (tree ctx, score_wide_int *score, bool declare_simd)
{
tree construct = omp_get_context_selector (ctx, "construct", NULL);
bool has_kind = omp_get_context_selector (ctx, "device", "kind");
@@ -2007,7 +2011,11 @@ omp_context_compute_score (tree ctx, widest_int *score, bool declare_simd)
if (TREE_PURPOSE (t3)
&& strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t3)), " score") == 0
&& TREE_CODE (TREE_VALUE (t3)) == INTEGER_CST)
- *score += wi::to_widest (TREE_VALUE (t3));
+ {
+ tree t4 = TREE_VALUE (t3);
+ *score += score_wide_int::from (wi::to_wide (t4),
+ TYPE_SIGN (TREE_TYPE (t4)));
+ }
if (construct || has_kind || has_arch || has_isa)
{
int scores[12];
@@ -2028,16 +2036,16 @@ omp_context_compute_score (tree ctx, widest_int *score, bool declare_simd)
*score = -1;
return ret;
}
- *score += wi::shifted_mask <widest_int> (scores[b + n], 1, false);
+ *score += wi::shifted_mask <score_wide_int> (scores[b + n], 1, false);
}
if (has_kind)
- *score += wi::shifted_mask <widest_int> (scores[b + nconstructs],
+ *score += wi::shifted_mask <score_wide_int> (scores[b + nconstructs],
1, false);
if (has_arch)
- *score += wi::shifted_mask <widest_int> (scores[b + nconstructs] + 1,
+ *score += wi::shifted_mask <score_wide_int> (scores[b + nconstructs] + 1,
1, false);
if (has_isa)
- *score += wi::shifted_mask <widest_int> (scores[b + nconstructs] + 2,
+ *score += wi::shifted_mask <score_wide_int> (scores[b + nconstructs] + 2,
1, false);
}
else /* FIXME: Implement this. */
@@ -2051,9 +2059,9 @@ struct GTY(()) omp_declare_variant_entry {
/* NODE of the variant. */
cgraph_node *variant;
/* Score if not in declare simd clone. */
- widest_int score;
+ score_wide_int score;
/* Score if in declare simd clone. */
- widest_int score_in_declare_simd_clone;
+ score_wide_int score_in_declare_simd_clone;
/* Context selector for the variant. */
tree ctx;
/* True if the context selector is known to match already. */
@@ -2214,12 +2222,12 @@ omp_resolve_late_declare_variant (tree alt)
}
}
- widest_int max_score = -1;
+ score_wide_int max_score = -1;
varentry2 = NULL;
FOR_EACH_VEC_SAFE_ELT (entryp->variants, i, varentry1)
if (matches[i])
{
- widest_int score
+ score_wide_int score
= (cur_node->simdclone ? varentry1->score_in_declare_simd_clone
: varentry1->score);
if (score > max_score)
@@ -2300,8 +2308,8 @@ omp_resolve_declare_variant (tree base)
if (any_deferred)
{
- widest_int max_score1 = 0;
- widest_int max_score2 = 0;
+ score_wide_int max_score1 = 0;
+ score_wide_int max_score2 = 0;
bool first = true;
unsigned int i;
tree attr1, attr2;
@@ -2311,8 +2319,8 @@ omp_resolve_declare_variant (tree base)
vec_alloc (entry.variants, variants.length ());
FOR_EACH_VEC_ELT (variants, i, attr1)
{
- widest_int score1;
- widest_int score2;
+ score_wide_int score1;
+ score_wide_int score2;
bool need_two;
tree ctx = TREE_VALUE (TREE_VALUE (attr1));
need_two = omp_context_compute_score (ctx, &score1, false);
@@ -2471,16 +2479,16 @@ omp_resolve_declare_variant (tree base)
variants[j] = NULL_TREE;
}
}
- widest_int max_score1 = 0;
- widest_int max_score2 = 0;
+ score_wide_int max_score1 = 0;
+ score_wide_int max_score2 = 0;
bool first = true;
FOR_EACH_VEC_ELT (variants, i, attr1)
if (attr1)
{
if (variant1)
{
- widest_int score1;
- widest_int score2;
+ score_wide_int score1;
+ score_wide_int score2;
bool need_two;
tree ctx;
if (first)
@@ -2552,7 +2560,7 @@ omp_lto_output_declare_variant_alt (lto_simple_output_block *ob,
gcc_assert (nvar != LCC_NOT_FOUND);
streamer_write_hwi_stream (ob->main_stream, nvar);
- for (widest_int *w = &varentry->score; ;
+ for (score_wide_int *w = &varentry->score; ;
w = &varentry->score_in_declare_simd_clone)
{
unsigned len = w->get_len ();
@@ -2602,15 +2610,15 @@ omp_lto_input_declare_variant_alt (lto_input_block *ib, cgraph_node *node,
omp_declare_variant_entry varentry;
varentry.variant
= dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
- for (widest_int *w = &varentry.score; ;
+ for (score_wide_int *w = &varentry.score; ;
w = &varentry.score_in_declare_simd_clone)
{
unsigned len2 = streamer_read_hwi (ib);
- HOST_WIDE_INT arr[WIDE_INT_MAX_ELTS];
- gcc_assert (len2 <= WIDE_INT_MAX_ELTS);
+ HOST_WIDE_INT arr[WIDE_INT_MAX_HWIS (1024)];
+ gcc_assert (len2 <= WIDE_INT_MAX_HWIS (1024));
for (unsigned int j = 0; j < len2; j++)
arr[j] = streamer_read_hwi (ib);
- *w = widest_int::from_array (arr, len2, true);
+ *w = score_wide_int::from_array (arr, len2, true);
if (w == &varentry.score_in_declare_simd_clone)
break;
}
diff --git a/gcc/poly-int.h b/gcc/poly-int.h
index 3146ba3..828714e 100644
--- a/gcc/poly-int.h
+++ b/gcc/poly-int.h
@@ -96,6 +96,20 @@ struct poly_coeff_traits<T, wi::VAR_PRECISION>
};
template<typename T>
+struct poly_coeff_traits<T, wi::INL_CONST_PRECISION>
+{
+ typedef WI_UNARY_RESULT (T) result;
+ typedef int int_type;
+ /* These types are always signed. */
+ static const int signedness = 1;
+ static const int precision = wi::int_traits<T>::precision;
+ static const int rank = precision * 2 / CHAR_BIT;
+
+ template<typename Arg>
+ struct init_cast { using type = const Arg &; };
+};
+
+template<typename T>
struct poly_coeff_traits<T, wi::CONST_PRECISION>
{
typedef WI_UNARY_RESULT (T) result;
diff --git a/gcc/print-tree.cc b/gcc/print-tree.cc
index 62451b6..e4ee8b8 100644
--- a/gcc/print-tree.cc
+++ b/gcc/print-tree.cc
@@ -365,13 +365,13 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
fputs (code == CALL_EXPR ? " must-tail-call" : " static", file);
if (TREE_DEPRECATED (node))
fputs (" deprecated", file);
- if (TREE_UNAVAILABLE (node))
- fputs (" unavailable", file);
if (TREE_VISITED (node))
fputs (" visited", file);
if (code != TREE_VEC && code != INTEGER_CST && code != SSA_NAME)
{
+ if (TREE_UNAVAILABLE (node))
+ fputs (" unavailable", file);
if (TREE_LANG_FLAG_0 (node))
fputs (" tree_0", file);
if (TREE_LANG_FLAG_1 (node))
diff --git a/gcc/real.cc b/gcc/real.cc
index fc6b3a7..a9996c8 100644
--- a/gcc/real.cc
+++ b/gcc/real.cc
@@ -1477,7 +1477,7 @@ real_to_integer (const REAL_VALUE_TYPE *r)
wide_int
real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision)
{
- HOST_WIDE_INT val[2 * WIDE_INT_MAX_ELTS];
+ HOST_WIDE_INT valb[WIDE_INT_MAX_INL_ELTS], *val;
int exp;
int words, w;
wide_int result;
@@ -1516,7 +1516,11 @@ real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision)
is the smallest HWI-multiple that has at least PRECISION bits.
This ensures that the top bit of the significand is in the
top bit of the wide_int. */
- words = (precision + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT;
+ words = ((precision + HOST_BITS_PER_WIDE_INT - 1)
+ / HOST_BITS_PER_WIDE_INT);
+ val = valb;
+ if (UNLIKELY (words > WIDE_INT_MAX_INL_ELTS))
+ val = XALLOCAVEC (HOST_WIDE_INT, words);
w = words * HOST_BITS_PER_WIDE_INT;
#if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
diff --git a/gcc/testsuite/gcc.dg/bitint-38.c b/gcc/testsuite/gcc.dg/bitint-38.c
new file mode 100644
index 0000000..95673dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitint-38.c
@@ -0,0 +1,18 @@
+/* PR c/102989 */
+/* { dg-do compile { target { bitint } } } */
+/* { dg-options "-std=c2x" } */
+
+#if __BITINT_MAXWIDTH__ >= 16319
+constexpr unsigned _BitInt(16319) a
+ = 468098567701677261276215481936770442254383643766995378241600227179396283432916865881332215867106489159251577495372085663487092317743244770597287633199005374998455333587280357490149993101811392051483761495987108264964738337118155155862715438910721661230332533185335581757600511846854115932637261969633134365868695363914570578110064471868475841348589366933645410987699979080140212849909081188170910464967486231358935212897096260626033055536141835599284498474737858487658470115144771923114826312283863035503700600141440724426364699636330240414271275626021294939422483250619629005959992243418661230122132667769781183790338759345884903821695590991577228520523725302048215447841573113840811593638413425054938213262961448317898574140533090004992732688525115004782973893244091427000396890427152225308661078954671066069234453757593181753900865203439035402480306413572239610467142591920809187367438071170100969567440044691427487959785637338381651309916782063670286046547585240837892307170928849485877186793280707600840866783471799148179250818387716183127323346199533387463363442356218803779697005759324410376476855222420876262425985571982818180353870410149824214544313013285199544193496624223219986402944849622489422007678564946174797892795089330899535624727777525330789492703574564112252955147770942929761545604350869404246558274752353510370157229485004402131043153454290397929387276374054938578976878606467217359398684275050519104413914286024106808116340712273059427362293703151355498336213170698894448405369398757188523160460292714875857879968173578328191358215972493513271297875634400793301929250052822258636015650857683023900709845410838487936778533250407886180954576046340697908584020951295048844938047865657029072850797442976146895294184993736999505485665742811313795405530674199848055802759901786376822069529342971261963119332476504064285869362049662083405789828433132154933242817432809415810548180658750393692272729586232842065658490971201927780014258815333115459695117942273551876646844821076723664040282772834511419891351278169017103987094803829594286352340468346618726088781492626816188657331359104171819822673805856317828499039088088223137258297373929043307673570090396947789598799922928643843532617012164811074618881774622628943539037974883812689130801860915090035870244061005819418130068390986470314677853605080103313411837904358287837401546257413240466939893527508931541065241929872307203876443882106193262544652290132364691671910332006127864146991404015366683569317248057949596070354929361158326955551600236075268435044105880162798380799161607987365282458662031599096921825176202707890730023698706855762932691688259365358964076595824577775275991183149118372047206055118463112864604063853894820407249837871368934941438119680605528546887256934334246075596746410297954458632358171428714141820918183384435681332379317541048252391710712196623406338702061195213724569303285402242853671386113148211535691685461836458295037538034378318055108240082414441205300401526732399959228346926528586852743389490978734787926721999855388794711837164423007719626109179005466113706450765269687580819822772189301084503627297389675134228222337286867641110511061980231247884533492442898936743429641958314135329073406495776369208158032115883850691010569048983941126771477990976092252391972812691669847446798507244106121667885423025613769258102773855537509733295805013313937402282804897213847221072647111605172349464564089914906493508133855389627177663426057763252086286325343811254757681803068276278048757997425284334713190226818463023074461900176958010055572434983135171145365242339273326984465181064287264645470832091115100640584104375577304056951969456200138485313560009272338228103637763863289261673258726736753407044143664079479496972580560534494806170810469304773005873590626280072387999668522546747985701599613975101188543857852141559251634058676718308000324869809628199442681565615662912626022796064414496106344236431285697688357707992989966561557171729972093533007476947862215922583204811189015550505642082475400647639520782187776825395598257421714106473869797642678266380755873356747812273977691604147842741151722919464734890326772594979022403228191075586910464204870254674290437668861177639713112762996390246102030994917186957826982084194156870398312336059100521566034092740694642613192909850644003933745129291062576341213874815510099835708723355432970090139671120232910747665906191360160259512198160849784197597300106223945960886603127136037120000864968668651452411048372895607382907494278810971475663944948791458618662250238375166523484847507342040066801856222328988662049579299600545682490412754483621051190231623196265549391964259780178070495642538883789503379406531279338866955157646654913405181879254189185904298325865503395688786311067669273609670603076582607253527084977744533187145642686236350165593980428575119329911921382240780504527422630654086941060242757131313184709635181001199631726283364158943337968797uwb
+ + 9935443518057456429927126655222257817207511311671335832560065573055276678747990652907348839741818562757939084649073348172108397183827020377941725983107513636287406530526358253508437290241937276908386282904353079102904535675608604576486162998319427702851278408213641454837223079616401615875672453250148421679223829417834227518133091055180270249266161676677176149675164257640812344297935650729629801878758059944090168862730519817203352341458310363811482318083270232434329317323822818991134500601669868922396013512969477839456472345812312321924215241849772147687455760224559240952737319009348540894966363568158349501355229264646770018071590502441702787269097973979899837683122194103110089728425676690246091146993955037918425772840022288222832932542516091501149477160856564464376910293230091963573119230648026667896399352790982611957569978972038178519570278447540707502861678502657905192743225893225663994807568918644898273702285483676385717651104042002105352993176512166420085064452431753181365805833548922676748890412420332694609096819779765600345216390394307257556778223743443958983962113723193551247897995423762348092103893683711373897139168289420267660611409947644548715007787832959251167553175096639147674776117973100447903243626902892382263767591328038235708593401563793019418124453166386471792468421003855894206584354731489363668134077946203546067237235657746480296831651791790385981397558458905904641394246279782746736009101862366868068363411976388557697921914317179371206444085390779634831369723370050764678852846779369497232374780691905280992368079762747352245519607264154197148958896955661904214909184952289996142050604821608749900417845137727596903100452350067551305840998280482775209883278873071895588751811462342517825753493814997918418437455474992422243919549967371964423457440287296270855605850954685912644303354019058716916735522533065323057755479803668782530250381988211075034655760123250249441440684338450953823290346909689822527652698723502872312570305261196768477498898020793071808758903381796873868682378850925211629392760628685222745073544116615635557910805357623590218023715832716372532519372862093828545797325567803691998051785156065861566888871461130133522039321843439017964382030080752476709398731341173062430275003111954907627837208488348686666904765710656917706470924318432160155450726007668035494571779793129212242101293274853237850848806152774463689243426683295884648680790240363097015218347966399166380090370628591288712305133171869639679922854066493076773166970190482988828017031016891561971986279675371963020932469337264061317786330566839383989384760935590299287963546863848119999451739548405124001514033096695605580766121611440638549988895970262425133218159848061727217163487131806481686766843789971465247903534853837951413845786667122427182648989156599529647439419553785158561613114023267303869927565170507781782366447011340851258178534101585950081423437703778492347448230473897643505773957385504112182446690585033823747175966929091293693201061858670141209129091452861292276276012910624071241165402089161606944423826245461608594935732481900198240862293409442308800690019550831630479883000579884614601906961723011354449804576794339826056986957680090916046848673419723529694384653809400377218545075269148766129194637039408225515678013332188074997217667835494940043014917877438354902673107453164275280010251040360040937308738925689475725131639032011979009642713542292894219059352972933151112376197383814925363288670995556269447804994925086791728136906693249507115097807060365872110998210768336078389508724184863597285987736912073071980137162590779664675033429119327855307827174673749257462983054221631797527009987595732460222197367608440973488211898471439302051388806818521659685873672383828021329848153410204926607710971678268541677584421695238011784351386047869158787156634630693872428067864980320063293435887574745859067024988485742353278548704467544298793511583587659713711677065792371199329419372392720321981862269890024832348999865449339856339220386853162641984444934998176248821703154774794026863423846665361147912580310179333239849314145158103813724371277156031826070213656189218428551171492579367736652650240510840524479280661922149370381404863668038229922105064658335083314946842545978050497021795217124947959575065471749872278802756371390871441004232633252611825748658593540667831098874027223327541523742857750954119615708541514145110863925049204517574000824797900817585376961462754521495100198829675100958066639531958106704159717265035205597161047879510849900587565746603225763129877434317949842105742386965886137117798642168190733367414126797929434627532307855448841035433795229031275545885872876848846666666475465866905332293095381494096702328649920740506658930503053162777944821433383407283155178707970906458023827141681140372968356084617001053870499079884384019820875585843129082894687740533946763756846924952825251383026364635539377880784234770789463152435704464616uwb;
+constexpr unsigned _BitInt(16319) b
+ = 20129744567093027275741005070628998262449166046517026903695683755854448756834360166513132405078796314602781998330705368407367482030156637206994877425582250124595106718397028199112773892105727478029626122540718672466812244172521968825004812596684190534400169291245019886664334632347203172906471830047918779870667296830826108769036384267604969509336398421516482677170697323144807237345130767733861415665037591249948490085867356183319101541167176586195051721766552194667530417142250556133895688441663400613014781276825394358975458967475147806589013506569415945496841131100738180426238464950629268379774013285627049621529192047736803089092751891513992605419086502588233332057296638567290306093910878742093500873864277174719410183640765821580587831967716708363976225535905317908137780497267444416760176647705834046996010820212494244083222254037700699529789991033448979912128507710343500466786839351071045788239200231971288879352062329627654083430317549832483148696514166354870702716570783257707960927427529476249626444239951812293100465038963807939297639901456086408459677292249078230581624034160083198437374539728677906306289960873601083706201882999243554025429957091619812945018432503309674349427513057767160754691227365332241845175797106713295593063635202655344273695438810685712451003351469460085582752740414723264094665962205140763820691773090780866423727990711323748512766522537850976590598658397979845215595029782750537140603588592215363608992433922289542233458102634259275757690440754308009593855238137227351798446486981151672766513716998027602215751256719370429397129549459120277202327118788743080998483470436192625398340057850391478909668185290635380423955404607217710958636050373730838469336370845039431945543326700579270919052885975364141422331087288874462285858637176621255141698264412903522678033317989170115880081516284097559300133507799471895326457336815172421155995525168781635131143991136416642016744949082321204689839861376266795485532171923826942486502913400286963940309484507484129423576156798044985198780159055788525538310878089397895175129162099671894337526801235280427428321205321530735108239848594278720839317921782831352363541199919557577597546876704462612904924694431903072332864341465745291866718067601041404212430941956177407763481845568339170224196193106463030409080073136605433869775860974939991008596874978506245689726966715206639438259724689301019692258116991317695012205036157177039536905494005833948384397446492918129185274359806145454148241131925838562069991934872329314452016900728948186477387223161994145551216156032211038319475270853818660079065895119923373317496777184177315345923787700803986965175033224375435249224949151191006574511519055220741174631165879299688118138728380219550143006894817522270338472413899079751917314505754802052988622174392135207139715960212346858882422543222621408433817817181595201086403368301839080592455115463829425708132345811270911456928961301265223101989524481521721969838980208647528038509328501705428950749820080720418776718084142086501267418284241370398868561282277848391673847937247873117719906103441015578245152673184719538896073697272475250261227685660058944107087333786104761624391816175414338999215260190162551489343436332492645887029551964578826432156700872459216605843463884228343167159924792752429816064841479438134662749621639560203443871326810129872763539114284811330805213188716333471069710270583945841626338361700846410927750916663908367683188084193258384935122236639934335284160522042065088923421928660724095726039642836343542211473282392554371973074108770797447448654428325845253304889062021031599531436606775029315849674756213988932349651640552571880780461452187094400408403309806507698230071584809861634596000425300485805174853406774961321055086995665513868382285048348264250174388793184093524675621762558537763747237314473883173686633576273836946507237880619627632543093619281096675643877749217588495383292078713230253993525326209732859301842016440189010027733234997657748351253359664018894197346327201303258090754079801393874104215986193719394144148559622409051961205332355846077533183278890738832391535561074612724819789952480872328880408266970201766239451001690274739141595541572957753788951050043026811943691163688663710637928472363177936029259448725818579129920714382357882142208643606823754520733994646572586821541644398149238544337745998203264678454665487925173493921777764033537269522992103115842823750405588538846833724101543165897489915300004787110814394934465518176677482202804123781727309993329004830726928892557850582806559007396866888620985629055058474721708813614135721948922060211334334572381348586196886746758900465692833094336637178459072850215866106799456460266354416689624866015411034238864944123721969568161372557215009049887790769403406590484422511214573790761107726077762451440539965975955360773797196902546431341823788555069435728043202455375041817472821677779625286961992491729576392881089462100341878uwb
+ / 42uwb;
+constexpr unsigned _BitInt(16319) c
+ = 26277232382028447345935282100364413976442241120491848683780108318345774920397366452596924421335605374686659278612312801604887370376076386444511450318895545695570784577285598906650901929444302296033412199632594998376064124714220414913923213779444306833277388995703552219430575080927111195417046911177019070713847128826447830096432003962403463656558600431115273248877177875063381111477888059798858016050213420475851620413016793445517539227019973682699447952322388748860981947593432985730684746088183583225184347825110697327973294826205227564425769950503423435597165969299975681406974619941538502827193742760455245269483134360940023933986344217577102114800134253879530890064362520368475535738854741806292542624386473461274620987891355541987873664157022522167908591164654787501854546457737341526763516705032705254046172926268968997302379261582933264475402063191548343982201230445504659038868786347667710658240088825869575188227013335559298579845948690316856611693386990691782821847535492639223427223360712994033576990398197160051785889033125034223732954451076425681456628201904077784454089380196178912326887148822779198657689238010492393879170486604804437202791286852035982584159978541711417080787022338893101116171974852272032081114570327098305927880933671644227124990161298341841320653588271798586647749346370617067175316167393884414111921877638201303618067479025167446526964230732790261566590993315887290551248612349150417516918700813876388862131622594037955509016393068514645257179527317715173019090736514553638608004576856188118523434383702648256819068546345047653068719910165573154521302405552789235554333112380164692074092017083602440917300094238211450798274305773890594242881597233221582216100516212402569681571888843321851284369613879319709906369098535804168065394213774970627125064665536078444150533436796088491087726051879648804306086489894004214709726215682689504951069889191755818331155532574370572928592103344141366890552816031266922028893616252999452323417869066941579667306347161357254079241809644500681547267163742601555111699376923690500014172294337681007418735910341792131377741308586228268385825579773985382339854821729670313925456724869607910114957040810377671394779834675225181536565444830551924417794139736686594557660483813045525089850285373756403594900392226296617656189774567019900237644329891280192776067340109751100025818473155267503490628146429306493520953677660612094758307190480072039980575323428994009982415676875786338343681850769724258724712947129844865182522700509869810541147515988955709784790248266593581532414091983670376426534289079098742549505127694160521110700035496658932724007621759500091227595477831200325335242614162624218010753586306794482732500765136299548052958345872488446969032973871418565484570096440609125401439516349061951073344772753817168731533186740449206533184858409824331269879276752302819075938894191764603880669059804914705202932220114574769307945938446355744093058483466098741029671133305308451601510124097336668044362140994842230895354232007936193610666215236351383330719496758577095102466235782700820575938453736277546445932135116947993404356975890051717304128693125699951445791328843668647245439797933691355015781238038148597339831348341049751957204680813855138272253234219030458164179195368888878989362640509486440530112337687890165646824152338885218611665567933423652236621168833497594762922586523151554244316284075364923316223457798336995440229801638249044555841786652868778333857626201712694823945146208412572567947403078655159448178467488335673853886982143607843369103504905837049147006413324087204923968347162406372146304110247436210704329838033967549296094708909042352807942165389054391217609084676765464997803900415653278041220586434133698802658726748950122980183615091029049242919298428066745937148593879994539254240070220900694662200741796632687373414952817000938093930497338259168439649970963774406833411431113922194082765390241161715106142638681072839764035976877223152727829248475639970029777900589595383604989099084081251802305001465530685587689066710306032849298712531664047230963409638484129598076118133347670029704549206295184751171783054889490211218045322681317529569999778899567668829982207035948032411418382057247326141072264502161892285323531743728756335449414720326329614400327415751813608405440522389476951223717685562226240221655814783640319063683104993438443847695342093582440489676230855515734722099028773790309518629302472390856918840009781940193713784596688294176313226823907143925396584175086934911386332502448539920116580493698106175151294846382915609543814748269873022997601962804377576934064368480060369871027634248583037300264157126892396407333810094970488786868749240778818119777818968060847669660858189435863648299750130319878885182309492320093569553086644726783916663680961005542160003603514646606310756647257217877792590840884087816175376150368236330721380807047180835128240716072193739218623529235235449408073833764uwb
+ >> 171;
+static_assert (a == 10403542085759133691203342137159028259461894955438331210801665800234672962180907518788681055608925051917190662144445433835595489501570265148539013616306519011285861864113638610998587283343748668959870044400340187367869274012726759732348878437230149364081610941398977036594823591463255731808309715219781556045092524781748798096243155527048746090614751043610821560662864236720952557147844731917800712343725546175449104075627616077829385396994452199410766816558008090921987787438967590914249326913953731957899714113110918563882837045448642562338486517475793442626878243475178869958697311252767202125088496235928130685145568023992654921893286093433280015789621699281948053130963767216950901322064090115301029360256916486236324346980555378227825665231041206505932451054100655891377307183657244188881780309602697733965633806548575793711470844175477213922050584861112947113328821094578714380110663964395764964375008963336325761662071121014767368961020824065775639039724097407257977371623360602667242992626829630277589757195892131842788347638167481783472539736593840645020141666099662762763659119482517961624374850646183224354529879255694192077493038699570091875155722960929748259201284457182471153956119946261637096783796538046622701136421992223281799392319105563566498086105138357131671079600937329401554014025354725298453142629483842874038291307431207948198280389112036878226218928165845324560374437065373122000792930554833265840423016148390974876479752688661617125284208020330726704780298561478529279775092768807953202013307072084373090254748865483609183726295735240865516817482898554990450888147008484162850924835809973020042760450232447237837196378388135483084055028396408249214425019231777824054821326738728924661602608905318664721047678808734917923923121217803736039325080641571812479260200189082647677675380297657174607422686495562781202604884582727406463545308236800937463493199421020490845203940782000643133713413924683795888948837880891750307666957538835987772265423203470320354145742841869795472799186154631385288573730129094228733379855432514817031425884584962254283999586850250406406681047191820544352342046667950146374296364655891915135310082529994904874562441551527081311638121766367661807914647092917287784017613115795691373814041086838720316968010349263776702775009771662737124600992709418630470128579612748138807983617697487500079502839532266478317788699680283395230308668613168191852557234122469290277763000256531531071762280960597416576452124575885006363492171314551026369237325119844147154972582617127637240421323781252125819313268498872048683068789228870983086306586111793007178693570562554975762384431236664489360478109692520183356042112794589756922036102025380888246082763911915622037570736969677850621708281909652070776450422110772285659921383413532725137107621514770958361581240471968542997294446402584844918179956881219978405772785713402046471903103404871352324277109089891640558983922159359479964068994923538490500501798825116238188381267330618026093160290205596669795981834842352271011063939632623926629960113926326029952143452354640614061049438932665467928443113232214498101774523178129020155017228802221901469548072234073334681052461327832268955923701109732874360984002493130025470753861967432493102395766279717815113135763810886216491770265724160887688887515282293447287121039545323777928286876711267049135547760773655845950622676327972280622345486253084626121247885891757458308974259466441284967765824561478351421051923081842594791616249682768594796413184742007504540382141773556098929461233842797978566466734240436032269122908057438314319410489575244845739320693764798687398942275314333361838560358278583766983210126081046020231469705836544611252075187733112560778125560225565803349953151880800601890382648216375737077015744684142132303864494083237680306898134033570758401131735819237730280209424231954121970154195575070728876653187928423918894211617093567094857926079694003950142962763480728907322409338954277493711834363423032309296862081371923061150409402403668284066920335645815769603890931600189625120845560771835017710222988445713995722670892970377791415975424998772977793133120924108755323766471601770964843725827421304729349535336212587039242582503381150992918495310760366078232133800372960134691178665615437284018675587037783965019497398984583781291648236566997741116811234934754542646608973862932050896956712947890625239848619289180051302224085308716715734850608995498117691600907423641124622236235949675965926735290984369155077055324647942699875972019355174794849379024365265476001505043957802797349447782453767742359446787304217770032967959809288342189111153359045680464231699344620995535326063943372491385550455978845273436611631962336651743357242055102619760848116407351488643448217122169718350824452317641509534606434395208225350712889271762643740106849245478364448395994915755050465135468245061369394410933866013068008514339549345174558881983866497072827311379042433413uwb);
+static_assert (b == 479279632549833982755738215967357101486884905869453021516563898948915446591294289678884104882828483681018619007873937343032559095956110409690354224418625002966550159961834004740780330764422082810229193393826635058733624861250523067262019347540099774628575459315357616349150824579695313640630281667807589996920649924543478780215152006371546893079438057655154349456445174360590648508217399231758605134881847410713059287758746575793311941456361347290358374327775052253988819455767870384140373534325319062214637649448223675213701403987503519204500321584986093940400979311922337629196153927395934961423190792514929752893552191612781025930779806940809347748073488156862698382316586632554531097474068541478416687472958980350462147229542043370966376951612302580094672036569174235908042392792082009922861348754900810642762162386011767716267196524707159512614047405558309045526869231198654773018734270263596328291409529332649735222668150705420335319769465472201979730869384913211207207537399601373999069700655463720229201053332186006978582500927709712840419997653716343058563745053549481680514857956192457105651774755444712054911665735085740088242901976172465572034046597419519355833772202459754151176845548994456208445029222984100996313709454921745133168181790539412958897510447873469344071508368320478228160779533683887240349189576312875329064089835494782533898285493126755916970631488996451823585682342809043933704643566255965170014371156957508657356962712435465291272811967482363708516439065578762133187029479457794090439202070979801732536040880905419100375029921889772128503084510931435171483979018779597166630558819909348223770001377390273307373052030729413819617985823981374070443715485088829487365151686786653141560555397632839783786973475603908129103121125925582435377586599443363217659482486021512444715078999742145616192417054383275221431750185701711793487079447980295741809417265923372265027237884200396238493927359102885825948568128006352273465051712472070059202450319054451522388321059702003081513718019001071076161432358471155369959782811652330837503075288087426055655400029411438748293362031465017502577139252244731448555188613876936961036695236179942323751116112011014592974397486473882674592008130136792663493287323834319147915022427528033518178139180198551672004671264439595962120954122300129377851806213689047404966592261393005849755403969409681891387136302126214754577574214078992738385834194218500941354892714424617818676129678402812599649389519193939384481931712519965763571236544579269391714688112594004439937791027666527275028956096005024721892268353662349049501568931426746983749923266289936079664852088114380642027976981532748458314879741695023966059798072743350980348361092364278288527112580481417860547783209941006436630295569025708378983678708447667928300527961717504931897999052674925211486251029110033534138519456704647644914365911948549537915597987234033945431722519315974082307832411934886264333083916226707665948547147824941143774031630992986403589281430493343304207573431954440506367102005746914258775268625663056944615427077330312326664431034309894720122682694874274735620802316011315482410182991906165335883031756812018133914090861319389023790839528337203606889129436487920140167370284870924438860873830296648014424844378195912932551426780779819757525353368558050825303562419989528653425507781193568399131883673447888828695552112293654073088339775808234324436627659543962164946450396759723040075906766506152022264815158093674649622869572430121164843379253826764183953324829436751005035078152203675523168431161209463034491772102996315554878311000500752369796109685119745615468446576523546008325039060775520970963367909216533343057221662059707100715990114520515109428581554773471551782223970832412406073499896797949247197263055911053575580685552002226777990994346631851517791364630330551754443656577948498726362806681419705536740324268597539896282803552799726080554573302695958428417269671660306173853381343814024048279362738039470198839365706286164147555864933364363287875097138128425573909904433183795098670203800533548856219174579901097084123411402160448390274656216062207733804522678116007830485911118338137291415500040244636646228465275546613185451215477214924093897408659253897872331630294361379429268082112519489979283826532913282908147824847781517964779380824918394924322420104717839012960422523766744397106063463998218416521947089619846125464833145312281971994057275917591591279145274837283273569411904875883590818927011083766111368623876288661469697856984023924541117354584710728162060928747544449729071086406072820826707352705098469570212430005031769870770984490147544922541878582516496026055634218534739829767044431114272772863484628968800592047985977005687260574374332608765746965647976405949709304033414442630581488362251756922883517287565772653346189666094175256518980878632057889091042584644510374477219106080358138511257658994752983022904583136418485544787844335722425uwb);
+static_assert (c == 8779107423697189837569390605084121179785924908521985744210325591223667924519652625818373720019509245903707006132632572173386255064201355735198759440688262514780984111791042739566301784897316373994922192050963272288434060342288511971569697680026523760811225516430052699754044682818892679819131995600216280966062736732384732411361657444399695883865096103428759622813867735547259978529319436889864013687219390567604283318011100799953451520968441264866031813954488628058475114348729275414143158917874709599556247183695853838552321088973445876088042556810479910661449374661999675082811103814453353294194886612961492737263277271551889038610730760478459569256149321998350414023066363814989311109728311712989022996247280182587921449185353922885937877604500400738774240008709945289791605011177739657720181601453512259882004564462415828652714904289727235210537277721389816687643366145200001177712112197515695578887483792988755435401388456145854488880537088360397994643216014828495662460205686448548113229841097955613958440901375416256532864511852298696327611517233241324799070919491286426159788792631723833717451538043437364017185237743182402835670087683125602640318887451596650323528720128188198547270462971612157603487958526705005955580409441670771849388016438035850194585870327013409236236730914217722025655319472231141666790287955685713636274653565577454275838590350806168639165264676470440930351612992518904664647715805865941038423768376846697817543122409517591717292238745940345900530458551468519245767864531742102178628854376524513367983209186974575765707273973775386840081238803880335095740836386527208267311808973522450391189055739828936937359693167240524660624945856907042041257347192086984009640984509322622503890256046324768341632643546455779035376002061691113121234273164937984171774242327769915688742564049454163158318121818582764775268091292470889088445575108022688069271697198283151469645400870507006663799330661702702747443254220478311056407220749648103123435473381583520873055218734115120978678440455896458852497569989966723235965608706826593607128847630137618509151255834742636438796285569873869967729341871213521030011427372987388572674228441333458857512226049283243347521457804912008781036966786374760325341492033297848368160903260470019067535330611645909560888797451907088389764190403007998305168673029446934012245138838180596098559442570696150011296218144186387024615885302290744905340666905921743970013779813332493771192048043297281423248489056841417013807670308191095732464221451376997270745468459702152796818222745730565721202663103043121160101459833683249558684459108862536961994308535039970814557821268170388745941980378838969910592895670554291811739768771829941043857819603751246957962236091154755893962038363120690483862423001038948620681611253867149296463690417828034303547922792249098522404751428960713875050463906134150846089705714470303918299012691600285355859412924847760497076978432722446602521825089097454542343354847347396045079587757210635356999268706465425788833311190517623061860675230010994127196459030322166751571656642321690787471906609473496034789643710478162255664092991251446787887635351852933826820719781733754578161073401362668109819113924252291125741395271474342305574536974918273938513597418963787308994593434191890687730302495910686072338836413159162281072263542758257699588089838677469397467899348065293581751035844389848387161847435160327276066603683131703246410409122832793376751512688745195564021646069245992363396468100513536211651450610523315211697125774638845313243973083536417692075962486918844667432144353019722959653638632948294049984266861870151255315023346724671430499257993958049088066160870545025276597975154855537620265690354041028742742755074396597631965320380782500944568424053420038357524917125099241334990032189526465838192972110970861380060986802081948044345526414857158569939005895236672306344348212805851269920711043891306875873016330601673973249327072503571873518366750575070091051288590764788630190966776854031578939382690709022667421734442841784680826494146620589862829612704279521637740421694195051400095278084716974624615208392585573200182664157066813849346058321763156523965698465901396025152159642193562900743812715885811057212579017860488539960334406702752688595217360219470968738009774067915037157027492209108801337707562571266897723911401203374308490793226200974353356835311756384895692909802720948968131504604855466961987314701846460342135201914356152591684810924688350929140120187693089324255924634578576427004426339299493833434502951593902551451002292839635000904253250021884625417628756439862964325562720709528784964868687330847894476999577326582332350213148861205413652337499383416531545707272907994755638339630221576707954964236210962693804639714754668679841134928393081284209158098202683744650513918920168330598432362389777471870631039488408769354863001967531729415686631571754649uwb);
+#endif
diff --git a/gcc/tree-affine.cc b/gcc/tree-affine.cc
index ecab467..eff38f0 100644
--- a/gcc/tree-affine.cc
+++ b/gcc/tree-affine.cc
@@ -805,6 +805,7 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
continue;
}
exp = XNEW (class name_expansion);
+ ::new (static_cast<void *> (exp)) name_expansion ();
exp->in_progress = 1;
if (!*cache)
*cache = new hash_map<tree, name_expansion *>;
@@ -860,6 +861,7 @@ tree_to_aff_combination_expand (tree expr, tree type, aff_tree *comb,
bool
free_name_expansion (tree const &, name_expansion **value, void *)
{
+ (*value)->~name_expansion ();
free (*value);
return true;
}
diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
index e048675..1a555ae 100644
--- a/gcc/tree-ssa-ccp.cc
+++ b/gcc/tree-ssa-ccp.cc
@@ -1966,7 +1966,8 @@ bit_value_binop (enum tree_code code, signop sgn, int width,
}
else
{
- widest_int upper = wi::udiv_trunc (r1max, r2min);
+ widest_int upper
+ = wi::udiv_trunc (wi::zext (r1max, width), r2min);
unsigned int lzcount = wi::clz (upper);
unsigned int bits = wi::get_precision (upper) - lzcount;
*mask = wi::mask <widest_int> (bits, false);
diff --git a/gcc/tree-ssa-loop-ivcanon.cc b/gcc/tree-ssa-loop-ivcanon.cc
index 1330cf8..5856f76 100644
--- a/gcc/tree-ssa-loop-ivcanon.cc
+++ b/gcc/tree-ssa-loop-ivcanon.cc
@@ -622,10 +622,11 @@ remove_redundant_iv_tests (class loop *loop)
|| !integer_zerop (niter.may_be_zero)
|| !niter.niter
|| TREE_CODE (niter.niter) != INTEGER_CST
- || !wi::ltu_p (loop->nb_iterations_upper_bound,
+ || !wi::ltu_p (widest_int::from (loop->nb_iterations_upper_bound,
+ SIGNED),
wi::to_widest (niter.niter)))
continue;
-
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Removed pointless exit: ");
diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc
index 339f37d..2c1f084 100644
--- a/gcc/tree-ssa-loop-ivopts.cc
+++ b/gcc/tree-ssa-loop-ivopts.cc
@@ -1036,10 +1036,12 @@ niter_for_exit (struct ivopts_data *data, edge exit)
names that appear in phi nodes on abnormal edges, so that we do not
create overlapping life ranges for them (PR 27283). */
desc = XNEW (class tree_niter_desc);
+ ::new (static_cast<void*> (desc)) tree_niter_desc ();
if (!number_of_iterations_exit (data->current_loop,
exit, desc, true)
|| contains_abnormal_ssa_name_p (desc->niter))
{
+ desc->~tree_niter_desc ();
XDELETE (desc);
desc = NULL;
}
@@ -7894,7 +7896,11 @@ remove_unused_ivs (struct ivopts_data *data, bitmap toremove)
bool
free_tree_niter_desc (edge const &, tree_niter_desc *const &value, void *)
{
- free (value);
+ if (value)
+ {
+ value->~tree_niter_desc ();
+ free (value);
+ }
return true;
}
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index 705bcc0..a0a6b27 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -3873,12 +3873,17 @@ do_warn_aggressive_loop_optimizations (class loop *loop,
return;
gimple *estmt = last_nondebug_stmt (e->src);
- char buf[WIDE_INT_PRINT_BUFFER_SIZE];
- print_dec (i_bound, buf, TYPE_UNSIGNED (TREE_TYPE (loop->nb_iterations))
+ char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
+ unsigned len = i_bound.get_len ();
+ if (len > WIDE_INT_MAX_INL_ELTS)
+ p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+ else
+ p = buf;
+ print_dec (i_bound, p, TYPE_UNSIGNED (TREE_TYPE (loop->nb_iterations))
? UNSIGNED : SIGNED);
auto_diagnostic_group d;
if (warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations,
- "iteration %s invokes undefined behavior", buf))
+ "iteration %s invokes undefined behavior", p))
inform (gimple_location (estmt), "within this loop");
loop->warned_aggressive_loop_optimizations = true;
}
@@ -3915,6 +3920,9 @@ record_estimate (class loop *loop, tree bound, const widest_int &i_bound,
else
gcc_checking_assert (i_bound == wi::to_widest (bound));
+ if (wi::min_precision (i_bound, SIGNED) > bound_wide_int ().get_precision ())
+ return;
+
/* If we have a guaranteed upper bound, record it in the appropriate
list, unless this is an !is_exit bound (i.e. undefined behavior in
at_stmt) in a loop with known constant number of iterations. */
@@ -3925,7 +3933,7 @@ record_estimate (class loop *loop, tree bound, const widest_int &i_bound,
{
class nb_iter_bound *elt = ggc_alloc<nb_iter_bound> ();
- elt->bound = i_bound;
+ elt->bound = bound_wide_int::from (i_bound, SIGNED);
elt->stmt = at_stmt;
elt->is_exit = is_exit;
elt->next = loop->bounds;
@@ -4410,8 +4418,8 @@ infer_loop_bounds_from_undefined (class loop *loop, basic_block *bbs)
static int
wide_int_cmp (const void *p1, const void *p2)
{
- const widest_int *d1 = (const widest_int *) p1;
- const widest_int *d2 = (const widest_int *) p2;
+ const bound_wide_int *d1 = (const bound_wide_int *) p1;
+ const bound_wide_int *d2 = (const bound_wide_int *) p2;
return wi::cmpu (*d1, *d2);
}
@@ -4419,7 +4427,7 @@ wide_int_cmp (const void *p1, const void *p2)
Lookup by binary search. */
static int
-bound_index (const vec<widest_int> &bounds, const widest_int &bound)
+bound_index (const vec<bound_wide_int> &bounds, const bound_wide_int &bound)
{
unsigned int end = bounds.length ();
unsigned int begin = 0;
@@ -4428,7 +4436,7 @@ bound_index (const vec<widest_int> &bounds, const widest_int &bound)
while (begin != end)
{
unsigned int middle = (begin + end) / 2;
- widest_int index = bounds[middle];
+ bound_wide_int index = bounds[middle];
if (index == bound)
return middle;
@@ -4450,7 +4458,7 @@ static void
discover_iteration_bound_by_body_walk (class loop *loop)
{
class nb_iter_bound *elt;
- auto_vec<widest_int> bounds;
+ auto_vec<bound_wide_int> bounds;
vec<vec<basic_block> > queues = vNULL;
vec<basic_block> queue = vNULL;
ptrdiff_t queue_index;
@@ -4459,7 +4467,7 @@ discover_iteration_bound_by_body_walk (class loop *loop)
/* Discover what bounds may interest us. */
for (elt = loop->bounds; elt; elt = elt->next)
{
- widest_int bound = elt->bound;
+ bound_wide_int bound = elt->bound;
/* Exit terminates loop at given iteration, while non-exits produce undefined
effect on the next iteration. */
@@ -4492,7 +4500,7 @@ discover_iteration_bound_by_body_walk (class loop *loop)
hash_map<basic_block, ptrdiff_t> bb_bounds;
for (elt = loop->bounds; elt; elt = elt->next)
{
- widest_int bound = elt->bound;
+ bound_wide_int bound = elt->bound;
if (!elt->is_exit)
{
bound += 1;
@@ -4601,7 +4609,8 @@ discover_iteration_bound_by_body_walk (class loop *loop)
print_decu (bounds[latch_index], dump_file);
fprintf (dump_file, "\n");
}
- record_niter_bound (loop, bounds[latch_index], false, true);
+ record_niter_bound (loop, widest_int::from (bounds[latch_index],
+ SIGNED), false, true);
}
queues.release ();
@@ -4704,7 +4713,8 @@ maybe_lower_iteration_bound (class loop *loop)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Reducing loop iteration estimate by 1; "
"undefined statement must be executed at the last iteration.\n");
- record_niter_bound (loop, loop->nb_iterations_upper_bound - 1,
+ record_niter_bound (loop, widest_int::from (loop->nb_iterations_upper_bound,
+ SIGNED) - 1,
false, true);
}
@@ -4860,10 +4870,13 @@ estimate_numbers_of_iterations (class loop *loop)
not break code with undefined behavior by not recording smaller
maximum number of iterations. */
if (loop->nb_iterations
- && TREE_CODE (loop->nb_iterations) == INTEGER_CST)
+ && TREE_CODE (loop->nb_iterations) == INTEGER_CST
+ && (wi::min_precision (wi::to_widest (loop->nb_iterations), SIGNED)
+ <= bound_wide_int ().get_precision ()))
{
loop->any_upper_bound = true;
- loop->nb_iterations_upper_bound = wi::to_widest (loop->nb_iterations);
+ loop->nb_iterations_upper_bound
+ = bound_wide_int::from (wi::to_widest (loop->nb_iterations), SIGNED);
}
}
@@ -5114,7 +5127,7 @@ n_of_executions_at_most (gimple *stmt,
class nb_iter_bound *niter_bound,
tree niter)
{
- widest_int bound = niter_bound->bound;
+ widest_int bound = widest_int::from (niter_bound->bound, SIGNED);
tree nit_type = TREE_TYPE (niter), e;
enum tree_code cmp;
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 82b793d..89bdcaa 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -11672,7 +11672,7 @@ vect_transform_loop (loop_vec_info loop_vinfo, gimple *loop_vectorized_call)
LOOP_VINFO_VECT_FACTOR (loop_vinfo),
&bound))
loop->nb_iterations_upper_bound
- = wi::umin ((widest_int) (bound - 1),
+ = wi::umin ((bound_wide_int) (bound - 1),
loop->nb_iterations_upper_bound);
}
}
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 850a4de..6fa85cc 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -2676,13 +2676,13 @@ build_zero_cst (tree type)
tree
build_replicated_int_cst (tree type, unsigned int width, HOST_WIDE_INT value)
{
- int n = (TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1)
- / HOST_BITS_PER_WIDE_INT;
+ int n = ((TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1)
+ / HOST_BITS_PER_WIDE_INT);
unsigned HOST_WIDE_INT low, mask;
- HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
+ HOST_WIDE_INT a[WIDE_INT_MAX_INL_ELTS];
int i;
- gcc_assert (n && n <= WIDE_INT_MAX_ELTS);
+ gcc_assert (n && n <= WIDE_INT_MAX_INL_ELTS);
if (width == HOST_BITS_PER_WIDE_INT)
low = value;
@@ -2696,8 +2696,8 @@ build_replicated_int_cst (tree type, unsigned int width, HOST_WIDE_INT value)
a[i] = low;
gcc_assert (TYPE_PRECISION (type) <= MAX_BITSIZE_MODE_ANY_INT);
- return wide_int_to_tree
- (type, wide_int::from_array (a, n, TYPE_PRECISION (type)));
+ return wide_int_to_tree (type, wide_int::from_array (a, n,
+ TYPE_PRECISION (type)));
}
/* If floating-point type TYPE has an IEEE-style sign bit, return an
diff --git a/gcc/tree.h b/gcc/tree.h
index 005c157..e06a5c8 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -6258,13 +6258,14 @@ namespace wi
template <int N>
struct int_traits <extended_tree <N> >
{
- static const enum precision_type precision_type = CONST_PRECISION;
+ static const enum precision_type precision_type
+ = N == ADDR_MAX_PRECISION ? INL_CONST_PRECISION : CONST_PRECISION;
static const bool host_dependent_precision = false;
static const bool is_sign_extended = true;
static const unsigned int precision = N;
};
- typedef extended_tree <WIDE_INT_MAX_PRECISION> widest_extended_tree;
+ typedef extended_tree <WIDEST_INT_MAX_PRECISION> widest_extended_tree;
typedef extended_tree <ADDR_MAX_PRECISION> offset_extended_tree;
typedef const generic_wide_int <widest_extended_tree> tree_to_widest_ref;
@@ -6292,7 +6293,8 @@ namespace wi
tree_to_poly_wide_ref to_poly_wide (const_tree);
template <int N>
- struct ints_for <generic_wide_int <extended_tree <N> >, CONST_PRECISION>
+ struct ints_for <generic_wide_int <extended_tree <N> >,
+ int_traits <extended_tree <N> >::precision_type>
{
typedef generic_wide_int <extended_tree <N> > extended;
static extended zero (const extended &);
@@ -6308,7 +6310,7 @@ namespace wi
/* Used to convert a tree to a widest2_int like this:
widest2_int foo = widest2_int_cst (some_tree). */
-typedef generic_wide_int <wi::extended_tree <WIDE_INT_MAX_PRECISION * 2> >
+typedef generic_wide_int <wi::extended_tree <WIDEST_INT_MAX_PRECISION * 2> >
widest2_int_cst;
/* Refer to INTEGER_CST T as though it were a widest_int.
@@ -6444,7 +6446,7 @@ wi::extended_tree <N>::get_len () const
{
if (N == ADDR_MAX_PRECISION)
return TREE_INT_CST_OFFSET_NUNITS (m_t);
- else if (N >= WIDE_INT_MAX_PRECISION)
+ else if (N >= WIDEST_INT_MAX_PRECISION)
return TREE_INT_CST_EXT_NUNITS (m_t);
else
/* This class is designed to be used for specific output precisions
@@ -6530,7 +6532,8 @@ wi::to_poly_wide (const_tree t)
template <int N>
inline generic_wide_int <wi::extended_tree <N> >
wi::ints_for <generic_wide_int <wi::extended_tree <N> >,
- wi::CONST_PRECISION>::zero (const extended &x)
+ wi::int_traits <wi::extended_tree <N> >::precision_type
+ >::zero (const extended &x)
{
return build_zero_cst (TREE_TYPE (x.get_tree ()));
}
diff --git a/gcc/value-range-pretty-print.cc b/gcc/value-range-pretty-print.cc
index c95b09d..26173b8 100644
--- a/gcc/value-range-pretty-print.cc
+++ b/gcc/value-range-pretty-print.cc
@@ -99,12 +99,19 @@ vrange_printer::print_irange_bitmasks (const irange &r) const
return;
pp_string (pp, " MASK ");
- char buf[WIDE_INT_PRINT_BUFFER_SIZE];
- print_hex (bm.mask (), buf);
- pp_string (pp, buf);
+ char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
+ unsigned len_mask = bm.mask ().get_len ();
+ unsigned len_val = bm.value ().get_len ();
+ unsigned len = MAX (len_mask, len_val);
+ if (len > WIDE_INT_MAX_INL_ELTS)
+ p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+ else
+ p = buf;
+ print_hex (bm.mask (), p);
+ pp_string (pp, p);
pp_string (pp, " VALUE ");
- print_hex (bm.value (), buf);
- pp_string (pp, buf);
+ print_hex (bm.value (), p);
+ pp_string (pp, p);
}
void
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 391cef6..333245e 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -245,17 +245,24 @@ vrange::dump (FILE *file) const
void
irange_bitmask::dump (FILE *file) const
{
- char buf[WIDE_INT_PRINT_BUFFER_SIZE];
+ char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
pretty_printer buffer;
pp_needs_newline (&buffer) = true;
buffer.buffer->stream = file;
pp_string (&buffer, "MASK ");
- print_hex (m_mask, buf);
- pp_string (&buffer, buf);
+ unsigned len_mask = m_mask.get_len ();
+ unsigned len_val = m_value.get_len ();
+ unsigned len = MAX (len_mask, len_val);
+ if (len > WIDE_INT_MAX_INL_ELTS)
+ p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+ else
+ p = buf;
+ print_hex (m_mask, p);
+ pp_string (&buffer, p);
pp_string (&buffer, " VALUE ");
- print_hex (m_value, buf);
- pp_string (&buffer, buf);
+ print_hex (m_value, p);
+ pp_string (&buffer, p);
pp_flush (&buffer);
}
diff --git a/gcc/value-range.h b/gcc/value-range.h
index a792c59..c00b151 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -626,7 +626,9 @@ irange::maybe_resize (int needed)
{
m_max_ranges = HARD_MAX_RANGES;
wide_int *newmem = new wide_int[m_max_ranges * 2];
- memcpy (newmem, m_base, sizeof (wide_int) * num_pairs () * 2);
+ unsigned n = num_pairs () * 2;
+ for (unsigned i = 0; i < n; ++i)
+ newmem[i] = m_base[i];
m_base = newmem;
}
}
diff --git a/gcc/wide-int-print.cc b/gcc/wide-int-print.cc
index f3a1871..ea6840b 100644
--- a/gcc/wide-int-print.cc
+++ b/gcc/wide-int-print.cc
@@ -74,9 +74,12 @@ print_decs (const wide_int_ref &wi, char *buf)
void
print_decs (const wide_int_ref &wi, FILE *file)
{
- char buf[WIDE_INT_PRINT_BUFFER_SIZE];
- print_decs (wi, buf);
- fputs (buf, file);
+ char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
+ unsigned len = wi.get_len ();
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+ print_decs (wi, p);
+ fputs (p, file);
}
/* Try to print the unsigned self in decimal to BUF if the number fits
@@ -98,9 +101,12 @@ print_decu (const wide_int_ref &wi, char *buf)
void
print_decu (const wide_int_ref &wi, FILE *file)
{
- char buf[WIDE_INT_PRINT_BUFFER_SIZE];
- print_decu (wi, buf);
- fputs (buf, file);
+ char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
+ unsigned len = wi.get_len ();
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+ print_decu (wi, p);
+ fputs (p, file);
}
void
@@ -134,9 +140,12 @@ print_hex (const wide_int_ref &val, char *buf)
void
print_hex (const wide_int_ref &wi, FILE *file)
{
- char buf[WIDE_INT_PRINT_BUFFER_SIZE];
- print_hex (wi, buf);
- fputs (buf, file);
+ char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
+ unsigned len = wi.get_len ();
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+ print_hex (wi, p);
+ fputs (p, file);
}
/* Print larger precision wide_int. Not defined as inline in a header
diff --git a/gcc/wide-int-print.h b/gcc/wide-int-print.h
index 5aca037..a69cd5f 100644
--- a/gcc/wide-int-print.h
+++ b/gcc/wide-int-print.h
@@ -22,7 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include <stdio.h>
-#define WIDE_INT_PRINT_BUFFER_SIZE (WIDE_INT_MAX_PRECISION / 4 + 4)
+#define WIDE_INT_PRINT_BUFFER_SIZE (WIDE_INT_MAX_INL_PRECISION / 4 + 4)
/* Printing functions. */
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index 81b7be8..6212a90 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -51,7 +51,7 @@ typedef unsigned int UDWtype __attribute__ ((mode (TI)));
#include "longlong.h"
#endif
-static const HOST_WIDE_INT zeros[WIDE_INT_MAX_ELTS] = {};
+static const HOST_WIDE_INT zeros[1] = {};
/*
* Internal utilities.
@@ -62,8 +62,7 @@ static const HOST_WIDE_INT zeros[WIDE_INT_MAX_ELTS] = {};
#define HALF_INT_MASK ((HOST_WIDE_INT_1 << HOST_BITS_PER_HALF_WIDE_INT) - 1)
#define BLOCK_OF(TARGET) ((TARGET) / HOST_BITS_PER_WIDE_INT)
-#define BLOCKS_NEEDED(PREC) \
- (PREC ? (((PREC) + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT) : 1)
+#define BLOCKS_NEEDED(PREC) (PREC ? CEIL (PREC, HOST_BITS_PER_WIDE_INT) : 1)
#define SIGN_MASK(X) ((HOST_WIDE_INT) (X) < 0 ? -1 : 0)
/* Return the value a VAL[I] if I < LEN, otherwise, return 0 or -1
@@ -96,7 +95,7 @@ canonize (HOST_WIDE_INT *val, unsigned int len, unsigned int precision)
top = val[len - 1];
if (len * HOST_BITS_PER_WIDE_INT > precision)
val[len - 1] = top = sext_hwi (top, precision % HOST_BITS_PER_WIDE_INT);
- if (top != 0 && top != (HOST_WIDE_INT)-1)
+ if (top != 0 && top != HOST_WIDE_INT_M1)
return len;
/* At this point we know that the top is either 0 or -1. Find the
@@ -163,7 +162,7 @@ wi::from_buffer (const unsigned char *buffer, unsigned int buffer_len)
/* We have to clear all the bits ourself, as we merely or in values
below. */
unsigned int len = BLOCKS_NEEDED (precision);
- HOST_WIDE_INT *val = result.write_val ();
+ HOST_WIDE_INT *val = result.write_val (0);
for (unsigned int i = 0; i < len; ++i)
val[i] = 0;
@@ -232,8 +231,7 @@ wi::to_mpz (const wide_int_ref &x, mpz_t result, signop sgn)
}
else if (excess < 0 && wi::neg_p (x))
{
- int extra
- = (-excess + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT;
+ int extra = CEIL (-excess, HOST_BITS_PER_WIDE_INT);
HOST_WIDE_INT *t = XALLOCAVEC (HOST_WIDE_INT, len + extra);
for (int i = 0; i < len; i++)
t[i] = v[i];
@@ -280,8 +278,8 @@ wi::from_mpz (const_tree type, mpz_t x, bool wrap)
extracted from the GMP manual, section "Integer Import and Export":
http://gmplib.org/manual/Integer-Import-and-Export.html */
numb = CHAR_BIT * sizeof (HOST_WIDE_INT);
- count = (mpz_sizeinbase (x, 2) + numb - 1) / numb;
- HOST_WIDE_INT *val = res.write_val ();
+ count = CEIL (mpz_sizeinbase (x, 2), numb);
+ HOST_WIDE_INT *val = res.write_val (0);
/* Read the absolute value.
Write directly to the wide_int storage if possible, otherwise leave
@@ -289,7 +287,7 @@ wi::from_mpz (const_tree type, mpz_t x, bool wrap)
to use mpz_tdiv_r_2exp for the latter case, but the situation is
pathological and it seems safer to operate on the original mpz value
in all cases. */
- void *valres = mpz_export (count <= WIDE_INT_MAX_ELTS ? val : 0,
+ void *valres = mpz_export (count <= WIDE_INT_MAX_INL_ELTS ? val : 0,
&count, -1, sizeof (HOST_WIDE_INT), 0, 0, x);
if (count < 1)
{
@@ -1334,21 +1332,6 @@ wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1val,
unsigned HOST_WIDE_INT o0, o1, k, t;
unsigned int i;
unsigned int j;
- unsigned int blocks_needed = BLOCKS_NEEDED (prec);
- unsigned int half_blocks_needed = blocks_needed * 2;
- /* The sizes here are scaled to support a 2x largest mode by 2x
- largest mode yielding a 4x largest mode result. This is what is
- needed by vpn. */
-
- unsigned HOST_HALF_WIDE_INT
- u[4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
- unsigned HOST_HALF_WIDE_INT
- v[4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
- /* The '2' in 'R' is because we are internally doing a full
- multiply. */
- unsigned HOST_HALF_WIDE_INT
- r[2 * 4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
- HOST_WIDE_INT mask = ((HOST_WIDE_INT)1 << HOST_BITS_PER_HALF_WIDE_INT) - 1;
/* If the top level routine did not really pass in an overflow, then
just make sure that we never attempt to set it. */
@@ -1469,6 +1452,37 @@ wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1val,
return 1;
}
+ /* The sizes here are scaled to support a 2x WIDE_INT_MAX_INL_PRECISION by 2x
+ WIDE_INT_MAX_INL_PRECISION yielding a 4x WIDE_INT_MAX_INL_PRECISION
+ result. */
+
+ unsigned HOST_HALF_WIDE_INT
+ ubuf[4 * WIDE_INT_MAX_INL_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
+ unsigned HOST_HALF_WIDE_INT
+ vbuf[4 * WIDE_INT_MAX_INL_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
+ /* The '2' in 'R' is because we are internally doing a full
+ multiply. */
+ unsigned HOST_HALF_WIDE_INT
+ rbuf[2 * 4 * WIDE_INT_MAX_INL_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
+ const HOST_WIDE_INT mask
+ = (HOST_WIDE_INT_1 << HOST_BITS_PER_HALF_WIDE_INT) - 1;
+ unsigned HOST_HALF_WIDE_INT *u = ubuf;
+ unsigned HOST_HALF_WIDE_INT *v = vbuf;
+ unsigned HOST_HALF_WIDE_INT *r = rbuf;
+
+ if (!high)
+ prec = MIN ((op1len + op2len + 1) * HOST_BITS_PER_WIDE_INT, prec);
+ unsigned int blocks_needed = BLOCKS_NEEDED (prec);
+ unsigned int half_blocks_needed = blocks_needed * 2;
+ if (UNLIKELY (prec > WIDE_INT_MAX_INL_PRECISION))
+ {
+ unsigned HOST_HALF_WIDE_INT *buf
+ = XALLOCAVEC (unsigned HOST_HALF_WIDE_INT, 4 * 4 * blocks_needed);
+ u = buf;
+ v = u + 4 * blocks_needed;
+ r = v + 4 * blocks_needed;
+ }
+
/* We do unsigned mul and then correct it. */
wi_unpack (u, op1val, op1len, half_blocks_needed, prec, SIGNED);
wi_unpack (v, op2val, op2len, half_blocks_needed, prec, SIGNED);
@@ -1782,16 +1796,6 @@ wi::divmod_internal (HOST_WIDE_INT *quotient, unsigned int *remainder_len,
unsigned int divisor_prec, signop sgn,
wi::overflow_type *oflow)
{
- unsigned int dividend_blocks_needed = 2 * BLOCKS_NEEDED (dividend_prec);
- unsigned int divisor_blocks_needed = 2 * BLOCKS_NEEDED (divisor_prec);
- unsigned HOST_HALF_WIDE_INT
- b_quotient[4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
- unsigned HOST_HALF_WIDE_INT
- b_remainder[4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
- unsigned HOST_HALF_WIDE_INT
- b_dividend[(4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT) + 1];
- unsigned HOST_HALF_WIDE_INT
- b_divisor[4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
unsigned int m, n;
bool dividend_neg = false;
bool divisor_neg = false;
@@ -1910,6 +1914,44 @@ wi::divmod_internal (HOST_WIDE_INT *quotient, unsigned int *remainder_len,
}
}
+ unsigned HOST_HALF_WIDE_INT
+ b_quotient_buf[4 * WIDE_INT_MAX_INL_PRECISION
+ / HOST_BITS_PER_HALF_WIDE_INT];
+ unsigned HOST_HALF_WIDE_INT
+ b_remainder_buf[4 * WIDE_INT_MAX_INL_PRECISION
+ / HOST_BITS_PER_HALF_WIDE_INT];
+ unsigned HOST_HALF_WIDE_INT
+ b_dividend_buf[(4 * WIDE_INT_MAX_INL_PRECISION
+ / HOST_BITS_PER_HALF_WIDE_INT) + 1];
+ unsigned HOST_HALF_WIDE_INT
+ b_divisor_buf[4 * WIDE_INT_MAX_INL_PRECISION
+ / HOST_BITS_PER_HALF_WIDE_INT];
+ unsigned HOST_HALF_WIDE_INT *b_quotient = b_quotient_buf;
+ unsigned HOST_HALF_WIDE_INT *b_remainder = b_remainder_buf;
+ unsigned HOST_HALF_WIDE_INT *b_dividend = b_dividend_buf;
+ unsigned HOST_HALF_WIDE_INT *b_divisor = b_divisor_buf;
+
+ if (sgn == SIGNED || dividend_val[dividend_len - 1] >= 0)
+ dividend_prec = MIN ((dividend_len + 1) * HOST_BITS_PER_WIDE_INT,
+ dividend_prec);
+ if (sgn == SIGNED || divisor_val[divisor_len - 1] >= 0)
+ divisor_prec = MIN (divisor_len * HOST_BITS_PER_WIDE_INT, divisor_prec);
+ unsigned int dividend_blocks_needed = 2 * BLOCKS_NEEDED (dividend_prec);
+ unsigned int divisor_blocks_needed = 2 * BLOCKS_NEEDED (divisor_prec);
+ if (UNLIKELY (dividend_prec > WIDE_INT_MAX_INL_PRECISION)
+ || UNLIKELY (divisor_prec > WIDE_INT_MAX_INL_PRECISION))
+ {
+ unsigned HOST_HALF_WIDE_INT *buf
+ = XALLOCAVEC (unsigned HOST_HALF_WIDE_INT,
+ 12 * dividend_blocks_needed
+ + 4 * divisor_blocks_needed + 1);
+ b_quotient = buf;
+ b_remainder = b_quotient + 4 * dividend_blocks_needed;
+ b_dividend = b_remainder + 4 * dividend_blocks_needed;
+ b_divisor = b_dividend + 4 * dividend_blocks_needed + 1;
+ memset (b_quotient, 0,
+ 4 * dividend_blocks_needed * sizeof (HOST_HALF_WIDE_INT));
+ }
wi_unpack (b_dividend, dividend.get_val (), dividend.get_len (),
dividend_blocks_needed, dividend_prec, UNSIGNED);
wi_unpack (b_divisor, divisor.get_val (), divisor.get_len (),
@@ -1924,7 +1966,8 @@ wi::divmod_internal (HOST_WIDE_INT *quotient, unsigned int *remainder_len,
while (n > 1 && b_divisor[n - 1] == 0)
n--;
- memset (b_quotient, 0, sizeof (b_quotient));
+ if (b_quotient == b_quotient_buf)
+ memset (b_quotient_buf, 0, sizeof (b_quotient_buf));
divmod_internal_2 (b_quotient, b_remainder, b_dividend, b_divisor, m, n);
@@ -1970,6 +2013,7 @@ wi::lshift_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
/* The whole-block shift fills with zeros. */
unsigned int len = BLOCKS_NEEDED (precision);
+ len = MIN (xlen + skip + 1, len);
for (unsigned int i = 0; i < skip; ++i)
val[i] = 0;
@@ -1993,22 +2037,17 @@ wi::lshift_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
return canonize (val, len, precision);
}
-/* Right shift XVAL by SHIFT and store the result in VAL. Return the
+/* Right shift XVAL by SHIFT and store the result in VAL. LEN is the
number of blocks in VAL. The input has XPRECISION bits and the
output has XPRECISION - SHIFT bits. */
-static unsigned int
+static void
rshift_large_common (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
- unsigned int xlen, unsigned int xprecision,
- unsigned int shift)
+ unsigned int xlen, unsigned int shift, unsigned int len)
{
/* Split the shift into a whole-block shift and a subblock shift. */
unsigned int skip = shift / HOST_BITS_PER_WIDE_INT;
unsigned int small_shift = shift % HOST_BITS_PER_WIDE_INT;
- /* Work out how many blocks are needed to store the significant bits
- (excluding the upper zeros or signs). */
- unsigned int len = BLOCKS_NEEDED (xprecision - shift);
-
/* It's easier to handle the simple block case specially. */
if (small_shift == 0)
for (unsigned int i = 0; i < len; ++i)
@@ -2025,7 +2064,6 @@ rshift_large_common (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
val[i] |= curr << (-small_shift % HOST_BITS_PER_WIDE_INT);
}
}
- return len;
}
/* Logically right shift XVAL by SHIFT and store the result in VAL.
@@ -2036,11 +2074,18 @@ wi::lrshift_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
unsigned int xlen, unsigned int xprecision,
unsigned int precision, unsigned int shift)
{
- unsigned int len = rshift_large_common (val, xval, xlen, xprecision, shift);
+ /* Work out how many blocks are needed to store the significant bits
+ (excluding the upper zeros or signs). */
+ unsigned int blocks_needed = BLOCKS_NEEDED (xprecision - shift);
+ unsigned int len = blocks_needed;
+ if (len > xlen && xval[xlen - 1] >= 0)
+ len = xlen;
+
+ rshift_large_common (val, xval, xlen, shift, len);
/* The value we just created has precision XPRECISION - SHIFT.
Zero-extend it to wider precisions. */
- if (precision > xprecision - shift)
+ if (precision > xprecision - shift && len == blocks_needed)
{
unsigned int small_prec = (xprecision - shift) % HOST_BITS_PER_WIDE_INT;
if (small_prec)
@@ -2063,11 +2108,16 @@ wi::arshift_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
unsigned int xlen, unsigned int xprecision,
unsigned int precision, unsigned int shift)
{
- unsigned int len = rshift_large_common (val, xval, xlen, xprecision, shift);
+ /* Work out how many blocks are needed to store the significant bits
+ (excluding the upper zeros or signs). */
+ unsigned int blocks_needed = BLOCKS_NEEDED (xprecision - shift);
+ unsigned int len = MIN (xlen, blocks_needed);
+
+ rshift_large_common (val, xval, xlen, shift, len);
/* The value we just created has precision XPRECISION - SHIFT.
Sign-extend it to wider types. */
- if (precision > xprecision - shift)
+ if (precision > xprecision - shift && len == blocks_needed)
{
unsigned int small_prec = (xprecision - shift) % HOST_BITS_PER_WIDE_INT;
if (small_prec)
@@ -2399,9 +2449,12 @@ from_int (int i)
static void
assert_deceq (const char *expected, const wide_int_ref &wi, signop sgn)
{
- char buf[WIDE_INT_PRINT_BUFFER_SIZE];
- print_dec (wi, buf, sgn);
- ASSERT_STREQ (expected, buf);
+ char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
+ unsigned len = wi.get_len ();
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+ print_dec (wi, p, sgn);
+ ASSERT_STREQ (expected, p);
}
/* Likewise for base 16. */
@@ -2409,9 +2462,12 @@ assert_deceq (const char *expected, const wide_int_ref &wi, signop sgn)
static void
assert_hexeq (const char *expected, const wide_int_ref &wi)
{
- char buf[WIDE_INT_PRINT_BUFFER_SIZE];
- print_hex (wi, buf);
- ASSERT_STREQ (expected, buf);
+ char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
+ unsigned len = wi.get_len ();
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+ print_hex (wi, p);
+ ASSERT_STREQ (expected, p);
}
/* Test cases. */
@@ -2428,7 +2484,7 @@ test_printing ()
assert_hexeq ("0x1fffffffffffffffff", wi::shwi (-1, 69));
assert_hexeq ("0xffffffffffffffff", wi::mask (64, false, 69));
assert_hexeq ("0xffffffffffffffff", wi::mask <widest_int> (64, false));
- if (WIDE_INT_MAX_PRECISION > 128)
+ if (WIDE_INT_MAX_INL_PRECISION > 128)
{
assert_hexeq ("0x20000000000000000fffffffffffffffe",
wi::lshift (1, 129) + wi::lshift (1, 64) - 2);
diff --git a/gcc/wide-int.h b/gcc/wide-int.h
index 498d14d..1b12472 100644
--- a/gcc/wide-int.h
+++ b/gcc/wide-int.h
@@ -53,6 +53,10 @@ along with GCC; see the file COPYING3. If not see
multiply, division, shifts, comparisons, and operations that need
overflow detected), the signedness must be specified separately.
+ For precisions up to WIDE_INT_MAX_INL_PRECISION, it uses an inline
+ buffer in the type, for larger precisions up to WIDEST_INT_MAX_PRECISION
+ it uses a pointer to heap allocated buffer.
+
2) offset_int. This is a fixed-precision integer that can hold
any address offset, measured in either bits or bytes, with at
least one extra sign bit. At the moment the maximum address
@@ -79,8 +83,7 @@ along with GCC; see the file COPYING3. If not see
3) widest_int. This representation is an approximation of
infinite precision math. However, it is not really infinite
precision math as in the GMP library. It is really finite
- precision math where the precision is 4 times the size of the
- largest integer that the target port can represent.
+ precision math where the precision is WIDEST_INT_MAX_PRECISION.
Like offset_int, widest_int is wider than all the values that
it needs to represent, so the integers are logically signed.
@@ -231,17 +234,31 @@ along with GCC; see the file COPYING3. If not see
can be arbitrarily different from X. */
/* The MAX_BITSIZE_MODE_ANY_INT is automatically generated by a very
- early examination of the target's mode file. The WIDE_INT_MAX_ELTS
+ early examination of the target's mode file. The WIDE_INT_MAX_INL_ELTS
can accomodate at least 1 more bit so that unsigned numbers of that
mode can be represented as a signed value. Note that it is still
possible to create fixed_wide_ints that have precisions greater than
MAX_BITSIZE_MODE_ANY_INT. This can be useful when representing a
double-width multiplication result, for example. */
-#define WIDE_INT_MAX_ELTS \
- ((MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT) / HOST_BITS_PER_WIDE_INT)
+#define WIDE_INT_MAX_INL_ELTS \
+ ((MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT) \
+ / HOST_BITS_PER_WIDE_INT)
+
+#define WIDE_INT_MAX_INL_PRECISION \
+ (WIDE_INT_MAX_INL_ELTS * HOST_BITS_PER_WIDE_INT)
+/* Precision of wide_int and largest _BitInt precision + 1 we can
+ support. */
+#define WIDE_INT_MAX_ELTS 255
#define WIDE_INT_MAX_PRECISION (WIDE_INT_MAX_ELTS * HOST_BITS_PER_WIDE_INT)
+/* Precision of widest_int and largest _BitInt precision + 1 we can
+ support. */
+#define WIDEST_INT_MAX_ELTS 510
+#define WIDEST_INT_MAX_PRECISION (WIDEST_INT_MAX_ELTS * HOST_BITS_PER_WIDE_INT)
+
+STATIC_ASSERT (WIDE_INT_MAX_INL_ELTS < WIDE_INT_MAX_ELTS);
+
/* This is the max size of any pointer on any machine. It does not
seem to be as easy to sniff this out of the machine description as
it is for MAX_BITSIZE_MODE_ANY_INT since targets may support
@@ -307,17 +324,18 @@ along with GCC; see the file COPYING3. If not see
#define WI_BINARY_RESULT_VAR(RESULT, VAL, T1, X, T2, Y) \
WI_BINARY_RESULT (T1, T2) RESULT = \
wi::int_traits <WI_BINARY_RESULT (T1, T2)>::get_binary_result (X, Y); \
- HOST_WIDE_INT *VAL = RESULT.write_val ()
+ HOST_WIDE_INT *VAL = RESULT.write_val (0)
/* Similar for the result of a unary operation on X, which has type T. */
#define WI_UNARY_RESULT_VAR(RESULT, VAL, T, X) \
WI_UNARY_RESULT (T) RESULT = \
wi::int_traits <WI_UNARY_RESULT (T)>::get_binary_result (X, X); \
- HOST_WIDE_INT *VAL = RESULT.write_val ()
+ HOST_WIDE_INT *VAL = RESULT.write_val (0)
template <typename T> class generic_wide_int;
template <int N> class fixed_wide_int_storage;
class wide_int_storage;
+template <int N> class widest_int_storage;
/* An N-bit integer. Until we can use typedef templates, use this instead. */
#define FIXED_WIDE_INT(N) \
@@ -325,10 +343,8 @@ class wide_int_storage;
typedef generic_wide_int <wide_int_storage> wide_int;
typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) offset_int;
-typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION) widest_int;
-/* Spelled out explicitly (rather than through FIXED_WIDE_INT)
- so as not to confuse gengtype. */
-typedef generic_wide_int < fixed_wide_int_storage <WIDE_INT_MAX_PRECISION * 2> > widest2_int;
+typedef generic_wide_int <widest_int_storage <WIDEST_INT_MAX_PRECISION> > widest_int;
+typedef generic_wide_int <widest_int_storage <WIDEST_INT_MAX_PRECISION * 2> > widest2_int;
/* wi::storage_ref can be a reference to a primitive type,
so this is the conservatively-correct setting. */
@@ -378,8 +394,12 @@ namespace wi
/* The integer has a variable precision but no defined signedness. */
VAR_PRECISION,
- /* The integer has a constant precision (known at GCC compile time)
- and is signed. */
+ /* The integer has a constant precision (known at GCC compile time),
+ is signed and all elements are in inline buffer. */
+ INL_CONST_PRECISION,
+
+ /* Like INL_CONST_PRECISION, but elements can be heap allocated for
+ larger lengths. */
CONST_PRECISION
};
@@ -390,7 +410,8 @@ namespace wi
Classifies the type of T.
static const unsigned int precision;
- Only defined if precision_type == CONST_PRECISION. Specifies the
+ Only defined if precision_type == INL_CONST_PRECISION or
+ precision_type == CONST_PRECISION. Specifies the
precision of all integers of type T.
static const bool host_dependent_precision;
@@ -415,9 +436,10 @@ namespace wi
struct binary_traits;
/* Specify the result type for each supported combination of binary
- inputs. Note that CONST_PRECISION and VAR_PRECISION cannot be
- mixed, in order to give stronger type checking. When both inputs
- are CONST_PRECISION, they must have the same precision. */
+ inputs. Note that INL_CONST_PRECISION, CONST_PRECISION and
+ VAR_PRECISION cannot be mixed, in order to give stronger type
+ checking. When both inputs are INL_CONST_PRECISION or both are
+ CONST_PRECISION, they must have the same precision. */
template <typename T1, typename T2>
struct binary_traits <T1, T2, FLEXIBLE_PRECISION, FLEXIBLE_PRECISION>
{
@@ -434,7 +456,7 @@ namespace wi
};
template <typename T1, typename T2>
- struct binary_traits <T1, T2, FLEXIBLE_PRECISION, CONST_PRECISION>
+ struct binary_traits <T1, T2, FLEXIBLE_PRECISION, INL_CONST_PRECISION>
{
/* Spelled out explicitly (rather than through FIXED_WIDE_INT)
so as not to confuse gengtype. */
@@ -447,6 +469,17 @@ namespace wi
};
template <typename T1, typename T2>
+ struct binary_traits <T1, T2, FLEXIBLE_PRECISION, CONST_PRECISION>
+ {
+ typedef generic_wide_int < widest_int_storage
+ <int_traits <T2>::precision> > result_type;
+ typedef result_type operator_result;
+ typedef bool predicate_result;
+ typedef result_type signed_shift_result_type;
+ typedef bool signed_predicate_result;
+ };
+
+ template <typename T1, typename T2>
struct binary_traits <T1, T2, VAR_PRECISION, FLEXIBLE_PRECISION>
{
typedef wide_int result_type;
@@ -455,7 +488,7 @@ namespace wi
};
template <typename T1, typename T2>
- struct binary_traits <T1, T2, CONST_PRECISION, FLEXIBLE_PRECISION>
+ struct binary_traits <T1, T2, INL_CONST_PRECISION, FLEXIBLE_PRECISION>
{
/* Spelled out explicitly (rather than through FIXED_WIDE_INT)
so as not to confuse gengtype. */
@@ -468,7 +501,18 @@ namespace wi
};
template <typename T1, typename T2>
- struct binary_traits <T1, T2, CONST_PRECISION, CONST_PRECISION>
+ struct binary_traits <T1, T2, CONST_PRECISION, FLEXIBLE_PRECISION>
+ {
+ typedef generic_wide_int < widest_int_storage
+ <int_traits <T1>::precision> > result_type;
+ typedef result_type operator_result;
+ typedef bool predicate_result;
+ typedef result_type signed_shift_result_type;
+ typedef bool signed_predicate_result;
+ };
+
+ template <typename T1, typename T2>
+ struct binary_traits <T1, T2, INL_CONST_PRECISION, INL_CONST_PRECISION>
{
STATIC_ASSERT (int_traits <T1>::precision == int_traits <T2>::precision);
/* Spelled out explicitly (rather than through FIXED_WIDE_INT)
@@ -482,6 +526,18 @@ namespace wi
};
template <typename T1, typename T2>
+ struct binary_traits <T1, T2, CONST_PRECISION, CONST_PRECISION>
+ {
+ STATIC_ASSERT (int_traits <T1>::precision == int_traits <T2>::precision);
+ typedef generic_wide_int < widest_int_storage
+ <int_traits <T1>::precision> > result_type;
+ typedef result_type operator_result;
+ typedef bool predicate_result;
+ typedef result_type signed_shift_result_type;
+ typedef bool signed_predicate_result;
+ };
+
+ template <typename T1, typename T2>
struct binary_traits <T1, T2, VAR_PRECISION, VAR_PRECISION>
{
typedef wide_int result_type;
@@ -709,8 +765,10 @@ wi::storage_ref::get_val () const
Although not required by generic_wide_int itself, writable storage
classes can also provide the following functions:
- HOST_WIDE_INT *write_val ()
- Get a modifiable version of get_val ()
+ HOST_WIDE_INT *write_val (unsigned int)
+ Get a modifiable version of get_val (). The argument should be
+ upper estimation for LEN (ignored by all storages but
+ widest_int_storage).
unsigned int set_len (unsigned int len)
Set the value returned by get_len () to LEN. */
@@ -777,6 +835,8 @@ public:
static const bool is_sign_extended
= wi::int_traits <generic_wide_int <storage> >::is_sign_extended;
+ static const bool needs_write_val_arg
+ = wi::int_traits <generic_wide_int <storage> >::needs_write_val_arg;
};
template <typename storage>
@@ -1049,6 +1109,7 @@ namespace wi
static const enum precision_type precision_type = VAR_PRECISION;
static const bool host_dependent_precision = HDP;
static const bool is_sign_extended = SE;
+ static const bool needs_write_val_arg = false;
};
}
@@ -1065,7 +1126,11 @@ namespace wi
class GTY(()) wide_int_storage
{
private:
- HOST_WIDE_INT val[WIDE_INT_MAX_ELTS];
+ union
+ {
+ HOST_WIDE_INT val[WIDE_INT_MAX_INL_ELTS];
+ HOST_WIDE_INT *valp;
+ } GTY((skip)) u;
unsigned int len;
unsigned int precision;
@@ -1073,14 +1138,17 @@ public:
wide_int_storage ();
template <typename T>
wide_int_storage (const T &);
+ wide_int_storage (const wide_int_storage &);
+ ~wide_int_storage ();
/* The standard generic_wide_int storage methods. */
unsigned int get_precision () const;
const HOST_WIDE_INT *get_val () const;
unsigned int get_len () const;
- HOST_WIDE_INT *write_val ();
+ HOST_WIDE_INT *write_val (unsigned int);
void set_len (unsigned int, bool = false);
+ wide_int_storage &operator = (const wide_int_storage &);
template <typename T>
wide_int_storage &operator = (const T &);
@@ -1099,12 +1167,15 @@ namespace wi
/* Guaranteed by a static assert in the wide_int_storage constructor. */
static const bool host_dependent_precision = false;
static const bool is_sign_extended = true;
+ static const bool needs_write_val_arg = false;
template <typename T1, typename T2>
static wide_int get_binary_result (const T1 &, const T2 &);
+ template <typename T1, typename T2>
+ static unsigned int get_binary_precision (const T1 &, const T2 &);
};
}
-inline wide_int_storage::wide_int_storage () {}
+inline wide_int_storage::wide_int_storage () : precision (0) {}
/* Initialize the storage from integer X, in its natural precision.
Note that we do not allow integers with host-dependent precision
@@ -1113,21 +1184,67 @@ inline wide_int_storage::wide_int_storage () {}
template <typename T>
inline wide_int_storage::wide_int_storage (const T &x)
{
- { STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision); }
- { STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::CONST_PRECISION); }
+ STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision);
+ STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::CONST_PRECISION);
+ STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::INL_CONST_PRECISION);
WIDE_INT_REF_FOR (T) xi (x);
precision = xi.precision;
+ if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
+ u.valp = XNEWVEC (HOST_WIDE_INT, CEIL (precision, HOST_BITS_PER_WIDE_INT));
wi::copy (*this, xi);
}
+inline wide_int_storage::wide_int_storage (const wide_int_storage &x)
+{
+ memcpy (this, &x, sizeof (wide_int_storage));
+ if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
+ {
+ u.valp = XNEWVEC (HOST_WIDE_INT, CEIL (precision, HOST_BITS_PER_WIDE_INT));
+ memcpy (u.valp, x.u.valp, len * sizeof (HOST_WIDE_INT));
+ }
+}
+
+inline wide_int_storage::~wide_int_storage ()
+{
+ if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
+ XDELETEVEC (u.valp);
+}
+
+inline wide_int_storage&
+wide_int_storage::operator = (const wide_int_storage &x)
+{
+ if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
+ {
+ if (this == &x)
+ return *this;
+ XDELETEVEC (u.valp);
+ }
+ memcpy (this, &x, sizeof (wide_int_storage));
+ if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
+ {
+ u.valp = XNEWVEC (HOST_WIDE_INT, CEIL (precision, HOST_BITS_PER_WIDE_INT));
+ memcpy (u.valp, x.u.valp, len * sizeof (HOST_WIDE_INT));
+ }
+ return *this;
+}
+
template <typename T>
inline wide_int_storage&
wide_int_storage::operator = (const T &x)
{
- { STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision); }
- { STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::CONST_PRECISION); }
+ STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision);
+ STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::CONST_PRECISION);
+ STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::INL_CONST_PRECISION);
WIDE_INT_REF_FOR (T) xi (x);
- precision = xi.precision;
+ if (UNLIKELY (precision != xi.precision))
+ {
+ if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
+ XDELETEVEC (u.valp);
+ precision = xi.precision;
+ if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
+ u.valp = XNEWVEC (HOST_WIDE_INT,
+ CEIL (precision, HOST_BITS_PER_WIDE_INT));
+ }
wi::copy (*this, xi);
return *this;
}
@@ -1141,7 +1258,7 @@ wide_int_storage::get_precision () const
inline const HOST_WIDE_INT *
wide_int_storage::get_val () const
{
- return val;
+ return UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION) ? u.valp : u.val;
}
inline unsigned int
@@ -1151,9 +1268,9 @@ wide_int_storage::get_len () const
}
inline HOST_WIDE_INT *
-wide_int_storage::write_val ()
+wide_int_storage::write_val (unsigned int)
{
- return val;
+ return UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION) ? u.valp : u.val;
}
inline void
@@ -1161,8 +1278,10 @@ wide_int_storage::set_len (unsigned int l, bool is_sign_extended)
{
len = l;
if (!is_sign_extended && len * HOST_BITS_PER_WIDE_INT > precision)
- val[len - 1] = sext_hwi (val[len - 1],
- precision % HOST_BITS_PER_WIDE_INT);
+ {
+ HOST_WIDE_INT &v = write_val (len)[len - 1];
+ v = sext_hwi (v, precision % HOST_BITS_PER_WIDE_INT);
+ }
}
/* Treat X as having signedness SGN and convert it to a PRECISION-bit
@@ -1172,7 +1291,7 @@ wide_int_storage::from (const wide_int_ref &x, unsigned int precision,
signop sgn)
{
wide_int result = wide_int::create (precision);
- result.set_len (wi::force_to_size (result.write_val (), x.val, x.len,
+ result.set_len (wi::force_to_size (result.write_val (x.len), x.val, x.len,
x.precision, precision, sgn));
return result;
}
@@ -1185,7 +1304,7 @@ wide_int_storage::from_array (const HOST_WIDE_INT *val, unsigned int len,
unsigned int precision, bool need_canon_p)
{
wide_int result = wide_int::create (precision);
- result.set_len (wi::from_array (result.write_val (), val, len, precision,
+ result.set_len (wi::from_array (result.write_val (len), val, len, precision,
need_canon_p));
return result;
}
@@ -1196,6 +1315,9 @@ wide_int_storage::create (unsigned int precision)
{
wide_int x;
x.precision = precision;
+ if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
+ x.u.valp = XNEWVEC (HOST_WIDE_INT,
+ CEIL (precision, HOST_BITS_PER_WIDE_INT));
return x;
}
@@ -1212,6 +1334,20 @@ wi::int_traits <wide_int_storage>::get_binary_result (const T1 &x, const T2 &y)
return wide_int::create (wi::get_precision (x));
}
+template <typename T1, typename T2>
+inline unsigned int
+wi::int_traits <wide_int_storage>::get_binary_precision (const T1 &x,
+ const T2 &y)
+{
+ /* This shouldn't be used for two flexible-precision inputs. */
+ STATIC_ASSERT (wi::int_traits <T1>::precision_type != FLEXIBLE_PRECISION
+ || wi::int_traits <T2>::precision_type != FLEXIBLE_PRECISION);
+ if (wi::int_traits <T1>::precision_type == FLEXIBLE_PRECISION)
+ return wi::get_precision (y);
+ else
+ return wi::get_precision (x);
+}
+
/* The storage used by FIXED_WIDE_INT (N). */
template <int N>
class GTY(()) fixed_wide_int_storage
@@ -1221,7 +1357,7 @@ private:
unsigned int len;
public:
- fixed_wide_int_storage ();
+ fixed_wide_int_storage () = default;
template <typename T>
fixed_wide_int_storage (const T &);
@@ -1229,7 +1365,7 @@ public:
unsigned int get_precision () const;
const HOST_WIDE_INT *get_val () const;
unsigned int get_len () const;
- HOST_WIDE_INT *write_val ();
+ HOST_WIDE_INT *write_val (unsigned int);
void set_len (unsigned int, bool = false);
static FIXED_WIDE_INT (N) from (const wide_int_ref &, signop);
@@ -1242,18 +1378,18 @@ namespace wi
template <int N>
struct int_traits < fixed_wide_int_storage <N> >
{
- static const enum precision_type precision_type = CONST_PRECISION;
+ static const enum precision_type precision_type = INL_CONST_PRECISION;
static const bool host_dependent_precision = false;
static const bool is_sign_extended = true;
+ static const bool needs_write_val_arg = false;
static const unsigned int precision = N;
template <typename T1, typename T2>
static FIXED_WIDE_INT (N) get_binary_result (const T1 &, const T2 &);
+ template <typename T1, typename T2>
+ static unsigned int get_binary_precision (const T1 &, const T2 &);
};
}
-template <int N>
-inline fixed_wide_int_storage <N>::fixed_wide_int_storage () {}
-
/* Initialize the storage from integer X, in precision N. */
template <int N>
template <typename T>
@@ -1288,7 +1424,7 @@ fixed_wide_int_storage <N>::get_len () const
template <int N>
inline HOST_WIDE_INT *
-fixed_wide_int_storage <N>::write_val ()
+fixed_wide_int_storage <N>::write_val (unsigned int)
{
return val;
}
@@ -1308,7 +1444,7 @@ inline FIXED_WIDE_INT (N)
fixed_wide_int_storage <N>::from (const wide_int_ref &x, signop sgn)
{
FIXED_WIDE_INT (N) result;
- result.set_len (wi::force_to_size (result.write_val (), x.val, x.len,
+ result.set_len (wi::force_to_size (result.write_val (x.len), x.val, x.len,
x.precision, N, sgn));
return result;
}
@@ -1323,7 +1459,7 @@ fixed_wide_int_storage <N>::from_array (const HOST_WIDE_INT *val,
bool need_canon_p)
{
FIXED_WIDE_INT (N) result;
- result.set_len (wi::from_array (result.write_val (), val, len,
+ result.set_len (wi::from_array (result.write_val (len), val, len,
N, need_canon_p));
return result;
}
@@ -1337,6 +1473,236 @@ get_binary_result (const T1 &, const T2 &)
return FIXED_WIDE_INT (N) ();
}
+template <int N>
+template <typename T1, typename T2>
+inline unsigned int
+wi::int_traits < fixed_wide_int_storage <N> >::
+get_binary_precision (const T1 &, const T2 &)
+{
+ return N;
+}
+
+#define WIDEST_INT(N) generic_wide_int < widest_int_storage <N> >
+
+/* The storage used by widest_int. */
+template <int N>
+class GTY(()) widest_int_storage
+{
+private:
+ union
+ {
+ HOST_WIDE_INT val[WIDE_INT_MAX_INL_ELTS];
+ HOST_WIDE_INT *valp;
+ } GTY((skip)) u;
+ unsigned int len;
+
+public:
+ widest_int_storage ();
+ widest_int_storage (const widest_int_storage &);
+ template <typename T>
+ widest_int_storage (const T &);
+ ~widest_int_storage ();
+ widest_int_storage &operator = (const widest_int_storage &);
+ template <typename T>
+ inline widest_int_storage& operator = (const T &);
+
+ /* The standard generic_wide_int storage methods. */
+ unsigned int get_precision () const;
+ const HOST_WIDE_INT *get_val () const;
+ unsigned int get_len () const;
+ HOST_WIDE_INT *write_val (unsigned int);
+ void set_len (unsigned int, bool = false);
+
+ static WIDEST_INT (N) from (const wide_int_ref &, signop);
+ static WIDEST_INT (N) from_array (const HOST_WIDE_INT *, unsigned int,
+ bool = true);
+};
+
+namespace wi
+{
+ template <int N>
+ struct int_traits < widest_int_storage <N> >
+ {
+ static const enum precision_type precision_type = CONST_PRECISION;
+ static const bool host_dependent_precision = false;
+ static const bool is_sign_extended = true;
+ static const bool needs_write_val_arg = true;
+ static const unsigned int precision = N;
+ template <typename T1, typename T2>
+ static WIDEST_INT (N) get_binary_result (const T1 &, const T2 &);
+ template <typename T1, typename T2>
+ static unsigned int get_binary_precision (const T1 &, const T2 &);
+ };
+}
+
+template <int N>
+inline widest_int_storage <N>::widest_int_storage () : len (0) {}
+
+/* Initialize the storage from integer X, in precision N. */
+template <int N>
+template <typename T>
+inline widest_int_storage <N>::widest_int_storage (const T &x) : len (0)
+{
+ /* Check for type compatibility. We don't want to initialize a
+ widest integer from something like a wide_int. */
+ WI_BINARY_RESULT (T, WIDEST_INT (N)) *assertion ATTRIBUTE_UNUSED;
+ wi::copy (*this, WIDE_INT_REF_FOR (T) (x, N));
+}
+
+template <int N>
+inline
+widest_int_storage <N>::widest_int_storage (const widest_int_storage &x)
+{
+ memcpy (this, &x, sizeof (widest_int_storage));
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ {
+ u.valp = XNEWVEC (HOST_WIDE_INT, len);
+ memcpy (u.valp, x.u.valp, len * sizeof (HOST_WIDE_INT));
+ }
+}
+
+template <int N>
+inline widest_int_storage <N>::~widest_int_storage ()
+{
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ XDELETEVEC (u.valp);
+}
+
+template <int N>
+inline widest_int_storage <N>&
+widest_int_storage <N>::operator = (const widest_int_storage &x)
+{
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ {
+ if (this == &x)
+ return *this;
+ XDELETEVEC (u.valp);
+ }
+ memcpy (this, &x, sizeof (widest_int_storage));
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ {
+ u.valp = XNEWVEC (HOST_WIDE_INT, len);
+ memcpy (u.valp, x.u.valp, len * sizeof (HOST_WIDE_INT));
+ }
+ return *this;
+}
+
+template <int N>
+template <typename T>
+inline widest_int_storage <N>&
+widest_int_storage <N>::operator = (const T &x)
+{
+ /* Check for type compatibility. We don't want to assign a
+ widest integer from something like a wide_int. */
+ WI_BINARY_RESULT (T, WIDEST_INT (N)) *assertion ATTRIBUTE_UNUSED;
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ XDELETEVEC (u.valp);
+ len = 0;
+ wi::copy (*this, WIDE_INT_REF_FOR (T) (x, N));
+ return *this;
+}
+
+template <int N>
+inline unsigned int
+widest_int_storage <N>::get_precision () const
+{
+ return N;
+}
+
+template <int N>
+inline const HOST_WIDE_INT *
+widest_int_storage <N>::get_val () const
+{
+ return UNLIKELY (len > WIDE_INT_MAX_INL_ELTS) ? u.valp : u.val;
+}
+
+template <int N>
+inline unsigned int
+widest_int_storage <N>::get_len () const
+{
+ return len;
+}
+
+template <int N>
+inline HOST_WIDE_INT *
+widest_int_storage <N>::write_val (unsigned int l)
+{
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
+ XDELETEVEC (u.valp);
+ len = l;
+ if (UNLIKELY (l > WIDE_INT_MAX_INL_ELTS))
+ {
+ u.valp = XNEWVEC (HOST_WIDE_INT, l);
+ return u.valp;
+ }
+ return u.val;
+}
+
+template <int N>
+inline void
+widest_int_storage <N>::set_len (unsigned int l, bool)
+{
+ gcc_checking_assert (l <= len);
+ if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS)
+ && l <= WIDE_INT_MAX_INL_ELTS)
+ {
+ HOST_WIDE_INT *valp = u.valp;
+ memcpy (u.val, valp, l * sizeof (u.val[0]));
+ XDELETEVEC (valp);
+ }
+ len = l;
+ /* There are no excess bits in val[len - 1]. */
+ STATIC_ASSERT (N % HOST_BITS_PER_WIDE_INT == 0);
+}
+
+/* Treat X as having signedness SGN and convert it to an N-bit number. */
+template <int N>
+inline WIDEST_INT (N)
+widest_int_storage <N>::from (const wide_int_ref &x, signop sgn)
+{
+ WIDEST_INT (N) result;
+ unsigned int exp_len = x.len;
+ unsigned int prec = result.get_precision ();
+ if (sgn == UNSIGNED && prec > x.precision && x.val[x.len - 1] < 0)
+ exp_len = CEIL (x.precision, HOST_BITS_PER_WIDE_INT) + 1;
+ result.set_len (wi::force_to_size (result.write_val (exp_len), x.val, x.len,
+ x.precision, prec, sgn));
+ return result;
+}
+
+/* Create a WIDEST_INT (N) from the explicit block encoding given by
+ VAL and LEN. NEED_CANON_P is true if the encoding may have redundant
+ trailing blocks. */
+template <int N>
+inline WIDEST_INT (N)
+widest_int_storage <N>::from_array (const HOST_WIDE_INT *val,
+ unsigned int len,
+ bool need_canon_p)
+{
+ WIDEST_INT (N) result;
+ result.set_len (wi::from_array (result.write_val (len), val, len,
+ result.get_precision (), need_canon_p));
+ return result;
+}
+
+template <int N>
+template <typename T1, typename T2>
+inline WIDEST_INT (N)
+wi::int_traits < widest_int_storage <N> >::
+get_binary_result (const T1 &, const T2 &)
+{
+ return WIDEST_INT (N) ();
+}
+
+template <int N>
+template <typename T1, typename T2>
+inline unsigned int
+wi::int_traits < widest_int_storage <N> >::
+get_binary_precision (const T1 &, const T2 &)
+{
+ return N;
+}
+
/* A reference to one element of a trailing_wide_ints structure. */
class trailing_wide_int_storage
{
@@ -1359,7 +1725,7 @@ public:
unsigned int get_len () const;
unsigned int get_precision () const;
const HOST_WIDE_INT *get_val () const;
- HOST_WIDE_INT *write_val ();
+ HOST_WIDE_INT *write_val (unsigned int);
void set_len (unsigned int, bool = false);
template <typename T>
@@ -1445,7 +1811,7 @@ trailing_wide_int_storage::get_val () const
}
inline HOST_WIDE_INT *
-trailing_wide_int_storage::write_val ()
+trailing_wide_int_storage::write_val (unsigned int)
{
return m_val;
}
@@ -1528,6 +1894,7 @@ namespace wi
static const enum precision_type precision_type = FLEXIBLE_PRECISION;
static const bool host_dependent_precision = true;
static const bool is_sign_extended = true;
+ static const bool needs_write_val_arg = false;
static unsigned int get_precision (T);
static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int, T);
};
@@ -1699,6 +2066,7 @@ namespace wi
precision of HOST_WIDE_INT. */
static const bool host_dependent_precision = false;
static const bool is_sign_extended = true;
+ static const bool needs_write_val_arg = false;
static unsigned int get_precision (const wi::hwi_with_prec &);
static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int,
const wi::hwi_with_prec &);
@@ -1804,8 +2172,8 @@ template <typename T1, typename T2>
inline unsigned int
wi::get_binary_precision (const T1 &x, const T2 &y)
{
- return get_precision (wi::int_traits <WI_BINARY_RESULT (T1, T2)>::
- get_binary_result (x, y));
+ using res_traits = wi::int_traits <WI_BINARY_RESULT (T1, T2)>;
+ return res_traits::get_binary_precision (x, y);
}
/* Copy the contents of Y to X, but keeping X's current precision. */
@@ -1813,14 +2181,17 @@ template <typename T1, typename T2>
inline void
wi::copy (T1 &x, const T2 &y)
{
- HOST_WIDE_INT *xval = x.write_val ();
- const HOST_WIDE_INT *yval = y.get_val ();
unsigned int len = y.get_len ();
+ HOST_WIDE_INT *xval = x.write_val (len);
+ const HOST_WIDE_INT *yval = y.get_val ();
unsigned int i = 0;
do
xval[i] = yval[i];
while (++i < len);
- x.set_len (len, y.is_sign_extended);
+ /* For widest_int write_val is called with an exact value, not
+ upper bound for len, so nothing is needed further. */
+ if (!wi::int_traits <T1>::needs_write_val_arg)
+ x.set_len (len, y.is_sign_extended);
}
/* Return true if X fits in a HOST_WIDE_INT with no loss of precision. */
@@ -2162,6 +2533,8 @@ wi::bit_not (const T &x)
{
WI_UNARY_RESULT_VAR (result, val, T, x);
WIDE_INT_REF_FOR (T) xi (x, get_precision (result));
+ if (result.needs_write_val_arg)
+ val = result.write_val (xi.len);
for (unsigned int i = 0; i < xi.len; ++i)
val[i] = ~xi.val[i];
result.set_len (xi.len);
@@ -2203,6 +2576,9 @@ wi::sext (const T &x, unsigned int offset)
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T) xi (x, precision);
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len,
+ CEIL (offset, HOST_BITS_PER_WIDE_INT)));
if (offset <= HOST_BITS_PER_WIDE_INT)
{
val[0] = sext_hwi (xi.ulow (), offset);
@@ -2230,6 +2606,9 @@ wi::zext (const T &x, unsigned int offset)
return result;
}
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len,
+ offset / HOST_BITS_PER_WIDE_INT + 1));
/* In these cases we know that at least the top bit will be clear,
so no sign extension is necessary. */
if (offset < HOST_BITS_PER_WIDE_INT)
@@ -2259,6 +2638,9 @@ wi::set_bit (const T &x, unsigned int bit)
WI_UNARY_RESULT_VAR (result, val, T, x);
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T) xi (x, precision);
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len,
+ bit / HOST_BITS_PER_WIDE_INT + 1));
if (precision <= HOST_BITS_PER_WIDE_INT)
{
val[0] = xi.ulow () | (HOST_WIDE_INT_1U << bit);
@@ -2280,6 +2662,8 @@ wi::bswap (const T &x)
WI_UNARY_RESULT_VAR (result, val, T, x);
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T) xi (x, precision);
+ static_assert (!result.needs_write_val_arg,
+ "bswap on widest_int makes no sense");
result.set_len (bswap_large (val, xi.val, xi.len, precision));
return result;
}
@@ -2292,6 +2676,8 @@ wi::bitreverse (const T &x)
WI_UNARY_RESULT_VAR (result, val, T, x);
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T) xi (x, precision);
+ static_assert (!result.needs_write_val_arg,
+ "bitreverse on widest_int makes no sense");
result.set_len (bitreverse_large (val, xi.val, xi.len, precision));
return result;
}
@@ -2368,6 +2754,8 @@ wi::bit_and (const T1 &x, const T2 &y)
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended;
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len, yi.len));
if (LIKELY (xi.len + yi.len == 2))
{
val[0] = xi.ulow () & yi.ulow ();
@@ -2389,6 +2777,8 @@ wi::bit_and_not (const T1 &x, const T2 &y)
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended;
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len, yi.len));
if (LIKELY (xi.len + yi.len == 2))
{
val[0] = xi.ulow () & ~yi.ulow ();
@@ -2410,6 +2800,8 @@ wi::bit_or (const T1 &x, const T2 &y)
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended;
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len, yi.len));
if (LIKELY (xi.len + yi.len == 2))
{
val[0] = xi.ulow () | yi.ulow ();
@@ -2431,6 +2823,8 @@ wi::bit_or_not (const T1 &x, const T2 &y)
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended;
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len, yi.len));
if (LIKELY (xi.len + yi.len == 2))
{
val[0] = xi.ulow () | ~yi.ulow ();
@@ -2452,6 +2846,8 @@ wi::bit_xor (const T1 &x, const T2 &y)
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended;
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len, yi.len));
if (LIKELY (xi.len + yi.len == 2))
{
val[0] = xi.ulow () ^ yi.ulow ();
@@ -2472,6 +2868,8 @@ wi::add (const T1 &x, const T2 &y)
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len, yi.len) + 1);
if (precision <= HOST_BITS_PER_WIDE_INT)
{
val[0] = xi.ulow () + yi.ulow ();
@@ -2515,6 +2913,8 @@ wi::add (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len, yi.len) + 1);
if (precision <= HOST_BITS_PER_WIDE_INT)
{
unsigned HOST_WIDE_INT xl = xi.ulow ();
@@ -2558,6 +2958,8 @@ wi::sub (const T1 &x, const T2 &y)
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len, yi.len) + 1);
if (precision <= HOST_BITS_PER_WIDE_INT)
{
val[0] = xi.ulow () - yi.ulow ();
@@ -2601,6 +3003,8 @@ wi::sub (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
+ if (result.needs_write_val_arg)
+ val = result.write_val (MAX (xi.len, yi.len) + 1);
if (precision <= HOST_BITS_PER_WIDE_INT)
{
unsigned HOST_WIDE_INT xl = xi.ulow ();
@@ -2643,6 +3047,8 @@ wi::mul (const T1 &x, const T2 &y)
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
+ if (result.needs_write_val_arg)
+ val = result.write_val (xi.len + yi.len + 2);
if (precision <= HOST_BITS_PER_WIDE_INT)
{
val[0] = xi.ulow () * yi.ulow ();
@@ -2664,6 +3070,8 @@ wi::mul (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
+ if (result.needs_write_val_arg)
+ val = result.write_val (xi.len + yi.len + 2);
result.set_len (mul_internal (val, xi.val, xi.len,
yi.val, yi.len, precision,
sgn, overflow, false));
@@ -2698,6 +3106,8 @@ wi::mul_high (const T1 &x, const T2 &y, signop sgn)
unsigned int precision = get_precision (result);
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y, precision);
+ static_assert (!result.needs_write_val_arg,
+ "mul_high on widest_int doesn't make sense");
result.set_len (mul_internal (val, xi.val, xi.len,
yi.val, yi.len, precision,
sgn, 0, true));
@@ -2716,6 +3126,12 @@ wi::div_trunc (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
WIDE_INT_REF_FOR (T1) xi (x, precision);
WIDE_INT_REF_FOR (T2) yi (y);
+ if (quotient.needs_write_val_arg)
+ quotient_val = quotient.write_val ((sgn == UNSIGNED
+ && xi.val[xi.len - 1] < 0)
+ ? CEIL (precision,
+ HOST_BITS_PER_WIDE_INT) + 1
+ : xi.len + 1);
quotient.set_len (divmod_internal (quotient_val, 0, 0, xi.val, xi.len,
precision,
yi.val, yi.len, yi.precision,
@@ -2753,6 +3169,16 @@ wi::div_floor (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
WIDE_INT_REF_FOR (T2) yi (y);
unsigned int remainder_len;
+ if (quotient.needs_write_val_arg)
+ {
+ unsigned int est_len;
+ if (sgn == UNSIGNED && xi.val[xi.len - 1] < 0)
+ est_len = CEIL (precision, HOST_BITS_PER_WIDE_INT) + 1;
+ else
+ est_len = xi.len + 1;
+ quotient_val = quotient.write_val (est_len);
+ remainder_val = remainder.write_val (est_len);
+ }
quotient.set_len (divmod_internal (quotient_val,
&remainder_len, remainder_val,
xi.val, xi.len, precision,
@@ -2795,6 +3221,16 @@ wi::div_ceil (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
WIDE_INT_REF_FOR (T2) yi (y);
unsigned int remainder_len;
+ if (quotient.needs_write_val_arg)
+ {
+ unsigned int est_len;
+ if (sgn == UNSIGNED && xi.val[xi.len - 1] < 0)
+ est_len = CEIL (precision, HOST_BITS_PER_WIDE_INT) + 1;
+ else
+ est_len = xi.len + 1;
+ quotient_val = quotient.write_val (est_len);
+ remainder_val = remainder.write_val (est_len);
+ }
quotient.set_len (divmod_internal (quotient_val,
&remainder_len, remainder_val,
xi.val, xi.len, precision,
@@ -2828,6 +3264,16 @@ wi::div_round (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
WIDE_INT_REF_FOR (T2) yi (y);
unsigned int remainder_len;
+ if (quotient.needs_write_val_arg)
+ {
+ unsigned int est_len;
+ if (sgn == UNSIGNED && xi.val[xi.len - 1] < 0)
+ est_len = CEIL (precision, HOST_BITS_PER_WIDE_INT) + 1;
+ else
+ est_len = xi.len + 1;
+ quotient_val = quotient.write_val (est_len);
+ remainder_val = remainder.write_val (est_len);
+ }
quotient.set_len (divmod_internal (quotient_val,
&remainder_len, remainder_val,
xi.val, xi.len, precision,
@@ -2871,6 +3317,16 @@ wi::divmod_trunc (const T1 &x, const T2 &y, signop sgn,
WIDE_INT_REF_FOR (T2) yi (y);
unsigned int remainder_len;
+ if (quotient.needs_write_val_arg)
+ {
+ unsigned int est_len;
+ if (sgn == UNSIGNED && xi.val[xi.len - 1] < 0)
+ est_len = CEIL (precision, HOST_BITS_PER_WIDE_INT) + 1;
+ else
+ est_len = xi.len + 1;
+ quotient_val = quotient.write_val (est_len);
+ remainder_val = remainder.write_val (est_len);
+ }
quotient.set_len (divmod_internal (quotient_val,
&remainder_len, remainder_val,
xi.val, xi.len, precision,
@@ -2915,6 +3371,12 @@ wi::mod_trunc (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
WIDE_INT_REF_FOR (T2) yi (y);
unsigned int remainder_len;
+ if (remainder.needs_write_val_arg)
+ remainder_val = remainder.write_val ((sgn == UNSIGNED
+ && xi.val[xi.len - 1] < 0)
+ ? CEIL (precision,
+ HOST_BITS_PER_WIDE_INT) + 1
+ : xi.len + 1);
divmod_internal (0, &remainder_len, remainder_val,
xi.val, xi.len, precision,
yi.val, yi.len, yi.precision, sgn, overflow);
@@ -2955,6 +3417,16 @@ wi::mod_floor (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
WIDE_INT_REF_FOR (T2) yi (y);
unsigned int remainder_len;
+ if (quotient.needs_write_val_arg)
+ {
+ unsigned int est_len;
+ if (sgn == UNSIGNED && xi.val[xi.len - 1] < 0)
+ est_len = CEIL (precision, HOST_BITS_PER_WIDE_INT) + 1;
+ else
+ est_len = xi.len + 1;
+ quotient_val = quotient.write_val (est_len);
+ remainder_val = remainder.write_val (est_len);
+ }
quotient.set_len (divmod_internal (quotient_val,
&remainder_len, remainder_val,
xi.val, xi.len, precision,
@@ -2991,6 +3463,16 @@ wi::mod_ceil (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
WIDE_INT_REF_FOR (T2) yi (y);
unsigned int remainder_len;
+ if (quotient.needs_write_val_arg)
+ {
+ unsigned int est_len;
+ if (sgn == UNSIGNED && xi.val[xi.len - 1] < 0)
+ est_len = CEIL (precision, HOST_BITS_PER_WIDE_INT) + 1;
+ else
+ est_len = xi.len + 1;
+ quotient_val = quotient.write_val (est_len);
+ remainder_val = remainder.write_val (est_len);
+ }
quotient.set_len (divmod_internal (quotient_val,
&remainder_len, remainder_val,
xi.val, xi.len, precision,
@@ -3017,6 +3499,16 @@ wi::mod_round (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
WIDE_INT_REF_FOR (T2) yi (y);
unsigned int remainder_len;
+ if (quotient.needs_write_val_arg)
+ {
+ unsigned int est_len;
+ if (sgn == UNSIGNED && xi.val[xi.len - 1] < 0)
+ est_len = CEIL (precision, HOST_BITS_PER_WIDE_INT) + 1;
+ else
+ est_len = xi.len + 1;
+ quotient_val = quotient.write_val (est_len);
+ remainder_val = remainder.write_val (est_len);
+ }
quotient.set_len (divmod_internal (quotient_val,
&remainder_len, remainder_val,
xi.val, xi.len, precision,
@@ -3086,12 +3578,16 @@ wi::lshift (const T1 &x, const T2 &y)
/* Handle the simple cases quickly. */
if (geu_p (yi, precision))
{
+ if (result.needs_write_val_arg)
+ val = result.write_val (1);
val[0] = 0;
result.set_len (1);
}
else
{
unsigned int shift = yi.to_uhwi ();
+ if (result.needs_write_val_arg)
+ val = result.write_val (xi.len + shift / HOST_BITS_PER_WIDE_INT + 1);
/* For fixed-precision integers like offset_int and widest_int,
handle the case where the shift value is constant and the
result is a single nonnegative HWI (meaning that we don't
@@ -3130,12 +3626,23 @@ wi::lrshift (const T1 &x, const T2 &y)
/* Handle the simple cases quickly. */
if (geu_p (yi, xi.precision))
{
+ if (result.needs_write_val_arg)
+ val = result.write_val (1);
val[0] = 0;
result.set_len (1);
}
else
{
unsigned int shift = yi.to_uhwi ();
+ if (result.needs_write_val_arg)
+ {
+ unsigned int est_len = xi.len;
+ if (xi.val[xi.len - 1] < 0 && shift)
+ /* Logical right shift of sign-extended value might need a very
+ large precision e.g. for widest_int. */
+ est_len = CEIL (xi.precision - shift, HOST_BITS_PER_WIDE_INT) + 1;
+ val = result.write_val (est_len);
+ }
/* For fixed-precision integers like offset_int and widest_int,
handle the case where the shift value is constant and the
shifted value is a single nonnegative HWI (meaning that all
@@ -3171,6 +3678,8 @@ wi::arshift (const T1 &x, const T2 &y)
since the result can be no larger than that. */
WIDE_INT_REF_FOR (T1) xi (x);
WIDE_INT_REF_FOR (T2) yi (y);
+ if (result.needs_write_val_arg)
+ val = result.write_val (xi.len);
/* Handle the simple cases quickly. */
if (geu_p (yi, xi.precision))
{
@@ -3374,25 +3883,41 @@ operator % (const T1 &x, const T2 &y)
return wi::smod_trunc (x, y);
}
-template<typename T>
+void gt_ggc_mx (generic_wide_int <wide_int_storage> *) = delete;
+void gt_pch_nx (generic_wide_int <wide_int_storage> *) = delete;
+void gt_pch_nx (generic_wide_int <wide_int_storage> *,
+ gt_pointer_operator, void *) = delete;
+
+template<int N>
void
-gt_ggc_mx (generic_wide_int <T> *)
+gt_ggc_mx (generic_wide_int <fixed_wide_int_storage <N> > *)
{
}
-template<typename T>
+template<int N>
void
-gt_pch_nx (generic_wide_int <T> *)
+gt_pch_nx (generic_wide_int <fixed_wide_int_storage <N> > *)
{
}
-template<typename T>
+template<int N>
void
-gt_pch_nx (generic_wide_int <T> *, gt_pointer_operator, void *)
+gt_pch_nx (generic_wide_int <fixed_wide_int_storage <N> > *,
+ gt_pointer_operator, void *)
{
}
template<int N>
+void gt_ggc_mx (generic_wide_int <widest_int_storage <N> > *) = delete;
+
+template<int N>
+void gt_pch_nx (generic_wide_int <widest_int_storage <N> > *) = delete;
+
+template<int N>
+void gt_pch_nx (generic_wide_int <widest_int_storage <N> > *,
+ gt_pointer_operator, void *) = delete;
+
+template<int N>
void
gt_ggc_mx (trailing_wide_ints <N> *)
{
@@ -3465,7 +3990,7 @@ inline wide_int
wi::mask (unsigned int width, bool negate_p, unsigned int precision)
{
wide_int result = wide_int::create (precision);
- result.set_len (mask (result.write_val (), width, negate_p, precision));
+ result.set_len (mask (result.write_val (0), width, negate_p, precision));
return result;
}
@@ -3477,7 +4002,7 @@ wi::shifted_mask (unsigned int start, unsigned int width, bool negate_p,
unsigned int precision)
{
wide_int result = wide_int::create (precision);
- result.set_len (shifted_mask (result.write_val (), start, width, negate_p,
+ result.set_len (shifted_mask (result.write_val (0), start, width, negate_p,
precision));
return result;
}
@@ -3498,8 +4023,8 @@ wi::mask (unsigned int width, bool negate_p)
{
STATIC_ASSERT (wi::int_traits<T>::precision);
T result;
- result.set_len (mask (result.write_val (), width, negate_p,
- wi::int_traits <T>::precision));
+ result.set_len (mask (result.write_val (width / HOST_BITS_PER_WIDE_INT + 1),
+ width, negate_p, wi::int_traits <T>::precision));
return result;
}
@@ -3512,9 +4037,13 @@ wi::shifted_mask (unsigned int start, unsigned int width, bool negate_p)
{
STATIC_ASSERT (wi::int_traits<T>::precision);
T result;
- result.set_len (shifted_mask (result.write_val (), start, width,
- negate_p,
- wi::int_traits <T>::precision));
+ unsigned int prec = wi::int_traits <T>::precision;
+ unsigned int est_len
+ = result.needs_write_val_arg
+ ? ((start + (width > prec - start ? prec - start : width))
+ / HOST_BITS_PER_WIDE_INT + 1) : 0;
+ result.set_len (shifted_mask (result.write_val (est_len), start, width,
+ negate_p, prec));
return result;
}