X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fweb.c;h=b729be7b9eee30eafa47cd64f52d43952288f717;hb=72a99552f26e88fbb7728a971409e5412aa2b163;hp=a8f9f04dd4c872e45f9a4c91a45135d1d7cee544;hpb=8b5b1013b9a1d3a959fa5d9dcaefadfb2d095361;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/web.c b/gcc/web.c index a8f9f04dd4c..b729be7b9ee 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 Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2004, 2006 + Free Software Foundation, Inc. This file is part of GCC. @@ -16,11 +17,11 @@ 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 effectivity of other optimizations. The optimization can + increasing effectiveness of other optimizations. The optimization can serve as an example of use for the dataflow module. We don't split registers with REG_USERVAR set unless -fmessy-debugging @@ -51,10 +52,13 @@ 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. */ @@ -66,22 +70,17 @@ struct web_entry rtx reg; }; -static struct web_entry *unionfind_root PARAMS ((struct web_entry *)); -static void unionfind_union PARAMS ((struct web_entry *, - struct web_entry *)); -static void union_defs PARAMS ((struct df *, struct ref *, - struct web_entry *, - struct web_entry *)); -static rtx entry_register PARAMS ((struct web_entry *, - struct ref *, char *, char *)); -static void replace_ref PARAMS ((struct ref *, rtx)); -static int mark_addressof PARAMS ((rtx *, void *)); +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 df_ref *, struct web_entry *, + struct web_entry *); +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 * -unionfind_root (element) - struct web_entry *element; +unionfind_root (struct web_entry *element) { struct web_entry *element1 = element, *element2; @@ -99,8 +98,7 @@ unionfind_root (element) /* Union sets. */ static void -unionfind_union (first, second) - struct web_entry *first, *second; +unionfind_union (struct web_entry *first, struct web_entry *second) { first = unionfind_root (first); second = unionfind_root (second); @@ -113,16 +111,13 @@ unionfind_union (first, second) register, union them. */ static void -union_defs (df, use, def_entry, use_entry) - struct df *df; - struct ref *use; - struct web_entry *def_entry; - struct web_entry *use_entry; +union_defs (struct df *df, struct df_ref *use, struct web_entry *def_entry, + struct web_entry *use_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); + struct df_ref *use_link = DF_INSN_USES (df, insn); + struct df_ref *def_link = DF_INSN_DEFS (df, insn); rtx set = single_set (insn); /* Some instructions may use match_dup for their operands. In case the @@ -132,11 +127,11 @@ union_defs (df, use, def_entry, use_entry) while (use_link) { - if (use != use_link->ref - && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (use_link->ref)) + if (use != use_link + && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (use_link)) unionfind_union (use_entry + DF_REF_ID (use), - use_entry + DF_REF_ID (use_link->ref)); - use_link = use_link->next; + use_entry + DF_REF_ID (use_link)); + use_link = use_link->next_ref; } /* Recognize trivial noop moves and attempt to keep them as noop. @@ -149,10 +144,10 @@ union_defs (df, use, def_entry, use_entry) { while (def_link) { - if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link->ref)) + if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link)) unionfind_union (use_entry + DF_REF_ID (use), - def_entry + DF_REF_ID (def_link->ref)); - def_link = def_link->next; + def_entry + DF_REF_ID (def_link)); + def_link = def_link->next_ref; } } while (link) @@ -166,24 +161,22 @@ union_defs (df, use, def_entry, use_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 = DF_INSN_DEFS (df, DF_REF_INSN (use)); - while (DF_REF_REAL_REG (link->ref) != DF_REF_REAL_REG (use)) - link = link->next; - - unionfind_union (use_entry + DF_REF_ID (use), - def_entry + DF_REF_ID (link->ref)); + while (link) + { + if (DF_REF_REAL_REG (link) == DF_REF_REAL_REG (use)) + unionfind_union (use_entry + DF_REF_ID (use), + def_entry + DF_REF_ID (link)); + link = link->next_ref; + } } } /* Find the corresponding register for the given entry. */ static rtx -entry_register (entry, ref, used, use_addressof) - struct web_entry *entry; - struct ref *ref; - char *used; - char *use_addressof; +entry_register (struct web_entry *entry, struct df_ref *ref, char *used) { struct web_entry *root; rtx reg, newreg; @@ -202,29 +195,19 @@ entry_register (entry, ref, used, use_addressof) else if (REG_USERVAR_P (reg) && 0/*&& !flag_messy_debugging*/) { newreg = reg; - if (rtl_dump_file) - fprintf (rtl_dump_file, + if (dump_file) + fprintf (dump_file, "New web forced to keep reg=%i (user variable)\n", REGNO (reg)); } - else if (use_addressof [REGNO (reg)]) - { - newreg = reg; - if (rtl_dump_file) - fprintf (rtl_dump_file, - "New web forced to keep reg=%i (address taken)\n", - REGNO (reg)); - } else { 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 (rtl_dump_file) - fprintf (rtl_dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg), + if (dump_file) + fprintf (dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg), REGNO (newreg)); } @@ -235,40 +218,23 @@ entry_register (entry, ref, used, use_addressof) /* Replace the reference by REG. */ static void -replace_ref (ref, reg) - 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); if (oldreg == reg) return; - if (rtl_dump_file) - fprintf (rtl_dump_file, "Updating insn %i (%i->%i)\n", + if (dump_file) + fprintf (dump_file, "Updating insn %i (%i->%i)\n", INSN_UID (DF_REF_INSN (ref)), REGNO (oldreg), REGNO (reg)); *loc = reg; } -/* Mark each pseudo whose address is taken. */ - -static int -mark_addressof (rtl, data) - rtx *rtl; - void *data; -{ - if (!*rtl) - return 0; - if (GET_CODE (*rtl) == ADDRESSOF - && REG_P (XEXP (*rtl, 0))) - ((char *)data)[REGNO (XEXP (*rtl, 0))] = 1; - return 0; -} - /* Main entry point. */ -void -web_main () +static void +web_main (void) { struct df *df; struct web_entry *def_entry; @@ -276,39 +242,32 @@ web_main () unsigned int i; int max = max_reg_num (); char *used; - char *use_addressof; - rtx insn; - df = df_init (); - df_analyse (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 = - (struct web_entry *) xcalloc (df->n_defs, sizeof (struct web_entry)); - use_entry = - (struct web_entry *) xcalloc (df->n_uses, sizeof (struct web_entry)); - used = (char *) xcalloc (max, sizeof (char)); - use_addressof = (char *) 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 (rtl_dump_file) - df_dump (df, DF_UD_CHAIN | DF_DU_CHAIN, rtl_dump_file); + if (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); - - /* We can not safely rename registers whose address is taken. */ - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - if (INSN_P (insn)) - for_each_rtx (&PATTERN (insn), mark_addressof, use_addressof); + for (i = 0; i < DF_USES_SIZE (df); i++) + union_defs (df, DF_USES_GET (df, i), def_entry, use_entry); /* 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, use_addressof)); - for (i = 0; i < df->n_defs; i++) - replace_ref (df->defs[i], entry_register (def_entry + i, df->defs[i], - used, use_addressof)); + 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 @@ -316,6 +275,40 @@ web_main () free (def_entry); free (use_entry); free (used); - free (use_addressof); 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 */ +}; +