diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2017-10-10 16:55:34 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2017-10-10 16:55:34 +0000 |
commit | 8e6cdc90d41633e09a3a34bb8c6f71cf246101b2 (patch) | |
tree | c8d6aac483b647ae892778e9398965071da02686 /gcc/tree.h | |
parent | 3934b625ee2f522edf455191d1eaaa42e265a1d9 (diff) | |
download | gcc-8e6cdc90d41633e09a3a34bb8c6f71cf246101b2.zip gcc-8e6cdc90d41633e09a3a34bb8c6f71cf246101b2.tar.gz gcc-8e6cdc90d41633e09a3a34bb8c6f71cf246101b2.tar.bz2 |
Require wi::to_wide for trees
The wide_int routines allow things like:
wi::add (t, 1)
to add 1 to an INTEGER_CST T in its native precision. But 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
This patch therefore requires:
wi::to_wide (t)
when operating on INTEGER_CSTs in their native precision. This is
just as efficient, and makes 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) INTEGER_CSTs in their native precision 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.
2017-10-10 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, 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.
From-SVN: r253595
Diffstat (limited to 'gcc/tree.h')
-rw-r--r-- | gcc/tree.h | 129 |
1 files changed, 94 insertions, 35 deletions
@@ -5120,20 +5120,6 @@ extern bool anon_aggrname_p (const_tree); /* 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 { @@ -5157,42 +5143,115 @@ namespace wi 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); + 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); } -inline unsigned int -wi::int_traits <const_tree>::get_precision (const_tree tcst) -{ - return TYPE_PRECISION (TREE_TYPE (tcst)); -} +/* Refer to INTEGER_CST T as though it were a widest_int. -/* 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); -} + 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 is + 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: -inline generic_wide_int <wi::extended_tree <WIDE_INT_MAX_PRECISION> > + widest_int wt = wi::to_widest (t). */ + +inline wi::tree_to_widest_ref wi::to_widest (const_tree t) { return t; } -inline generic_wide_int <wi::extended_tree <ADDR_MAX_PRECISION> > +/* 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 is + 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. */ @@ -5200,7 +5259,7 @@ wi::to_offset (const_tree t) inline wide_int wi::to_wide (const_tree t, unsigned int prec) { - return wide_int::from (t, prec, TYPE_SIGN (TREE_TYPE (t))); + return wide_int::from (wi::to_wide (t), prec, TYPE_SIGN (TREE_TYPE (t))); } template <int N> |