xref: /dflybsd-src/contrib/gcc-4.7/gcc/web.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Web construction code for GNU compiler.
2*e4b17023SJohn Marino    Contributed by Jan Hubicka.
3*e4b17023SJohn Marino    Copyright (C) 2001, 2002, 2004, 2006, 2007, 2008, 2010
4*e4b17023SJohn Marino    Free Software Foundation, Inc.
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino /* Simple optimization pass that splits independent uses of each pseudo,
23*e4b17023SJohn Marino    increasing effectiveness of other optimizations.  The optimization can
24*e4b17023SJohn Marino    serve as an example of use for the dataflow module.
25*e4b17023SJohn Marino 
26*e4b17023SJohn Marino    We don't split registers with REG_USERVAR set unless -fmessy-debugging
27*e4b17023SJohn Marino    is specified, because debugging information about such split variables
28*e4b17023SJohn Marino    is almost unusable.
29*e4b17023SJohn Marino 
30*e4b17023SJohn Marino    TODO
31*e4b17023SJohn Marino     - We may use profile information and ignore infrequent use for the
32*e4b17023SJohn Marino       purpose of web unifying, inserting the compensation code later to
33*e4b17023SJohn Marino       implement full induction variable expansion for loops (currently
34*e4b17023SJohn Marino       we expand only if the induction variable is dead afterward, which
35*e4b17023SJohn Marino       is often the case).  */
36*e4b17023SJohn Marino 
37*e4b17023SJohn Marino #include "config.h"
38*e4b17023SJohn Marino #include "system.h"
39*e4b17023SJohn Marino #include "coretypes.h"
40*e4b17023SJohn Marino #include "tm.h"
41*e4b17023SJohn Marino #include "diagnostic-core.h"
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino #include "rtl.h"
44*e4b17023SJohn Marino #include "hard-reg-set.h"
45*e4b17023SJohn Marino #include "flags.h"
46*e4b17023SJohn Marino #include "obstack.h"
47*e4b17023SJohn Marino #include "basic-block.h"
48*e4b17023SJohn Marino #include "output.h"
49*e4b17023SJohn Marino #include "df.h"
50*e4b17023SJohn Marino #include "function.h"
51*e4b17023SJohn Marino #include "insn-config.h"
52*e4b17023SJohn Marino #include "recog.h"
53*e4b17023SJohn Marino #include "timevar.h"
54*e4b17023SJohn Marino #include "tree-pass.h"
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino 
57*e4b17023SJohn Marino /* Find the root of unionfind tree (the representative of set).  */
58*e4b17023SJohn Marino 
59*e4b17023SJohn Marino struct web_entry *
unionfind_root(struct web_entry * element)60*e4b17023SJohn Marino unionfind_root (struct web_entry *element)
61*e4b17023SJohn Marino {
62*e4b17023SJohn Marino   struct web_entry *element1 = element, *element2;
63*e4b17023SJohn Marino 
64*e4b17023SJohn Marino   while (element->pred)
65*e4b17023SJohn Marino     element = element->pred;
66*e4b17023SJohn Marino   while (element1->pred)
67*e4b17023SJohn Marino     {
68*e4b17023SJohn Marino       element2 = element1->pred;
69*e4b17023SJohn Marino       element1->pred = element;
70*e4b17023SJohn Marino       element1 = element2;
71*e4b17023SJohn Marino     }
72*e4b17023SJohn Marino   return element;
73*e4b17023SJohn Marino }
74*e4b17023SJohn Marino 
75*e4b17023SJohn Marino /* Union sets.
76*e4b17023SJohn Marino    Return true if FIRST and SECOND points to the same web entry structure and
77*e4b17023SJohn Marino    nothing is done.  Otherwise, return false.  */
78*e4b17023SJohn Marino 
79*e4b17023SJohn Marino bool
unionfind_union(struct web_entry * first,struct web_entry * second)80*e4b17023SJohn Marino unionfind_union (struct web_entry *first, struct web_entry *second)
81*e4b17023SJohn Marino {
82*e4b17023SJohn Marino   first = unionfind_root (first);
83*e4b17023SJohn Marino   second = unionfind_root (second);
84*e4b17023SJohn Marino   if (first == second)
85*e4b17023SJohn Marino     return true;
86*e4b17023SJohn Marino   second->pred = first;
87*e4b17023SJohn Marino   return false;
88*e4b17023SJohn Marino }
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino /* For INSN, union all defs and uses that are linked by match_dup.
91*e4b17023SJohn Marino    FUN is the function that does the union.  */
92*e4b17023SJohn Marino 
93*e4b17023SJohn Marino 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 *))94*e4b17023SJohn Marino union_match_dups (rtx insn, struct web_entry *def_entry,
95*e4b17023SJohn Marino 		  struct web_entry *use_entry,
96*e4b17023SJohn Marino 		  bool (*fun) (struct web_entry *, struct web_entry *))
97*e4b17023SJohn Marino {
98*e4b17023SJohn Marino   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
99*e4b17023SJohn Marino   df_ref *use_link = DF_INSN_INFO_USES (insn_info);
100*e4b17023SJohn Marino   df_ref *def_link = DF_INSN_INFO_DEFS (insn_info);
101*e4b17023SJohn Marino   int i;
102*e4b17023SJohn Marino 
103*e4b17023SJohn Marino   extract_insn (insn);
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino   for (i = 0; i < recog_data.n_dups; i++)
106*e4b17023SJohn Marino     {
107*e4b17023SJohn Marino       int op = recog_data.dup_num[i];
108*e4b17023SJohn Marino       enum op_type type = recog_data.operand_type[op];
109*e4b17023SJohn Marino       df_ref *ref, *dupref;
110*e4b17023SJohn Marino       struct web_entry *entry;
111*e4b17023SJohn Marino 
112*e4b17023SJohn Marino       for (dupref = use_link; *dupref; dupref++)
113*e4b17023SJohn Marino 	if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i])
114*e4b17023SJohn Marino 	  break;
115*e4b17023SJohn Marino 
116*e4b17023SJohn Marino       if (*dupref == NULL
117*e4b17023SJohn Marino 	  || DF_REF_REGNO (*dupref) < FIRST_PSEUDO_REGISTER)
118*e4b17023SJohn Marino 	continue;
119*e4b17023SJohn Marino 
120*e4b17023SJohn Marino       ref = type == OP_IN ? use_link : def_link;
121*e4b17023SJohn Marino       entry = type == OP_IN ? use_entry : def_entry;
122*e4b17023SJohn Marino       for (; *ref; ref++)
123*e4b17023SJohn Marino 	if (DF_REF_LOC (*ref) == recog_data.operand_loc[op])
124*e4b17023SJohn Marino 	  break;
125*e4b17023SJohn Marino 
126*e4b17023SJohn Marino       (*fun) (use_entry + DF_REF_ID (*dupref), entry + DF_REF_ID (*ref));
127*e4b17023SJohn Marino     }
128*e4b17023SJohn Marino }
129*e4b17023SJohn Marino 
130*e4b17023SJohn Marino /* For each use, all possible defs reaching it must come in the same
131*e4b17023SJohn Marino    register, union them.
132*e4b17023SJohn Marino    FUN is the function that does the union.
133*e4b17023SJohn Marino 
134*e4b17023SJohn Marino    In USED, we keep the DF_REF_ID of the first uninitialized uses of a
135*e4b17023SJohn Marino    register, so that all uninitialized uses of the register can be
136*e4b17023SJohn Marino    combined into a single web.  We actually offset it by 2, because
137*e4b17023SJohn Marino    the values 0 and 1 are reserved for use by entry_register.  */
138*e4b17023SJohn Marino 
139*e4b17023SJohn Marino 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 *))140*e4b17023SJohn Marino union_defs (df_ref use, struct web_entry *def_entry,
141*e4b17023SJohn Marino 	    unsigned int *used, struct web_entry *use_entry,
142*e4b17023SJohn Marino  	    bool (*fun) (struct web_entry *, struct web_entry *))
143*e4b17023SJohn Marino {
144*e4b17023SJohn Marino   struct df_insn_info *insn_info = DF_REF_INSN_INFO (use);
145*e4b17023SJohn Marino   struct df_link *link = DF_REF_CHAIN (use);
146*e4b17023SJohn Marino   df_ref *eq_use_link;
147*e4b17023SJohn Marino   df_ref *def_link;
148*e4b17023SJohn Marino   rtx set;
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino   if (insn_info)
151*e4b17023SJohn Marino     {
152*e4b17023SJohn Marino       rtx insn = insn_info->insn;
153*e4b17023SJohn Marino       eq_use_link = DF_INSN_INFO_EQ_USES (insn_info);
154*e4b17023SJohn Marino       def_link = DF_INSN_INFO_DEFS (insn_info);
155*e4b17023SJohn Marino       set = single_set (insn);
156*e4b17023SJohn Marino     }
157*e4b17023SJohn Marino   else
158*e4b17023SJohn Marino     {
159*e4b17023SJohn Marino       /* An artificial use.  It links up with nothing.  */
160*e4b17023SJohn Marino       eq_use_link = NULL;
161*e4b17023SJohn Marino       def_link = NULL;
162*e4b17023SJohn Marino       set = NULL;
163*e4b17023SJohn Marino     }
164*e4b17023SJohn Marino 
165*e4b17023SJohn Marino   /* Union all occurrences of the same register in reg notes.  */
166*e4b17023SJohn Marino 
167*e4b17023SJohn Marino   if (eq_use_link)
168*e4b17023SJohn Marino     while (*eq_use_link)
169*e4b17023SJohn Marino       {
170*e4b17023SJohn Marino 	if (use != *eq_use_link
171*e4b17023SJohn Marino 	    && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (*eq_use_link))
172*e4b17023SJohn Marino 	  (*fun) (use_entry + DF_REF_ID (use),
173*e4b17023SJohn Marino 		  use_entry + DF_REF_ID (*eq_use_link));
174*e4b17023SJohn Marino 	eq_use_link++;
175*e4b17023SJohn Marino     }
176*e4b17023SJohn Marino 
177*e4b17023SJohn Marino   /* Recognize trivial noop moves and attempt to keep them as noop.  */
178*e4b17023SJohn Marino 
179*e4b17023SJohn Marino   if (set
180*e4b17023SJohn Marino       && SET_SRC (set) == DF_REF_REG (use)
181*e4b17023SJohn Marino       && SET_SRC (set) == SET_DEST (set))
182*e4b17023SJohn Marino     {
183*e4b17023SJohn Marino       if (def_link)
184*e4b17023SJohn Marino 	while (*def_link)
185*e4b17023SJohn Marino 	  {
186*e4b17023SJohn Marino 	    if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (*def_link))
187*e4b17023SJohn Marino 	      (*fun) (use_entry + DF_REF_ID (use),
188*e4b17023SJohn Marino 		      def_entry + DF_REF_ID (*def_link));
189*e4b17023SJohn Marino 	    def_link++;
190*e4b17023SJohn Marino 	  }
191*e4b17023SJohn Marino     }
192*e4b17023SJohn Marino 
193*e4b17023SJohn Marino   /* UD chains of uninitialized REGs are empty.  Keeping all uses of
194*e4b17023SJohn Marino      the same uninitialized REG in a single web is not necessary for
195*e4b17023SJohn Marino      correctness, since the uses are undefined, but it's wasteful to
196*e4b17023SJohn Marino      allocate one register or slot for each reference.  Furthermore,
197*e4b17023SJohn Marino      creating new pseudos for uninitialized references in debug insns
198*e4b17023SJohn Marino      (see PR 42631) causes -fcompare-debug failures.  We record the
199*e4b17023SJohn Marino      number of the first uninitialized reference we found, and merge
200*e4b17023SJohn Marino      with it any other uninitialized references to the same
201*e4b17023SJohn Marino      register.  */
202*e4b17023SJohn Marino   if (!link)
203*e4b17023SJohn Marino     {
204*e4b17023SJohn Marino       int regno = REGNO (DF_REF_REAL_REG (use));
205*e4b17023SJohn Marino       if (used[regno])
206*e4b17023SJohn Marino 	(*fun) (use_entry + DF_REF_ID (use), use_entry + used[regno] - 2);
207*e4b17023SJohn Marino       else
208*e4b17023SJohn Marino 	used[regno] = DF_REF_ID (use) + 2;
209*e4b17023SJohn Marino     }
210*e4b17023SJohn Marino 
211*e4b17023SJohn Marino   while (link)
212*e4b17023SJohn Marino     {
213*e4b17023SJohn Marino       (*fun) (use_entry + DF_REF_ID (use),
214*e4b17023SJohn Marino 	      def_entry + DF_REF_ID (link->ref));
215*e4b17023SJohn Marino       link = link->next;
216*e4b17023SJohn Marino     }
217*e4b17023SJohn Marino 
218*e4b17023SJohn Marino   /* A READ_WRITE use requires the corresponding def to be in the same
219*e4b17023SJohn Marino      register.  Find it and union.  */
220*e4b17023SJohn Marino   if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
221*e4b17023SJohn Marino     {
222*e4b17023SJohn Marino       df_ref *link;
223*e4b17023SJohn Marino 
224*e4b17023SJohn Marino       if (insn_info)
225*e4b17023SJohn Marino 	link = DF_INSN_INFO_DEFS (insn_info);
226*e4b17023SJohn Marino       else
227*e4b17023SJohn Marino 	link = NULL;
228*e4b17023SJohn Marino 
229*e4b17023SJohn Marino       if (link)
230*e4b17023SJohn Marino 	while (*link)
231*e4b17023SJohn Marino 	  {
232*e4b17023SJohn Marino 	    if (DF_REF_REAL_REG (*link) == DF_REF_REAL_REG (use))
233*e4b17023SJohn Marino 	      (*fun) (use_entry + DF_REF_ID (use),
234*e4b17023SJohn Marino 		      def_entry + DF_REF_ID (*link));
235*e4b17023SJohn Marino 	    link++;
236*e4b17023SJohn Marino 	  }
237*e4b17023SJohn Marino     }
238*e4b17023SJohn Marino }
239*e4b17023SJohn Marino 
240*e4b17023SJohn Marino /* Find the corresponding register for the given entry.  */
241*e4b17023SJohn Marino 
242*e4b17023SJohn Marino static rtx
entry_register(struct web_entry * entry,df_ref ref,unsigned int * used)243*e4b17023SJohn Marino entry_register (struct web_entry *entry, df_ref ref, unsigned int *used)
244*e4b17023SJohn Marino {
245*e4b17023SJohn Marino   struct web_entry *root;
246*e4b17023SJohn Marino   rtx reg, newreg;
247*e4b17023SJohn Marino 
248*e4b17023SJohn Marino   /* Find the corresponding web and see if it has been visited.  */
249*e4b17023SJohn Marino   root = unionfind_root (entry);
250*e4b17023SJohn Marino   if (root->reg)
251*e4b17023SJohn Marino     return root->reg;
252*e4b17023SJohn Marino 
253*e4b17023SJohn Marino   /* We are seeing this web for the first time, do the assignment.  */
254*e4b17023SJohn Marino   reg = DF_REF_REAL_REG (ref);
255*e4b17023SJohn Marino 
256*e4b17023SJohn Marino   /* In case the original register is already assigned, generate new
257*e4b17023SJohn Marino      one.  Since we use USED to merge uninitialized refs into a single
258*e4b17023SJohn Marino      web, we might found an element to be nonzero without our having
259*e4b17023SJohn Marino      used it.  Test for 1, because union_defs saves it for our use,
260*e4b17023SJohn Marino      and there won't be any use for the other values when we get to
261*e4b17023SJohn Marino      this point.  */
262*e4b17023SJohn Marino   if (used[REGNO (reg)] != 1)
263*e4b17023SJohn Marino     newreg = reg, used[REGNO (reg)] = 1;
264*e4b17023SJohn Marino   else
265*e4b17023SJohn Marino     {
266*e4b17023SJohn Marino       newreg = gen_reg_rtx (GET_MODE (reg));
267*e4b17023SJohn Marino       REG_USERVAR_P (newreg) = REG_USERVAR_P (reg);
268*e4b17023SJohn Marino       REG_POINTER (newreg) = REG_POINTER (reg);
269*e4b17023SJohn Marino       REG_ATTRS (newreg) = REG_ATTRS (reg);
270*e4b17023SJohn Marino       if (dump_file)
271*e4b17023SJohn Marino 	fprintf (dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg),
272*e4b17023SJohn Marino 		 REGNO (newreg));
273*e4b17023SJohn Marino     }
274*e4b17023SJohn Marino 
275*e4b17023SJohn Marino   root->reg = newreg;
276*e4b17023SJohn Marino   return newreg;
277*e4b17023SJohn Marino }
278*e4b17023SJohn Marino 
279*e4b17023SJohn Marino /* Replace the reference by REG.  */
280*e4b17023SJohn Marino 
281*e4b17023SJohn Marino static void
replace_ref(df_ref ref,rtx reg)282*e4b17023SJohn Marino replace_ref (df_ref ref, rtx reg)
283*e4b17023SJohn Marino {
284*e4b17023SJohn Marino   rtx oldreg = DF_REF_REAL_REG (ref);
285*e4b17023SJohn Marino   rtx *loc = DF_REF_REAL_LOC (ref);
286*e4b17023SJohn Marino   unsigned int uid = DF_REF_INSN_UID (ref);
287*e4b17023SJohn Marino 
288*e4b17023SJohn Marino   if (oldreg == reg)
289*e4b17023SJohn Marino     return;
290*e4b17023SJohn Marino   if (dump_file)
291*e4b17023SJohn Marino     fprintf (dump_file, "Updating insn %i (%i->%i)\n",
292*e4b17023SJohn Marino 	     uid, REGNO (oldreg), REGNO (reg));
293*e4b17023SJohn Marino   *loc = reg;
294*e4b17023SJohn Marino   df_insn_rescan (DF_REF_INSN (ref));
295*e4b17023SJohn Marino }
296*e4b17023SJohn Marino 
297*e4b17023SJohn Marino 
298*e4b17023SJohn Marino static bool
gate_handle_web(void)299*e4b17023SJohn Marino gate_handle_web (void)
300*e4b17023SJohn Marino {
301*e4b17023SJohn Marino   return (optimize > 0 && flag_web);
302*e4b17023SJohn Marino }
303*e4b17023SJohn Marino 
304*e4b17023SJohn Marino /* Main entry point.  */
305*e4b17023SJohn Marino 
306*e4b17023SJohn Marino static unsigned int
web_main(void)307*e4b17023SJohn Marino web_main (void)
308*e4b17023SJohn Marino {
309*e4b17023SJohn Marino   struct web_entry *def_entry;
310*e4b17023SJohn Marino   struct web_entry *use_entry;
311*e4b17023SJohn Marino   unsigned int max = max_reg_num ();
312*e4b17023SJohn Marino   unsigned int *used;
313*e4b17023SJohn Marino   basic_block bb;
314*e4b17023SJohn Marino   unsigned int uses_num = 0;
315*e4b17023SJohn Marino   rtx insn;
316*e4b17023SJohn Marino 
317*e4b17023SJohn Marino   df_set_flags (DF_NO_HARD_REGS + DF_EQ_NOTES);
318*e4b17023SJohn Marino   df_chain_add_problem (DF_UD_CHAIN);
319*e4b17023SJohn Marino   df_analyze ();
320*e4b17023SJohn Marino   df_set_flags (DF_DEFER_INSN_RESCAN);
321*e4b17023SJohn Marino 
322*e4b17023SJohn Marino   /* Assign ids to the uses.  */
323*e4b17023SJohn Marino   FOR_ALL_BB (bb)
324*e4b17023SJohn Marino     FOR_BB_INSNS (bb, insn)
325*e4b17023SJohn Marino     {
326*e4b17023SJohn Marino       unsigned int uid = INSN_UID (insn);
327*e4b17023SJohn Marino       if (NONDEBUG_INSN_P (insn))
328*e4b17023SJohn Marino 	{
329*e4b17023SJohn Marino 	  df_ref *use_rec;
330*e4b17023SJohn Marino 	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
331*e4b17023SJohn Marino 	    {
332*e4b17023SJohn Marino 	      df_ref use = *use_rec;
333*e4b17023SJohn Marino 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
334*e4b17023SJohn Marino 		DF_REF_ID (use) = uses_num++;
335*e4b17023SJohn Marino 	    }
336*e4b17023SJohn Marino 	  for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
337*e4b17023SJohn Marino 	    {
338*e4b17023SJohn Marino 	      df_ref use = *use_rec;
339*e4b17023SJohn Marino 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
340*e4b17023SJohn Marino 		DF_REF_ID (use) = uses_num++;
341*e4b17023SJohn Marino 	    }
342*e4b17023SJohn Marino 	}
343*e4b17023SJohn Marino     }
344*e4b17023SJohn Marino 
345*e4b17023SJohn Marino   /* Record the number of uses and defs at the beginning of the optimization.  */
346*e4b17023SJohn Marino   def_entry = XCNEWVEC (struct web_entry, DF_DEFS_TABLE_SIZE());
347*e4b17023SJohn Marino   used = XCNEWVEC (unsigned, max);
348*e4b17023SJohn Marino   use_entry = XCNEWVEC (struct web_entry, uses_num);
349*e4b17023SJohn Marino 
350*e4b17023SJohn Marino   /* Produce the web.  */
351*e4b17023SJohn Marino   FOR_ALL_BB (bb)
352*e4b17023SJohn Marino     FOR_BB_INSNS (bb, insn)
353*e4b17023SJohn Marino     {
354*e4b17023SJohn Marino       unsigned int uid = INSN_UID (insn);
355*e4b17023SJohn Marino       if (NONDEBUG_INSN_P (insn))
356*e4b17023SJohn Marino 	{
357*e4b17023SJohn Marino 	  df_ref *use_rec;
358*e4b17023SJohn Marino 	  union_match_dups (insn, def_entry, use_entry, unionfind_union);
359*e4b17023SJohn Marino 	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
360*e4b17023SJohn Marino 	    {
361*e4b17023SJohn Marino 	      df_ref use = *use_rec;
362*e4b17023SJohn Marino 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
363*e4b17023SJohn Marino 		union_defs (use, def_entry, used, use_entry, unionfind_union);
364*e4b17023SJohn Marino 	    }
365*e4b17023SJohn Marino 	  for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
366*e4b17023SJohn Marino 	    {
367*e4b17023SJohn Marino 	      df_ref use = *use_rec;
368*e4b17023SJohn Marino 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
369*e4b17023SJohn Marino 		union_defs (use, def_entry, used, use_entry, unionfind_union);
370*e4b17023SJohn Marino 	    }
371*e4b17023SJohn Marino 	}
372*e4b17023SJohn Marino     }
373*e4b17023SJohn Marino 
374*e4b17023SJohn Marino   /* Update the instruction stream, allocating new registers for split pseudos
375*e4b17023SJohn Marino      in progress.  */
376*e4b17023SJohn Marino   FOR_ALL_BB (bb)
377*e4b17023SJohn Marino     FOR_BB_INSNS (bb, insn)
378*e4b17023SJohn Marino     {
379*e4b17023SJohn Marino       unsigned int uid = INSN_UID (insn);
380*e4b17023SJohn Marino 
381*e4b17023SJohn Marino       if (NONDEBUG_INSN_P (insn)
382*e4b17023SJohn Marino 	  /* Ignore naked clobber.  For example, reg 134 in the second insn
383*e4b17023SJohn Marino 	     of the following sequence will not be replaced.
384*e4b17023SJohn Marino 
385*e4b17023SJohn Marino 	       (insn (clobber (reg:SI 134)))
386*e4b17023SJohn Marino 
387*e4b17023SJohn Marino 	       (insn (set (reg:SI 0 r0) (reg:SI 134)))
388*e4b17023SJohn Marino 
389*e4b17023SJohn Marino 	     Thus the later passes can optimize them away.  */
390*e4b17023SJohn Marino 	  && GET_CODE (PATTERN (insn)) != CLOBBER)
391*e4b17023SJohn Marino 	{
392*e4b17023SJohn Marino 	  df_ref *use_rec;
393*e4b17023SJohn Marino 	  df_ref *def_rec;
394*e4b17023SJohn Marino 	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
395*e4b17023SJohn Marino 	    {
396*e4b17023SJohn Marino 	      df_ref use = *use_rec;
397*e4b17023SJohn Marino 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
398*e4b17023SJohn Marino 		replace_ref (use, entry_register (use_entry + DF_REF_ID (use), use, used));
399*e4b17023SJohn Marino 	    }
400*e4b17023SJohn Marino 	  for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
401*e4b17023SJohn Marino 	    {
402*e4b17023SJohn Marino 	      df_ref use = *use_rec;
403*e4b17023SJohn Marino 	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
404*e4b17023SJohn Marino 		replace_ref (use, entry_register (use_entry + DF_REF_ID (use), use, used));
405*e4b17023SJohn Marino 	    }
406*e4b17023SJohn Marino 	  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
407*e4b17023SJohn Marino 	    {
408*e4b17023SJohn Marino 	      df_ref def = *def_rec;
409*e4b17023SJohn Marino 	      if (DF_REF_REGNO (def) >= FIRST_PSEUDO_REGISTER)
410*e4b17023SJohn Marino 		replace_ref (def, entry_register (def_entry + DF_REF_ID (def), def, used));
411*e4b17023SJohn Marino 	    }
412*e4b17023SJohn Marino 	}
413*e4b17023SJohn Marino     }
414*e4b17023SJohn Marino 
415*e4b17023SJohn Marino   free (def_entry);
416*e4b17023SJohn Marino   free (use_entry);
417*e4b17023SJohn Marino   free (used);
418*e4b17023SJohn Marino   return 0;
419*e4b17023SJohn Marino }
420*e4b17023SJohn Marino 
421*e4b17023SJohn Marino struct rtl_opt_pass pass_web =
422*e4b17023SJohn Marino {
423*e4b17023SJohn Marino  {
424*e4b17023SJohn Marino   RTL_PASS,
425*e4b17023SJohn Marino   "web",                                /* name */
426*e4b17023SJohn Marino   gate_handle_web,                      /* gate */
427*e4b17023SJohn Marino   web_main,		                /* execute */
428*e4b17023SJohn Marino   NULL,                                 /* sub */
429*e4b17023SJohn Marino   NULL,                                 /* next */
430*e4b17023SJohn Marino   0,                                    /* static_pass_number */
431*e4b17023SJohn Marino   TV_WEB,                               /* tv_id */
432*e4b17023SJohn Marino   0,                                    /* properties_required */
433*e4b17023SJohn Marino   0,                                    /* properties_provided */
434*e4b17023SJohn Marino   0,                                    /* properties_destroyed */
435*e4b17023SJohn Marino   0,                                    /* todo_flags_start */
436*e4b17023SJohn Marino   TODO_df_finish | TODO_verify_rtl_sharing  /* todo_flags_finish */
437*e4b17023SJohn Marino  }
438*e4b17023SJohn Marino };
439