[multiple changes]
[gcc.git] / gcc / web.c
1 /* Web construction code for GNU compiler.
2 Contributed by Jan Hubicka.
3 Copyright (C) 2001-2014 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>. */
20
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.
24
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.
28
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). */
35
36 #include "config.h"
37 #include "system.h"
38 #include "coretypes.h"
39 #include "tm.h"
40 #include "diagnostic-core.h"
41
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"
57
58
59 /* Find the root of unionfind tree (the representative of set). */
60
61 web_entry_base *
62 web_entry_base::unionfind_root ()
63 {
64 web_entry_base *element = this, *element1 = this, *element2;
65
66 while (element->pred ())
67 element = element->pred ();
68 while (element1->pred ())
69 {
70 element2 = element1->pred ();
71 element1->set_pred (element);
72 element1 = element2;
73 }
74 return element;
75 }
76
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. */
80
81 bool
82 unionfind_union (web_entry_base *first, web_entry_base *second)
83 {
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;
90 }
91
92 class web_entry : public web_entry_base
93 {
94 private:
95 rtx reg_pvt;
96
97 public:
98 rtx reg () { return reg_pvt; }
99 void set_reg (rtx r) { reg_pvt = r; }
100 };
101
102 /* For INSN, union all defs and uses that are linked by match_dup.
103 FUN is the function that does the union. */
104
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 *))
108 {
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;
114
115 extract_insn (insn);
116
117 for (i = 0; i < recog_data.n_dups; i++)
118 {
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;
123
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;
128
129 if (dupref == NULL && type == OP_INOUT)
130 {
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;
135 }
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;
146
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))
150 {
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;
156 }
157
158 if (!ref && type == OP_INOUT)
159 {
160 entry = use_entry;
161 for (ref = use_link; ref; ref = DF_REF_NEXT_LOC (ref))
162 {
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;
168 }
169 }
170
171 gcc_assert (ref);
172 (*fun) (dup_entry + DF_REF_ID (dupref), entry + DF_REF_ID (ref));
173 }
174 }
175
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.
179
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. */
184
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 *))
189 {
190 struct df_insn_info *insn_info = DF_REF_INSN_INFO (use);
191 struct df_link *link = DF_REF_CHAIN (use);
192 rtx set;
193
194 if (insn_info)
195 {
196 df_ref eq_use;
197
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));
203 }
204 else
205 set = NULL;
206
207 /* Union all occurrences of the same register in reg notes. */
208
209 /* Recognize trivial noop moves and attempt to keep them as noop. */
210
211 if (set
212 && SET_SRC (set) == DF_REF_REG (use)
213 && SET_SRC (set) == SET_DEST (set))
214 {
215 df_ref def;
216
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));
220 }
221
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)
232 {
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;
238 }
239
240 while (link)
241 {
242 (*fun) (use_entry + DF_REF_ID (use),
243 def_entry + DF_REF_ID (link->ref));
244 link = link->next;
245 }
246
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)
251 {
252 df_ref def;
253
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));
257 }
258 }
259
260 /* Find the corresponding register for the given entry. */
261
262 static rtx
263 entry_register (web_entry *entry, df_ref ref, unsigned int *used)
264 {
265 web_entry *root;
266 rtx reg, newreg;
267
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 ();
272
273 /* We are seeing this web for the first time, do the assignment. */
274 reg = DF_REF_REAL_REG (ref);
275
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
285 {
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));
293 }
294
295 root->set_reg (newreg);
296 return newreg;
297 }
298
299 /* Replace the reference by REG. */
300
301 static void
302 replace_ref (df_ref ref, rtx reg)
303 {
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);
307
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));
315 }
316
317 \f
318 namespace {
319
320 const pass_data pass_data_web =
321 {
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 */
331 };
332
333 class pass_web : public rtl_opt_pass
334 {
335 public:
336 pass_web (gcc::context *ctxt)
337 : rtl_opt_pass (pass_data_web, ctxt)
338 {}
339
340 /* opt_pass methods: */
341 virtual bool gate (function *) { return (optimize > 0 && flag_web); }
342 virtual unsigned int execute (function *);
343
344 }; // class pass_web
345
346 unsigned int
347 pass_web::execute (function *fun)
348 {
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;
356
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);
362
363 /* Assign ids to the uses. */
364 FOR_ALL_BB_FN (bb, fun)
365 FOR_BB_INSNS (bb, insn)
366 {
367 if (NONDEBUG_INSN_P (insn))
368 {
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++;
377 }
378 }
379
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);
384
385 /* Produce the web. */
386 FOR_ALL_BB_FN (bb, fun)
387 FOR_BB_INSNS (bb, insn)
388 if (NONDEBUG_INSN_P (insn))
389 {
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);
399 }
400
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.
408
409 (insn (clobber (reg:SI 134)))
410
411 (insn (set (reg:SI 0 r0) (reg:SI 134)))
412
413 Thus the later passes can optimize them away. */
414 && GET_CODE (PATTERN (insn)) != CLOBBER)
415 {
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));
430 }
431
432 free (def_entry);
433 free (use_entry);
434 free (used);
435 return 0;
436 }
437 \f
438 } // anon namespace
439
440 rtl_opt_pass *
441 make_pass_web (gcc::context *ctxt)
442 {
443 return new pass_web (ctxt);
444 }