00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "config.h"
00046 #include "system.h"
00047 #include "coretypes.h"
00048 #include "tm.h"
00049 #include "toplev.h"
00050
00051 #include "rtl.h"
00052 #include "hard-reg-set.h"
00053 #include "flags.h"
00054 #include "obstack.h"
00055 #include "basic-block.h"
00056 #include "output.h"
00057 #include "df.h"
00058 #include "function.h"
00059
00060
00061
00062 struct web_entry
00063 {
00064
00065 struct web_entry *pred;
00066
00067 rtx reg;
00068 };
00069
00070 static struct web_entry *unionfind_root (struct web_entry *);
00071 static void unionfind_union (struct web_entry *, struct web_entry *);
00072 static void union_defs (struct df *, struct ref *, struct web_entry *,
00073 struct web_entry *);
00074 static rtx entry_register (struct web_entry *, struct ref *, char *);
00075 static void replace_ref (struct ref *, rtx);
00076
00077
00078
00079 static struct web_entry *
00080 unionfind_root (struct web_entry *element)
00081 {
00082 struct web_entry *element1 = element, *element2;
00083
00084 while (element->pred)
00085 element = element->pred;
00086 while (element1->pred)
00087 {
00088 element2 = element1->pred;
00089 element1->pred = element;
00090 element1 = element2;
00091 }
00092 return element;
00093 }
00094
00095
00096
00097 static void
00098 unionfind_union (struct web_entry *first, struct web_entry *second)
00099 {
00100 first = unionfind_root (first);
00101 second = unionfind_root (second);
00102 if (first == second)
00103 return;
00104 second->pred = first;
00105 }
00106
00107
00108
00109
00110 static void
00111 union_defs (struct df *df, struct ref *use, struct web_entry *def_entry,
00112 struct web_entry *use_entry)
00113 {
00114 rtx insn = DF_REF_INSN (use);
00115 struct df_link *link = DF_REF_CHAIN (use);
00116 struct df_link *use_link = DF_INSN_USES (df, insn);
00117 struct df_link *def_link = DF_INSN_DEFS (df, insn);
00118 rtx set = single_set (insn);
00119
00120
00121
00122
00123
00124
00125 while (use_link)
00126 {
00127 if (use != use_link->ref
00128 && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (use_link->ref))
00129 unionfind_union (use_entry + DF_REF_ID (use),
00130 use_entry + DF_REF_ID (use_link->ref));
00131 use_link = use_link->next;
00132 }
00133
00134
00135
00136
00137
00138 if (set
00139 && SET_SRC (set) == DF_REF_REG (use)
00140 && SET_SRC (set) == SET_DEST (set))
00141 {
00142 while (def_link)
00143 {
00144 if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link->ref))
00145 unionfind_union (use_entry + DF_REF_ID (use),
00146 def_entry + DF_REF_ID (def_link->ref));
00147 def_link = def_link->next;
00148 }
00149 }
00150 while (link)
00151 {
00152 unionfind_union (use_entry + DF_REF_ID (use),
00153 def_entry + DF_REF_ID (link->ref));
00154 link = link->next;
00155 }
00156
00157
00158
00159 if (use->flags & DF_REF_READ_WRITE)
00160 {
00161 struct df_link *link = DF_INSN_DEFS (df, DF_REF_INSN (use));
00162
00163 while (link)
00164 {
00165 if (DF_REF_REAL_REG (link->ref) == DF_REF_REAL_REG (use))
00166 unionfind_union (use_entry + DF_REF_ID (use),
00167 def_entry + DF_REF_ID (link->ref));
00168 link = link->next;
00169 }
00170 }
00171 }
00172
00173
00174
00175 static rtx
00176 entry_register (struct web_entry *entry, struct ref *ref, char *used)
00177 {
00178 struct web_entry *root;
00179 rtx reg, newreg;
00180
00181
00182 root = unionfind_root (entry);
00183 if (root->reg)
00184 return root->reg;
00185
00186
00187 reg = DF_REF_REAL_REG (ref);
00188
00189
00190 if (!used[REGNO (reg)])
00191 newreg = reg, used[REGNO (reg)] = 1;
00192 else if (REG_USERVAR_P (reg) && 0)
00193 {
00194 newreg = reg;
00195 if (dump_file)
00196 fprintf (dump_file,
00197 "New web forced to keep reg=%i (user variable)\n",
00198 REGNO (reg));
00199 }
00200 else
00201 {
00202 newreg = gen_reg_rtx (GET_MODE (reg));
00203 REG_USERVAR_P (newreg) = REG_USERVAR_P (reg);
00204 REG_POINTER (newreg) = REG_POINTER (reg);
00205 REG_ATTRS (newreg) = REG_ATTRS (reg);
00206 if (dump_file)
00207 fprintf (dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg),
00208 REGNO (newreg));
00209 }
00210
00211 root->reg = newreg;
00212 return newreg;
00213 }
00214
00215
00216
00217 static void
00218 replace_ref (struct ref *ref, rtx reg)
00219 {
00220 rtx oldreg = DF_REF_REAL_REG (ref);
00221 rtx *loc = DF_REF_REAL_LOC (ref);
00222
00223 if (oldreg == reg)
00224 return;
00225 if (dump_file)
00226 fprintf (dump_file, "Updating insn %i (%i->%i)\n",
00227 INSN_UID (DF_REF_INSN (ref)), REGNO (oldreg), REGNO (reg));
00228 *loc = reg;
00229 }
00230
00231
00232
00233 void
00234 web_main (void)
00235 {
00236 struct df *df;
00237 struct web_entry *def_entry;
00238 struct web_entry *use_entry;
00239 unsigned int i;
00240 int max = max_reg_num ();
00241 char *used;
00242
00243 df = df_init ();
00244 df_analyze (df, 0, DF_UD_CHAIN | DF_EQUIV_NOTES);
00245
00246 def_entry = xcalloc (df->n_defs, sizeof (struct web_entry));
00247 use_entry = xcalloc (df->n_uses, sizeof (struct web_entry));
00248 used = xcalloc (max, sizeof (char));
00249
00250 if (dump_file)
00251 df_dump (df, DF_UD_CHAIN | DF_DU_CHAIN, dump_file);
00252
00253
00254 for (i = 0; i < df->n_uses; i++)
00255 union_defs (df, df->uses[i], def_entry, use_entry);
00256
00257
00258
00259 for (i = 0; i < df->n_uses; i++)
00260 replace_ref (df->uses[i], entry_register (use_entry + i, df->uses[i],
00261 used));
00262 for (i = 0; i < df->n_defs; i++)
00263 replace_ref (df->defs[i], entry_register (def_entry + i, df->defs[i],
00264 used));
00265
00266
00267
00268
00269 free (def_entry);
00270 free (use_entry);
00271 free (used);
00272 df_finish (df);
00273 }