On Tue, Oct 3, 2017 at 9:14 PM, Richard Sandiford <richard.sandif...@linaro.org> wrote: > One of the original requirements for getting wide-int.h accepted > was that it should work efficiently on trees. Through a process > that I no longer recall exactly, this ended up meaning that we can > use things like: > > wi::add (t, 1) > > to add 1 to an INTEGER_CST T in its native precision. However, we also have: > > wi::to_offset (t) // Treat T as an offset_int > wi::to_widest (t) // Treat T as a widest_int > > Recently we also gained: > > wi::to_wide (t, prec) // Treat T as a wide_int in preccision PREC > > I'd like to revisit the decision to treat "wide_int trees" differently. > Requiring: > > wi::to_wide (t) > > would be just as efficient, and would make it clearer that a deliberate > choice is being made to treat the tree as a wide_int in its native > precision. This also removes the inconsistency that > > a) wide_int trees can be used without an accessor but must use wi:: > functions instead of C++ operators > > b) the other forms need an explicit accessor but the result can be used > with C++ operators. > > It also helps with SVE, where there's the additional possibility > that the tree could be a runtime value. > > Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu. > Also tested by comparing the testsuite assembly output on at least one > target per CPU directory. OK to install?
So I thought on this on and off. I like the consistency, not sure if it adds much clarity to the casual observer though. I don't like the verbosity too much but lookign at the patch it isn't too bad. Thus ... ok. Thanks, Richard. > If so, it might make sense to use wi::to_wide (rtx, mode) for rtxes too. > > Richard > > > 2017-10-03 Richard Sandiford <richard.sandif...@linaro.org> > > gcc/ > * wide-int.h (wide_int_ref_storage): Make host_dependent_precision > a template parameter. > (WIDE_INT_REF_FOR): Update accordingly. > * tree.h (wi::int_traits <const_tree>): Delete. > (wi::tree_to_widest_ref, wi::tree_to_offset_ref): New typedefs. > (wi::to_widest, wi::to_offset): Use them. Expand commentary. > (wi::tree_to_wide_ref): New typedef. > (wi::to_wide): New function. > * calls.c (get_size_range): Use wi::to_wide when operating on > trees as wide_ints. > * cgraph.c (cgraph_node::create_thunk): Likewise. > * config/i386/i386.c (ix86_data_alignment): Likewise. > (ix86_local_alignment): Likewise. > * dbxout.c (stabstr_O): Likewise. > * dwarf2out.c (add_scalar_info, gen_enumeration_type_die): Likewise. > * expr.c (const_vector_from_tree): Likewise. > * fold-const-call.c (host_size_t_cst_p, fold_const_call_1): Likewise. > * fold-const.c (may_negate_without_overflow_p, negate_expr_p) > (fold_negate_expr_1, int_const_binop_1, const_binop) > (fold_convert_const_int_from_real, optimize_bit_field_compare) > (all_ones_mask_p, sign_bit_p, build_range_check, unextend) > (extract_muldiv_1, fold_div_compare, fold_single_bit_test) > (fold_plusminus_mult_expr, pointer_may_wrap_p, expr_not_equal_to) > (fold_binary_loc, fold_ternary_loc, multiple_of_p, fold_negate_const) > (fold_abs_const, fold_not_const, round_up_loc): Likewise. > * gimple-fold.c (gimple_fold_indirect_ref): Likewise. > * gimple-ssa-warn-alloca.c (alloca_call_type_by_arg): Likewise. > (alloca_call_type): Likewise. > * gimple.c (preprocess_case_label_vec_for_gimple): Likewise. > * godump.c (go_output_typedef): Likewise. > * graphite-sese-to-poly.c (tree_int_to_gmp): Likewise. > * internal-fn.c (get_min_precision): Likewise. > * ipa-cp.c (ipcp_store_vr_results): Likewise. > * ipa-polymorphic-call.c > (ipa_polymorphic_call_context::ipa_polymorphic_call_context): > Likewise. > * ipa-prop.c (ipa_print_node_jump_functions_for_edge): Likewise. > (ipa_modify_call_arguments): Likewise. > * match.pd: Likewise. > * omp-low.c (scan_omp_1_op, lower_omp_ordered_clauses): Likewise. > * print-tree.c (print_node_brief, print_node): Likewise. > * stmt.c (expand_case): Likewise. > * stor-layout.c (layout_type): Likewise. > * tree-affine.c (tree_to_aff_combination): Likewise. > * tree-cfg.c (group_case_labels_stmt): Likewise. > * tree-data-ref.c (dr_analyze_indices): Likewise. > (prune_runtime_alias_test_list): Likewise. > * tree-dump.c (dequeue_and_dump): Likewise. > * tree-inline.c (remap_gimple_op_r, copy_tree_body_r): Likewise. > * tree-predcom.c (is_inv_store_elimination_chain): Likewise. > * tree-pretty-print.c (dump_generic_node): Likewise. > * tree-scalar-evolution.c (iv_can_overflow_p): Likewise. > (simple_iv_with_niters): Likewise. > * tree-ssa-address.c (addr_for_mem_ref): Likewise. > * tree-ssa-ccp.c (ccp_finalize, evaluate_stmt): Likewise. > * tree-ssa-loop-ivopts.c (constant_multiple_of): Likewise. > * tree-ssa-loop-niter.c (split_to_var_and_offset) > (refine_value_range_using_guard, number_of_iterations_ne_max) > (number_of_iterations_lt_to_ne, number_of_iterations_lt) > (get_cst_init_from_scev, record_nonwrapping_iv) > (scev_var_range_cant_overflow): Likewise. > * tree-ssa-phiopt.c (minmax_replacement): Likewise. > * tree-ssa-pre.c (compute_avail): Likewise. > * tree-ssa-sccvn.c (vn_reference_fold_indirect): Likewise. > (vn_reference_maybe_forwprop_address, valueized_wider_op): Likewise. > * tree-ssa-structalias.c (get_constraint_for_ptr_offset): Likewise. > * tree-ssa-uninit.c (is_pred_expr_subset_of): Likewise. > * tree-ssanames.c (set_nonzero_bits, get_nonzero_bits): Likewise. > * tree-switch-conversion.c (collect_switch_conv_info, > array_value_type) > (dump_case_nodes, try_switch_expansion): Likewise. > * tree-vect-loop-manip.c (vect_gen_vector_loop_niters): Likewise. > (vect_do_peeling): Likewise. > * tree-vect-patterns.c (vect_recog_bool_pattern): Likewise. > * tree-vect-stmts.c (vectorizable_load): Likewise. > * tree-vrp.c (compare_values_warnv, vrp_int_const_binop): Likewise. > (zero_nonzero_bits_from_vr, ranges_from_anti_range): Likewise. > (extract_range_from_binary_expr_1, adjust_range_with_scev): Likewise. > (overflow_comparison_p_1, register_edge_assert_for_2): Likewise. > (is_masked_range_test, find_switch_asserts, maybe_set_nonzero_bits) > (vrp_evaluate_conditional_warnv_with_ops, intersect_ranges): Likewise. > (range_fits_type_p, two_valued_val_range_p, vrp_finalize): Likewise. > (evrp_dom_walker::before_dom_children): Likewise. > * tree.c (cache_integer_cst, real_value_from_int_cst, integer_zerop) > (integer_all_onesp, integer_pow2p, integer_nonzerop, tree_log2) > (tree_floor_log2, tree_ctz, mem_ref_offset, tree_int_cst_sign_bit) > (tree_int_cst_sgn, get_unwidened, int_fits_type_p): Likewise. > (get_type_static_bounds, num_ending_zeros, drop_tree_overflow) > (get_range_pos_neg): Likewise. > * ubsan.c (ubsan_expand_ptr_ifn): Likewise. > * config/darwin.c (darwin_mergeable_constant_section): Likewise. > * config/aarch64/aarch64.c (aapcs_vfp_sub_candidate): Likewise. > * config/arm/arm.c (aapcs_vfp_sub_candidate): Likewise. > * config/avr/avr.c (avr_fold_builtin): Likewise. > * config/bfin/bfin.c (bfin_local_alignment): Likewise. > * config/msp430/msp430.c (msp430_attr): Likewise. > * config/nds32/nds32.c (nds32_insert_attributes): Likewise. > * config/powerpcspe/powerpcspe-c.c > (altivec_resolve_overloaded_builtin): Likewise. > * config/powerpcspe/powerpcspe.c (rs6000_aggregate_candidate) > (rs6000_expand_ternop_builtin): Likewise. > * config/rs6000/rs6000-c.c > (altivec_resolve_overloaded_builtin): Likewise. > * config/rs6000/rs6000.c (rs6000_aggregate_candidate): Likewise. > (rs6000_expand_ternop_builtin): Likewise. > * config/s390/s390.c (s390_handle_hotpatch_attribute): Likewise. > > gcc/ada/ > * gcc-interface/decl.c (annotate_value): Use wi::to_wide when > operating on trees as wide_ints. > > gcc/c/ > * c-parser.c (c_parser_cilk_clause_vectorlength): Use wi::to_wide when > operating on trees as wide_ints. > * c-typeck.c (build_c_cast, c_finish_omp_clauses): Likewise. > (c_tree_equal): Likewise. > > gcc/c-family/ > * c-ada-spec.c (dump_generic_ada_node): Use wi::to_wide when > operating on trees as wide_ints. > * c-common.c (pointer_int_sum): Likewise. > * c-pretty-print.c (pp_c_integer_constant): Likewise. > * c-warn.c (match_case_to_enum_1): Likewise. > (c_do_switch_warnings): Likewise. > (maybe_warn_shift_overflow): Likewise. > > gcc/cp/ > * cvt.c (ignore_overflows): Use wi::to_wide when > operating on trees as wide_ints. > * decl.c (check_array_designated_initializer): Likewise. > * mangle.c (write_integer_cst): Likewise. > * semantics.c (cp_finish_omp_clause_depend_sink): Likewise. > > gcc/fortran/ > * target-memory.c (gfc_interpret_logical): Use wi::to_wide when > operating on trees as wide_ints. > * trans-const.c (gfc_conv_tree_to_mpz): Likewise. > * trans-expr.c (gfc_conv_cst_int_power): Likewise. > * trans-intrinsic.c (trans_this_image): Likewise. > (gfc_conv_intrinsic_bound): Likewise. > (conv_intrinsic_cobound): Likewise. > > gcc/lto/ > * lto.c (compare_tree_sccs_1): Use wi::to_wide when > operating on trees as wide_ints. > > gcc/objc/ > * objc-act.c (objc_decl_method_attributes): Use wi::to_wide when > operating on trees as wide_ints. > > Index: gcc/wide-int.h > =================================================================== > *** gcc/wide-int.h 2017-10-03 19:57:02.809678461 +0100 > --- gcc/wide-int.h 2017-10-03 19:57:03.680691854 +0100 > *************** #define WIDE_INT_H > *** 150,164 **** > and in wider precisions. > > There are constructors to create the various forms of wide_int from > ! trees, rtl and constants. For trees you can simply say: > > tree t = ...; > ! wide_int x = t; > > ! However, a little more syntax is required for rtl constants since > ! they do not have an explicit precision. To make an rtl into a > ! wide_int, you have to pair it with a mode. The canonical way to do > ! this is with rtx_mode_t as in: > > rtx r = ... > wide_int x = rtx_mode_t (r, mode); > --- 150,172 ---- > and in wider precisions. > > There are constructors to create the various forms of wide_int from > ! trees, rtl and constants. For trees the options are: > > tree t = ...; > ! wi::to_wide (t) // Treat T as a wide_int > ! wi::to_offset (t) // Treat T as an offset_int > ! wi::to_widest (t) // Treat T as a widest_int > ! > ! All three are light-weight accessors that should have no overhead > ! in release builds. If it is useful for readability reasons to > ! store the result in a temporary variable, the preferred method is: > ! > ! wi::tree_to_wide_ref twide = wi::to_wide (t); > ! wi::tree_to_offset_ref toffset = wi::to_offset (t); > ! wi::tree_to_widest_ref twidest = wi::to_widest (t); > > ! To make an rtx into a wide_int, you have to pair it with a mode. > ! The canonical way to do this is with rtx_mode_t as in: > > rtx r = ... > wide_int x = rtx_mode_t (r, mode); > *************** #define WIDE_INT_H > *** 175,197 **** > offset_int x = (int) c; // sign-extend C > widest_int x = (unsigned int) c; // zero-extend C > > ! It is also possible to do arithmetic directly on trees, rtxes and > constants. For example: > > ! wi::add (t1, t2); // add equal-sized INTEGER_CSTs t1 and t2 > ! wi::add (t1, 1); // add 1 to INTEGER_CST t1 > ! wi::add (r1, r2); // add equal-sized rtx constants r1 and r2 > wi::lshift (1, 100); // 1 << 100 as a widest_int > > Many binary operations place restrictions on the combinations of inputs, > using the following rules: > > ! - {tree, rtx, wide_int} op {tree, rtx, wide_int} -> wide_int > The inputs must be the same precision. The result is a wide_int > of the same precision > > ! - {tree, rtx, wide_int} op (un)signed HOST_WIDE_INT -> wide_int > ! (un)signed HOST_WIDE_INT op {tree, rtx, wide_int} -> wide_int > The HOST_WIDE_INT is extended or truncated to the precision of > the other input. The result is a wide_int of the same precision > as that input. > --- 183,204 ---- > offset_int x = (int) c; // sign-extend C > widest_int x = (unsigned int) c; // zero-extend C > > ! It is also possible to do arithmetic directly on rtx_mode_ts and > constants. For example: > > ! wi::add (r1, r2); // add equal-sized rtx_mode_ts r1 and r2 > ! wi::add (r1, 1); // add 1 to rtx_mode_t r1 > wi::lshift (1, 100); // 1 << 100 as a widest_int > > Many binary operations place restrictions on the combinations of inputs, > using the following rules: > > ! - {rtx, wide_int} op {rtx, wide_int} -> wide_int > The inputs must be the same precision. The result is a wide_int > of the same precision > > ! - {rtx, wide_int} op (un)signed HOST_WIDE_INT -> wide_int > ! (un)signed HOST_WIDE_INT op {rtx, wide_int} -> wide_int > The HOST_WIDE_INT is extended or truncated to the precision of > the other input. The result is a wide_int of the same precision > as that input. > *************** typedef generic_wide_int <wide_int_stora > *** 316,322 **** > typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) offset_int; > typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION) widest_int; > > ! template <bool SE> > struct wide_int_ref_storage; > > typedef generic_wide_int <wide_int_ref_storage <false> > wide_int_ref; > --- 323,331 ---- > typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) offset_int; > typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION) widest_int; > > ! /* wi::storage_ref can be a reference to a primitive type, > ! so this is the conservatively-correct setting. */ > ! template <bool SE, bool HDP = true> > struct wide_int_ref_storage; > > typedef generic_wide_int <wide_int_ref_storage <false> > wide_int_ref; > *************** typedef generic_wide_int <wide_int_ref_s > *** 330,336 **** > to use those. */ > #define WIDE_INT_REF_FOR(T) \ > generic_wide_int \ > ! <wide_int_ref_storage <wi::int_traits <T>::is_sign_extended> > > > namespace wi > { > --- 339,346 ---- > to use those. */ > #define WIDE_INT_REF_FOR(T) \ > generic_wide_int \ > ! <wide_int_ref_storage <wi::int_traits <T>::is_sign_extended, \ > ! wi::int_traits <T>::host_dependent_precision> > > > namespace wi > { > *************** decompose (HOST_WIDE_INT *, unsigned int > *** 929,935 **** > /* Provide the storage for a wide_int_ref. This acts like a read-only > wide_int, with the optimization that VAL is normally a pointer to > another integer's storage, so that no array copy is needed. */ > ! template <bool SE> > struct wide_int_ref_storage : public wi::storage_ref > { > private: > --- 939,945 ---- > /* Provide the storage for a wide_int_ref. This acts like a read-only > wide_int, with the optimization that VAL is normally a pointer to > another integer's storage, so that no array copy is needed. */ > ! template <bool SE, bool HDP> > struct wide_int_ref_storage : public wi::storage_ref > { > private: > *************** struct wide_int_ref_storage : public wi: > *** 948,955 **** > }; > > /* Create a reference from an existing reference. */ > ! template <bool SE> > ! inline wide_int_ref_storage <SE>:: > wide_int_ref_storage (const wi::storage_ref &x) > : storage_ref (x) > {} > --- 958,965 ---- > }; > > /* Create a reference from an existing reference. */ > ! template <bool SE, bool HDP> > ! inline wide_int_ref_storage <SE, HDP>:: > wide_int_ref_storage (const wi::storage_ref &x) > : storage_ref (x) > {} > *************** wide_int_ref_storage (const wi::storage_ > *** 957,988 **** > /* Create a reference to integer X in its natural precision. Note > that the natural precision is host-dependent for primitive > types. */ > ! template <bool SE> > template <typename T> > ! inline wide_int_ref_storage <SE>::wide_int_ref_storage (const T &x) > : storage_ref (wi::int_traits <T>::decompose (scratch, > wi::get_precision (x), x)) > { > } > > /* Create a reference to integer X in precision PRECISION. */ > ! template <bool SE> > template <typename T> > ! inline wide_int_ref_storage <SE>::wide_int_ref_storage (const T &x, > ! unsigned int > precision) > : storage_ref (wi::int_traits <T>::decompose (scratch, precision, x)) > { > } > > namespace wi > { > ! template <bool SE> > ! struct int_traits <wide_int_ref_storage <SE> > > { > static const enum precision_type precision_type = VAR_PRECISION; > ! /* wi::storage_ref can be a reference to a primitive type, > ! so this is the conservatively-correct setting. */ > ! static const bool host_dependent_precision = true; > static const bool is_sign_extended = SE; > }; > } > --- 967,996 ---- > /* Create a reference to integer X in its natural precision. Note > that the natural precision is host-dependent for primitive > types. */ > ! template <bool SE, bool HDP> > template <typename T> > ! inline wide_int_ref_storage <SE, HDP>::wide_int_ref_storage (const T &x) > : storage_ref (wi::int_traits <T>::decompose (scratch, > wi::get_precision (x), x)) > { > } > > /* Create a reference to integer X in precision PRECISION. */ > ! template <bool SE, bool HDP> > template <typename T> > ! inline wide_int_ref_storage <SE, HDP>:: > ! wide_int_ref_storage (const T &x, unsigned int precision) > : storage_ref (wi::int_traits <T>::decompose (scratch, precision, x)) > { > } > > namespace wi > { > ! template <bool SE, bool HDP> > ! struct int_traits <wide_int_ref_storage <SE, HDP> > > { > static const enum precision_type precision_type = VAR_PRECISION; > ! static const bool host_dependent_precision = HDP; > static const bool is_sign_extended = SE; > }; > } > Index: gcc/tree.h > =================================================================== > *** gcc/tree.h 2017-10-03 19:57:02.809678461 +0100 > --- gcc/tree.h 2017-10-03 19:57:03.678792572 +0100 > *************** extern bool anon_aggrname_p (const_tree) > *** 5120,5139 **** > /* The tree and const_tree overload templates. */ > namespace wi > { > - template <> > - struct int_traits <const_tree> > - { > - static const enum precision_type precision_type = VAR_PRECISION; > - static const bool host_dependent_precision = false; > - static const bool is_sign_extended = false; > - static unsigned int get_precision (const_tree); > - static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int, > - const_tree); > - }; > - > - template <> > - struct int_traits <tree> : public int_traits <const_tree> {}; > - > template <int N> > class extended_tree > { > --- 5120,5125 ---- > *************** extern bool anon_aggrname_p (const_tree) > *** 5157,5198 **** > static const unsigned int precision = N; > }; > > ! generic_wide_int <extended_tree <WIDE_INT_MAX_PRECISION> > > ! to_widest (const_tree); > ! > ! generic_wide_int <extended_tree <ADDR_MAX_PRECISION> > to_offset > (const_tree); > ! > wide_int to_wide (const_tree, unsigned int); > } > > ! inline unsigned int > ! wi::int_traits <const_tree>::get_precision (const_tree tcst) > ! { > ! return TYPE_PRECISION (TREE_TYPE (tcst)); > ! } > > ! /* Convert the tree_cst X into a wide_int of PRECISION. */ > ! inline wi::storage_ref > ! wi::int_traits <const_tree>::decompose (HOST_WIDE_INT *, > ! unsigned int precision, const_tree x) > ! { > ! gcc_checking_assert (precision == TYPE_PRECISION (TREE_TYPE (x))); > ! return wi::storage_ref (&TREE_INT_CST_ELT (x, 0), TREE_INT_CST_NUNITS (x), > ! precision); > ! } > > ! inline generic_wide_int <wi::extended_tree <WIDE_INT_MAX_PRECISION> > > wi::to_widest (const_tree t) > { > return t; > } > > ! inline generic_wide_int <wi::extended_tree <ADDR_MAX_PRECISION> > > wi::to_offset (const_tree t) > { > return t; > } > > /* Convert INTEGER_CST T to a wide_int of precision PREC, extending or > truncating as necessary. When extending, use sign extension if T's > type is signed and zero extension if T's type is unsigned. */ > --- 5143,5257 ---- > static const unsigned int precision = N; > }; > > ! typedef const generic_wide_int <extended_tree <WIDE_INT_MAX_PRECISION> > > ! tree_to_widest_ref; > ! typedef const generic_wide_int <extended_tree <ADDR_MAX_PRECISION> > > ! tree_to_offset_ref; > ! typedef const generic_wide_int<wide_int_ref_storage<false, false> > > ! tree_to_wide_ref; > ! > ! tree_to_widest_ref to_widest (const_tree); > ! tree_to_offset_ref to_offset (const_tree); > ! tree_to_wide_ref to_wide (const_tree); > wide_int to_wide (const_tree, unsigned int); > } > > ! /* Refer to INTEGER_CST T as though it were a widest_int. > > ! This function gives T's actual numerical value, influenced by the > ! signedness of its type. For example, a signed byte with just the > ! top bit set would be -128 while an unsigned byte with the same > ! bit pattern would be 128. > ! > ! This is the right choice when operating on groups of INTEGER_CSTs > ! that might have different signedness or precision. It is also the > ! right choice in code that specifically needs an approximation of > ! infinite-precision arithmetic instead of normal modulo arithmetic. > ! > ! The approximation of infinite precision is good enough for realistic > ! numbers of additions and subtractions of INTEGER_CSTs (where > ! "realistic" includes any number less than 1 << 31) but it cannot > ! represent the result of multiplying the two largest supported > ! INTEGER_CSTs. The overflow-checking form of wi::mul provides a way > ! of multiplying two arbitrary INTEGER_CSTs and checking that the > ! result is representable as a widest_int. > ! > ! Note that any overflow checking done on these values is relative to > ! the range of widest_int rather than the range of a TREE_TYPE. > ! > ! Calling this function should have no overhead in release builds, > ! so it is OK to call it several times for the same tree. If it > ! useful for readability reasons to reduce the number of calls, > ! it is more efficient to use: > ! > ! wi::tree_to_widest_ref wt = wi::to_widest (t); > ! > ! instead of: > > ! widest_int wt = wi::to_widest (t). */ > ! > ! inline wi::tree_to_widest_ref > wi::to_widest (const_tree t) > { > return t; > } > > ! /* Refer to INTEGER_CST T as though it were an offset_int. > ! > ! This function is an optimisation of wi::to_widest for cases > ! in which T is known to be a bit or byte count in the range > ! (-(2 ^ (N + BITS_PER_UNIT)), 2 ^ (N + BITS_PER_UNIT)), where N is > ! the target's address size in bits. > ! > ! This is the right choice when operating on bit or byte counts as > ! untyped numbers rather than M-bit values. The wi::to_widest comments > ! about addition, subtraction and multiplication apply here: sequences > ! of 1 << 31 additions and subtractions do not induce overflow, but > ! multiplying the largest sizes might. Again, > ! > ! wi::tree_to_offset_ref wt = wi::to_offset (t); > ! > ! is more efficient than: > ! > ! offset_int wt = wi::to_offset (t). */ > ! > ! inline wi::tree_to_offset_ref > wi::to_offset (const_tree t) > { > return t; > } > > + /* Refer to INTEGER_CST T as though it were a wide_int. > + > + In contrast to the approximation of infinite-precision numbers given > + by wi::to_widest and wi::to_offset, this function treats T as a > + signless collection of N bits, where N is the precision of T's type. > + As with machine registers, signedness is determined by the operation > + rather than the operands; for example, there is a distinction between > + signed and unsigned division. > + > + This is the right choice when operating on values with the same type > + using normal modulo arithmetic. The overflow-checking forms of things > + like wi::add check whether the result can be represented in T's type. > + > + Calling this function should have no overhead in release builds, > + so it is OK to call it several times for the same tree. If it > + useful for readability reasons to reduce the number of calls, > + it is more efficient to use: > + > + wi::tree_to_wide_ref wt = wi::to_wide (t); > + > + instead of: > + > + wide_int wt = wi::to_wide (t). */ > + > + inline wi::tree_to_wide_ref > + wi::to_wide (const_tree t) > + { > + return wi::storage_ref (&TREE_INT_CST_ELT (t, 0), TREE_INT_CST_NUNITS (t), > + TYPE_PRECISION (TREE_TYPE (t))); > + } > + > /* Convert INTEGER_CST T to a wide_int of precision PREC, extending or > truncating as necessary. When extending, use sign extension if T's > type is signed and zero extension if T's type is unsigned. */ > *************** wi::to_offset (const_tree t) > *** 5200,5206 **** > inline wide_int > wi::to_wide (const_tree t, unsigned int prec) > { > ! return wide_int::from (t, prec, TYPE_SIGN (TREE_TYPE (t))); > } > > template <int N> > --- 5259,5265 ---- > inline wide_int > wi::to_wide (const_tree t, unsigned int prec) > { > ! return wide_int::from (wi::to_wide (t), prec, TYPE_SIGN (TREE_TYPE (t))); > } > > template <int N> >