aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel1@de.ibm.com>2004-03-06 01:21:28 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2004-03-06 01:21:28 +0000
commit2b3493c8bb8ee8d00e93c55d9cad5b322aa9f76e (patch)
tree357cb8fd1a073e3842ae68057a07998e44bc5205 /gcc
parent1a4a7065a972b721e9a5555dc87cd8d4d4ce755e (diff)
downloadgcc-2b3493c8bb8ee8d00e93c55d9cad5b322aa9f76e.zip
gcc-2b3493c8bb8ee8d00e93c55d9cad5b322aa9f76e.tar.gz
gcc-2b3493c8bb8ee8d00e93c55d9cad5b322aa9f76e.tar.bz2
rtl.h (mem_expr_equal_p): Function prototype added.
2004-03-05 Andreas Krebbel <krebbel1@de.ibm.com> * rtl.h (mem_expr_equal_p): Function prototype added. * cfgcleanup.c (merge_memattrs): New function. (flow_find_cross_jump): Call merge_memattrs for matching insns. * emit-rtl.c (mem_expr_equal_p): New function. 2004-03-05 Andreas Krebbel <krebbel1@de.ibm.com> * gcc.dg/20040305-1.c: New test. From-SVN: r79005
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/cfgcleanup.c86
-rw-r--r--gcc/emit-rtl.c34
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/20040305-1.c50
6 files changed, 182 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9200bbd..76710e7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2004-03-05 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * rtl.h (mem_expr_equal_p): Function prototype added.
+ * cfgcleanup.c (merge_memattrs): New function.
+ (flow_find_cross_jump): Call merge_memattrs for matching insns.
+ * emit-rtl.c (mem_expr_equal_p): New function.
+
2004-03-05 Ziemowit Laski <zlaski@apple.com>
* objc/objc-act.c (synth_module_prologue): Const-qualify
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index b2dd093..9029b5f 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -49,6 +49,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm_p.h"
#include "target.h"
#include "regs.h"
+#include "expr.h"
/* cleanup_cfg maintains following flags for each basic block. */
@@ -87,6 +88,7 @@ static bool mark_effect (rtx, bitmap);
static void notice_new_block (basic_block);
static void update_forwarder_flag (basic_block);
static int mentions_nonequal_regs (rtx *, void *);
+static void merge_memattrs (rtx, rtx);
/* Set flags for newly created block. */
@@ -862,6 +864,88 @@ merge_blocks_move (edge e, basic_block b, basic_block c, int mode)
}
+/* Removes the memory attributes of MEM expression
+ if they are not equal. */
+
+void
+merge_memattrs (rtx x, rtx y)
+{
+ int i;
+ int j;
+ enum rtx_code code;
+ const char *fmt;
+
+ if (x == y)
+ return;
+ if (x == 0 || y == 0)
+ return;
+
+ code = GET_CODE (x);
+
+ if (code != GET_CODE (y))
+ return;
+
+ if (GET_MODE (x) != GET_MODE (y))
+ return;
+
+ if (code == MEM && MEM_ATTRS (x) != MEM_ATTRS (y))
+ {
+ if (! MEM_ATTRS (x))
+ MEM_ATTRS (y) = 0;
+ else if (! MEM_ATTRS (y))
+ MEM_ATTRS (x) = 0;
+ else
+ {
+ if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y))
+ {
+ set_mem_alias_set (x, 0);
+ set_mem_alias_set (y, 0);
+ }
+
+ if (! mem_expr_equal_p (MEM_EXPR (x), MEM_EXPR (y)))
+ {
+ set_mem_expr (x, 0);
+ set_mem_expr (y, 0);
+ set_mem_offset (x, 0);
+ set_mem_offset (y, 0);
+ }
+ else if (MEM_OFFSET (x) != MEM_OFFSET (y))
+ {
+ set_mem_offset (x, 0);
+ set_mem_offset (y, 0);
+ }
+
+ set_mem_size (x, MAX (MEM_SIZE (x), MEM_SIZE (y)));
+ set_mem_size (y, MEM_SIZE (x));
+
+ set_mem_align (x, MIN (MEM_ALIGN (x), MEM_ALIGN (y)));
+ set_mem_align (y, MEM_ALIGN (x));
+ }
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ switch (fmt[i])
+ {
+ case 'E':
+ /* Two vectors must have the same length. */
+ if (XVECLEN (x, i) != XVECLEN (y, i))
+ return;
+
+ for (j = 0; j < XVECLEN (x, i); j++)
+ merge_memattrs (XVECEXP (x, i, j), XVECEXP (y, i, j));
+
+ break;
+
+ case 'e':
+ merge_memattrs (XEXP (x, i), XEXP (y, i));
+ }
+ }
+ return;
+}
+
+
/* Return true if I1 and I2 are equivalent and thus can be crossjumped. */
static bool
@@ -1022,6 +1106,8 @@ flow_find_cross_jump (int mode ATTRIBUTE_UNUSED, basic_block bb1,
if (!insns_match_p (mode, i1, i2))
break;
+ merge_memattrs (i1, i2);
+
/* Don't begin a cross-jump with a NOTE insn. */
if (INSN_P (i1))
{
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 6872afa..3032b53 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1434,6 +1434,40 @@ component_ref_for_mem_expr (tree ref)
TREE_OPERAND (ref, 1));
}
+/* Returns 1 if both MEM_EXPR can be considered equal
+ and 0 otherwise. */
+
+int
+mem_expr_equal_p (tree expr1, tree expr2)
+{
+ if (expr1 == expr2)
+ return 1;
+
+ if (! expr1 || ! expr2)
+ return 0;
+
+ if (TREE_CODE (expr1) != TREE_CODE (expr2))
+ return 0;
+
+ if (TREE_CODE (expr1) == COMPONENT_REF)
+ return
+ mem_expr_equal_p (TREE_OPERAND (expr1, 0),
+ TREE_OPERAND (expr2, 0))
+ && mem_expr_equal_p (TREE_OPERAND (expr1, 1), /* field decl */
+ TREE_OPERAND (expr2, 1));
+
+ if (TREE_CODE (expr1) == INDIRECT_REF)
+ return mem_expr_equal_p (TREE_OPERAND (expr1, 0),
+ TREE_OPERAND (expr2, 0));
+
+ /* Decls with different pointers can't be equal. */
+ if (DECL_P (expr1))
+ return 0;
+
+ abort(); /* ARRAY_REFs, ARRAY_RANGE_REFs and BIT_FIELD_REFs should already
+ have been resolved here. */
+}
+
/* Given REF, a MEM, and T, either the type of X or the expression
corresponding to REF, set the memory attributes. OBJECTP is nonzero
if we are making a new object of this type. BITPOS is nonzero if
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 94dc136..6da7768 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1569,6 +1569,7 @@ extern void set_reg_attrs_from_mem (rtx, rtx);
extern void set_mem_attrs_from_reg (rtx, rtx);
extern void set_reg_attrs_for_parm (rtx, rtx);
extern void set_reg_pointer_align (rtx, unsigned int);
+extern int mem_expr_equal_p (tree, tree);
/* In rtl.c */
extern rtx rtx_alloc_stat (RTX_CODE MEM_STAT_DECL);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 115c67e..00a174a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2004-03-05 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * gcc.dg/20040305-1.c: New test.
+
2004-03-05 Hans-Peter Nilsson <hp@axis.com>
PR other/14354
diff --git a/gcc/testsuite/gcc.dg/20040305-1.c b/gcc/testsuite/gcc.dg/20040305-1.c
new file mode 100644
index 0000000..62b920c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20040305-1.c
@@ -0,0 +1,50 @@
+
+/* The testcase failed due to corrupted alias information.
+ During the crossjump analyzing step the mem alias info of the
+ st instructions are merged and get copied during basic block
+ reordering which leads to an insn with wrong alias info.
+ The scheduler afterwards exchanges the mvc and st instructions
+ not recognizing the anti dependence. */
+/* { dg-do run { target s390-*-* } } */
+/* { dg-options "-O3 -mtune=z990 -fno-inline" } */
+
+int f;
+int g;
+int h;
+
+int* x = &f;
+int* p1 = &g;
+int* p2 = &h;
+
+int
+foo(void)
+{
+
+ if (*x == 0)
+ {
+ x = p1; /* mvc - memory to memory */
+ p1 = (int*)0; /* st - register to memory */
+ return 1;
+ }
+ if (*x == 5)
+ {
+ f = 1;
+ g = 2;
+
+ p2 = (int*)0; /* st */
+ return 1;
+ }
+}
+
+int
+main (int argc, char** argv)
+{
+ foo ();
+
+ /* If the scheduler has exchanged the mvc and st instructions,
+ x is 0. The expected result is &g. */
+ if (x == &g)
+ exit (0);
+ else
+ abort ();
+}