diff options
author | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-01-09 14:41:51 +0000 |
---|---|---|
committer | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-01-09 14:41:51 +0000 |
commit | 388bf4a226969bd8ff1279184724e0c4ee318a41 (patch) | |
tree | ed5ab688eeb1a68f38482e716ff1ef905d7d4d17 /gcc/web.c | |
parent | 3b3940d77620362e5d82c258325ae8a4dd5773e7 (diff) | |
download | gcc-388bf4a226969bd8ff1279184724e0c4ee318a41.tar.gz |
gcc/ChangeLog:
PR debug/42631
* web.c (union_defs): Add used argument, to combine uses of
uninitialized regs.
(entry_register): Adjust type and tests of used argument.
(web_main): Widen used for new use. Pass it to union_defs.
* df.h (union_defs): Adjust prototype.
gcc/testsuite/ChangeLog:
PR debug/42631
* gcc.dg/pr42631.c: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@155765 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/web.c')
-rw-r--r-- | gcc/web.c | 66 |
1 files changed, 38 insertions, 28 deletions
diff --git a/gcc/web.c b/gcc/web.c index 27e7f919fe2..d562807ec60 100644 --- a/gcc/web.c +++ b/gcc/web.c @@ -28,14 +28,6 @@ along with GCC; see the file COPYING3. If not see is almost unusable. TODO - - Add code to keep debugging up-to-date after splitting user variable - pseudos. This can be done by keeping track of all the pseudos used - for the variable and using life analysis information before reload - to determine which one is live and, in case more than one are live, - choose the one with the latest definition. - - Other optimization passes can benefit from the infrastructure too. - - We may use profile information and ignore infrequent use for the purpose of web unifying, inserting the compensation code later to implement full induction variable expansion for loops (currently @@ -60,9 +52,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-pass.h" -static rtx entry_register (struct web_entry *, df_ref, char *); -static void replace_ref (df_ref, rtx); - /* Find the root of unionfind tree (the representative of set). */ struct web_entry * @@ -98,11 +87,16 @@ unionfind_union (struct web_entry *first, struct web_entry *second) /* For each use, all possible defs reaching it must come in the same register, union them. - FUN is the function that does the union. */ + FUN is the function that does the union. + + In USED, we keep the DF_REF_ID of the first uninitialized uses of a + register, so that all uninitialized uses of the register can be + combined into a single web. We actually offset it by 2, because + the values 0 and 1 are reserved for use by entry_register. */ void union_defs (df_ref use, struct web_entry *def_entry, - struct web_entry *use_entry, + unsigned int *used, struct web_entry *use_entry, bool (*fun) (struct web_entry *, struct web_entry *)) { struct df_insn_info *insn_info = DF_REF_INSN_INFO (use); @@ -169,6 +163,25 @@ union_defs (df_ref use, struct web_entry *def_entry, def_link++; } } + + /* UD chains of uninitialized REGs are empty. Keeping all uses of + the same uninitialized REG in a single web is not necessary for + correctness, since the uses are undefined, but it's wasteful to + allocate one register or slot for each reference. Furthermore, + creating new pseudos for uninitialized references in debug insns + (see PR 42631) causes -fcompare-debug failures. We record the + number of the first uninitialized reference we found, and merge + with it any other uninitialized references to the same + register. */ + if (!link) + { + int regno = REGNO (DF_REF_REAL_REG (use)); + if (used[regno]) + (*fun) (use_entry + DF_REF_ID (use), use_entry + used[regno] - 2); + else + used[regno] = DF_REF_ID (use) + 2; + } + while (link) { (*fun) (use_entry + DF_REF_ID (use), @@ -201,7 +214,7 @@ union_defs (df_ref use, struct web_entry *def_entry, /* Find the corresponding register for the given entry. */ static rtx -entry_register (struct web_entry *entry, df_ref ref, char *used) +entry_register (struct web_entry *entry, df_ref ref, unsigned int *used) { struct web_entry *root; rtx reg, newreg; @@ -214,17 +227,14 @@ entry_register (struct web_entry *entry, df_ref ref, char *used) /* We are seeing this web for the first time, do the assignment. */ reg = DF_REF_REAL_REG (ref); - /* In case the original register is already assigned, generate new one. */ - if (!used[REGNO (reg)]) + /* In case the original register is already assigned, generate new + one. Since we use USED to merge uninitialized refs into a single + web, we might found an element to be nonzero without our having + used it. Test for 1, because union_defs saves it for our use, + and there won't be any use for the other values when we get to + this point. */ + if (used[REGNO (reg)] != 1) newreg = reg, used[REGNO (reg)] = 1; - else if (REG_USERVAR_P (reg) && 0/*&& !flag_messy_debugging*/) - { - newreg = reg; - if (dump_file) - fprintf (dump_file, - "New web forced to keep reg=%i (user variable)\n", - REGNO (reg)); - } else { newreg = gen_reg_rtx (GET_MODE (reg)); @@ -273,7 +283,7 @@ web_main (void) struct web_entry *def_entry; struct web_entry *use_entry; unsigned int max = max_reg_num (); - char *used; + unsigned int *used; basic_block bb; unsigned int uses_num = 0; rtx insn; @@ -308,7 +318,7 @@ web_main (void) /* Record the number of uses and defs at the beginning of the optimization. */ def_entry = XCNEWVEC (struct web_entry, DF_DEFS_TABLE_SIZE()); - used = XCNEWVEC (char, max); + used = XCNEWVEC (unsigned, max); use_entry = XCNEWVEC (struct web_entry, uses_num); /* Produce the web. */ @@ -323,13 +333,13 @@ web_main (void) { df_ref use = *use_rec; if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER) - union_defs (use, def_entry, use_entry, unionfind_union); + union_defs (use, def_entry, used, use_entry, unionfind_union); } for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++) { df_ref use = *use_rec; if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER) - union_defs (use, def_entry, use_entry, unionfind_union); + union_defs (use, def_entry, used, use_entry, unionfind_union); } } } |