diff options
author | Andreas Krebbel <krebbel1@de.ibm.com> | 2004-03-06 01:21:28 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@gcc.gnu.org> | 2004-03-06 01:21:28 +0000 |
commit | 2b3493c8bb8ee8d00e93c55d9cad5b322aa9f76e (patch) | |
tree | 357cb8fd1a073e3842ae68057a07998e44bc5205 /gcc | |
parent | 1a4a7065a972b721e9a5555dc87cd8d4d4ce755e (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cfgcleanup.c | 86 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 34 | ||||
-rw-r--r-- | gcc/rtl.h | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/20040305-1.c | 50 |
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 @@ -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 (); +} |