aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/alias.c3
-rw-r--r--gcc/alias.h1
-rw-r--r--gcc/cse.c17
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr35258.c28
6 files changed, 59 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 13ca11e..fa691e7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2008-02-25 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ PR target/35258
+ * cse.c (cse_insn): Avoid creation of overlapping MEMs.
+ * alias.c (nonoverlapping_memrefs_p): Export for use in other modules.
+ * alias.h (nonoverlapping_memrefs_p): Likewise.
+
2008-02-25 Jan Beulich <jbeulich@novell.com>
* Makefile.in: Also prefix uses of crt0.o and mcrt0.o with
diff --git a/gcc/alias.c b/gcc/alias.c
index bd5c277..56afa86 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -164,7 +164,6 @@ static int aliases_everything_p (const_rtx);
static bool nonoverlapping_component_refs_p (const_tree, const_tree);
static tree decl_for_component_ref (tree);
static rtx adjust_offset_for_component_ref (tree, rtx);
-static int nonoverlapping_memrefs_p (const_rtx, const_rtx);
static int write_dependence_p (const_rtx, const_rtx, int);
static void memory_modified_1 (rtx, const_rtx, void *);
@@ -1976,7 +1975,7 @@ adjust_offset_for_component_ref (tree x, rtx offset)
/* Return nonzero if we can determine the exprs corresponding to memrefs
X and Y and they do not overlap. */
-static int
+int
nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
{
tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
diff --git a/gcc/alias.h b/gcc/alias.h
index a245493..772aea0 100644
--- a/gcc/alias.h
+++ b/gcc/alias.h
@@ -28,6 +28,7 @@ extern alias_set_type get_varargs_alias_set (void);
extern alias_set_type get_frame_alias_set (void);
extern bool component_uses_parent_alias_set (const_tree);
extern bool alias_set_subset_of (alias_set_type, alias_set_type);
+extern int nonoverlapping_memrefs_p (const_rtx, const_rtx);
/* This alias set can be used to force a memory to conflict with all
other memories, creating a barrier across which no memory reference
diff --git a/gcc/cse.c b/gcc/cse.c
index f6660e4..9f31e67 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4753,6 +4753,23 @@ cse_insn (rtx insn, rtx libcall_insn)
src_elt_cost = MAX_COST;
}
+ /* Avoid creation of overlapping memory moves. */
+ if (MEM_P (trial) && MEM_P (SET_DEST (sets[i].rtl)))
+ {
+ rtx src, dest;
+
+ /* BLKmode moves are not handled by cse anyway. */
+ if (GET_MODE (trial) == BLKmode)
+ break;
+
+ src = canon_rtx (trial);
+ dest = canon_rtx (SET_DEST (sets[i].rtl));
+
+ if (!MEM_P (src) || !MEM_P (dest)
+ || !nonoverlapping_memrefs_p (src, dest))
+ break;
+ }
+
/* We don't normally have an insn matching (set (pc) (pc)), so
check for this separately here. We will delete such an
insn below.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cc2d87c..0e3977d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2008-02-25 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ PR target/35258
+ * gcc.dg/pr35258.c: New testcase.
+
2008-02-25 Jan Beulich <jbeulich@novell.com>
* gcc.dg/20020426-2.c: Remove bogus workaround.
diff --git a/gcc/testsuite/gcc.dg/pr35258.c b/gcc/testsuite/gcc.dg/pr35258.c
new file mode 100644
index 0000000..d1c45a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr35258.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+extern void *memcpy (void *, const void *, __SIZE_TYPE__);
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+extern void abort(void);
+
+char str[9] = "1234";
+
+void
+bar (void)
+{
+ unsigned int temp;
+ char *p = &str[2];
+
+ memcpy (&temp, &str[1], 4);
+ memcpy (p, &temp, 4);
+ str[1] = '.';
+}
+
+int main()
+{
+ bar();
+ if (memcmp (str, "1.234", 5) != 0)
+ abort ();
+
+ return 0;
+}