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
@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
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;
size = base_size;
}
- return total.low > (unsigned HOST_WIDE_INT) size;
+ return total.to_uhwi () > (unsigned HOST_WIDE_INT) size;
}
- double_int d = tree_to_double_int (t);
- return d.sext (TYPE_PRECISION (TREE_TYPE (t))).low;
+ /* 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)
+ {
++ 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
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. */
return NULL_TREE;
}
-can_use_doloop_if_innermost (double_int, double_int,
+ /* 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;
+ }
#include "gt-targhooks.h"
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;
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
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 *);
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;
/* 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:
{
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);
struct iv *iv = XCNEW (struct iv);
gcc_assert (step != NULL_TREE);
- double_int size;
+ /* 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;
++ 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;
#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)
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))
{
return;
}
- double_int minc, maxc;
+ 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);
- minv = minv.max (minc, TYPE_UNSIGNED (type));
- maxv = maxv.min (maxc, TYPE_UNSIGNED (type));
- gcc_assert (minv.cmp (maxv, TYPE_UNSIGNED (type)) <= 0);
++ 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
+ {
- 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;
- mpz_set_double_int (minm, minv, TYPE_UNSIGNED (type));
- mpz_set_double_int (maxm, maxv, TYPE_UNSIGNED (type));
++ gcc_assert (wi::les_p (minv, maxv));
+ mpz_init (minm);
+ mpz_init (maxm);
++ 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;
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 ())
{
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))
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)
{
TYPE_ATTRIBUTES (base)));
}
- HOST_WIDE_INT type_size = tree_low_cst (TYPE_SIZE (type), 1);
+ /* 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_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. */
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
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.
return tree_code_name[code];
}
- return build_int_cst_wide (TREE_TYPE (t),
- TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t));
+ /* 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 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"
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);