===================================================================
@@ -8370,37 +8376,26 @@ fold_builtin_memory_op (location_t loc,
}
/* If *src and *dest can't overlap, optimize into memcpy as well. */
- srcvar = build_fold_indirect_ref_loc (loc, src);
- destvar = build_fold_indirect_ref_loc (loc, dest);
- if (srcvar
- && !TREE_THIS_VOLATILE (srcvar)
- && destvar
- && !TREE_THIS_VOLATILE (destvar))
+ if (TREE_CODE (src) == ADDR_EXPR
+ && TREE_CODE (dest) == ADDR_EXPR)
{
tree src_base, dest_base, fn;
HOST_WIDE_INT src_offset = 0, dest_offset = 0;
HOST_WIDE_INT size = -1;
HOST_WIDE_INT maxsize = -1;
- src_base = srcvar;
- if (handled_component_p (src_base))
- src_base = get_ref_base_and_extent (src_base, &src_offset,
- &size, &maxsize);
- dest_base = destvar;
- if (handled_component_p (dest_base))
- dest_base = get_ref_base_and_extent (dest_base, &dest_offset,
- &size, &maxsize);
+ srcvar = TREE_OPERAND (src, 0);
+ src_base = get_ref_base_and_extent (srcvar, &src_offset,
+ &size, &maxsize);
+ destvar = TREE_OPERAND (dest, 0);
+ dest_base = get_ref_base_and_extent (destvar, &dest_offset,
+ &size, &maxsize);
if (host_integerp (len, 1))
- {
- maxsize = tree_low_cst (len, 1);
- if (maxsize
- > INTTYPE_MAXIMUM (HOST_WIDE_INT) / BITS_PER_UNIT)
- maxsize = -1;
- else
- maxsize *= BITS_PER_UNIT;
- }
+ maxsize = tree_low_cst (len, 1);
else
maxsize = -1;
+ src_offset /= BITS_PER_UNIT;
+ dest_offset /= BITS_PER_UNIT;
if (SSA_VAR_P (src_base)
&& SSA_VAR_P (dest_base))
{
@@ -8409,13 +8404,25 @@ fold_builtin_memory_op (location_t loc,
dest_offset, maxsize))
return NULL_TREE;
}
- else if (TREE_CODE (src_base) == INDIRECT_REF
- && TREE_CODE (dest_base) == INDIRECT_REF)
+ else if (TREE_CODE (src_base) == MEM_REF
+ && TREE_CODE (dest_base) == MEM_REF)
{
+ double_int off;
if (! operand_equal_p (TREE_OPERAND (src_base, 0),
- TREE_OPERAND (dest_base, 0), 0)
- || ranges_overlap_p (src_offset, maxsize,
- dest_offset, maxsize))
+ TREE_OPERAND (dest_base, 0), 0))
+ return NULL_TREE;
+ off = double_int_add (mem_ref_offset (src_base),
+ shwi_to_double_int (src_offset));
+ if (!double_int_fits_in_shwi_p (off))
+ return NULL_TREE;
+ src_offset = off.low;
+ off = double_int_add (mem_ref_offset (dest_base),
+ shwi_to_double_int (dest_offset));
+ if (!double_int_fits_in_shwi_p (off))
+ return NULL_TREE;
+ dest_offset = off.low;
+ if (ranges_overlap_p (src_offset, maxsize,
+ dest_offset, maxsize))
return NULL_TREE;
}
else