/* Statement simplification on GIMPLE.
- Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ Copyright (C) 2010-2018 Free Software Foundation, Inc.
Split out from tree-ssa-ccp.c.
This file is part of GCC.
&& TREE_CODE (dest) == ADDR_EXPR)
{
tree src_base, dest_base, fn;
- HOST_WIDE_INT src_offset = 0, dest_offset = 0;
- HOST_WIDE_INT maxsize;
+ poly_int64 src_offset = 0, dest_offset = 0;
+ poly_uint64 maxsize;
srcvar = TREE_OPERAND (src, 0);
src_base = get_addr_base_and_unit_offset (srcvar, &src_offset);
&dest_offset);
if (dest_base == NULL)
dest_base = destvar;
- if (tree_fits_uhwi_p (len))
- maxsize = tree_to_uhwi (len);
- else
+ if (!poly_int_tree_p (len, &maxsize))
maxsize = -1;
if (SSA_VAR_P (src_base)
&& SSA_VAR_P (dest_base))
{
if (operand_equal_p (src_base, dest_base, 0)
- && ranges_overlap_p (src_offset, maxsize,
- dest_offset, maxsize))
+ && ranges_maybe_overlap_p (src_offset, maxsize,
+ dest_offset, maxsize))
return false;
}
else if (TREE_CODE (src_base) == MEM_REF
if (! operand_equal_p (TREE_OPERAND (src_base, 0),
TREE_OPERAND (dest_base, 0), 0))
return false;
- offset_int off = mem_ref_offset (src_base) + src_offset;
- if (!wi::fits_shwi_p (off))
- return false;
- src_offset = off.to_shwi ();
-
- off = mem_ref_offset (dest_base) + dest_offset;
- if (!wi::fits_shwi_p (off))
- return false;
- dest_offset = off.to_shwi ();
- if (ranges_overlap_p (src_offset, maxsize,
- dest_offset, maxsize))
+ poly_offset_int full_src_offset
+ = mem_ref_offset (src_base) + src_offset;
+ poly_offset_int full_dest_offset
+ = mem_ref_offset (dest_base) + dest_offset;
+ if (ranges_maybe_overlap_p (full_src_offset, maxsize,
+ full_dest_offset, maxsize))
return false;
}
else
{
int axis = oacc_get_ifn_dim_arg (call);
int size = oacc_get_fn_dim_size (current_function_decl, axis);
- bool is_pos = gimple_call_internal_fn (call) == IFN_GOACC_DIM_POS;
tree result = NULL_TREE;
+ tree type = TREE_TYPE (gimple_call_lhs (call));
- /* If the size is 1, or we only want the size and it is not dynamic,
- we know the answer. */
- if (size == 1 || (!is_pos && size))
+ switch (gimple_call_internal_fn (call))
{
- tree type = TREE_TYPE (gimple_call_lhs (call));
- result = build_int_cst (type, size - is_pos);
+ case IFN_GOACC_DIM_POS:
+ /* If the size is 1, we know the answer. */
+ if (size == 1)
+ result = build_int_cst (type, 0);
+ break;
+ case IFN_GOACC_DIM_SIZE:
+ /* If the size is not dynamic, we know the answer. */
+ if (size)
+ result = build_int_cst (type, size);
+ break;
+ default:
+ break;
}
return result;
/* Don't optimize floating point expected vars, VIEW_CONVERT_EXPRs
might not preserve all the bits. See PR71716. */
|| SCALAR_FLOAT_TYPE_P (etype)
- || TYPE_PRECISION (etype) != GET_MODE_BITSIZE (TYPE_MODE (etype)))
+ || maybe_ne (TYPE_PRECISION (etype),
+ GET_MODE_BITSIZE (TYPE_MODE (etype))))
return false;
tree weak = gimple_call_arg (stmt, 3);
|| handled_component_p (TREE_OPERAND (addr, 0))))
{
tree base;
- HOST_WIDE_INT coffset;
+ poly_int64 coffset;
base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
&coffset);
if (!base)
else if (TREE_CODE (rhs) == ADDR_EXPR
&& !is_gimple_min_invariant (rhs))
{
- HOST_WIDE_INT offset = 0;
+ poly_int64 offset = 0;
tree base;
base = get_addr_base_and_unit_offset_1 (TREE_OPERAND (rhs, 0),
&offset,
}
else if (TREE_CODE (rhs) == CONSTRUCTOR
&& TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE
- && (CONSTRUCTOR_NELTS (rhs)
- == TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs))))
+ && known_eq (CONSTRUCTOR_NELTS (rhs),
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs))))
{
unsigned i, nelts;
tree val;
- nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs));
+ nelts = CONSTRUCTOR_NELTS (rhs);
tree_vector_builder vec (TREE_TYPE (rhs), nelts, 1);
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
{
is not explicitly available, but it is known to be zero
such as 'static const int a;'. */
static tree
-get_base_constructor (tree base, HOST_WIDE_INT *bit_offset,
+get_base_constructor (tree base, poly_int64_pod *bit_offset,
tree (*valueize)(tree))
{
- HOST_WIDE_INT bit_offset2, size, max_size;
+ poly_int64 bit_offset2, size, max_size;
bool reverse;
if (TREE_CODE (base) == MEM_REF)
{
if (!tree_fits_shwi_p (TREE_OPERAND (base, 1)))
return NULL_TREE;
- *bit_offset += (mem_ref_offset (base).to_short_addr ()
+ *bit_offset += (mem_ref_offset (base).force_shwi ()
* BITS_PER_UNIT);
}
case COMPONENT_REF:
base = get_ref_base_and_extent (base, &bit_offset2, &size, &max_size,
&reverse);
- if (max_size == -1 || size != max_size)
+ if (!known_size_p (max_size) || maybe_ne (size, max_size))
return NULL_TREE;
*bit_offset += bit_offset2;
return get_base_constructor (base, bit_offset, valueize);
return build_zero_cst (type);
}
-/* CTOR is value initializing memory, fold reference of type TYPE and size SIZE
- to the memory at bit OFFSET. */
+/* CTOR is value initializing memory, fold reference of type TYPE and
+ size POLY_SIZE to the memory at bit POLY_OFFSET. */
tree
-fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
- unsigned HOST_WIDE_INT size, tree from_decl)
+fold_ctor_reference (tree type, tree ctor, poly_uint64 poly_offset,
+ poly_uint64 poly_size, tree from_decl)
{
tree ret;
/* We found the field with exact match. */
if (useless_type_conversion_p (type, TREE_TYPE (ctor))
- && !offset)
+ && known_eq (poly_offset, 0U))
return canonicalize_constructor_val (unshare_expr (ctor), from_decl);
+ /* The remaining optimizations need a constant size and offset. */
+ unsigned HOST_WIDE_INT size, offset;
+ if (!poly_size.is_constant (&size) || !poly_offset.is_constant (&offset))
+ return NULL_TREE;
+
/* We are at the end of walk, see if we can view convert the
result. */
if (!AGGREGATE_TYPE_P (TREE_TYPE (ctor)) && !offset
fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
{
tree ctor, idx, base;
- HOST_WIDE_INT offset, size, max_size;
+ poly_int64 offset, size, max_size;
tree tem;
bool reverse;
if (TREE_CODE (TREE_OPERAND (t, 1)) == SSA_NAME
&& valueize
&& (idx = (*valueize) (TREE_OPERAND (t, 1)))
- && TREE_CODE (idx) == INTEGER_CST)
+ && poly_int_tree_p (idx))
{
tree low_bound, unit_size;
/* If the resulting bit-offset is constant, track it. */
if ((low_bound = array_ref_low_bound (t),
- TREE_CODE (low_bound) == INTEGER_CST)
+ poly_int_tree_p (low_bound))
&& (unit_size = array_ref_element_size (t),
tree_fits_uhwi_p (unit_size)))
{
- offset_int woffset
- = wi::sext (wi::to_offset (idx) - wi::to_offset (low_bound),
+ poly_offset_int woffset
+ = wi::sext (wi::to_poly_offset (idx)
+ - wi::to_poly_offset (low_bound),
TYPE_PRECISION (TREE_TYPE (idx)));
- if (wi::fits_shwi_p (woffset))
+ if (woffset.to_shwi (&offset))
{
- offset = woffset.to_shwi ();
/* TODO: This code seems wrong, multiply then check
to see if it fits. */
offset *= tree_to_uhwi (unit_size);
return build_zero_cst (TREE_TYPE (t));
/* Out of bound array access. Value is undefined,
but don't fold. */
- if (offset < 0)
+ if (maybe_lt (offset, 0))
return NULL_TREE;
/* We can not determine ctor. */
if (!ctor)
if (ctor == error_mark_node)
return build_zero_cst (TREE_TYPE (t));
/* We do not know precise address. */
- if (max_size == -1 || max_size != size)
+ if (!known_size_p (max_size) || maybe_ne (max_size, size))
return NULL_TREE;
/* We can not determine ctor. */
if (!ctor)
return NULL_TREE;
/* Out of bound array access. Value is undefined, but don't fold. */
- if (offset < 0)
+ if (maybe_lt (offset, 0))
return NULL_TREE;
return fold_ctor_reference (TREE_TYPE (t), ctor, offset, size,
= tree_to_shwi (part_width) / BITS_PER_UNIT;
unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
tree index = bitsize_int (indexi);
- if (offset / part_widthi
- < TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype)))
+ if (known_lt (offset / part_widthi,
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype))))
return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0),
part_width, index);
}
gimple_build_vector_from_val (gimple_seq *seq, location_t loc, tree type,
tree op)
{
+ if (!TYPE_VECTOR_SUBPARTS (type).is_constant ()
+ && !CONSTANT_CLASS_P (op))
+ return gimple_build (seq, loc, VEC_DUPLICATE_EXPR, type, op);
+
tree res, vec = build_vector_from_val (type, op);
if (is_gimple_val (vec))
return vec;
if (!TREE_CONSTANT ((*builder)[i]))
{
tree type = builder->type ();
- unsigned int nelts = TYPE_VECTOR_SUBPARTS (type);
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
vec<constructor_elt, va_gc> *v;
vec_alloc (v, nelts);
for (i = 0; i < nelts; ++i)