X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fweb.c;h=7f5ae67d9af069038cad299a25a885502b0f6f08;hp=01b54254450d5a8716b6cfcf3158335ea80ca67e;hb=eebb423d73c49ec76fe9c1813616aa8bea4a1cb2;hpb=e8825bb05c80adfdb34722fab0d3030ef5ef4823 diff --git a/gcc/web.c b/gcc/web.c index 01b54254450..7f5ae67d9af 100644 --- a/gcc/web.c +++ b/gcc/web.c @@ -1,6 +1,7 @@ /* Web construction code for GNU compiler. Contributed by Jan Hubicka. - Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2004, 2006 + Free Software Foundation, Inc. This file is part of GCC. @@ -16,8 +17,8 @@ for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ /* Simple optimization pass that splits independent uses of each pseudo, increasing effectiveness of other optimizations. The optimization can @@ -51,31 +52,21 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "rtl.h" #include "hard-reg-set.h" #include "flags.h" +#include "obstack.h" #include "basic-block.h" #include "output.h" #include "df.h" #include "function.h" +#include "timevar.h" +#include "tree-pass.h" -/* This entry is allocated for each reference in the insn stream. */ -struct web_entry -{ - /* Pointer to the parent in the union/find tree. */ - struct web_entry *pred; - /* Newly assigned register to the entry. Set only for roots. */ - rtx reg; -}; - -static struct web_entry *unionfind_root (struct web_entry *); -static void unionfind_union (struct web_entry *, struct web_entry *); -static void union_defs (struct df *, struct ref *, struct web_entry *, - struct web_entry *); -static rtx entry_register (struct web_entry *, struct ref *, char *); -static void replace_ref (struct ref *, rtx); +static rtx entry_register (struct web_entry *, struct df_ref *, char *); +static void replace_ref (struct df_ref *, rtx); /* Find the root of unionfind tree (the representative of set). */ -static struct web_entry * +struct web_entry * unionfind_root (struct web_entry *element) { struct web_entry *element1 = element, *element2; @@ -91,30 +82,48 @@ unionfind_root (struct web_entry *element) return element; } -/* Union sets. */ +/* Union sets. + Return true if FIRST and SECOND points to the same web entry structure and + nothing is done. Otherwise, return false. */ -static void +bool unionfind_union (struct web_entry *first, struct web_entry *second) { first = unionfind_root (first); second = unionfind_root (second); if (first == second) - return; + return true; second->pred = first; + return false; } /* For each use, all possible defs reaching it must come in the same - register, union them. */ + register, union them. + FUN is the function that does the union. */ -static void -union_defs (struct df *df, struct ref *use, struct web_entry *def_entry, - struct web_entry *use_entry) +void +union_defs (struct df *df, struct df_ref *use, struct web_entry *def_entry, + struct web_entry *use_entry, + bool (*fun) (struct web_entry *, struct web_entry *)) { rtx insn = DF_REF_INSN (use); struct df_link *link = DF_REF_CHAIN (use); - struct df_link *use_link = DF_INSN_USES (df, insn); - struct df_link *def_link = DF_INSN_DEFS (df, insn); - rtx set = single_set (insn); + struct df_ref *use_link; + struct df_ref *def_link; + rtx set; + + if (insn) + { + use_link = DF_INSN_USES (df, insn); + def_link = DF_INSN_DEFS (df, insn); + set = single_set (insn); + } + else + { + 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 @@ -123,11 +132,11 @@ union_defs (struct df *df, struct ref *use, struct web_entry *def_entry, while (use_link) { - if (use != use_link->ref - && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (use_link->ref)) - unionfind_union (use_entry + DF_REF_ID (use), - use_entry + DF_REF_ID (use_link->ref)); - use_link = use_link->next; + 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 = use_link->next_ref; } /* Recognize trivial noop moves and attempt to keep them as noop. @@ -140,16 +149,16 @@ union_defs (struct df *df, struct ref *use, struct web_entry *def_entry, { while (def_link) { - if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link->ref)) - unionfind_union (use_entry + DF_REF_ID (use), - def_entry + DF_REF_ID (def_link->ref)); - def_link = def_link->next; + if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link)) + (*fun) (use_entry + DF_REF_ID (use), + def_entry + DF_REF_ID (def_link)); + def_link = def_link->next_ref; } } while (link) { - unionfind_union (use_entry + DF_REF_ID (use), - def_entry + DF_REF_ID (link->ref)); + (*fun) (use_entry + DF_REF_ID (use), + def_entry + DF_REF_ID (link->ref)); link = link->next; } @@ -157,14 +166,19 @@ union_defs (struct df *df, struct ref *use, struct web_entry *def_entry, register. Find it and union. */ if (use->flags & DF_REF_READ_WRITE) { - struct df_link *link = DF_INSN_DEFS (df, DF_REF_INSN (use)); + struct df_ref *link; + + if (DF_REF_INSN (use)) + link = DF_INSN_DEFS (df, DF_REF_INSN (use)); + else + link = NULL; while (link) { - if (DF_REF_REAL_REG (link->ref) == DF_REF_REAL_REG (use)) - unionfind_union (use_entry + DF_REF_ID (use), - def_entry + DF_REF_ID (link->ref)); - link = link->next; + if (DF_REF_REAL_REG (link) == DF_REF_REAL_REG (use)) + (*fun) (use_entry + DF_REF_ID (use), + def_entry + DF_REF_ID (link)); + link = link->next_ref; } } } @@ -172,7 +186,7 @@ union_defs (struct df *df, struct ref *use, struct web_entry *def_entry, /* Find the corresponding register for the given entry. */ static rtx -entry_register (struct web_entry *entry, struct ref *ref, char *used) +entry_register (struct web_entry *entry, struct df_ref *ref, char *used) { struct web_entry *root; rtx reg, newreg; @@ -201,8 +215,6 @@ entry_register (struct web_entry *entry, struct ref *ref, char *used) newreg = gen_reg_rtx (GET_MODE (reg)); REG_USERVAR_P (newreg) = REG_USERVAR_P (reg); REG_POINTER (newreg) = REG_POINTER (reg); - REG_LOOP_TEST_P (newreg) = REG_LOOP_TEST_P (reg); - RTX_UNCHANGING_P (newreg) = RTX_UNCHANGING_P (reg); REG_ATTRS (newreg) = REG_ATTRS (reg); if (dump_file) fprintf (dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg), @@ -216,7 +228,7 @@ entry_register (struct web_entry *entry, struct ref *ref, char *used) /* Replace the reference by REG. */ static void -replace_ref (struct ref *ref, rtx reg) +replace_ref (struct df_ref *ref, rtx reg) { rtx oldreg = DF_REF_REAL_REG (ref); rtx *loc = DF_REF_REAL_LOC (ref); @@ -231,7 +243,7 @@ replace_ref (struct ref *ref, rtx reg) /* Main entry point. */ -void +static void web_main (void) { struct df *df; @@ -241,28 +253,31 @@ web_main (void) int max = max_reg_num (); char *used; - df = df_init (); - df_analyze (df, 0, DF_UD_CHAIN | DF_EQUIV_NOTES); + df = df_init (DF_EQUIV_NOTES); + df_chain_add_problem (df, DF_UD_CHAIN); + df_analyze (df); + df_reorganize_refs (&df->def_info); + df_reorganize_refs (&df->use_info); - def_entry = xcalloc (df->n_defs, sizeof (struct web_entry)); - use_entry = xcalloc (df->n_uses, sizeof (struct web_entry)); - used = xcalloc (max, sizeof (char)); + def_entry = XCNEWVEC (struct web_entry, DF_DEFS_SIZE (df)); + use_entry = XCNEWVEC (struct web_entry, DF_USES_SIZE (df)); + used = XCNEWVEC (char, max); if (dump_file) - df_dump (df, DF_UD_CHAIN | DF_DU_CHAIN, dump_file); + df_dump (df, dump_file); /* Produce the web. */ - for (i = 0; i < df->n_uses; i++) - union_defs (df, df->uses[i], def_entry, use_entry); + for (i = 0; i < DF_USES_SIZE (df); i++) + union_defs (df, DF_USES_GET (df, i), def_entry, use_entry, unionfind_union); /* Update the instruction stream, allocating new registers for split pseudos in progress. */ - for (i = 0; i < df->n_uses; i++) - replace_ref (df->uses[i], entry_register (use_entry + i, df->uses[i], - used)); - for (i = 0; i < df->n_defs; i++) - replace_ref (df->defs[i], entry_register (def_entry + i, df->defs[i], - used)); + for (i = 0; i < DF_USES_SIZE (df); i++) + replace_ref (DF_USES_GET (df, i), + entry_register (use_entry + i, DF_USES_GET (df, i), used)); + for (i = 0; i < DF_DEFS_SIZE (df); i++) + replace_ref (DF_DEFS_GET (df, i), + entry_register (def_entry + i, DF_DEFS_GET (df, i), used)); /* Dataflow information is corrupt here, but it can be easily updated by creating new entries for new registers and updates or calling @@ -271,4 +286,39 @@ web_main (void) free (use_entry); free (used); df_finish (df); + df = NULL; +} + +static bool +gate_handle_web (void) +{ + return (optimize > 0 && flag_web); +} + +static unsigned int +rest_of_handle_web (void) +{ + web_main (); + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (get_insns (), max_reg_num ()); + return 0; } + +struct tree_opt_pass pass_web = +{ + "web", /* name */ + gate_handle_web, /* gate */ + rest_of_handle_web, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_WEB, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'Z' /* letter */ +}; +