From: rsandifo Date: Sat, 9 Nov 2013 13:55:27 +0000 (+0000) Subject: Merge with trunk. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=55af3bae674945beea2845ed091e5ea341e8aabf;p=thirdparty%2Fgcc.git Merge with trunk. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@204616 138bc75d-0d04-0410-961f-82ee72b054a4 --- 55af3bae674945beea2845ed091e5ea341e8aabf diff --cc gcc/doc/tm.texi index 7fdca1986907,35cfa995583d..e92089eae9d3 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@@ -11494,49 -11500,6 +11494,52 @@@ The support includes the assembler, lin The default value of this hook is based on target's libc. @end deftypefn + @deftypefn {Target Hook} void TARGET_ATOMIC_ASSIGN_EXPAND_FENV (tree *@var{hold}, tree *@var{clear}, tree *@var{update}) + ISO C11 requires atomic compound assignments that may raise floating-point exceptions to raise exceptions corresponding to the arithmetic operation whose result was successfully stored in a compare-and-exchange sequence. This requires code equivalent to calls to @code{feholdexcept}, @code{feclearexcept} and @code{feupdateenv} to be generated at appropriate points in the compare-and-exchange sequence. This hook should set @code{*@var{hold}} to an expression equivalent to the call to @code{feholdexcept}, @code{*@var{clear}} to an expression equivalent to the call to @code{feclearexcept} and @code{*@var{update}} to an expression equivalent to the call to @code{feupdateenv}. The three expressions are @code{NULL_TREE} on entry to the hook and may be left as @code{NULL_TREE} if no code is required in a particular place. The default implementation leaves all three expressions as @code{NULL_TREE}. The @code{__atomic_feraiseexcept} function from @code{libatomic} may be of use as part of the code generated in @code{*@var{update}}. + @end deftypefn ++ +@defmac TARGET_SUPPORTS_WIDE_INT + +On older ports, large integers are stored in @code{CONST_DOUBLE} rtl +objects. Newer ports define @code{TARGET_SUPPORTS_WIDE_INT} to be non +zero to indicate that large integers are stored in +@code{CONST_WIDE_INT} rtl objects. The @code{CONST_WIDE_INT} allows +very large integer constants to be represented. @code{CONST_DOUBLE} +are limited to twice the size of host's @code{HOST_WIDE_INT} +representation. + +Converting a port mostly requires looking for the places where +@code{CONST_DOUBLES} are used with @code{VOIDmode} and replacing that +code with code that accesses @code{CONST_WIDE_INT}s. @samp{"grep -i +const_double"} at the port level gets you to 95% of the changes that +need to be made. There are a few places that require a deeper look. + +@itemize @bullet +@item +There is no equivalent to @code{hval} and @code{lval} for +@code{CONST_WIDE_INT}s. This would be difficult to express in the md +language since there are a variable number of elements. + +Most ports only check that @code{hval} is either 0 or -1 to see if the +value is small. As mentioned above, this will no longer be necessary +since small constants are always @code{CONST_INT}. Of course there +are still a few exceptions, the alpha's constraint used by the zap +instruction certainly requires careful examination by C code. +However, all the current code does is pass the hval and lval to C +code, so evolving the c code to look at the @code{CONST_WIDE_INT} is +not really a large change. + +@item +Because there is no standard template that ports use to materialize +constants, there is likely to be some futzing that is unique to each +port in this code. + +@item +The rtx costs may have to be adjusted to properly account for larger +constants that are represented as @code{CONST_WIDE_INT}. +@end itemize + +All and all it does not takes long to convert ports that the +maintainer is familiar with. + +@end defmac - diff --cc gcc/doc/tm.texi.in index 906621209755,b10ecd7dda8d..008f65c89816 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@@ -8401,49 -8407,4 +8401,50 @@@ and the associated definitions of thos @hook TARGET_HAS_IFUNC_P + @hook TARGET_ATOMIC_ASSIGN_EXPAND_FENV ++ +@defmac TARGET_SUPPORTS_WIDE_INT + +On older ports, large integers are stored in @code{CONST_DOUBLE} rtl +objects. Newer ports define @code{TARGET_SUPPORTS_WIDE_INT} to be non +zero to indicate that large integers are stored in +@code{CONST_WIDE_INT} rtl objects. The @code{CONST_WIDE_INT} allows +very large integer constants to be represented. @code{CONST_DOUBLE} +are limited to twice the size of host's @code{HOST_WIDE_INT} +representation. + +Converting a port mostly requires looking for the places where +@code{CONST_DOUBLES} are used with @code{VOIDmode} and replacing that +code with code that accesses @code{CONST_WIDE_INT}s. @samp{"grep -i +const_double"} at the port level gets you to 95% of the changes that +need to be made. There are a few places that require a deeper look. + +@itemize @bullet +@item +There is no equivalent to @code{hval} and @code{lval} for +@code{CONST_WIDE_INT}s. This would be difficult to express in the md +language since there are a variable number of elements. + +Most ports only check that @code{hval} is either 0 or -1 to see if the +value is small. As mentioned above, this will no longer be necessary +since small constants are always @code{CONST_INT}. Of course there +are still a few exceptions, the alpha's constraint used by the zap +instruction certainly requires careful examination by C code. +However, all the current code does is pass the hval and lval to C +code, so evolving the c code to look at the @code{CONST_WIDE_INT} is +not really a large change. + +@item +Because there is no standard template that ports use to materialize +constants, there is likely to be some futzing that is unique to each +port in this code. + +@item +The rtx costs may have to be adjusted to properly account for larger +constants that are represented as @code{CONST_WIDE_INT}. +@end itemize + +All and all it does not takes long to convert ports that the +maintainer is familiar with. + +@end defmac - diff --cc gcc/expr.c index aae57ac65de2,28b43320798c..52044ae37ebd --- a/gcc/expr.c +++ b/gcc/expr.c @@@ -4536,19 -4566,18 +4536,18 @@@ get_bit_range (unsigned HOST_WIDE_INT * relative to the representative. DECL_FIELD_OFFSET of field and repr are the same by construction if they are not constants, see finish_bitfield_layout. */ - if (host_integerp (DECL_FIELD_OFFSET (field), 1) - && host_integerp (DECL_FIELD_OFFSET (repr), 1)) - bitoffset = (tree_low_cst (DECL_FIELD_OFFSET (field), 1) - - tree_low_cst (DECL_FIELD_OFFSET (repr), 1)) * BITS_PER_UNIT; + if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field)) + && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr))) + bitoffset = (tree_to_uhwi (DECL_FIELD_OFFSET (field)) + - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT; else bitoffset = 0; - bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) - - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); + bitoffset += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)) + - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr))); /* If the adjustment is larger than bitpos, we would have a negative bit - position for the lower bound and this may wreak havoc later. This can - occur only if we have a non-null offset, so adjust offset and bitpos - to make the lower bound non-negative. */ + position for the lower bound and this may wreak havoc later. Adjust + offset and bitpos to make the lower bound non-negative in that case. */ if (bitoffset > *bitpos) { HOST_WIDE_INT adjust = bitoffset - *bitpos; diff --cc gcc/fold-const.c index f91a4b191c67,3e6f15887dbb..6aee8c4b33c1 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@@ -8892,9 -8941,20 +8892,23 @@@ pointer_may_wrap_p (tree base, tree off size = base_size; } - return total.low > (unsigned HOST_WIDE_INT) size; + return total.to_uhwi () > (unsigned HOST_WIDE_INT) size; } + /* Return the HOST_WIDE_INT least significant bits of T, a sizetype + kind INTEGER_CST. This makes sure to properly sign-extend the + constant. */ + + static HOST_WIDE_INT + size_low_cst (const_tree t) + { - double_int d = tree_to_double_int (t); - return d.sext (TYPE_PRECISION (TREE_TYPE (t))).low; ++ HOST_WIDE_INT w = TREE_INT_CST_ELT (t, 0); ++ int prec = TYPE_PRECISION (TREE_TYPE (t)); ++ if (prec < HOST_BITS_PER_WIDE_INT) ++ return sext_hwi (w, prec); ++ return w; + } + /* Subroutine of fold_binary. This routine performs all of the transformations that are common to the equality/inequality operators (EQ_EXPR and NE_EXPR) and the ordering operators diff --cc gcc/targhooks.c index b136020b3736,a671486453a4..9bb925af854d --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@@ -272,16 -272,7 +272,6 @@@ default_cxx_guard_type (void return long_long_integer_type_node; } - /* An implementation of TARGET_CAN_USE_DOLOOP_P for targets that do - not support nested low-overhead loops. */ - - bool - can_use_doloop_if_innermost (const widest_int &, const widest_int &, - unsigned int loop_depth, bool) - { - return loop_depth == 1; - } -- /* Returns the size of the cookie to use when allocating an array whose elements have the indicated TYPE. Assumes that it is already known that a cookie is needed. */ @@@ -1740,5 -1738,14 +1737,14 @@@ default_builtin_chkp_function (unsigne return NULL_TREE; } + /* An implementation of TARGET_CAN_USE_DOLOOP_P for targets that do + not support nested low-overhead loops. */ + + bool -can_use_doloop_if_innermost (double_int, double_int, ++can_use_doloop_if_innermost (const widest_int &, const widest_int &, + unsigned int loop_depth, bool) + { + return loop_depth == 1; + } #include "gt-targhooks.h" diff --cc gcc/tree-affine.c index 239b78099256,b492ff0a2118..07a5d2eda62a --- a/gcc/tree-affine.c +++ b/gcc/tree-affine.c @@@ -870,11 -874,12 +870,12 @@@ debug_aff (aff_tree *val fprintf (stderr, "\n"); } - /* Returns address of the reference REF in ADDR. The size of the accessed - location is stored to SIZE. */ + /* Computes address of the reference REF in ADDR. The size of the accessed + location is stored to SIZE. Returns the ultimate containing object to + which REF refers. */ - void + tree -get_inner_reference_aff (tree ref, aff_tree *addr, double_int *size) +get_inner_reference_aff (tree ref, aff_tree *addr, widest_int *size) { HOST_WIDE_INT bitsize, bitpos; tree toff; @@@ -895,10 -900,13 +896,12 @@@ aff_combination_add (addr, &tmp); } - aff_combination_const (&tmp, sizetype, - double_int::from_shwi (bitpos / BITS_PER_UNIT)); + aff_combination_const (&tmp, sizetype, bitpos / BITS_PER_UNIT); aff_combination_add (addr, &tmp); - *size = double_int::from_shwi ((bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT); + *size = (bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT; + + return base; } /* Returns true if a region of size SIZE1 at position 0 and a region of diff --cc gcc/tree-affine.h index 941d45aeb414,86f90d82da08..758684bc5c3c --- a/gcc/tree-affine.h +++ b/gcc/tree-affine.h @@@ -76,10 -74,9 +76,10 @@@ bool aff_combination_constant_multiple_ void aff_combination_expand (aff_tree *, struct pointer_map_t **); void tree_to_aff_combination_expand (tree, tree, aff_tree *, struct pointer_map_t **); - void get_inner_reference_aff (tree, aff_tree *, widest_int *); -tree get_inner_reference_aff (tree, aff_tree *, double_int *); ++tree get_inner_reference_aff (tree, aff_tree *, widest_int *); void free_affine_expand_cache (struct pointer_map_t **); -bool aff_comb_cannot_overlap_p (aff_tree *, double_int, double_int); +bool aff_comb_cannot_overlap_p (aff_tree *, const widest_int &, + const widest_int &); /* Debugging functions. */ void debug_aff (aff_tree *); diff --cc gcc/tree-dfa.c index 8228199308f3,a31a0a28161a..03e5bccd25e0 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@@ -567,10 -566,10 +567,10 @@@ get_ref_base_and_extent (tree exp, HOST padding that is there for alignment purposes. */ if (seen_variable_array_ref && maxsize != -1 - && (!bit_offset.fits_shwi () - || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1) + && (!wi::fits_shwi_p (bit_offset) + || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp))) || (bit_offset.to_shwi () + maxsize - == (signed) tree_to_uhwi - == (HOST_WIDE_INT) TREE_INT_CST_LOW ++ == (HOST_WIDE_INT) tree_to_uhwi (TYPE_SIZE (TREE_TYPE (exp)))))) maxsize = -1; @@@ -604,10 -603,11 +604,10 @@@ /* We need to deal with variable arrays ending structures. */ if (seen_variable_array_ref && maxsize != -1 - && (!bit_offset.fits_shwi () - || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1) + && (!wi::fits_shwi_p (bit_offset) + || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp))) || (bit_offset.to_shwi () + maxsize - == (signed) tree_to_uhwi (TYPE_SIZE (TREE_TYPE (exp)))))) - == (HOST_WIDE_INT) TREE_INT_CST_LOW - (TYPE_SIZE (TREE_TYPE (exp)))))) ++ == (HOST_WIDE_INT) tree_to_uhwi (TYPE_SIZE (TREE_TYPE (exp)))))) maxsize = -1; done: diff --cc gcc/tree-ssa-ccp.c index a85cb5bd3588,b4dfd4928cdc..3c6a233ed6b6 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@@ -576,8 -575,8 +583,8 @@@ get_value_for_expr (tree expr, bool for { val.lattice_val = CONSTANT; val.value = expr; - val.mask = double_int_zero; + val.mask = 0; - canonicalize_float_value (&val); + canonicalize_value (&val); } else if (TREE_CODE (expr) == ADDR_EXPR) val = get_value_from_alignment (expr); diff --cc gcc/tree-ssa-loop-ivopts.c index fe9a1dca8115,f7da12674161..1ca3d0bb8761 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@@ -927,8 -928,26 +928,26 @@@ alloc_iv (tree base, tree step struct iv *iv = XCNEW (struct iv); gcc_assert (step != NULL_TREE); + /* Lower all address expressions except ones with DECL_P as operand. + By doing this: + 1) More accurate cost can be computed for address expressions; + 2) Duplicate candidates won't be created for bases in different + forms, like &a[0] and &a. */ + STRIP_NOPS (base_object); + if (TREE_CODE (base_object) == ADDR_EXPR + && !DECL_P (TREE_OPERAND (base_object, 0))) + { + aff_tree comb; - double_int size; ++ widest_int size; + base_object = get_inner_reference_aff (TREE_OPERAND (base_object, 0), + &comb, &size); + gcc_assert (base_object != NULL_TREE); + base_object = build_fold_addr_expr (base_object); + base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb)); + } + iv->base = base; - iv->base_object = determine_base_object (base); + iv->base_object = determine_base_object (base_object); iv->step = step; iv->biv_p = false; iv->have_use_for = false; diff --cc gcc/tree-ssa-loop-niter.c index 9a07db20e61e,3014faae7968..ef3367c51c65 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@@ -45,7 -45,7 +45,8 @@@ along with GCC; see the file COPYING3 #include "diagnostic-core.h" #include "tree-inline.h" #include "tree-pass.h" + #include "tree-ssanames.h" +#include "wide-int-print.h" #define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0) @@@ -116,9 -120,12 +117,12 @@@ split_to_var_and_offset (tree expr, tre in TYPE to MIN and MAX. */ static void - determine_value_range (tree type, tree var, mpz_t off, + determine_value_range (struct loop *loop, tree type, tree var, mpz_t off, mpz_t min, mpz_t max) { - double_int minv, maxv; ++ widest_int minv, maxv; + enum value_range_type rtype = VR_VARYING; + /* If the expression is a constant, we know its value exactly. */ if (integer_zerop (var)) { @@@ -127,9 -134,73 +131,73 @@@ return; } + get_type_static_bounds (type, min, max); + + /* See if we have some range info from VRP. */ + if (TREE_CODE (var) == SSA_NAME && INTEGRAL_TYPE_P (type)) + { + edge e = loop_preheader_edge (loop); + gimple_stmt_iterator gsi; + + /* Either for VAR itself... */ + rtype = get_range_info (var, &minv, &maxv); + /* Or for PHI results in loop->header where VAR is used as + PHI argument from the loop preheader edge. */ + for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple phi = gsi_stmt (gsi); - double_int minc, maxc; ++ widest_int minc, maxc; + if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var + && (get_range_info (gimple_phi_result (phi), &minc, &maxc) + == VR_RANGE)) + { + if (rtype != VR_RANGE) + { + rtype = VR_RANGE; + minv = minc; + maxv = maxc; + } + else + { - minv = minv.max (minc, TYPE_UNSIGNED (type)); - maxv = maxv.min (maxc, TYPE_UNSIGNED (type)); - gcc_assert (minv.cmp (maxv, TYPE_UNSIGNED (type)) <= 0); ++ minv = wi::smax (minv, minc); ++ maxv = wi::smin (maxv, maxc); ++ gcc_assert (wi::les_p (minv, maxv)); + } + } + } + if (rtype == VR_RANGE) + { + mpz_t minm, maxm; - gcc_assert (minv.cmp (maxv, TYPE_UNSIGNED (type)) <= 0); ++ gcc_assert (wi::les_p (minv, maxv)); + mpz_init (minm); + mpz_init (maxm); - mpz_set_double_int (minm, minv, TYPE_UNSIGNED (type)); - mpz_set_double_int (maxm, maxv, TYPE_UNSIGNED (type)); ++ wi::to_mpz (minv, minm, SIGNED); ++ wi::to_mpz (maxv, maxm, SIGNED); + mpz_add (minm, minm, off); + mpz_add (maxm, maxm, off); + /* If the computation may not wrap or off is zero, then this + is always fine. If off is negative and minv + off isn't + smaller than type's minimum, or off is positive and + maxv + off isn't bigger than type's maximum, use the more + precise range too. */ + if (nowrap_type_p (type) + || mpz_sgn (off) == 0 + || (mpz_sgn (off) < 0 && mpz_cmp (minm, min) >= 0) + || (mpz_sgn (off) > 0 && mpz_cmp (maxm, max) <= 0)) + { + mpz_set (min, minm); + mpz_set (max, maxm); + mpz_clear (minm); + mpz_clear (maxm); + return; + } + mpz_clear (minm); + mpz_clear (maxm); + } + } + /* If the computation may wrap, we know nothing about the value, except for the range of the type. */ - get_type_static_bounds (type, min, max); if (!nowrap_type_p (type)) return; diff --cc gcc/tree-vect-data-refs.c index 919db21fb96d,b2a31b1de4a3..2a203eb4e09d --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@@ -2671,52 -2757,182 +2757,180 @@@ vect_prune_runtime_alias_test_list (loo dump_printf_loc (MSG_NOTE, vect_location, "=== vect_prune_runtime_alias_test_list ===\n"); - for (i = 0; i < ddrs.length (); ) + if (may_alias_ddrs.is_empty ()) + return true; + + /* Basically, for each pair of dependent data refs store_ptr_0 + and load_ptr_0, we create an expression: + + ((store_ptr_0 + store_segment_length_0) <= load_ptr_0) + || (load_ptr_0 + load_segment_length_0) <= store_ptr_0)) + + for aliasing checks. However, in some cases we can decrease + the number of checks by combining two checks into one. For + example, suppose we have another pair of data refs store_ptr_0 + and load_ptr_1, and if the following condition is satisfied: + + load_ptr_0 < load_ptr_1 && + load_ptr_1 - load_ptr_0 - load_segment_length_0 < store_segment_length_0 + + (this condition means, in each iteration of vectorized loop, + the accessed memory of store_ptr_0 cannot be between the memory + of load_ptr_0 and load_ptr_1.) + + we then can use only the following expression to finish the + alising checks between store_ptr_0 & load_ptr_0 and + store_ptr_0 & load_ptr_1: + + ((store_ptr_0 + store_segment_length_0) <= load_ptr_0) + || (load_ptr_1 + load_segment_length_1 <= store_ptr_0)) + + Note that we only consider that load_ptr_0 and load_ptr_1 have the + same basic address. */ + + comp_alias_ddrs.create (may_alias_ddrs.length ()); + + /* First, we collect all data ref pairs for aliasing checks. */ + FOR_EACH_VEC_ELT (may_alias_ddrs, i, ddr) { - bool found; - ddr_p ddr_i; + struct data_reference *dr_a, *dr_b; + gimple dr_group_first_a, dr_group_first_b; + tree segment_length_a, segment_length_b; + gimple stmt_a, stmt_b; + + dr_a = DDR_A (ddr); + stmt_a = DR_STMT (DDR_A (ddr)); + dr_group_first_a = GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_a)); + if (dr_group_first_a) + { + stmt_a = dr_group_first_a; + dr_a = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_a)); + } - ddr_i = ddrs[i]; - found = false; + dr_b = DDR_B (ddr); + stmt_b = DR_STMT (DDR_B (ddr)); + dr_group_first_b = GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_b)); + if (dr_group_first_b) + { + stmt_b = dr_group_first_b; + dr_b = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_b)); + } - for (j = 0; j < i; j++) - { - ddr_p ddr_j = ddrs[j]; + if (!operand_equal_p (DR_STEP (dr_a), DR_STEP (dr_b), 0)) + length_factor = scalar_loop_iters; + else + length_factor = size_int (vect_factor); + segment_length_a = vect_vfa_segment_size (dr_a, length_factor); + segment_length_b = vect_vfa_segment_size (dr_b, length_factor); + + dr_addr_with_seg_len_pair_t dr_with_seg_len_pair + (dr_addr_with_seg_len + (dr_a, DR_BASE_ADDRESS (dr_a), + size_binop (PLUS_EXPR, DR_OFFSET (dr_a), DR_INIT (dr_a)), + segment_length_a), + dr_addr_with_seg_len + (dr_b, DR_BASE_ADDRESS (dr_b), + size_binop (PLUS_EXPR, DR_OFFSET (dr_b), DR_INIT (dr_b)), + segment_length_b)); + + if (compare_tree (dr_with_seg_len_pair.first.basic_addr, + dr_with_seg_len_pair.second.basic_addr) > 0) + swap (dr_with_seg_len_pair.first, dr_with_seg_len_pair.second); + + comp_alias_ddrs.safe_push (dr_with_seg_len_pair); + } + + /* Second, we sort the collected data ref pairs so that we can scan + them once to combine all possible aliasing checks. */ + comp_alias_ddrs.qsort (comp_dr_addr_with_seg_len_pair); - if (vect_vfa_range_equal (ddr_i, ddr_j)) + /* Third, we scan the sorted dr pairs and check if we can combine + alias checks of two neighbouring dr pairs. */ + for (size_t i = 1; i < comp_alias_ddrs.length (); ++i) + { + /* Deal with two ddrs (dr_a1, dr_b1) and (dr_a2, dr_b2). */ + dr_addr_with_seg_len *dr_a1 = &comp_alias_ddrs[i-1].first, + *dr_b1 = &comp_alias_ddrs[i-1].second, + *dr_a2 = &comp_alias_ddrs[i].first, + *dr_b2 = &comp_alias_ddrs[i].second; + + /* Remove duplicate data ref pairs. */ + if (*dr_a1 == *dr_a2 && *dr_b1 == *dr_b2) + { + if (dump_enabled_p ()) { - if (dump_enabled_p ()) - { - dump_printf_loc (MSG_NOTE, vect_location, - "found equal ranges "); - dump_generic_expr (MSG_NOTE, TDF_SLIM, - DR_REF (DDR_A (ddr_i))); - dump_printf (MSG_NOTE, ", "); - dump_generic_expr (MSG_NOTE, TDF_SLIM, - DR_REF (DDR_B (ddr_i))); - dump_printf (MSG_NOTE, " and "); - dump_generic_expr (MSG_NOTE, TDF_SLIM, - DR_REF (DDR_A (ddr_j))); - dump_printf (MSG_NOTE, ", "); - dump_generic_expr (MSG_NOTE, TDF_SLIM, - DR_REF (DDR_B (ddr_j))); - dump_printf (MSG_NOTE, "\n"); - } - found = true; - break; + dump_printf_loc (MSG_NOTE, vect_location, + "found equal ranges "); + dump_generic_expr (MSG_NOTE, TDF_SLIM, + DR_REF (dr_a1->dr)); + dump_printf (MSG_NOTE, ", "); + dump_generic_expr (MSG_NOTE, TDF_SLIM, + DR_REF (dr_b1->dr)); + dump_printf (MSG_NOTE, " and "); + dump_generic_expr (MSG_NOTE, TDF_SLIM, + DR_REF (dr_a2->dr)); + dump_printf (MSG_NOTE, ", "); + dump_generic_expr (MSG_NOTE, TDF_SLIM, + DR_REF (dr_b2->dr)); + dump_printf (MSG_NOTE, "\n"); } + + comp_alias_ddrs.ordered_remove (i--); + continue; } - if (found) - { - ddrs.ordered_remove (i); - continue; - } - i++; + if (*dr_a1 == *dr_a2 || *dr_b1 == *dr_b2) + { + /* We consider the case that DR_B1 and DR_B2 are same memrefs, + and DR_A1 and DR_A2 are two consecutive memrefs. */ + if (*dr_a1 == *dr_a2) + { + swap (dr_a1, dr_b1); + swap (dr_a2, dr_b2); + } + + if (!operand_equal_p (dr_a1->basic_addr, dr_a2->basic_addr, 0) - || !host_integerp (dr_a1->offset, 0) - || !host_integerp (dr_a2->offset, 0)) ++ || !tree_fits_shwi_p (dr_a1->offset) ++ || !tree_fits_shwi_p (dr_a2->offset)) + continue; + - HOST_WIDE_INT diff = TREE_INT_CST_LOW (dr_a2->offset) - - TREE_INT_CST_LOW (dr_a1->offset); ++ HOST_WIDE_INT diff = (tree_to_shwi (dr_a2->offset) ++ - tree_to_shwi (dr_a1->offset)); + + + /* Now we check if the following condition is satisfied: + + DIFF - SEGMENT_LENGTH_A < SEGMENT_LENGTH_B + + where DIFF = DR_A2->OFFSET - DR_A1->OFFSET. However, + SEGMENT_LENGTH_A or SEGMENT_LENGTH_B may not be constant so we + have to make a best estimation. We can get the minimum value + of SEGMENT_LENGTH_B as a constant, represented by MIN_SEG_LEN_B, + then either of the following two conditions can guarantee the + one above: + + 1: DIFF <= MIN_SEG_LEN_B + 2: DIFF - SEGMENT_LENGTH_A < MIN_SEG_LEN_B + + */ + - HOST_WIDE_INT - min_seg_len_b = (TREE_CODE (dr_b1->seg_len) == INTEGER_CST) ? - TREE_INT_CST_LOW (dr_b1->seg_len) : - vect_factor; ++ HOST_WIDE_INT min_seg_len_b = (tree_fits_shwi_p (dr_b1->seg_len) ++ ? tree_to_shwi (dr_b1->seg_len) ++ : vect_factor); + + if (diff <= min_seg_len_b - || (TREE_CODE (dr_a1->seg_len) == INTEGER_CST - && diff - (HOST_WIDE_INT) TREE_INT_CST_LOW (dr_a1->seg_len) < - min_seg_len_b)) ++ || (tree_fits_shwi_p (dr_a1->seg_len) ++ && diff - tree_to_shwi (dr_a1->seg_len) < min_seg_len_b)) + { + dr_a1->seg_len = size_binop (PLUS_EXPR, + dr_a2->seg_len, size_int (diff)); + comp_alias_ddrs.ordered_remove (i--); + } + } } - if (ddrs.length () > - (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS)) + if ((int) comp_alias_ddrs.length () > + PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS)) { if (dump_enabled_p ()) { diff --cc gcc/tree-vrp.c index 34c526ecedf1,8f8b5ebada78..3454140f67c6 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@@ -1986,16 -1973,15 +1968,16 @@@ vrp_int_const_binop (enum tree_code cod the bit is 1, otherwise it might be 0 or 1. */ static bool -zero_nonzero_bits_from_vr (value_range_t *vr, - double_int *may_be_nonzero, - double_int *must_be_nonzero) +zero_nonzero_bits_from_vr (const tree expr_type, + value_range_t *vr, + wide_int *may_be_nonzero, + wide_int *must_be_nonzero) { - *may_be_nonzero = double_int_minus_one; - *must_be_nonzero = double_int_zero; + *may_be_nonzero = wi::minus_one (TYPE_PRECISION (expr_type)); + *must_be_nonzero = wi::zero (TYPE_PRECISION (expr_type)); if (!range_int_cst_p (vr) - || TREE_OVERFLOW (vr->min) - || TREE_OVERFLOW (vr->max)) + || is_overflow_infinity (vr->min) + || is_overflow_infinity (vr->max)) return false; if (range_int_cst_singleton_p (vr)) diff --cc gcc/tree.c index e9b1b80b5ebe,686a680f94c6..3dbe6984fe74 --- a/gcc/tree.c +++ b/gcc/tree.c @@@ -589,85 -588,9 +589,9 @@@ decl_assembler_name (tree decl return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name; } - /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */ - - bool - decl_assembler_name_equal (tree decl, const_tree asmname) - { - tree decl_asmname = DECL_ASSEMBLER_NAME (decl); - const char *decl_str; - const char *asmname_str; - bool test = false; - - if (decl_asmname == asmname) - return true; - - decl_str = IDENTIFIER_POINTER (decl_asmname); - asmname_str = IDENTIFIER_POINTER (asmname); - - - /* If the target assembler name was set by the user, things are trickier. - We have a leading '*' to begin with. After that, it's arguable what - is the correct thing to do with -fleading-underscore. Arguably, we've - historically been doing the wrong thing in assemble_alias by always - printing the leading underscore. Since we're not changing that, make - sure user_label_prefix follows the '*' before matching. */ - if (decl_str[0] == '*') - { - size_t ulp_len = strlen (user_label_prefix); - - decl_str ++; - - if (ulp_len == 0) - test = true; - else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0) - decl_str += ulp_len, test=true; - else - decl_str --; - } - if (asmname_str[0] == '*') - { - size_t ulp_len = strlen (user_label_prefix); - - asmname_str ++; - - if (ulp_len == 0) - test = true; - else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0) - asmname_str += ulp_len, test=true; - else - asmname_str --; - } - - if (!test) - return false; - return strcmp (decl_str, asmname_str) == 0; - } - - /* Hash asmnames ignoring the user specified marks. */ - - hashval_t - decl_assembler_name_hash (const_tree asmname) - { - if (IDENTIFIER_POINTER (asmname)[0] == '*') - { - const char *decl_str = IDENTIFIER_POINTER (asmname) + 1; - size_t ulp_len = strlen (user_label_prefix); - - if (ulp_len == 0) - ; - else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0) - decl_str += ulp_len; - - return htab_hash_string (decl_str); - } - - return htab_hash_string (IDENTIFIER_POINTER (asmname)); - } - /* Compute the number of bytes occupied by a tree with code CODE. This function cannot be used for nodes that have variable sizes, - including TREE_VEC, STRING_CST, and CALL_EXPR. */ + including TREE_VEC, INTEGER_CST, STRING_CST, and CALL_EXPR. */ size_t tree_code_size (enum tree_code code) { @@@ -6245,6 -6084,48 +6094,48 @@@ check_aligned_type (const_tree cand, co TYPE_ATTRIBUTES (base))); } + /* This function checks to see if TYPE matches the size one of the built-in + atomic types, and returns that core atomic type. */ + + static tree + find_atomic_core_type (tree type) + { + tree base_atomic_type; + + /* Only handle complete types. */ + if (TYPE_SIZE (type) == NULL_TREE) + return NULL_TREE; + - HOST_WIDE_INT type_size = tree_low_cst (TYPE_SIZE (type), 1); ++ HOST_WIDE_INT type_size = tree_to_uhwi (TYPE_SIZE (type)); + switch (type_size) + { + case 8: + base_atomic_type = atomicQI_type_node; + break; + + case 16: + base_atomic_type = atomicHI_type_node; + break; + + case 32: + base_atomic_type = atomicSI_type_node; + break; + + case 64: + base_atomic_type = atomicDI_type_node; + break; + + case 128: + base_atomic_type = atomicTI_type_node; + break; + + default: + base_atomic_type = NULL_TREE; + } + + return base_atomic_type; + } + /* Return a version of the TYPE, qualified as indicated by the TYPE_QUALS, if one exists. If no qualified version exists yet, return NULL_TREE. */ @@@ -7026,23 -6938,45 +6930,9 @@@ tree_int_cst_lt (const_tree t1, const_t int tree_int_cst_compare (const_tree t1, const_tree t2) { - if (tree_int_cst_lt (t1, t2)) - return -1; - else if (tree_int_cst_lt (t2, t1)) - return 1; - else - return 0; -} - -/* Return 1 if T is an INTEGER_CST that can be manipulated efficiently on - the host. If POS is zero, the value can be represented in a single - HOST_WIDE_INT. If POS is nonzero, the value must be non-negative and can - be represented in a single unsigned HOST_WIDE_INT. */ - -int -host_integerp (const_tree t, int pos) -{ - if (t == NULL_TREE) - return 0; - - return (TREE_CODE (t) == INTEGER_CST - && ((TREE_INT_CST_HIGH (t) == 0 - && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0) - || (! pos && TREE_INT_CST_HIGH (t) == -1 - && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0 - && !TYPE_UNSIGNED (TREE_TYPE (t))) - || (pos && TREE_INT_CST_HIGH (t) == 0))); -} - -/* Return the HOST_WIDE_INT least significant bits of T if it is an - INTEGER_CST and there is no overflow. POS is nonzero if the result must - be non-negative. We must be able to satisfy the above conditions. */ - -HOST_WIDE_INT -tree_low_cst (const_tree t, int pos) -{ - gcc_assert (host_integerp (t, pos)); - return TREE_INT_CST_LOW (t); + return wi::cmps (wi::to_widest (t1), wi::to_widest (t2)); } - /* Return the HOST_WIDE_INT least significant bits of T, a sizetype - kind INTEGER_CST. This makes sure to properly sign-extend the - constant. */ - - HOST_WIDE_INT - size_low_cst (const_tree t) - { - HOST_WIDE_INT w = TREE_INT_CST_ELT (t, 0); - int prec = TYPE_PRECISION (TREE_TYPE (t)); - if (prec < HOST_BITS_PER_WIDE_INT) - return sext_hwi (w, prec); - return w; - } - /* Return the most significant (sign) bit of T. */ int @@@ -7092,27 -7035,9 +6982,9 @@@ tree_int_cst_min_precision (tree value if (integer_zerop (value)) return 1; else - return tree_floor_log2 (value) + 1 + !unsignedp; + return tree_floor_log2 (value) + 1 + (sgn == SIGNED ? 1 : 0) ; } - /* Compare two constructor-element-type constants. Return 1 if the lists - are known to be equal; otherwise return 0. */ - - int - simple_cst_list_equal (const_tree l1, const_tree l2) - { - while (l1 != NULL_TREE && l2 != NULL_TREE) - { - if (simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2)) != 1) - return 0; - - l1 = TREE_CHAIN (l1); - l2 = TREE_CHAIN (l2); - } - - return l1 == l2; - } - /* Return truthvalue of whether T1 is the same tree structure as T2. Return 1 if they are the same. Return 0 if they are understandably different. @@@ -12406,4 -12224,23 +12085,22 @@@ get_tree_code_name (enum tree_code code return tree_code_name[code]; } + /* Drops the TREE_OVERFLOW flag from T. */ + + tree + drop_tree_overflow (tree t) + { + gcc_checking_assert (TREE_OVERFLOW (t)); + + /* For tree codes with a sharing machinery re-build the result. */ + if (TREE_CODE (t) == INTEGER_CST) - return build_int_cst_wide (TREE_TYPE (t), - TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t)); ++ return wide_int_to_tree (TREE_TYPE (t), t); + + /* Otherwise, as all tcc_constants are possibly shared, copy the node + and drop the flag. */ + t = copy_node (t); + TREE_OVERFLOW (t) = 0; + return t; + } + #include "gt-tree.h" diff --cc gcc/tree.h index 1d8af651ed8c,c4b23d0864ab..8c5eb44fab1b --- a/gcc/tree.h +++ b/gcc/tree.h @@@ -3824,10 -3647,23 +3836,9 @@@ extern int attribute_list_contained (co extern int tree_int_cst_equal (const_tree, const_tree); extern int tree_int_cst_lt (const_tree, const_tree); extern int tree_int_cst_compare (const_tree, const_tree); - extern HOST_WIDE_INT size_low_cst (const_tree); -extern int host_integerp (const_tree, int) -#ifndef ENABLE_TREE_CHECKING - ATTRIBUTE_PURE /* host_integerp is pure only when checking is disabled. */ -#endif - ; -extern HOST_WIDE_INT tree_low_cst (const_tree, int); -#if !defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 4003) -extern inline __attribute__ ((__gnu_inline__)) HOST_WIDE_INT -tree_low_cst (const_tree t, int pos) -{ - gcc_assert (host_integerp (t, pos)); - return TREE_INT_CST_LOW (t); -} -#endif extern int tree_int_cst_sgn (const_tree); extern int tree_int_cst_sign_bit (const_tree); -extern unsigned int tree_int_cst_min_precision (tree, bool); +extern unsigned int tree_int_cst_min_precision (tree, signop); extern bool tree_expr_nonnegative_p (tree); extern bool tree_expr_nonnegative_warnv_p (tree, bool *); extern bool may_negate_without_overflow_p (const_tree);