aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.h
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2017-10-10 16:55:34 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2017-10-10 16:55:34 +0000
commit8e6cdc90d41633e09a3a34bb8c6f71cf246101b2 (patch)
treec8d6aac483b647ae892778e9398965071da02686 /gcc/tree.h
parent3934b625ee2f522edf455191d1eaaa42e265a1d9 (diff)
downloadgcc-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.h129
1 files changed, 94 insertions, 35 deletions
diff --git a/gcc/tree.h b/gcc/tree.h
index 5e8419e..7c2d2e7 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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>