This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Require wi::to_wide for trees


On Tue, Oct 3, 2017 at 9:14 PM, Richard Sandiford
<richard.sandiford@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.sandiford@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>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]