Fix gnu11 fallout on SPARC
[official-gcc.git] / gcc / web.c
blob90da6c90a750b2518a1a48e4c1f56a5d931cd76d
1 /* Web construction code for GNU compiler.
2 Contributed by Jan Hubicka.
3 Copyright (C) 2001-2014 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* Simple optimization pass that splits independent uses of each pseudo,
22 increasing effectiveness of other optimizations. The optimization can
23 serve as an example of use for the dataflow module.
25 We don't split registers with REG_USERVAR set unless -fmessy-debugging
26 is specified, because debugging information about such split variables
27 is almost unusable.
29 TODO
30 - We may use profile information and ignore infrequent use for the
31 purpose of web unifying, inserting the compensation code later to
32 implement full induction variable expansion for loops (currently
33 we expand only if the induction variable is dead afterward, which
34 is often the case). */
36 #include "config.h"
37 #include "system.h"
38 #include "coretypes.h"
39 #include "tm.h"
40 #include "diagnostic-core.h"
42 #include "rtl.h"
43 #include "hard-reg-set.h"
44 #include "flags.h"
45 #include "obstack.h"
46 #include "basic-block.h"
47 #include "df.h"
48 #include "hashtab.h"
49 #include "hash-set.h"
50 #include "vec.h"
51 #include "machmode.h"
52 #include "input.h"
53 #include "function.h"
54 #include "insn-config.h"
55 #include "recog.h"
56 #include "tree-pass.h"
59 /* Find the root of unionfind tree (the representative of set). */
61 web_entry_base *
62 web_entry_base::unionfind_root ()
64 web_entry_base *element = this, *element1 = this, *element2;
66 while (element->pred ())
67 element = element->pred ();
68 while (element1->pred ())
70 element2 = element1->pred ();
71 element1->set_pred (element);
72 element1 = element2;
74 return element;
77 /* Union sets.
78 Return true if FIRST and SECOND points to the same web entry structure and
79 nothing is done. Otherwise, return false. */
81 bool
82 unionfind_union (web_entry_base *first, web_entry_base *second)
84 first = first->unionfind_root ();
85 second = second->unionfind_root ();
86 if (first == second)
87 return true;
88 second->set_pred (first);
89 return false;
92 class web_entry : public web_entry_base
94 private:
95 rtx reg_pvt;
97 public:
98 rtx reg () { return reg_pvt; }
99 void set_reg (rtx r) { reg_pvt = r; }
102 /* For INSN, union all defs and uses that are linked by match_dup.
103 FUN is the function that does the union. */
105 static void
106 union_match_dups (rtx_insn *insn, web_entry *def_entry, web_entry *use_entry,
107 bool (*fun) (web_entry_base *, web_entry_base *))
109 struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
110 df_ref use_link = DF_INSN_INFO_USES (insn_info);
111 df_ref def_link = DF_INSN_INFO_DEFS (insn_info);
112 struct web_entry *dup_entry;
113 int i;
115 extract_insn (insn);
117 for (i = 0; i < recog_data.n_dups; i++)
119 int op = recog_data.dup_num[i];
120 enum op_type type = recog_data.operand_type[op];
121 df_ref ref, dupref;
122 struct web_entry *entry;
124 dup_entry = use_entry;
125 for (dupref = use_link; dupref; dupref = DF_REF_NEXT_LOC (dupref))
126 if (DF_REF_LOC (dupref) == recog_data.dup_loc[i])
127 break;
129 if (dupref == NULL && type == OP_INOUT)
131 dup_entry = def_entry;
132 for (dupref = def_link; dupref; dupref = DF_REF_NEXT_LOC (dupref))
133 if (DF_REF_LOC (dupref) == recog_data.dup_loc[i])
134 break;
136 /* ??? *DUPREF can still be zero, because when an operand matches
137 a memory, DF_REF_LOC (use_link[n]) points to the register part
138 of the address, whereas recog_data.dup_loc[m] points to the
139 entire memory ref, thus we fail to find the duplicate entry,
140 even though it is there.
141 Example: i686-pc-linux-gnu gcc.c-torture/compile/950607-1.c
142 -O3 -fomit-frame-pointer -funroll-loops */
143 if (dupref == NULL
144 || DF_REF_REGNO (dupref) < FIRST_PSEUDO_REGISTER)
145 continue;
147 ref = type == OP_IN ? use_link : def_link;
148 entry = type == OP_IN ? use_entry : def_entry;
149 for (; ref; ref = DF_REF_NEXT_LOC (ref))
151 rtx *l = DF_REF_LOC (ref);
152 if (l == recog_data.operand_loc[op])
153 break;
154 if (l && DF_REF_REAL_LOC (ref) == recog_data.operand_loc[op])
155 break;
158 if (!ref && type == OP_INOUT)
160 entry = use_entry;
161 for (ref = use_link; ref; ref = DF_REF_NEXT_LOC (ref))
163 rtx *l = DF_REF_LOC (ref);
164 if (l == recog_data.operand_loc[op])
165 break;
166 if (l && DF_REF_REAL_LOC (ref) == recog_data.operand_loc[op])
167 break;
171 gcc_assert (ref);
172 (*fun) (dup_entry + DF_REF_ID (dupref), entry + DF_REF_ID (ref));
176 /* For each use, all possible defs reaching it must come in the same
177 register, union them.
178 FUN is the function that does the union.
180 In USED, we keep the DF_REF_ID of the first uninitialized uses of a
181 register, so that all uninitialized uses of the register can be
182 combined into a single web. We actually offset it by 2, because
183 the values 0 and 1 are reserved for use by entry_register. */
185 void
186 union_defs (df_ref use, web_entry *def_entry,
187 unsigned int *used, web_entry *use_entry,
188 bool (*fun) (web_entry_base *, web_entry_base *))
190 struct df_insn_info *insn_info = DF_REF_INSN_INFO (use);
191 struct df_link *link = DF_REF_CHAIN (use);
192 rtx set;
194 if (insn_info)
196 df_ref eq_use;
198 set = single_set (insn_info->insn);
199 FOR_EACH_INSN_INFO_EQ_USE (eq_use, insn_info)
200 if (use != eq_use
201 && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (eq_use))
202 (*fun) (use_entry + DF_REF_ID (use), use_entry + DF_REF_ID (eq_use));
204 else
205 set = NULL;
207 /* Union all occurrences of the same register in reg notes. */
209 /* Recognize trivial noop moves and attempt to keep them as noop. */
211 if (set
212 && SET_SRC (set) == DF_REF_REG (use)
213 && SET_SRC (set) == SET_DEST (set))
215 df_ref def;
217 FOR_EACH_INSN_INFO_DEF (def, insn_info)
218 if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def))
219 (*fun) (use_entry + DF_REF_ID (use), def_entry + DF_REF_ID (def));
222 /* UD chains of uninitialized REGs are empty. Keeping all uses of
223 the same uninitialized REG in a single web is not necessary for
224 correctness, since the uses are undefined, but it's wasteful to
225 allocate one register or slot for each reference. Furthermore,
226 creating new pseudos for uninitialized references in debug insns
227 (see PR 42631) causes -fcompare-debug failures. We record the
228 number of the first uninitialized reference we found, and merge
229 with it any other uninitialized references to the same
230 register. */
231 if (!link)
233 int regno = REGNO (DF_REF_REAL_REG (use));
234 if (used[regno])
235 (*fun) (use_entry + DF_REF_ID (use), use_entry + used[regno] - 2);
236 else
237 used[regno] = DF_REF_ID (use) + 2;
240 while (link)
242 (*fun) (use_entry + DF_REF_ID (use),
243 def_entry + DF_REF_ID (link->ref));
244 link = link->next;
247 /* A READ_WRITE use requires the corresponding def to be in the same
248 register. Find it and union. */
249 if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
250 if (insn_info)
252 df_ref def;
254 FOR_EACH_INSN_INFO_DEF (def, insn_info)
255 if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def))
256 (*fun) (use_entry + DF_REF_ID (use), def_entry + DF_REF_ID (def));
260 /* Find the corresponding register for the given entry. */
262 static rtx
263 entry_register (web_entry *entry, df_ref ref, unsigned int *used)
265 web_entry *root;
266 rtx reg, newreg;
268 /* Find the corresponding web and see if it has been visited. */
269 root = (web_entry *)entry->unionfind_root ();
270 if (root->reg ())
271 return root->reg ();
273 /* We are seeing this web for the first time, do the assignment. */
274 reg = DF_REF_REAL_REG (ref);
276 /* In case the original register is already assigned, generate new
277 one. Since we use USED to merge uninitialized refs into a single
278 web, we might found an element to be nonzero without our having
279 used it. Test for 1, because union_defs saves it for our use,
280 and there won't be any use for the other values when we get to
281 this point. */
282 if (used[REGNO (reg)] != 1)
283 newreg = reg, used[REGNO (reg)] = 1;
284 else
286 newreg = gen_reg_rtx (GET_MODE (reg));
287 REG_USERVAR_P (newreg) = REG_USERVAR_P (reg);
288 REG_POINTER (newreg) = REG_POINTER (reg);
289 REG_ATTRS (newreg) = REG_ATTRS (reg);
290 if (dump_file)
291 fprintf (dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg),
292 REGNO (newreg));
295 root->set_reg (newreg);
296 return newreg;
299 /* Replace the reference by REG. */
301 static void
302 replace_ref (df_ref ref, rtx reg)
304 rtx oldreg = DF_REF_REAL_REG (ref);
305 rtx *loc = DF_REF_REAL_LOC (ref);
306 unsigned int uid = DF_REF_INSN_UID (ref);
308 if (oldreg == reg)
309 return;
310 if (dump_file)
311 fprintf (dump_file, "Updating insn %i (%i->%i)\n",
312 uid, REGNO (oldreg), REGNO (reg));
313 *loc = reg;
314 df_insn_rescan (DF_REF_INSN (ref));
318 namespace {
320 const pass_data pass_data_web =
322 RTL_PASS, /* type */
323 "web", /* name */
324 OPTGROUP_NONE, /* optinfo_flags */
325 TV_WEB, /* tv_id */
326 0, /* properties_required */
327 0, /* properties_provided */
328 0, /* properties_destroyed */
329 0, /* todo_flags_start */
330 TODO_df_finish, /* todo_flags_finish */
333 class pass_web : public rtl_opt_pass
335 public:
336 pass_web (gcc::context *ctxt)
337 : rtl_opt_pass (pass_data_web, ctxt)
340 /* opt_pass methods: */
341 virtual bool gate (function *) { return (optimize > 0 && flag_web); }
342 virtual unsigned int execute (function *);
344 }; // class pass_web
346 unsigned int
347 pass_web::execute (function *fun)
349 web_entry *def_entry;
350 web_entry *use_entry;
351 unsigned int max = max_reg_num ();
352 unsigned int *used;
353 basic_block bb;
354 unsigned int uses_num = 0;
355 rtx_insn *insn;
357 df_set_flags (DF_NO_HARD_REGS + DF_EQ_NOTES);
358 df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
359 df_chain_add_problem (DF_UD_CHAIN);
360 df_analyze ();
361 df_set_flags (DF_DEFER_INSN_RESCAN);
363 /* Assign ids to the uses. */
364 FOR_ALL_BB_FN (bb, fun)
365 FOR_BB_INSNS (bb, insn)
367 if (NONDEBUG_INSN_P (insn))
369 struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
370 df_ref use;
371 FOR_EACH_INSN_INFO_USE (use, insn_info)
372 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
373 DF_REF_ID (use) = uses_num++;
374 FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
375 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
376 DF_REF_ID (use) = uses_num++;
380 /* Record the number of uses and defs at the beginning of the optimization. */
381 def_entry = XCNEWVEC (web_entry, DF_DEFS_TABLE_SIZE ());
382 used = XCNEWVEC (unsigned, max);
383 use_entry = XCNEWVEC (web_entry, uses_num);
385 /* Produce the web. */
386 FOR_ALL_BB_FN (bb, fun)
387 FOR_BB_INSNS (bb, insn)
388 if (NONDEBUG_INSN_P (insn))
390 struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
391 df_ref use;
392 union_match_dups (insn, def_entry, use_entry, unionfind_union);
393 FOR_EACH_INSN_INFO_USE (use, insn_info)
394 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
395 union_defs (use, def_entry, used, use_entry, unionfind_union);
396 FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
397 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
398 union_defs (use, def_entry, used, use_entry, unionfind_union);
401 /* Update the instruction stream, allocating new registers for split pseudos
402 in progress. */
403 FOR_ALL_BB_FN (bb, fun)
404 FOR_BB_INSNS (bb, insn)
405 if (NONDEBUG_INSN_P (insn)
406 /* Ignore naked clobber. For example, reg 134 in the second insn
407 of the following sequence will not be replaced.
409 (insn (clobber (reg:SI 134)))
411 (insn (set (reg:SI 0 r0) (reg:SI 134)))
413 Thus the later passes can optimize them away. */
414 && GET_CODE (PATTERN (insn)) != CLOBBER)
416 struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
417 df_ref def, use;
418 FOR_EACH_INSN_INFO_USE (use, insn_info)
419 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
420 replace_ref (use, entry_register (use_entry + DF_REF_ID (use),
421 use, used));
422 FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
423 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
424 replace_ref (use, entry_register (use_entry + DF_REF_ID (use),
425 use, used));
426 FOR_EACH_INSN_INFO_DEF (def, insn_info)
427 if (DF_REF_REGNO (def) >= FIRST_PSEUDO_REGISTER)
428 replace_ref (def, entry_register (def_entry + DF_REF_ID (def),
429 def, used));
432 free (def_entry);
433 free (use_entry);
434 free (used);
435 return 0;
438 } // anon namespace
440 rtl_opt_pass *
441 make_pass_web (gcc::context *ctxt)
443 return new pass_web (ctxt);