Mercurial > hg > CbC > CbC_gcc
comparison 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 |
comparison
equal
deleted
inserted
replaced
56:3c8a44c06a95 | 63:b7f97abdc517 |
---|---|
1 /* Web construction code for GNU compiler. | 1 /* Web construction code for GNU compiler. |
2 Contributed by Jan Hubicka. | 2 Contributed by Jan Hubicka. |
3 Copyright (C) 2001, 2002, 2004, 2006, 2007, 2008 | 3 Copyright (C) 2001, 2002, 2004, 2006, 2007, 2008, 2010 |
4 Free Software Foundation, Inc. | 4 Free Software Foundation, Inc. |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
8 GCC is free software; you can redistribute it and/or modify it under | 8 GCC is free software; you can redistribute it and/or modify it under |
26 We don't split registers with REG_USERVAR set unless -fmessy-debugging | 26 We don't split registers with REG_USERVAR set unless -fmessy-debugging |
27 is specified, because debugging information about such split variables | 27 is specified, because debugging information about such split variables |
28 is almost unusable. | 28 is almost unusable. |
29 | 29 |
30 TODO | 30 TODO |
31 - Add code to keep debugging up-to-date after splitting user variable | |
32 pseudos. This can be done by keeping track of all the pseudos used | |
33 for the variable and using life analysis information before reload | |
34 to determine which one is live and, in case more than one are live, | |
35 choose the one with the latest definition. | |
36 | |
37 Other optimization passes can benefit from the infrastructure too. | |
38 | |
39 - We may use profile information and ignore infrequent use for the | 31 - We may use profile information and ignore infrequent use for the |
40 purpose of web unifying, inserting the compensation code later to | 32 purpose of web unifying, inserting the compensation code later to |
41 implement full induction variable expansion for loops (currently | 33 implement full induction variable expansion for loops (currently |
42 we expand only if the induction variable is dead afterward, which | 34 we expand only if the induction variable is dead afterward, which |
43 is often the case). */ | 35 is often the case). */ |
54 #include "obstack.h" | 46 #include "obstack.h" |
55 #include "basic-block.h" | 47 #include "basic-block.h" |
56 #include "output.h" | 48 #include "output.h" |
57 #include "df.h" | 49 #include "df.h" |
58 #include "function.h" | 50 #include "function.h" |
51 #include "insn-config.h" | |
52 #include "recog.h" | |
59 #include "timevar.h" | 53 #include "timevar.h" |
60 #include "tree-pass.h" | 54 #include "tree-pass.h" |
61 | 55 |
62 | |
63 static rtx entry_register (struct web_entry *, df_ref, char *); | |
64 static void replace_ref (df_ref, rtx); | |
65 | 56 |
66 /* Find the root of unionfind tree (the representative of set). */ | 57 /* Find the root of unionfind tree (the representative of set). */ |
67 | 58 |
68 struct web_entry * | 59 struct web_entry * |
69 unionfind_root (struct web_entry *element) | 60 unionfind_root (struct web_entry *element) |
94 return true; | 85 return true; |
95 second->pred = first; | 86 second->pred = first; |
96 return false; | 87 return false; |
97 } | 88 } |
98 | 89 |
90 /* For INSN, union all defs and uses that are linked by match_dup. | |
91 FUN is the function that does the union. */ | |
92 | |
93 static void | |
94 union_match_dups (rtx insn, struct web_entry *def_entry, | |
95 struct web_entry *use_entry, | |
96 bool (*fun) (struct web_entry *, struct web_entry *)) | |
97 { | |
98 struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn); | |
99 df_ref *use_link = DF_INSN_INFO_USES (insn_info); | |
100 df_ref *def_link = DF_INSN_INFO_DEFS (insn_info); | |
101 int i; | |
102 | |
103 extract_insn (insn); | |
104 | |
105 for (i = 0; i < recog_data.n_dups; i++) | |
106 { | |
107 int op = recog_data.dup_num[i]; | |
108 enum op_type type = recog_data.operand_type[op]; | |
109 df_ref *ref, *dupref; | |
110 struct web_entry *entry; | |
111 | |
112 for (dupref = use_link; *dupref; dupref++) | |
113 if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i]) | |
114 break; | |
115 | |
116 if (*dupref == NULL | |
117 || DF_REF_REGNO (*dupref) < FIRST_PSEUDO_REGISTER) | |
118 continue; | |
119 | |
120 ref = type == OP_IN ? use_link : def_link; | |
121 entry = type == OP_IN ? use_entry : def_entry; | |
122 for (; *ref; ref++) | |
123 if (DF_REF_LOC (*ref) == recog_data.operand_loc[op]) | |
124 break; | |
125 | |
126 (*fun) (use_entry + DF_REF_ID (*dupref), entry + DF_REF_ID (*ref)); | |
127 } | |
128 } | |
129 | |
99 /* For each use, all possible defs reaching it must come in the same | 130 /* For each use, all possible defs reaching it must come in the same |
100 register, union them. | 131 register, union them. |
101 FUN is the function that does the union. */ | 132 FUN is the function that does the union. |
133 | |
134 In USED, we keep the DF_REF_ID of the first uninitialized uses of a | |
135 register, so that all uninitialized uses of the register can be | |
136 combined into a single web. We actually offset it by 2, because | |
137 the values 0 and 1 are reserved for use by entry_register. */ | |
102 | 138 |
103 void | 139 void |
104 union_defs (df_ref use, struct web_entry *def_entry, | 140 union_defs (df_ref use, struct web_entry *def_entry, |
105 struct web_entry *use_entry, | 141 unsigned int *used, struct web_entry *use_entry, |
106 bool (*fun) (struct web_entry *, struct web_entry *)) | 142 bool (*fun) (struct web_entry *, struct web_entry *)) |
107 { | 143 { |
108 struct df_insn_info *insn_info = DF_REF_INSN_INFO (use); | 144 struct df_insn_info *insn_info = DF_REF_INSN_INFO (use); |
109 struct df_link *link = DF_REF_CHAIN (use); | 145 struct df_link *link = DF_REF_CHAIN (use); |
110 df_ref *use_link; | |
111 df_ref *eq_use_link; | 146 df_ref *eq_use_link; |
112 df_ref *def_link; | 147 df_ref *def_link; |
113 rtx set; | 148 rtx set; |
114 | 149 |
115 if (insn_info) | 150 if (insn_info) |
116 { | 151 { |
117 rtx insn = insn_info->insn; | 152 rtx insn = insn_info->insn; |
118 use_link = DF_INSN_INFO_USES (insn_info); | |
119 eq_use_link = DF_INSN_INFO_EQ_USES (insn_info); | 153 eq_use_link = DF_INSN_INFO_EQ_USES (insn_info); |
120 def_link = DF_INSN_INFO_DEFS (insn_info); | 154 def_link = DF_INSN_INFO_DEFS (insn_info); |
121 set = single_set (insn); | 155 set = single_set (insn); |
122 } | 156 } |
123 else | 157 else |
124 { | 158 { |
125 /* An artificial use. It links up with nothing. */ | 159 /* An artificial use. It links up with nothing. */ |
126 use_link = NULL; | |
127 eq_use_link = NULL; | 160 eq_use_link = NULL; |
128 def_link = NULL; | 161 def_link = NULL; |
129 set = NULL; | 162 set = NULL; |
130 } | 163 } |
131 | 164 |
132 /* Some instructions may use match_dup for their operands. In case the | 165 /* Union all occurrences of the same register in reg notes. */ |
133 operands are dead, we will assign them different pseudos, creating | |
134 invalid instructions, so union all uses of the same operand for each | |
135 insn. */ | |
136 | |
137 if (use_link) | |
138 while (*use_link) | |
139 { | |
140 if (use != *use_link | |
141 && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (*use_link)) | |
142 (*fun) (use_entry + DF_REF_ID (use), | |
143 use_entry + DF_REF_ID (*use_link)); | |
144 use_link++; | |
145 } | |
146 | 166 |
147 if (eq_use_link) | 167 if (eq_use_link) |
148 while (*eq_use_link) | 168 while (*eq_use_link) |
149 { | 169 { |
150 if (use != *eq_use_link | 170 if (use != *eq_use_link |
167 (*fun) (use_entry + DF_REF_ID (use), | 187 (*fun) (use_entry + DF_REF_ID (use), |
168 def_entry + DF_REF_ID (*def_link)); | 188 def_entry + DF_REF_ID (*def_link)); |
169 def_link++; | 189 def_link++; |
170 } | 190 } |
171 } | 191 } |
192 | |
193 /* UD chains of uninitialized REGs are empty. Keeping all uses of | |
194 the same uninitialized REG in a single web is not necessary for | |
195 correctness, since the uses are undefined, but it's wasteful to | |
196 allocate one register or slot for each reference. Furthermore, | |
197 creating new pseudos for uninitialized references in debug insns | |
198 (see PR 42631) causes -fcompare-debug failures. We record the | |
199 number of the first uninitialized reference we found, and merge | |
200 with it any other uninitialized references to the same | |
201 register. */ | |
202 if (!link) | |
203 { | |
204 int regno = REGNO (DF_REF_REAL_REG (use)); | |
205 if (used[regno]) | |
206 (*fun) (use_entry + DF_REF_ID (use), use_entry + used[regno] - 2); | |
207 else | |
208 used[regno] = DF_REF_ID (use) + 2; | |
209 } | |
210 | |
172 while (link) | 211 while (link) |
173 { | 212 { |
174 (*fun) (use_entry + DF_REF_ID (use), | 213 (*fun) (use_entry + DF_REF_ID (use), |
175 def_entry + DF_REF_ID (link->ref)); | 214 def_entry + DF_REF_ID (link->ref)); |
176 link = link->next; | 215 link = link->next; |
199 } | 238 } |
200 | 239 |
201 /* Find the corresponding register for the given entry. */ | 240 /* Find the corresponding register for the given entry. */ |
202 | 241 |
203 static rtx | 242 static rtx |
204 entry_register (struct web_entry *entry, df_ref ref, char *used) | 243 entry_register (struct web_entry *entry, df_ref ref, unsigned int *used) |
205 { | 244 { |
206 struct web_entry *root; | 245 struct web_entry *root; |
207 rtx reg, newreg; | 246 rtx reg, newreg; |
208 | 247 |
209 /* Find the corresponding web and see if it has been visited. */ | 248 /* Find the corresponding web and see if it has been visited. */ |
212 return root->reg; | 251 return root->reg; |
213 | 252 |
214 /* We are seeing this web for the first time, do the assignment. */ | 253 /* We are seeing this web for the first time, do the assignment. */ |
215 reg = DF_REF_REAL_REG (ref); | 254 reg = DF_REF_REAL_REG (ref); |
216 | 255 |
217 /* In case the original register is already assigned, generate new one. */ | 256 /* In case the original register is already assigned, generate new |
218 if (!used[REGNO (reg)]) | 257 one. Since we use USED to merge uninitialized refs into a single |
258 web, we might found an element to be nonzero without our having | |
259 used it. Test for 1, because union_defs saves it for our use, | |
260 and there won't be any use for the other values when we get to | |
261 this point. */ | |
262 if (used[REGNO (reg)] != 1) | |
219 newreg = reg, used[REGNO (reg)] = 1; | 263 newreg = reg, used[REGNO (reg)] = 1; |
220 else if (REG_USERVAR_P (reg) && 0/*&& !flag_messy_debugging*/) | |
221 { | |
222 newreg = reg; | |
223 if (dump_file) | |
224 fprintf (dump_file, | |
225 "New web forced to keep reg=%i (user variable)\n", | |
226 REGNO (reg)); | |
227 } | |
228 else | 264 else |
229 { | 265 { |
230 newreg = gen_reg_rtx (GET_MODE (reg)); | 266 newreg = gen_reg_rtx (GET_MODE (reg)); |
231 REG_USERVAR_P (newreg) = REG_USERVAR_P (reg); | 267 REG_USERVAR_P (newreg) = REG_USERVAR_P (reg); |
232 REG_POINTER (newreg) = REG_POINTER (reg); | 268 REG_POINTER (newreg) = REG_POINTER (reg); |
271 web_main (void) | 307 web_main (void) |
272 { | 308 { |
273 struct web_entry *def_entry; | 309 struct web_entry *def_entry; |
274 struct web_entry *use_entry; | 310 struct web_entry *use_entry; |
275 unsigned int max = max_reg_num (); | 311 unsigned int max = max_reg_num (); |
276 char *used; | 312 unsigned int *used; |
277 basic_block bb; | 313 basic_block bb; |
278 unsigned int uses_num = 0; | 314 unsigned int uses_num = 0; |
279 rtx insn; | 315 rtx insn; |
280 | 316 |
281 df_set_flags (DF_NO_HARD_REGS + DF_EQ_NOTES); | 317 df_set_flags (DF_NO_HARD_REGS + DF_EQ_NOTES); |
286 /* Assign ids to the uses. */ | 322 /* Assign ids to the uses. */ |
287 FOR_ALL_BB (bb) | 323 FOR_ALL_BB (bb) |
288 FOR_BB_INSNS (bb, insn) | 324 FOR_BB_INSNS (bb, insn) |
289 { | 325 { |
290 unsigned int uid = INSN_UID (insn); | 326 unsigned int uid = INSN_UID (insn); |
291 if (INSN_P (insn)) | 327 if (NONDEBUG_INSN_P (insn)) |
292 { | 328 { |
293 df_ref *use_rec; | 329 df_ref *use_rec; |
294 for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) | 330 for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) |
295 { | 331 { |
296 df_ref use = *use_rec; | 332 df_ref use = *use_rec; |
306 } | 342 } |
307 } | 343 } |
308 | 344 |
309 /* Record the number of uses and defs at the beginning of the optimization. */ | 345 /* Record the number of uses and defs at the beginning of the optimization. */ |
310 def_entry = XCNEWVEC (struct web_entry, DF_DEFS_TABLE_SIZE()); | 346 def_entry = XCNEWVEC (struct web_entry, DF_DEFS_TABLE_SIZE()); |
311 used = XCNEWVEC (char, max); | 347 used = XCNEWVEC (unsigned, max); |
312 use_entry = XCNEWVEC (struct web_entry, uses_num); | 348 use_entry = XCNEWVEC (struct web_entry, uses_num); |
313 | 349 |
314 /* Produce the web. */ | 350 /* Produce the web. */ |
315 FOR_ALL_BB (bb) | 351 FOR_ALL_BB (bb) |
316 FOR_BB_INSNS (bb, insn) | 352 FOR_BB_INSNS (bb, insn) |
317 { | 353 { |
318 unsigned int uid = INSN_UID (insn); | 354 unsigned int uid = INSN_UID (insn); |
319 if (INSN_P (insn)) | 355 if (NONDEBUG_INSN_P (insn)) |
320 { | 356 { |
321 df_ref *use_rec; | 357 df_ref *use_rec; |
358 union_match_dups (insn, def_entry, use_entry, unionfind_union); | |
322 for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) | 359 for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) |
323 { | 360 { |
324 df_ref use = *use_rec; | 361 df_ref use = *use_rec; |
325 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER) | 362 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER) |
326 union_defs (use, def_entry, use_entry, unionfind_union); | 363 union_defs (use, def_entry, used, use_entry, unionfind_union); |
327 } | 364 } |
328 for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++) | 365 for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++) |
329 { | 366 { |
330 df_ref use = *use_rec; | 367 df_ref use = *use_rec; |
331 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER) | 368 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER) |
332 union_defs (use, def_entry, use_entry, unionfind_union); | 369 union_defs (use, def_entry, used, use_entry, unionfind_union); |
333 } | 370 } |
334 } | 371 } |
335 } | 372 } |
336 | 373 |
337 /* Update the instruction stream, allocating new registers for split pseudos | 374 /* Update the instruction stream, allocating new registers for split pseudos |
338 in progress. */ | 375 in progress. */ |
339 FOR_ALL_BB (bb) | 376 FOR_ALL_BB (bb) |
340 FOR_BB_INSNS (bb, insn) | 377 FOR_BB_INSNS (bb, insn) |
341 { | 378 { |
342 unsigned int uid = INSN_UID (insn); | 379 unsigned int uid = INSN_UID (insn); |
343 if (INSN_P (insn)) | 380 if (NONDEBUG_INSN_P (insn)) |
344 { | 381 { |
345 df_ref *use_rec; | 382 df_ref *use_rec; |
346 df_ref *def_rec; | 383 df_ref *def_rec; |
347 for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) | 384 for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) |
348 { | 385 { |