summaryrefslogtreecommitdiff
path: root/gcc/web.c
diff options
context:
space:
mode:
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2012-10-15 11:20:02 +0000
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2012-10-15 11:20:02 +0000
commit4241a7ebdb910b0d2c6556e533fe1c7c7b42b964 (patch)
tree4bb1946929d0b4f58c34e16f1a365f4985dba9cc /gcc/web.c
parentd3909c678e112ec8c4b574932c2c9f273131f107 (diff)
downloadgcc-4241a7ebdb910b0d2c6556e533fe1c7c7b42b964.tar.gz
* web.c (union_match_dups): Properly handle OP_INOUT match_dups.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@192453 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/web.c')
-rw-r--r--gcc/web.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/gcc/web.c b/gcc/web.c
index 74904d2c350..7b6e8c6208e 100644
--- a/gcc/web.c
+++ b/gcc/web.c
@@ -96,6 +96,7 @@ union_match_dups (rtx insn, struct web_entry *def_entry,
struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
df_ref *use_link = DF_INSN_INFO_USES (insn_info);
df_ref *def_link = DF_INSN_INFO_DEFS (insn_info);
+ struct web_entry *dup_entry;
int i;
extract_insn (insn);
@@ -107,10 +108,24 @@ union_match_dups (rtx insn, struct web_entry *def_entry,
df_ref *ref, *dupref;
struct web_entry *entry;
- for (dupref = use_link; *dupref; dupref++)
+ for (dup_entry = use_entry, dupref = use_link; *dupref; dupref++)
if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i])
break;
+ if (*dupref == NULL && type == OP_INOUT)
+ {
+
+ for (dup_entry = def_entry, dupref = def_link; *dupref; dupref++)
+ if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i])
+ break;
+ }
+ /* ??? *DUPREF can still be zero, because when an operand matches
+ a memory, DF_REF_LOC (use_link[n]) points to the register part
+ of the address, whereas recog_data.dup_loc[m] points to the
+ entire memory ref, thus we fail to find the duplicate entry,
+ even though it is there.
+ Example: i686-pc-linux-gnu gcc.c-torture/compile/950607-1.c
+ -O3 -fomit-frame-pointer -funroll-loops */
if (*dupref == NULL
|| DF_REF_REGNO (*dupref) < FIRST_PSEUDO_REGISTER)
continue;
@@ -121,7 +136,15 @@ union_match_dups (rtx insn, struct web_entry *def_entry,
if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
break;
- (*fun) (use_entry + DF_REF_ID (*dupref), entry + DF_REF_ID (*ref));
+ if (!*ref && type == OP_INOUT)
+ {
+ for (ref = use_link, entry = use_entry; *ref; ref++)
+ if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
+ break;
+ }
+
+ gcc_assert (*ref);
+ (*fun) (dup_entry + DF_REF_ID (*dupref), entry + DF_REF_ID (*ref));
}
}