aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-10-06 13:46:53 -0700
committerRichard Henderson <rth@gcc.gnu.org>2005-10-06 13:46:53 -0700
commite2f9fe4298d7cdf587430ecd096d5b3d6b214b76 (patch)
treeb27cc11783abb4d2a33638ffa8c39cee31924335 /gcc
parent0c7c1604de7009d820bba46fb102b8d3f7d691da (diff)
downloadgcc-e2f9fe4298d7cdf587430ecd096d5b3d6b214b76.zip
gcc-e2f9fe4298d7cdf587430ecd096d5b3d6b214b76.tar.gz
gcc-e2f9fe4298d7cdf587430ecd096d5b3d6b214b76.tar.bz2
re PR tree-optimization/22237 (struct copy inlining generates overlapping memcpy)
PR tree-opt/22237 * tree-inline.c (declare_return_variable): Handle modify_dest not being a DECL. From-SVN: r105057
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c27
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c44
-rw-r--r--gcc/tree-inline.c19
4 files changed, 92 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f7a9c38..79124ff 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2005-10-06 Richard Henderson <rth@redhat.com>
+
+ PR tree-opt/22237
+ * tree-inline.c (declare_return_variable): Handle modify_dest not
+ being a DECL.
+
2005-10-06 Daniel Berlin <dberlin@dberlin.org>
Fix PR tree-optimization/22488
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c
new file mode 100644
index 0000000..4403235
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c
@@ -0,0 +1,27 @@
+extern void abort (void);
+
+void *
+memcpy (void *dst, const void *src, __SIZE_TYPE__ n)
+{
+ const char *srcp;
+ char *dstp;
+
+ srcp = src;
+ dstp = dst;
+
+ if (dst < src)
+ {
+ if (dst + n > src)
+ abort ();
+ }
+ else
+ {
+ if (src + n > dst)
+ abort ();
+ }
+
+ while (n-- != 0)
+ *dstp++ = *srcp++;
+
+ return dst;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c
new file mode 100644
index 0000000..957a47c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c
@@ -0,0 +1,44 @@
+extern void abort (void);
+extern void exit (int);
+struct s { unsigned char a[256]; };
+union u { struct { struct s b; int c; } d; struct { int c; struct s b; } e; };
+static union u v;
+static union u v0;
+static struct s *p = &v.d.b;
+static struct s *q = &v.e.b;
+
+static inline struct s rp (void) { return *p; }
+static inline struct s rq (void) { return *q; }
+static void pq (void) { *p = rq(); }
+static void qp (void) { *q = rp(); }
+
+static void
+init (struct s *sp)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ sp->a[i] = i;
+}
+
+static void
+check (struct s *sp)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (sp->a[i] != i)
+ abort ();
+}
+
+void
+main_test (void)
+{
+ v = v0;
+ init (p);
+ qp ();
+ check (q);
+ v = v0;
+ init (q);
+ pq ();
+ check (p);
+ exit (0);
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index afec40d..f22785c 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1260,10 +1260,21 @@ declare_return_variable (inline_data *id, tree return_slot_addr,
/* If the callee cannot possibly modify MODIFY_DEST, then we can
reuse it as the result of the call directly. Don't do this if
it would promote MODIFY_DEST to addressable. */
- else if (!TREE_STATIC (modify_dest)
- && !TREE_ADDRESSABLE (modify_dest)
- && !TREE_ADDRESSABLE (result))
- use_it = true;
+ else if (TREE_ADDRESSABLE (result))
+ use_it = false;
+ else
+ {
+ tree base_m = get_base_address (modify_dest);
+
+ /* If the base isn't a decl, then it's a pointer, and we don't
+ know where that's going to go. */
+ if (!DECL_P (base_m))
+ use_it = false;
+ else if (is_global_var (base_m))
+ use_it = false;
+ else if (!TREE_ADDRESSABLE (base_m))
+ use_it = true;
+ }
if (use_it)
{