Mercurial > hg > CbC > CbC_gcc
diff gcc/web.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
line wrap: on
line diff
--- a/gcc/web.c Fri Feb 12 23:41:23 2010 +0900 +++ b/gcc/web.c Mon May 24 12:47:05 2010 +0900 @@ -1,6 +1,6 @@ /* Web construction code for GNU compiler. Contributed by Jan Hubicka. - Copyright (C) 2001, 2002, 2004, 2006, 2007, 2008 + Copyright (C) 2001, 2002, 2004, 2006, 2007, 2008, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -28,14 +28,6 @@ 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 @@ -56,13 +48,12 @@ #include "output.h" #include "df.h" #include "function.h" +#include "insn-config.h" +#include "recog.h" #include "timevar.h" #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 * @@ -96,18 +87,62 @@ return false; } +/* For INSN, union all defs and uses that are linked by match_dup. + FUN is the function that does the union. */ + +static void +union_match_dups (rtx insn, struct web_entry *def_entry, + struct web_entry *use_entry, + bool (*fun) (struct web_entry *, struct web_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); + int i; + + extract_insn (insn); + + for (i = 0; i < recog_data.n_dups; i++) + { + int op = recog_data.dup_num[i]; + enum op_type type = recog_data.operand_type[op]; + df_ref *ref, *dupref; + struct web_entry *entry; + + for (dupref = use_link; *dupref; dupref++) + if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i]) + break; + + if (*dupref == NULL + || DF_REF_REGNO (*dupref) < FIRST_PSEUDO_REGISTER) + continue; + + ref = type == OP_IN ? use_link : def_link; + entry = type == OP_IN ? use_entry : def_entry; + for (; *ref; ref++) + if (DF_REF_LOC (*ref) == recog_data.operand_loc[op]) + break; + + (*fun) (use_entry + DF_REF_ID (*dupref), entry + DF_REF_ID (*ref)); + } +} + /* 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); struct df_link *link = DF_REF_CHAIN (use); - df_ref *use_link; df_ref *eq_use_link; df_ref *def_link; rtx set; @@ -115,7 +150,6 @@ if (insn_info) { rtx insn = insn_info->insn; - use_link = DF_INSN_INFO_USES (insn_info); eq_use_link = DF_INSN_INFO_EQ_USES (insn_info); def_link = DF_INSN_INFO_DEFS (insn_info); set = single_set (insn); @@ -123,26 +157,12 @@ else { /* An artificial use. It links up with nothing. */ - use_link = NULL; eq_use_link = NULL; def_link = NULL; set = NULL; } - /* Some instructions may use match_dup for their operands. In case the - operands are dead, we will assign them different pseudos, creating - invalid instructions, so union all uses of the same operand for each - insn. */ - - if (use_link) - while (*use_link) - { - if (use != *use_link - && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (*use_link)) - (*fun) (use_entry + DF_REF_ID (use), - use_entry + DF_REF_ID (*use_link)); - use_link++; - } + /* Union all occurrences of the same register in reg notes. */ if (eq_use_link) while (*eq_use_link) @@ -169,6 +189,25 @@ 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 +240,7 @@ /* 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 +253,14 @@ /* 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 +309,7 @@ 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; @@ -288,7 +324,7 @@ FOR_BB_INSNS (bb, insn) { unsigned int uid = INSN_UID (insn); - if (INSN_P (insn)) + if (NONDEBUG_INSN_P (insn)) { df_ref *use_rec; for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) @@ -308,7 +344,7 @@ /* 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. */ @@ -316,20 +352,21 @@ FOR_BB_INSNS (bb, insn) { unsigned int uid = INSN_UID (insn); - if (INSN_P (insn)) + if (NONDEBUG_INSN_P (insn)) { df_ref *use_rec; + union_match_dups (insn, def_entry, use_entry, unionfind_union); for (use_rec = DF_INSN_UID_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); } 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); } } } @@ -340,7 +377,7 @@ FOR_BB_INSNS (bb, insn) { unsigned int uid = INSN_UID (insn); - if (INSN_P (insn)) + if (NONDEBUG_INSN_P (insn)) { df_ref *use_rec; df_ref *def_rec;