* web.c (union_match_dups): Also check DF_REF_REAL_LOC.
[platform/upstream/gcc.git] / gcc / web.c
1 /* Web construction code for GNU compiler.
2    Contributed by Jan Hubicka.
3    Copyright (C) 2001-2013 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 "function.h"
49 #include "insn-config.h"
50 #include "recog.h"
51 #include "tree-pass.h"
52
53
54 /* Find the root of unionfind tree (the representative of set).  */
55
56 struct web_entry *
57 unionfind_root (struct web_entry *element)
58 {
59   struct web_entry *element1 = element, *element2;
60
61   while (element->pred)
62     element = element->pred;
63   while (element1->pred)
64     {
65       element2 = element1->pred;
66       element1->pred = element;
67       element1 = element2;
68     }
69   return element;
70 }
71
72 /* Union sets.
73    Return true if FIRST and SECOND points to the same web entry structure and
74    nothing is done.  Otherwise, return false.  */
75
76 bool
77 unionfind_union (struct web_entry *first, struct web_entry *second)
78 {
79   first = unionfind_root (first);
80   second = unionfind_root (second);
81   if (first == second)
82     return true;
83   second->pred = first;
84   return false;
85 }
86
87 /* For INSN, union all defs and uses that are linked by match_dup.
88    FUN is the function that does the union.  */
89
90 static void
91 union_match_dups (rtx insn, struct web_entry *def_entry,
92                   struct web_entry *use_entry,
93                   bool (*fun) (struct web_entry *, struct web_entry *))
94 {
95   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
96   df_ref *use_link = DF_INSN_INFO_USES (insn_info);
97   df_ref *def_link = DF_INSN_INFO_DEFS (insn_info);
98   struct web_entry *dup_entry;
99   int i;
100
101   extract_insn (insn);
102
103   for (i = 0; i < recog_data.n_dups; i++)
104     {
105       int op = recog_data.dup_num[i];
106       enum op_type type = recog_data.operand_type[op];
107       df_ref *ref, *dupref;
108       struct web_entry *entry;
109
110       for (dup_entry = use_entry, dupref = use_link; *dupref; dupref++)
111         if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i])
112           break;
113
114       if (*dupref == NULL && type == OP_INOUT)
115         {
116
117           for (dup_entry = def_entry, dupref = def_link; *dupref; dupref++)
118             if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i])
119               break;
120         }
121       /* ??? *DUPREF can still be zero, because when an operand matches
122          a memory, DF_REF_LOC (use_link[n]) points to the register part
123          of the address, whereas recog_data.dup_loc[m] points to the
124          entire memory ref, thus we fail to find the duplicate entry,
125          even though it is there.
126          Example: i686-pc-linux-gnu gcc.c-torture/compile/950607-1.c
127                   -O3 -fomit-frame-pointer -funroll-loops  */
128       if (*dupref == NULL
129           || DF_REF_REGNO (*dupref) < FIRST_PSEUDO_REGISTER)
130         continue;
131
132       ref = type == OP_IN ? use_link : def_link;
133       entry = type == OP_IN ? use_entry : def_entry;
134       for (; *ref; ref++)
135         {
136           if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
137             break;
138           if (DF_REF_REAL_LOC (*ref) == recog_data.operand_loc[op])
139             break;
140         }
141
142       if (!*ref && type == OP_INOUT)
143         {
144           for (ref = use_link, entry = use_entry; *ref; ref++)
145             {
146               if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
147                 break;
148               if (DF_REF_REAL_LOC (*ref) == recog_data.operand_loc[op])
149                 break;
150             }
151         }
152
153       gcc_assert (*ref);
154       (*fun) (dup_entry + DF_REF_ID (*dupref), entry + DF_REF_ID (*ref));
155     }
156 }
157
158 /* For each use, all possible defs reaching it must come in the same
159    register, union them.
160    FUN is the function that does the union.
161
162    In USED, we keep the DF_REF_ID of the first uninitialized uses of a
163    register, so that all uninitialized uses of the register can be
164    combined into a single web.  We actually offset it by 2, because
165    the values 0 and 1 are reserved for use by entry_register.  */
166
167 void
168 union_defs (df_ref use, struct web_entry *def_entry,
169             unsigned int *used, struct web_entry *use_entry,
170             bool (*fun) (struct web_entry *, struct web_entry *))
171 {
172   struct df_insn_info *insn_info = DF_REF_INSN_INFO (use);
173   struct df_link *link = DF_REF_CHAIN (use);
174   df_ref *eq_use_link;
175   df_ref *def_link;
176   rtx set;
177
178   if (insn_info)
179     {
180       rtx insn = insn_info->insn;
181       eq_use_link = DF_INSN_INFO_EQ_USES (insn_info);
182       def_link = DF_INSN_INFO_DEFS (insn_info);
183       set = single_set (insn);
184     }
185   else
186     {
187       /* An artificial use.  It links up with nothing.  */
188       eq_use_link = NULL;
189       def_link = NULL;
190       set = NULL;
191     }
192
193   /* Union all occurrences of the same register in reg notes.  */
194
195   if (eq_use_link)
196     while (*eq_use_link)
197       {
198         if (use != *eq_use_link
199             && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (*eq_use_link))
200           (*fun) (use_entry + DF_REF_ID (use),
201                   use_entry + DF_REF_ID (*eq_use_link));
202         eq_use_link++;
203     }
204
205   /* Recognize trivial noop moves and attempt to keep them as noop.  */
206
207   if (set
208       && SET_SRC (set) == DF_REF_REG (use)
209       && SET_SRC (set) == SET_DEST (set))
210     {
211       if (def_link)
212         while (*def_link)
213           {
214             if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (*def_link))
215               (*fun) (use_entry + DF_REF_ID (use),
216                       def_entry + DF_REF_ID (*def_link));
217             def_link++;
218           }
219     }
220
221   /* UD chains of uninitialized REGs are empty.  Keeping all uses of
222      the same uninitialized REG in a single web is not necessary for
223      correctness, since the uses are undefined, but it's wasteful to
224      allocate one register or slot for each reference.  Furthermore,
225      creating new pseudos for uninitialized references in debug insns
226      (see PR 42631) causes -fcompare-debug failures.  We record the
227      number of the first uninitialized reference we found, and merge
228      with it any other uninitialized references to the same
229      register.  */
230   if (!link)
231     {
232       int regno = REGNO (DF_REF_REAL_REG (use));
233       if (used[regno])
234         (*fun) (use_entry + DF_REF_ID (use), use_entry + used[regno] - 2);
235       else
236         used[regno] = DF_REF_ID (use) + 2;
237     }
238
239   while (link)
240     {
241       (*fun) (use_entry + DF_REF_ID (use),
242               def_entry + DF_REF_ID (link->ref));
243       link = link->next;
244     }
245
246   /* A READ_WRITE use requires the corresponding def to be in the same
247      register.  Find it and union.  */
248   if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
249     {
250       df_ref *link;
251
252       if (insn_info)
253         link = DF_INSN_INFO_DEFS (insn_info);
254       else
255         link = NULL;
256
257       if (link)
258         while (*link)
259           {
260             if (DF_REF_REAL_REG (*link) == DF_REF_REAL_REG (use))
261               (*fun) (use_entry + DF_REF_ID (use),
262                       def_entry + DF_REF_ID (*link));
263             link++;
264           }
265     }
266 }
267
268 /* Find the corresponding register for the given entry.  */
269
270 static rtx
271 entry_register (struct web_entry *entry, df_ref ref, unsigned int *used)
272 {
273   struct web_entry *root;
274   rtx reg, newreg;
275
276   /* Find the corresponding web and see if it has been visited.  */
277   root = unionfind_root (entry);
278   if (root->reg)
279     return root->reg;
280
281   /* We are seeing this web for the first time, do the assignment.  */
282   reg = DF_REF_REAL_REG (ref);
283
284   /* In case the original register is already assigned, generate new
285      one.  Since we use USED to merge uninitialized refs into a single
286      web, we might found an element to be nonzero without our having
287      used it.  Test for 1, because union_defs saves it for our use,
288      and there won't be any use for the other values when we get to
289      this point.  */
290   if (used[REGNO (reg)] != 1)
291     newreg = reg, used[REGNO (reg)] = 1;
292   else
293     {
294       newreg = gen_reg_rtx (GET_MODE (reg));
295       REG_USERVAR_P (newreg) = REG_USERVAR_P (reg);
296       REG_POINTER (newreg) = REG_POINTER (reg);
297       REG_ATTRS (newreg) = REG_ATTRS (reg);
298       if (dump_file)
299         fprintf (dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg),
300                  REGNO (newreg));
301     }
302
303   root->reg = newreg;
304   return newreg;
305 }
306
307 /* Replace the reference by REG.  */
308
309 static void
310 replace_ref (df_ref ref, rtx reg)
311 {
312   rtx oldreg = DF_REF_REAL_REG (ref);
313   rtx *loc = DF_REF_REAL_LOC (ref);
314   unsigned int uid = DF_REF_INSN_UID (ref);
315
316   if (oldreg == reg)
317     return;
318   if (dump_file)
319     fprintf (dump_file, "Updating insn %i (%i->%i)\n",
320              uid, REGNO (oldreg), REGNO (reg));
321   *loc = reg;
322   df_insn_rescan (DF_REF_INSN (ref));
323 }
324
325 \f
326 static bool
327 gate_handle_web (void)
328 {
329   return (optimize > 0 && flag_web);
330 }
331
332 /* Main entry point.  */
333
334 static unsigned int
335 web_main (void)
336 {
337   struct web_entry *def_entry;
338   struct web_entry *use_entry;
339   unsigned int max = max_reg_num ();
340   unsigned int *used;
341   basic_block bb;
342   unsigned int uses_num = 0;
343   rtx insn;
344
345   df_set_flags (DF_NO_HARD_REGS + DF_EQ_NOTES);
346   df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
347   df_chain_add_problem (DF_UD_CHAIN);
348   df_analyze ();
349   df_set_flags (DF_DEFER_INSN_RESCAN);
350
351   /* Assign ids to the uses.  */
352   FOR_ALL_BB (bb)
353     FOR_BB_INSNS (bb, insn)
354     {
355       unsigned int uid = INSN_UID (insn);
356       if (NONDEBUG_INSN_P (insn))
357         {
358           df_ref *use_rec;
359           for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
360             {
361               df_ref use = *use_rec;
362               if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
363                 DF_REF_ID (use) = uses_num++;
364             }
365           for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
366             {
367               df_ref use = *use_rec;
368               if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
369                 DF_REF_ID (use) = uses_num++;
370             }
371         }
372     }
373
374   /* Record the number of uses and defs at the beginning of the optimization.  */
375   def_entry = XCNEWVEC (struct web_entry, DF_DEFS_TABLE_SIZE());
376   used = XCNEWVEC (unsigned, max);
377   use_entry = XCNEWVEC (struct web_entry, uses_num);
378
379   /* Produce the web.  */
380   FOR_ALL_BB (bb)
381     FOR_BB_INSNS (bb, insn)
382     {
383       unsigned int uid = INSN_UID (insn);
384       if (NONDEBUG_INSN_P (insn))
385         {
386           df_ref *use_rec;
387           union_match_dups (insn, def_entry, use_entry, unionfind_union);
388           for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
389             {
390               df_ref use = *use_rec;
391               if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
392                 union_defs (use, def_entry, used, use_entry, unionfind_union);
393             }
394           for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
395             {
396               df_ref use = *use_rec;
397               if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
398                 union_defs (use, def_entry, used, use_entry, unionfind_union);
399             }
400         }
401     }
402
403   /* Update the instruction stream, allocating new registers for split pseudos
404      in progress.  */
405   FOR_ALL_BB (bb)
406     FOR_BB_INSNS (bb, insn)
407     {
408       unsigned int uid = INSN_UID (insn);
409
410       if (NONDEBUG_INSN_P (insn)
411           /* Ignore naked clobber.  For example, reg 134 in the second insn
412              of the following sequence will not be replaced.
413
414                (insn (clobber (reg:SI 134)))
415
416                (insn (set (reg:SI 0 r0) (reg:SI 134)))
417
418              Thus the later passes can optimize them away.  */
419           && GET_CODE (PATTERN (insn)) != CLOBBER)
420         {
421           df_ref *use_rec;
422           df_ref *def_rec;
423           for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
424             {
425               df_ref use = *use_rec;
426               if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
427                 replace_ref (use, entry_register (use_entry + DF_REF_ID (use), use, used));
428             }
429           for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
430             {
431               df_ref use = *use_rec;
432               if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
433                 replace_ref (use, entry_register (use_entry + DF_REF_ID (use), use, used));
434             }
435           for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
436             {
437               df_ref def = *def_rec;
438               if (DF_REF_REGNO (def) >= FIRST_PSEUDO_REGISTER)
439                 replace_ref (def, entry_register (def_entry + DF_REF_ID (def), def, used));
440             }
441         }
442     }
443
444   free (def_entry);
445   free (use_entry);
446   free (used);
447   return 0;
448 }
449 \f
450 struct rtl_opt_pass pass_web =
451 {
452  {
453   RTL_PASS,
454   "web",                                /* name */
455   OPTGROUP_NONE,                        /* optinfo_flags */
456   gate_handle_web,                      /* gate */
457   web_main,                             /* execute */
458   NULL,                                 /* sub */
459   NULL,                                 /* next */
460   0,                                    /* static_pass_number */
461   TV_WEB,                               /* tv_id */
462   0,                                    /* properties_required */
463   0,                                    /* properties_provided */
464   0,                                    /* properties_destroyed */
465   0,                                    /* todo_flags_start */
466   TODO_df_finish | TODO_verify_rtl_sharing  /* todo_flags_finish */
467  }
468 };