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 *
unionfind_root(struct web_entry * element)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
unionfind_union(struct web_entry * first,struct web_entry * second)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
union_match_dups(rtx insn,struct web_entry * def_entry,struct web_entry * use_entry,bool (* fun)(struct web_entry *,struct web_entry *))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 	if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
136 	  break;
137 
138       if (!*ref && type == OP_INOUT)
139 	{
140 	  for (ref = use_link, entry = use_entry; *ref; ref++)
141 	    if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
142 	      break;
143 	}
144 
145       gcc_assert (*ref);
146       (*fun) (dup_entry + DF_REF_ID (*dupref), entry + DF_REF_ID (*ref));
147     }
148 }
149 
150 /* For each use, all possible defs reaching it must come in the same
151    register, union them.
152    FUN is the function that does the union.
153 
154    In USED, we keep the DF_REF_ID of the first uninitialized uses of a
155    register, so that all uninitialized uses of the register can be
156    combined into a single web.  We actually offset it by 2, because
157    the values 0 and 1 are reserved for use by entry_register.  */
158 
159 void
union_defs(df_ref use,struct web_entry * def_entry,unsigned int * used,struct web_entry * use_entry,bool (* fun)(struct web_entry *,struct web_entry *))160 union_defs (df_ref use, struct web_entry *def_entry,
161 	    unsigned int *used, struct web_entry *use_entry,
162  	    bool (*fun) (struct web_entry *, struct web_entry *))
163 {
164   struct df_insn_info *insn_info = DF_REF_INSN_INFO (use);
165   struct df_link *link = DF_REF_CHAIN (use);
166   df_ref *eq_use_link;
167   df_ref *def_link;
168   rtx set;
169 
170   if (insn_info)
171     {
172       rtx insn = insn_info->insn;
173       eq_use_link = DF_INSN_INFO_EQ_USES (insn_info);
174       def_link = DF_INSN_INFO_DEFS (insn_info);
175       set = single_set (insn);
176     }
177   else
178     {
179       /* An artificial use.  It links up with nothing.  */
180       eq_use_link = NULL;
181       def_link = NULL;
182       set = NULL;
183     }
184 
185   /* Union all occurrences of the same register in reg notes.  */
186 
187   if (eq_use_link)
188     while (*eq_use_link)
189       {
190 	if (use != *eq_use_link
191 	    && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (*eq_use_link))
192 	  (*fun) (use_entry + DF_REF_ID (use),
193 		  use_entry + DF_REF_ID (*eq_use_link));
194 	eq_use_link++;
195     }
196 
197   /* Recognize trivial noop moves and attempt to keep them as noop.  */
198 
199   if (set
200       && SET_SRC (set) == DF_REF_REG (use)
201       && SET_SRC (set) == SET_DEST (set))
202     {
203       if (def_link)
204 	while (*def_link)
205 	  {
206 	    if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (*def_link))
207 	      (*fun) (use_entry + DF_REF_ID (use),
208 		      def_entry + DF_REF_ID (*def_link));
209 	    def_link++;
210 	  }
211     }
212 
213   /* UD chains of uninitialized REGs are empty.  Keeping all uses of
214      the same uninitialized REG in a single web is not necessary for
215      correctness, since the uses are undefined, but it's wasteful to
216      allocate one register or slot for each reference.  Furthermore,
217      creating new pseudos for uninitialized references in debug insns
218      (see PR 42631) causes -fcompare-debug failures.  We record the
219      number of the first uninitialized reference we found, and merge
220      with it any other uninitialized references to the same
221      register.  */
222   if (!link)
223     {
224       int regno = REGNO (DF_REF_REAL_REG (use));
225       if (used[regno])
226 	(*fun) (use_entry + DF_REF_ID (use), use_entry + used[regno] - 2);
227       else
228 	used[regno] = DF_REF_ID (use) + 2;
229     }
230 
231   while (link)
232     {
233       (*fun) (use_entry + DF_REF_ID (use),
234 	      def_entry + DF_REF_ID (link->ref));
235       link = link->next;
236     }
237 
238   /* A READ_WRITE use requires the corresponding def to be in the same
239      register.  Find it and union.  */
240   if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
241     {
242       df_ref *link;
243 
244       if (insn_info)
245 	link = DF_INSN_INFO_DEFS (insn_info);
246       else
247 	link = NULL;
248 
249       if (link)
250 	while (*link)
251 	  {
252 	    if (DF_REF_REAL_REG (*link) == DF_REF_REAL_REG (use))
253 	      (*fun) (use_entry + DF_REF_ID (use),
254 		      def_entry + DF_REF_ID (*link));
255 	    link++;
256 	  }
257     }
258 }
259 
260 /* Find the corresponding register for the given entry.  */
261 
262 static rtx
entry_register(struct web_entry * entry,df_ref ref,unsigned int * used)263 entry_register (struct web_entry *entry, df_ref ref, unsigned int *used)
264 {
265   struct web_entry *root;
266   rtx reg, newreg;
267 
268   /* Find the corresponding web and see if it has been visited.  */
269   root = unionfind_root (entry);
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->reg = newreg;
296   return newreg;
297 }
298 
299 /* Replace the reference by REG.  */
300 
301 static void
replace_ref(df_ref ref,rtx reg)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 
318 static bool
gate_handle_web(void)319 gate_handle_web (void)
320 {
321   return (optimize > 0 && flag_web);
322 }
323 
324 /* Main entry point.  */
325 
326 static unsigned int
web_main(void)327 web_main (void)
328 {
329   struct web_entry *def_entry;
330   struct web_entry *use_entry;
331   unsigned int max = max_reg_num ();
332   unsigned int *used;
333   basic_block bb;
334   unsigned int uses_num = 0;
335   rtx insn;
336 
337   df_set_flags (DF_NO_HARD_REGS + DF_EQ_NOTES);
338   df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
339   df_chain_add_problem (DF_UD_CHAIN);
340   df_analyze ();
341   df_set_flags (DF_DEFER_INSN_RESCAN);
342 
343   /* Assign ids to the uses.  */
344   FOR_ALL_BB (bb)
345     FOR_BB_INSNS (bb, insn)
346     {
347       unsigned int uid = INSN_UID (insn);
348       if (NONDEBUG_INSN_P (insn))
349 	{
350 	  df_ref *use_rec;
351 	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
352 	    {
353 	      df_ref use = *use_rec;
354 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
355 		DF_REF_ID (use) = uses_num++;
356 	    }
357 	  for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
358 	    {
359 	      df_ref use = *use_rec;
360 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
361 		DF_REF_ID (use) = uses_num++;
362 	    }
363 	}
364     }
365 
366   /* Record the number of uses and defs at the beginning of the optimization.  */
367   def_entry = XCNEWVEC (struct web_entry, DF_DEFS_TABLE_SIZE());
368   used = XCNEWVEC (unsigned, max);
369   use_entry = XCNEWVEC (struct web_entry, uses_num);
370 
371   /* Produce the web.  */
372   FOR_ALL_BB (bb)
373     FOR_BB_INSNS (bb, insn)
374     {
375       unsigned int uid = INSN_UID (insn);
376       if (NONDEBUG_INSN_P (insn))
377 	{
378 	  df_ref *use_rec;
379 	  union_match_dups (insn, def_entry, use_entry, unionfind_union);
380 	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
381 	    {
382 	      df_ref use = *use_rec;
383 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
384 		union_defs (use, def_entry, used, use_entry, unionfind_union);
385 	    }
386 	  for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
387 	    {
388 	      df_ref use = *use_rec;
389 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
390 		union_defs (use, def_entry, used, use_entry, unionfind_union);
391 	    }
392 	}
393     }
394 
395   /* Update the instruction stream, allocating new registers for split pseudos
396      in progress.  */
397   FOR_ALL_BB (bb)
398     FOR_BB_INSNS (bb, insn)
399     {
400       unsigned int uid = INSN_UID (insn);
401 
402       if (NONDEBUG_INSN_P (insn)
403 	  /* Ignore naked clobber.  For example, reg 134 in the second insn
404 	     of the following sequence will not be replaced.
405 
406 	       (insn (clobber (reg:SI 134)))
407 
408 	       (insn (set (reg:SI 0 r0) (reg:SI 134)))
409 
410 	     Thus the later passes can optimize them away.  */
411 	  && GET_CODE (PATTERN (insn)) != CLOBBER)
412 	{
413 	  df_ref *use_rec;
414 	  df_ref *def_rec;
415 	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
416 	    {
417 	      df_ref use = *use_rec;
418 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
419 		replace_ref (use, entry_register (use_entry + DF_REF_ID (use), use, used));
420 	    }
421 	  for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
422 	    {
423 	      df_ref use = *use_rec;
424 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
425 		replace_ref (use, entry_register (use_entry + DF_REF_ID (use), use, used));
426 	    }
427 	  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
428 	    {
429 	      df_ref def = *def_rec;
430 	      if (DF_REF_REGNO (def) >= FIRST_PSEUDO_REGISTER)
431 		replace_ref (def, entry_register (def_entry + DF_REF_ID (def), def, used));
432 	    }
433 	}
434     }
435 
436   free (def_entry);
437   free (use_entry);
438   free (used);
439   return 0;
440 }
441 
442 struct rtl_opt_pass pass_web =
443 {
444  {
445   RTL_PASS,
446   "web",                                /* name */
447   OPTGROUP_NONE,                        /* optinfo_flags */
448   gate_handle_web,                      /* gate */
449   web_main,		                /* execute */
450   NULL,                                 /* sub */
451   NULL,                                 /* next */
452   0,                                    /* static_pass_number */
453   TV_WEB,                               /* tv_id */
454   0,                                    /* properties_required */
455   0,                                    /* properties_provided */
456   0,                                    /* properties_destroyed */
457   0,                                    /* todo_flags_start */
458   TODO_df_finish | TODO_verify_rtl_sharing  /* todo_flags_finish */
459  }
460 };
461