Hi!
As mentioned in the PR and discussed on IRC, get_ref_base_and_extent
can return size != maxsize or maxsize -1 and then we really can't trust
the offset for the purposes we want. So this patch instead uses a different
function that just computes the base and offset if the offset is constant;
we don't really care about the access size.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/6.2,
for 5.5 the 4.9 patch applied to gimple-fold.c instead of bultins.c and for
4.9.4 the attached patch?
2016-07-19 Jakub Jelinek <ja...@redhat.com>
PR middle-end/71874
* gimple-fold.c (fold_builtin_memory_op): Use
get_addr_base_and_unit_offset instead of get_ref_base_and_extent.
* g++.dg/torture/pr71874.C: New test.
--- gcc/gimple-fold.c.jj 2016-07-19 15:24:42.870004660 +0200
+++ gcc/gimple-fold.c 2016-07-19 15:26:55.449343027 +0200
@@ -796,22 +796,21 @@ gimple_fold_builtin_memory_op (gimple_st
{
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;
- bool reverse;
+ HOST_WIDE_INT maxsize;
srcvar = TREE_OPERAND (src, 0);
- src_base = get_ref_base_and_extent (srcvar, &src_offset,
- &size, &maxsize, &reverse);
+ src_base = get_addr_base_and_unit_offset (srcvar, &src_offset);
+ if (src_base == NULL)
+ src_base = srcvar;
destvar = TREE_OPERAND (dest, 0);
- dest_base = get_ref_base_and_extent (destvar, &dest_offset,
- &size, &maxsize, &reverse);
+ dest_base = get_addr_base_and_unit_offset (destvar,
+ &dest_offset);
+ if (dest_base == NULL)
+ dest_base = destvar;
if (tree_fits_uhwi_p (len))
maxsize = tree_to_uhwi (len);
else
maxsize = -1;
- src_offset /= BITS_PER_UNIT;
- dest_offset /= BITS_PER_UNIT;
if (SSA_VAR_P (src_base)
&& SSA_VAR_P (dest_base))
{
--- gcc/testsuite/g++.dg/torture/pr71874.C.jj 2016-07-19 15:23:37.097832377
+0200
+++ gcc/testsuite/g++.dg/torture/pr71874.C 2016-07-19 15:23:37.097832377
+0200
@@ -0,0 +1,12 @@
+// PR middle-end/71874
+// { dg-do run }
+
+int
+main ()
+{
+ char str[] = "abcdefghijklmnopqrstuvwxyzABCDEF";
+ __builtin_memmove (str + 20, str + 15, 11);
+ if (__builtin_strcmp (str, "abcdefghijklmnopqrstpqrstuvwxyzF") != 0)
+ __builtin_abort ();
+ return 0;
+}
Jakub
2016-07-19 Jakub Jelinek <ja...@redhat.com>
PR middle-end/71874
* builtins.c (fold_builtin_memory_op): Use
get_addr_base_and_unit_offset instead of get_ref_base_and_extent.
* g++.dg/torture/pr71874.C: New test.
--- gcc/builtins.c.jj 2016-04-28 21:47:35.000000000 +0200
+++ gcc/builtins.c 2016-07-19 13:13:41.563148783 +0200
@@ -8793,21 +8793,21 @@ fold_builtin_memory_op (location_t loc,
{
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;
+ HOST_WIDE_INT maxsize;
srcvar = TREE_OPERAND (src, 0);
- src_base = get_ref_base_and_extent (srcvar, &src_offset,
- &size, &maxsize);
+ src_base = get_addr_base_and_unit_offset (srcvar, &src_offset);
+ if (src_base == NULL)
+ src_base = srcvar;
destvar = TREE_OPERAND (dest, 0);
- dest_base = get_ref_base_and_extent (destvar, &dest_offset,
- &size, &maxsize);
+ dest_base = get_addr_base_and_unit_offset (destvar,
+ &dest_offset);
+ if (dest_base == NULL)
+ dest_base = destvar;
if (tree_fits_uhwi_p (len))
maxsize = tree_to_uhwi (len);
else
maxsize = -1;
- src_offset /= BITS_PER_UNIT;
- dest_offset /= BITS_PER_UNIT;
if (SSA_VAR_P (src_base)
&& SSA_VAR_P (dest_base))
{
--- gcc/testsuite/g++.dg/torture/pr71874.C.jj 2016-07-19 12:58:54.816402724
+0200
+++ gcc/testsuite/g++.dg/torture/pr71874.C 2016-07-19 13:00:04.106521149
+0200
@@ -0,0 +1,12 @@
+// PR middle-end/71874
+// { dg-do run }
+
+int
+main ()
+{
+ char str[] = "abcdefghijklmnopqrstuvwxyzABCDEF";
+ __builtin_memmove (str + 20, str + 15, 11);
+ if (__builtin_strcmp (str, "abcdefghijklmnopqrstpqrstuvwxyzF") != 0)
+ __builtin_abort ();
+ return 0;
+}