xref: /dflybsd-src/contrib/gcc-4.7/gcc/df-scan.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Scanning of rtl for dataflow analysis.
2*e4b17023SJohn Marino    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
3*e4b17023SJohn Marino    2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Originally contributed by Michael P. Hayes
5*e4b17023SJohn Marino              (m.hayes@elec.canterbury.ac.nz, mhayes@redhat.com)
6*e4b17023SJohn Marino    Major rewrite contributed by Danny Berlin (dberlin@dberlin.org)
7*e4b17023SJohn Marino              and Kenneth Zadeck (zadeck@naturalbridge.com).
8*e4b17023SJohn Marino 
9*e4b17023SJohn Marino This file is part of GCC.
10*e4b17023SJohn Marino 
11*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
12*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
13*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
14*e4b17023SJohn Marino version.
15*e4b17023SJohn Marino 
16*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
18*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19*e4b17023SJohn Marino for more details.
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
22*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
23*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino #include "config.h"
26*e4b17023SJohn Marino #include "system.h"
27*e4b17023SJohn Marino #include "coretypes.h"
28*e4b17023SJohn Marino #include "tm.h"
29*e4b17023SJohn Marino #include "rtl.h"
30*e4b17023SJohn Marino #include "tm_p.h"
31*e4b17023SJohn Marino #include "insn-config.h"
32*e4b17023SJohn Marino #include "recog.h"
33*e4b17023SJohn Marino #include "function.h"
34*e4b17023SJohn Marino #include "regs.h"
35*e4b17023SJohn Marino #include "output.h"
36*e4b17023SJohn Marino #include "alloc-pool.h"
37*e4b17023SJohn Marino #include "flags.h"
38*e4b17023SJohn Marino #include "hard-reg-set.h"
39*e4b17023SJohn Marino #include "basic-block.h"
40*e4b17023SJohn Marino #include "sbitmap.h"
41*e4b17023SJohn Marino #include "bitmap.h"
42*e4b17023SJohn Marino #include "timevar.h"
43*e4b17023SJohn Marino #include "tree.h"
44*e4b17023SJohn Marino #include "target.h"
45*e4b17023SJohn Marino #include "target-def.h"
46*e4b17023SJohn Marino #include "df.h"
47*e4b17023SJohn Marino #include "tree-pass.h"
48*e4b17023SJohn Marino #include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino DEF_VEC_P(df_ref);
51*e4b17023SJohn Marino DEF_VEC_ALLOC_P_STACK(df_ref);
52*e4b17023SJohn Marino 
53*e4b17023SJohn Marino #define VEC_df_ref_stack_alloc(alloc) VEC_stack_alloc (df_ref, alloc)
54*e4b17023SJohn Marino 
55*e4b17023SJohn Marino typedef struct df_mw_hardreg *df_mw_hardreg_ptr;
56*e4b17023SJohn Marino 
57*e4b17023SJohn Marino DEF_VEC_P(df_mw_hardreg_ptr);
58*e4b17023SJohn Marino DEF_VEC_ALLOC_P_STACK(df_mw_hardreg_ptr);
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino #define VEC_df_mw_hardreg_ptr_stack_alloc(alloc) \
61*e4b17023SJohn Marino   VEC_stack_alloc (df_mw_hardreg_ptr, alloc)
62*e4b17023SJohn Marino 
63*e4b17023SJohn Marino #ifndef HAVE_epilogue
64*e4b17023SJohn Marino #define HAVE_epilogue 0
65*e4b17023SJohn Marino #endif
66*e4b17023SJohn Marino #ifndef HAVE_prologue
67*e4b17023SJohn Marino #define HAVE_prologue 0
68*e4b17023SJohn Marino #endif
69*e4b17023SJohn Marino #ifndef HAVE_sibcall_epilogue
70*e4b17023SJohn Marino #define HAVE_sibcall_epilogue 0
71*e4b17023SJohn Marino #endif
72*e4b17023SJohn Marino 
73*e4b17023SJohn Marino #ifndef EPILOGUE_USES
74*e4b17023SJohn Marino #define EPILOGUE_USES(REGNO)  0
75*e4b17023SJohn Marino #endif
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino /* The following two macros free the vecs that hold either the refs or
78*e4b17023SJohn Marino    the mw refs.  They are a little tricky because the vec has 0
79*e4b17023SJohn Marino    elements is special and is not to be freed.  */
80*e4b17023SJohn Marino #define df_scan_free_ref_vec(V) \
81*e4b17023SJohn Marino   do { \
82*e4b17023SJohn Marino     if (V && *V) \
83*e4b17023SJohn Marino       free (V);  \
84*e4b17023SJohn Marino   } while (0)
85*e4b17023SJohn Marino 
86*e4b17023SJohn Marino #define df_scan_free_mws_vec(V) \
87*e4b17023SJohn Marino   do { \
88*e4b17023SJohn Marino     if (V && *V) \
89*e4b17023SJohn Marino       free (V);  \
90*e4b17023SJohn Marino   } while (0)
91*e4b17023SJohn Marino 
92*e4b17023SJohn Marino /* The set of hard registers in eliminables[i].from. */
93*e4b17023SJohn Marino 
94*e4b17023SJohn Marino static HARD_REG_SET elim_reg_set;
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino /* Initialize ur_in and ur_out as if all hard registers were partially
97*e4b17023SJohn Marino    available.  */
98*e4b17023SJohn Marino 
99*e4b17023SJohn Marino struct df_collection_rec
100*e4b17023SJohn Marino {
101*e4b17023SJohn Marino   VEC(df_ref,stack) *def_vec;
102*e4b17023SJohn Marino   VEC(df_ref,stack) *use_vec;
103*e4b17023SJohn Marino   VEC(df_ref,stack) *eq_use_vec;
104*e4b17023SJohn Marino   VEC(df_mw_hardreg_ptr,stack) *mw_vec;
105*e4b17023SJohn Marino };
106*e4b17023SJohn Marino 
107*e4b17023SJohn Marino static df_ref df_null_ref_rec[1];
108*e4b17023SJohn Marino static struct df_mw_hardreg * df_null_mw_rec[1];
109*e4b17023SJohn Marino 
110*e4b17023SJohn Marino static void df_ref_record (enum df_ref_class, struct df_collection_rec *,
111*e4b17023SJohn Marino 			   rtx, rtx *,
112*e4b17023SJohn Marino 			   basic_block, struct df_insn_info *,
113*e4b17023SJohn Marino 			   enum df_ref_type, int ref_flags);
114*e4b17023SJohn Marino static void df_def_record_1 (struct df_collection_rec *, rtx,
115*e4b17023SJohn Marino 			     basic_block, struct df_insn_info *,
116*e4b17023SJohn Marino 			     int ref_flags);
117*e4b17023SJohn Marino static void df_defs_record (struct df_collection_rec *, rtx,
118*e4b17023SJohn Marino 			    basic_block, struct df_insn_info *,
119*e4b17023SJohn Marino 			    int ref_flags);
120*e4b17023SJohn Marino static void df_uses_record (struct df_collection_rec *,
121*e4b17023SJohn Marino 			    rtx *, enum df_ref_type,
122*e4b17023SJohn Marino 			    basic_block, struct df_insn_info *,
123*e4b17023SJohn Marino 			    int ref_flags);
124*e4b17023SJohn Marino 
125*e4b17023SJohn Marino static void df_install_ref_incremental (df_ref);
126*e4b17023SJohn Marino static df_ref df_ref_create_structure (enum df_ref_class,
127*e4b17023SJohn Marino 				       struct df_collection_rec *, rtx, rtx *,
128*e4b17023SJohn Marino 				       basic_block, struct df_insn_info *,
129*e4b17023SJohn Marino 				       enum df_ref_type, int ref_flags);
130*e4b17023SJohn Marino static void df_insn_refs_collect (struct df_collection_rec*,
131*e4b17023SJohn Marino 				  basic_block, struct df_insn_info *);
132*e4b17023SJohn Marino static void df_canonize_collection_rec (struct df_collection_rec *);
133*e4b17023SJohn Marino 
134*e4b17023SJohn Marino static void df_get_regular_block_artificial_uses (bitmap);
135*e4b17023SJohn Marino static void df_get_eh_block_artificial_uses (bitmap);
136*e4b17023SJohn Marino 
137*e4b17023SJohn Marino static void df_record_entry_block_defs (bitmap);
138*e4b17023SJohn Marino static void df_record_exit_block_uses (bitmap);
139*e4b17023SJohn Marino static void df_get_exit_block_use_set (bitmap);
140*e4b17023SJohn Marino static void df_get_entry_block_def_set (bitmap);
141*e4b17023SJohn Marino static void df_grow_ref_info (struct df_ref_info *, unsigned int);
142*e4b17023SJohn Marino static void df_ref_chain_delete_du_chain (df_ref *);
143*e4b17023SJohn Marino static void df_ref_chain_delete (df_ref *);
144*e4b17023SJohn Marino 
145*e4b17023SJohn Marino static void df_refs_add_to_chains (struct df_collection_rec *,
146*e4b17023SJohn Marino 				   basic_block, rtx);
147*e4b17023SJohn Marino 
148*e4b17023SJohn Marino static bool df_insn_refs_verify (struct df_collection_rec *, basic_block, rtx, bool);
149*e4b17023SJohn Marino static void df_entry_block_defs_collect (struct df_collection_rec *, bitmap);
150*e4b17023SJohn Marino static void df_exit_block_uses_collect (struct df_collection_rec *, bitmap);
151*e4b17023SJohn Marino static void df_install_ref (df_ref, struct df_reg_info *,
152*e4b17023SJohn Marino 			    struct df_ref_info *, bool);
153*e4b17023SJohn Marino 
154*e4b17023SJohn Marino static int df_ref_compare (const void *, const void *);
155*e4b17023SJohn Marino static int df_mw_compare (const void *, const void *);
156*e4b17023SJohn Marino 
157*e4b17023SJohn Marino /* Indexed by hardware reg number, is true if that register is ever
158*e4b17023SJohn Marino    used in the current function.
159*e4b17023SJohn Marino 
160*e4b17023SJohn Marino    In df-scan.c, this is set up to record the hard regs used
161*e4b17023SJohn Marino    explicitly.  Reload adds in the hard regs used for holding pseudo
162*e4b17023SJohn Marino    regs.  Final uses it to generate the code in the function prologue
163*e4b17023SJohn Marino    and epilogue to save and restore registers as needed.  */
164*e4b17023SJohn Marino 
165*e4b17023SJohn Marino static bool regs_ever_live[FIRST_PSEUDO_REGISTER];
166*e4b17023SJohn Marino 
167*e4b17023SJohn Marino /*----------------------------------------------------------------------------
168*e4b17023SJohn Marino    SCANNING DATAFLOW PROBLEM
169*e4b17023SJohn Marino 
170*e4b17023SJohn Marino    There are several ways in which scanning looks just like the other
171*e4b17023SJohn Marino    dataflow problems.  It shares the all the mechanisms for local info
172*e4b17023SJohn Marino    as well as basic block info.  Where it differs is when and how often
173*e4b17023SJohn Marino    it gets run.  It also has no need for the iterative solver.
174*e4b17023SJohn Marino ----------------------------------------------------------------------------*/
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino /* Problem data for the scanning dataflow function.  */
177*e4b17023SJohn Marino struct df_scan_problem_data
178*e4b17023SJohn Marino {
179*e4b17023SJohn Marino   alloc_pool ref_base_pool;
180*e4b17023SJohn Marino   alloc_pool ref_artificial_pool;
181*e4b17023SJohn Marino   alloc_pool ref_regular_pool;
182*e4b17023SJohn Marino   alloc_pool insn_pool;
183*e4b17023SJohn Marino   alloc_pool reg_pool;
184*e4b17023SJohn Marino   alloc_pool mw_reg_pool;
185*e4b17023SJohn Marino   bitmap_obstack reg_bitmaps;
186*e4b17023SJohn Marino   bitmap_obstack insn_bitmaps;
187*e4b17023SJohn Marino };
188*e4b17023SJohn Marino 
189*e4b17023SJohn Marino typedef struct df_scan_bb_info *df_scan_bb_info_t;
190*e4b17023SJohn Marino 
191*e4b17023SJohn Marino 
192*e4b17023SJohn Marino /* Internal function to shut down the scanning problem.  */
193*e4b17023SJohn Marino static void
df_scan_free_internal(void)194*e4b17023SJohn Marino df_scan_free_internal (void)
195*e4b17023SJohn Marino {
196*e4b17023SJohn Marino   struct df_scan_problem_data *problem_data
197*e4b17023SJohn Marino     = (struct df_scan_problem_data *) df_scan->problem_data;
198*e4b17023SJohn Marino   unsigned int i;
199*e4b17023SJohn Marino   basic_block bb;
200*e4b17023SJohn Marino 
201*e4b17023SJohn Marino   /* The vectors that hold the refs are not pool allocated because
202*e4b17023SJohn Marino      they come in many sizes.  This makes them impossible to delete
203*e4b17023SJohn Marino      all at once.  */
204*e4b17023SJohn Marino   for (i = 0; i < DF_INSN_SIZE(); i++)
205*e4b17023SJohn Marino     {
206*e4b17023SJohn Marino       struct df_insn_info *insn_info = DF_INSN_UID_GET(i);
207*e4b17023SJohn Marino       /* Skip the insns that have no insn_info or have been
208*e4b17023SJohn Marino 	 deleted.  */
209*e4b17023SJohn Marino       if (insn_info)
210*e4b17023SJohn Marino 	{
211*e4b17023SJohn Marino 	  df_scan_free_ref_vec (insn_info->defs);
212*e4b17023SJohn Marino 	  df_scan_free_ref_vec (insn_info->uses);
213*e4b17023SJohn Marino 	  df_scan_free_ref_vec (insn_info->eq_uses);
214*e4b17023SJohn Marino 	  df_scan_free_mws_vec (insn_info->mw_hardregs);
215*e4b17023SJohn Marino 	}
216*e4b17023SJohn Marino     }
217*e4b17023SJohn Marino 
218*e4b17023SJohn Marino   FOR_ALL_BB (bb)
219*e4b17023SJohn Marino     {
220*e4b17023SJohn Marino       unsigned int bb_index = bb->index;
221*e4b17023SJohn Marino       struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb_index);
222*e4b17023SJohn Marino       if (bb_info)
223*e4b17023SJohn Marino 	{
224*e4b17023SJohn Marino 	  df_scan_free_ref_vec (bb_info->artificial_defs);
225*e4b17023SJohn Marino 	  df_scan_free_ref_vec (bb_info->artificial_uses);
226*e4b17023SJohn Marino 	}
227*e4b17023SJohn Marino     }
228*e4b17023SJohn Marino 
229*e4b17023SJohn Marino   free (df->def_info.refs);
230*e4b17023SJohn Marino   free (df->def_info.begin);
231*e4b17023SJohn Marino   free (df->def_info.count);
232*e4b17023SJohn Marino   memset (&df->def_info, 0, (sizeof (struct df_ref_info)));
233*e4b17023SJohn Marino 
234*e4b17023SJohn Marino   free (df->use_info.refs);
235*e4b17023SJohn Marino   free (df->use_info.begin);
236*e4b17023SJohn Marino   free (df->use_info.count);
237*e4b17023SJohn Marino   memset (&df->use_info, 0, (sizeof (struct df_ref_info)));
238*e4b17023SJohn Marino 
239*e4b17023SJohn Marino   free (df->def_regs);
240*e4b17023SJohn Marino   df->def_regs = NULL;
241*e4b17023SJohn Marino   free (df->use_regs);
242*e4b17023SJohn Marino   df->use_regs = NULL;
243*e4b17023SJohn Marino   free (df->eq_use_regs);
244*e4b17023SJohn Marino   df->eq_use_regs = NULL;
245*e4b17023SJohn Marino   df->regs_size = 0;
246*e4b17023SJohn Marino   DF_REG_SIZE(df) = 0;
247*e4b17023SJohn Marino 
248*e4b17023SJohn Marino   free (df->insns);
249*e4b17023SJohn Marino   df->insns = NULL;
250*e4b17023SJohn Marino   DF_INSN_SIZE () = 0;
251*e4b17023SJohn Marino 
252*e4b17023SJohn Marino   free (df_scan->block_info);
253*e4b17023SJohn Marino   df_scan->block_info = NULL;
254*e4b17023SJohn Marino   df_scan->block_info_size = 0;
255*e4b17023SJohn Marino 
256*e4b17023SJohn Marino   bitmap_clear (&df->hardware_regs_used);
257*e4b17023SJohn Marino   bitmap_clear (&df->regular_block_artificial_uses);
258*e4b17023SJohn Marino   bitmap_clear (&df->eh_block_artificial_uses);
259*e4b17023SJohn Marino   BITMAP_FREE (df->entry_block_defs);
260*e4b17023SJohn Marino   BITMAP_FREE (df->exit_block_uses);
261*e4b17023SJohn Marino   bitmap_clear (&df->insns_to_delete);
262*e4b17023SJohn Marino   bitmap_clear (&df->insns_to_rescan);
263*e4b17023SJohn Marino   bitmap_clear (&df->insns_to_notes_rescan);
264*e4b17023SJohn Marino 
265*e4b17023SJohn Marino   free_alloc_pool (problem_data->ref_base_pool);
266*e4b17023SJohn Marino   free_alloc_pool (problem_data->ref_artificial_pool);
267*e4b17023SJohn Marino   free_alloc_pool (problem_data->ref_regular_pool);
268*e4b17023SJohn Marino   free_alloc_pool (problem_data->insn_pool);
269*e4b17023SJohn Marino   free_alloc_pool (problem_data->reg_pool);
270*e4b17023SJohn Marino   free_alloc_pool (problem_data->mw_reg_pool);
271*e4b17023SJohn Marino   bitmap_obstack_release (&problem_data->reg_bitmaps);
272*e4b17023SJohn Marino   bitmap_obstack_release (&problem_data->insn_bitmaps);
273*e4b17023SJohn Marino   free (df_scan->problem_data);
274*e4b17023SJohn Marino }
275*e4b17023SJohn Marino 
276*e4b17023SJohn Marino 
277*e4b17023SJohn Marino /* Free basic block info.  */
278*e4b17023SJohn Marino 
279*e4b17023SJohn Marino static void
df_scan_free_bb_info(basic_block bb,void * vbb_info)280*e4b17023SJohn Marino df_scan_free_bb_info (basic_block bb, void *vbb_info)
281*e4b17023SJohn Marino {
282*e4b17023SJohn Marino   struct df_scan_bb_info *bb_info = (struct df_scan_bb_info *) vbb_info;
283*e4b17023SJohn Marino   unsigned int bb_index = bb->index;
284*e4b17023SJohn Marino 
285*e4b17023SJohn Marino   /* See if bb_info is initialized.  */
286*e4b17023SJohn Marino   if (bb_info->artificial_defs)
287*e4b17023SJohn Marino     {
288*e4b17023SJohn Marino       rtx insn;
289*e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
290*e4b17023SJohn Marino 	{
291*e4b17023SJohn Marino 	  if (INSN_P (insn))
292*e4b17023SJohn Marino 	    /* Record defs within INSN.  */
293*e4b17023SJohn Marino 	    df_insn_delete (bb, INSN_UID (insn));
294*e4b17023SJohn Marino 	}
295*e4b17023SJohn Marino 
296*e4b17023SJohn Marino       if (bb_index < df_scan->block_info_size)
297*e4b17023SJohn Marino 	bb_info = df_scan_get_bb_info (bb_index);
298*e4b17023SJohn Marino 
299*e4b17023SJohn Marino       /* Get rid of any artificial uses or defs.  */
300*e4b17023SJohn Marino       if (bb_info->artificial_defs)
301*e4b17023SJohn Marino 	{
302*e4b17023SJohn Marino 	  df_ref_chain_delete_du_chain (bb_info->artificial_defs);
303*e4b17023SJohn Marino 	  df_ref_chain_delete_du_chain (bb_info->artificial_uses);
304*e4b17023SJohn Marino 	  df_ref_chain_delete (bb_info->artificial_defs);
305*e4b17023SJohn Marino 	  df_ref_chain_delete (bb_info->artificial_uses);
306*e4b17023SJohn Marino 	  bb_info->artificial_defs = NULL;
307*e4b17023SJohn Marino 	  bb_info->artificial_uses = NULL;
308*e4b17023SJohn Marino 	}
309*e4b17023SJohn Marino     }
310*e4b17023SJohn Marino }
311*e4b17023SJohn Marino 
312*e4b17023SJohn Marino 
313*e4b17023SJohn Marino /* Allocate the problem data for the scanning problem.  This should be
314*e4b17023SJohn Marino    called when the problem is created or when the entire function is to
315*e4b17023SJohn Marino    be rescanned.  */
316*e4b17023SJohn Marino void
df_scan_alloc(bitmap all_blocks ATTRIBUTE_UNUSED)317*e4b17023SJohn Marino df_scan_alloc (bitmap all_blocks ATTRIBUTE_UNUSED)
318*e4b17023SJohn Marino {
319*e4b17023SJohn Marino   struct df_scan_problem_data *problem_data;
320*e4b17023SJohn Marino   unsigned int insn_num = get_max_uid () + 1;
321*e4b17023SJohn Marino   unsigned int block_size = 400;
322*e4b17023SJohn Marino   basic_block bb;
323*e4b17023SJohn Marino 
324*e4b17023SJohn Marino   /* Given the number of pools, this is really faster than tearing
325*e4b17023SJohn Marino      everything apart.  */
326*e4b17023SJohn Marino   if (df_scan->problem_data)
327*e4b17023SJohn Marino     df_scan_free_internal ();
328*e4b17023SJohn Marino 
329*e4b17023SJohn Marino   problem_data = XNEW (struct df_scan_problem_data);
330*e4b17023SJohn Marino   df_scan->problem_data = problem_data;
331*e4b17023SJohn Marino   df_scan->computed = true;
332*e4b17023SJohn Marino 
333*e4b17023SJohn Marino   problem_data->ref_base_pool
334*e4b17023SJohn Marino     = create_alloc_pool ("df_scan ref base",
335*e4b17023SJohn Marino 			 sizeof (struct df_base_ref), block_size);
336*e4b17023SJohn Marino   problem_data->ref_artificial_pool
337*e4b17023SJohn Marino     = create_alloc_pool ("df_scan ref artificial",
338*e4b17023SJohn Marino 			 sizeof (struct df_artificial_ref), block_size);
339*e4b17023SJohn Marino   problem_data->ref_regular_pool
340*e4b17023SJohn Marino     = create_alloc_pool ("df_scan ref regular",
341*e4b17023SJohn Marino 			 sizeof (struct df_regular_ref), block_size);
342*e4b17023SJohn Marino   problem_data->insn_pool
343*e4b17023SJohn Marino     = create_alloc_pool ("df_scan insn",
344*e4b17023SJohn Marino 			 sizeof (struct df_insn_info), block_size);
345*e4b17023SJohn Marino   problem_data->reg_pool
346*e4b17023SJohn Marino     = create_alloc_pool ("df_scan reg",
347*e4b17023SJohn Marino 			 sizeof (struct df_reg_info), block_size);
348*e4b17023SJohn Marino   problem_data->mw_reg_pool
349*e4b17023SJohn Marino     = create_alloc_pool ("df_scan mw_reg",
350*e4b17023SJohn Marino 			 sizeof (struct df_mw_hardreg), block_size);
351*e4b17023SJohn Marino 
352*e4b17023SJohn Marino   bitmap_obstack_initialize (&problem_data->reg_bitmaps);
353*e4b17023SJohn Marino   bitmap_obstack_initialize (&problem_data->insn_bitmaps);
354*e4b17023SJohn Marino 
355*e4b17023SJohn Marino   insn_num += insn_num / 4;
356*e4b17023SJohn Marino   df_grow_reg_info ();
357*e4b17023SJohn Marino 
358*e4b17023SJohn Marino   df_grow_insn_info ();
359*e4b17023SJohn Marino   df_grow_bb_info (df_scan);
360*e4b17023SJohn Marino 
361*e4b17023SJohn Marino   FOR_ALL_BB (bb)
362*e4b17023SJohn Marino     {
363*e4b17023SJohn Marino       unsigned int bb_index = bb->index;
364*e4b17023SJohn Marino       struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb_index);
365*e4b17023SJohn Marino       bb_info->artificial_defs = NULL;
366*e4b17023SJohn Marino       bb_info->artificial_uses = NULL;
367*e4b17023SJohn Marino     }
368*e4b17023SJohn Marino 
369*e4b17023SJohn Marino   bitmap_initialize (&df->hardware_regs_used, &problem_data->reg_bitmaps);
370*e4b17023SJohn Marino   bitmap_initialize (&df->regular_block_artificial_uses, &problem_data->reg_bitmaps);
371*e4b17023SJohn Marino   bitmap_initialize (&df->eh_block_artificial_uses, &problem_data->reg_bitmaps);
372*e4b17023SJohn Marino   df->entry_block_defs = BITMAP_ALLOC (&problem_data->reg_bitmaps);
373*e4b17023SJohn Marino   df->exit_block_uses = BITMAP_ALLOC (&problem_data->reg_bitmaps);
374*e4b17023SJohn Marino   bitmap_initialize (&df->insns_to_delete, &problem_data->insn_bitmaps);
375*e4b17023SJohn Marino   bitmap_initialize (&df->insns_to_rescan, &problem_data->insn_bitmaps);
376*e4b17023SJohn Marino   bitmap_initialize (&df->insns_to_notes_rescan, &problem_data->insn_bitmaps);
377*e4b17023SJohn Marino   df_scan->optional_p = false;
378*e4b17023SJohn Marino }
379*e4b17023SJohn Marino 
380*e4b17023SJohn Marino 
381*e4b17023SJohn Marino /* Free all of the data associated with the scan problem.  */
382*e4b17023SJohn Marino 
383*e4b17023SJohn Marino static void
df_scan_free(void)384*e4b17023SJohn Marino df_scan_free (void)
385*e4b17023SJohn Marino {
386*e4b17023SJohn Marino   if (df_scan->problem_data)
387*e4b17023SJohn Marino     df_scan_free_internal ();
388*e4b17023SJohn Marino 
389*e4b17023SJohn Marino   if (df->blocks_to_analyze)
390*e4b17023SJohn Marino     {
391*e4b17023SJohn Marino       BITMAP_FREE (df->blocks_to_analyze);
392*e4b17023SJohn Marino       df->blocks_to_analyze = NULL;
393*e4b17023SJohn Marino     }
394*e4b17023SJohn Marino 
395*e4b17023SJohn Marino   free (df_scan);
396*e4b17023SJohn Marino }
397*e4b17023SJohn Marino 
398*e4b17023SJohn Marino /* Dump the preamble for DF_SCAN dump. */
399*e4b17023SJohn Marino static void
df_scan_start_dump(FILE * file ATTRIBUTE_UNUSED)400*e4b17023SJohn Marino df_scan_start_dump (FILE *file ATTRIBUTE_UNUSED)
401*e4b17023SJohn Marino {
402*e4b17023SJohn Marino   int i;
403*e4b17023SJohn Marino   int dcount = 0;
404*e4b17023SJohn Marino   int ucount = 0;
405*e4b17023SJohn Marino   int ecount = 0;
406*e4b17023SJohn Marino   int icount = 0;
407*e4b17023SJohn Marino   int ccount = 0;
408*e4b17023SJohn Marino   basic_block bb;
409*e4b17023SJohn Marino   rtx insn;
410*e4b17023SJohn Marino 
411*e4b17023SJohn Marino   fprintf (file, ";;  invalidated by call \t");
412*e4b17023SJohn Marino   df_print_regset (file, regs_invalidated_by_call_regset);
413*e4b17023SJohn Marino   fprintf (file, ";;  hardware regs used \t");
414*e4b17023SJohn Marino   df_print_regset (file, &df->hardware_regs_used);
415*e4b17023SJohn Marino   fprintf (file, ";;  regular block artificial uses \t");
416*e4b17023SJohn Marino   df_print_regset (file, &df->regular_block_artificial_uses);
417*e4b17023SJohn Marino   fprintf (file, ";;  eh block artificial uses \t");
418*e4b17023SJohn Marino   df_print_regset (file, &df->eh_block_artificial_uses);
419*e4b17023SJohn Marino   fprintf (file, ";;  entry block defs \t");
420*e4b17023SJohn Marino   df_print_regset (file, df->entry_block_defs);
421*e4b17023SJohn Marino   fprintf (file, ";;  exit block uses \t");
422*e4b17023SJohn Marino   df_print_regset (file, df->exit_block_uses);
423*e4b17023SJohn Marino   fprintf (file, ";;  regs ever live \t");
424*e4b17023SJohn Marino   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
425*e4b17023SJohn Marino     if (df_regs_ever_live_p (i))
426*e4b17023SJohn Marino       fprintf (file, " %d[%s]", i, reg_names[i]);
427*e4b17023SJohn Marino   fprintf (file, "\n;;  ref usage \t");
428*e4b17023SJohn Marino 
429*e4b17023SJohn Marino   for (i = 0; i < (int)df->regs_inited; i++)
430*e4b17023SJohn Marino     if (DF_REG_DEF_COUNT (i) || DF_REG_USE_COUNT (i) || DF_REG_EQ_USE_COUNT (i))
431*e4b17023SJohn Marino       {
432*e4b17023SJohn Marino 	const char * sep = "";
433*e4b17023SJohn Marino 
434*e4b17023SJohn Marino 	fprintf (file, "r%d={", i);
435*e4b17023SJohn Marino 	if (DF_REG_DEF_COUNT (i))
436*e4b17023SJohn Marino 	  {
437*e4b17023SJohn Marino 	    fprintf (file, "%dd", DF_REG_DEF_COUNT (i));
438*e4b17023SJohn Marino 	    sep = ",";
439*e4b17023SJohn Marino 	    dcount += DF_REG_DEF_COUNT (i);
440*e4b17023SJohn Marino 	  }
441*e4b17023SJohn Marino 	if (DF_REG_USE_COUNT (i))
442*e4b17023SJohn Marino 	  {
443*e4b17023SJohn Marino 	    fprintf (file, "%s%du", sep, DF_REG_USE_COUNT (i));
444*e4b17023SJohn Marino 	    sep = ",";
445*e4b17023SJohn Marino 	    ucount += DF_REG_USE_COUNT (i);
446*e4b17023SJohn Marino 	  }
447*e4b17023SJohn Marino 	if (DF_REG_EQ_USE_COUNT (i))
448*e4b17023SJohn Marino 	  {
449*e4b17023SJohn Marino 	    fprintf (file, "%s%de", sep, DF_REG_EQ_USE_COUNT (i));
450*e4b17023SJohn Marino 	    ecount += DF_REG_EQ_USE_COUNT (i);
451*e4b17023SJohn Marino 	  }
452*e4b17023SJohn Marino 	fprintf (file, "} ");
453*e4b17023SJohn Marino       }
454*e4b17023SJohn Marino 
455*e4b17023SJohn Marino   FOR_EACH_BB (bb)
456*e4b17023SJohn Marino     FOR_BB_INSNS (bb, insn)
457*e4b17023SJohn Marino       if (INSN_P (insn))
458*e4b17023SJohn Marino 	{
459*e4b17023SJohn Marino 	  if (CALL_P (insn))
460*e4b17023SJohn Marino 	    ccount++;
461*e4b17023SJohn Marino 	  else
462*e4b17023SJohn Marino 	    icount++;
463*e4b17023SJohn Marino 	}
464*e4b17023SJohn Marino 
465*e4b17023SJohn Marino   fprintf (file, "\n;;    total ref usage %d{%dd,%du,%de}"
466*e4b17023SJohn Marino 		 " in %d{%d regular + %d call} insns.\n",
467*e4b17023SJohn Marino 		 dcount + ucount + ecount, dcount, ucount, ecount,
468*e4b17023SJohn Marino 		 icount + ccount, icount, ccount);
469*e4b17023SJohn Marino }
470*e4b17023SJohn Marino 
471*e4b17023SJohn Marino /* Dump the bb_info for a given basic block. */
472*e4b17023SJohn Marino static void
df_scan_start_block(basic_block bb,FILE * file)473*e4b17023SJohn Marino df_scan_start_block (basic_block bb, FILE *file)
474*e4b17023SJohn Marino {
475*e4b17023SJohn Marino   struct df_scan_bb_info *bb_info
476*e4b17023SJohn Marino     = df_scan_get_bb_info (bb->index);
477*e4b17023SJohn Marino 
478*e4b17023SJohn Marino   if (bb_info)
479*e4b17023SJohn Marino     {
480*e4b17023SJohn Marino       fprintf (file, ";; bb %d artificial_defs: ", bb->index);
481*e4b17023SJohn Marino       df_refs_chain_dump (bb_info->artificial_defs, true, file);
482*e4b17023SJohn Marino       fprintf (file, "\n;; bb %d artificial_uses: ", bb->index);
483*e4b17023SJohn Marino       df_refs_chain_dump (bb_info->artificial_uses, true, file);
484*e4b17023SJohn Marino       fprintf (file, "\n");
485*e4b17023SJohn Marino     }
486*e4b17023SJohn Marino #if 0
487*e4b17023SJohn Marino   {
488*e4b17023SJohn Marino     rtx insn;
489*e4b17023SJohn Marino     FOR_BB_INSNS (bb, insn)
490*e4b17023SJohn Marino       if (INSN_P (insn))
491*e4b17023SJohn Marino 	df_insn_debug (insn, false, file);
492*e4b17023SJohn Marino   }
493*e4b17023SJohn Marino #endif
494*e4b17023SJohn Marino }
495*e4b17023SJohn Marino 
496*e4b17023SJohn Marino static struct df_problem problem_SCAN =
497*e4b17023SJohn Marino {
498*e4b17023SJohn Marino   DF_SCAN,                    /* Problem id.  */
499*e4b17023SJohn Marino   DF_NONE,                    /* Direction.  */
500*e4b17023SJohn Marino   df_scan_alloc,              /* Allocate the problem specific data.  */
501*e4b17023SJohn Marino   NULL,                       /* Reset global information.  */
502*e4b17023SJohn Marino   df_scan_free_bb_info,       /* Free basic block info.  */
503*e4b17023SJohn Marino   NULL,                       /* Local compute function.  */
504*e4b17023SJohn Marino   NULL,                       /* Init the solution specific data.  */
505*e4b17023SJohn Marino   NULL,                       /* Iterative solver.  */
506*e4b17023SJohn Marino   NULL,                       /* Confluence operator 0.  */
507*e4b17023SJohn Marino   NULL,                       /* Confluence operator n.  */
508*e4b17023SJohn Marino   NULL,                       /* Transfer function.  */
509*e4b17023SJohn Marino   NULL,                       /* Finalize function.  */
510*e4b17023SJohn Marino   df_scan_free,               /* Free all of the problem information.  */
511*e4b17023SJohn Marino   NULL,                       /* Remove this problem from the stack of dataflow problems.  */
512*e4b17023SJohn Marino   df_scan_start_dump,         /* Debugging.  */
513*e4b17023SJohn Marino   df_scan_start_block,        /* Debugging start block.  */
514*e4b17023SJohn Marino   NULL,                       /* Debugging end block.  */
515*e4b17023SJohn Marino   NULL,                       /* Incremental solution verify start.  */
516*e4b17023SJohn Marino   NULL,                       /* Incremental solution verify end.  */
517*e4b17023SJohn Marino   NULL,                       /* Dependent problem.  */
518*e4b17023SJohn Marino   sizeof (struct df_scan_bb_info),/* Size of entry of block_info array.  */
519*e4b17023SJohn Marino   TV_DF_SCAN,                 /* Timing variable.  */
520*e4b17023SJohn Marino   false                       /* Reset blocks on dropping out of blocks_to_analyze.  */
521*e4b17023SJohn Marino };
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino 
524*e4b17023SJohn Marino /* Create a new DATAFLOW instance and add it to an existing instance
525*e4b17023SJohn Marino    of DF.  The returned structure is what is used to get at the
526*e4b17023SJohn Marino    solution.  */
527*e4b17023SJohn Marino 
528*e4b17023SJohn Marino void
df_scan_add_problem(void)529*e4b17023SJohn Marino df_scan_add_problem (void)
530*e4b17023SJohn Marino {
531*e4b17023SJohn Marino   df_add_problem (&problem_SCAN);
532*e4b17023SJohn Marino }
533*e4b17023SJohn Marino 
534*e4b17023SJohn Marino 
535*e4b17023SJohn Marino /*----------------------------------------------------------------------------
536*e4b17023SJohn Marino    Storage Allocation Utilities
537*e4b17023SJohn Marino ----------------------------------------------------------------------------*/
538*e4b17023SJohn Marino 
539*e4b17023SJohn Marino 
540*e4b17023SJohn Marino /* First, grow the reg_info information.  If the current size is less than
541*e4b17023SJohn Marino    the number of pseudos, grow to 25% more than the number of
542*e4b17023SJohn Marino    pseudos.
543*e4b17023SJohn Marino 
544*e4b17023SJohn Marino    Second, assure that all of the slots up to max_reg_num have been
545*e4b17023SJohn Marino    filled with reg_info structures.  */
546*e4b17023SJohn Marino 
547*e4b17023SJohn Marino void
df_grow_reg_info(void)548*e4b17023SJohn Marino df_grow_reg_info (void)
549*e4b17023SJohn Marino {
550*e4b17023SJohn Marino   unsigned int max_reg = max_reg_num ();
551*e4b17023SJohn Marino   unsigned int new_size = max_reg;
552*e4b17023SJohn Marino   struct df_scan_problem_data *problem_data
553*e4b17023SJohn Marino     = (struct df_scan_problem_data *) df_scan->problem_data;
554*e4b17023SJohn Marino   unsigned int i;
555*e4b17023SJohn Marino 
556*e4b17023SJohn Marino   if (df->regs_size < new_size)
557*e4b17023SJohn Marino     {
558*e4b17023SJohn Marino       new_size += new_size / 4;
559*e4b17023SJohn Marino       df->def_regs = XRESIZEVEC (struct df_reg_info *, df->def_regs, new_size);
560*e4b17023SJohn Marino       df->use_regs = XRESIZEVEC (struct df_reg_info *, df->use_regs, new_size);
561*e4b17023SJohn Marino       df->eq_use_regs = XRESIZEVEC (struct df_reg_info *, df->eq_use_regs,
562*e4b17023SJohn Marino 				    new_size);
563*e4b17023SJohn Marino       df->def_info.begin = XRESIZEVEC (unsigned, df->def_info.begin, new_size);
564*e4b17023SJohn Marino       df->def_info.count = XRESIZEVEC (unsigned, df->def_info.count, new_size);
565*e4b17023SJohn Marino       df->use_info.begin = XRESIZEVEC (unsigned, df->use_info.begin, new_size);
566*e4b17023SJohn Marino       df->use_info.count = XRESIZEVEC (unsigned, df->use_info.count, new_size);
567*e4b17023SJohn Marino       df->regs_size = new_size;
568*e4b17023SJohn Marino     }
569*e4b17023SJohn Marino 
570*e4b17023SJohn Marino   for (i = df->regs_inited; i < max_reg; i++)
571*e4b17023SJohn Marino     {
572*e4b17023SJohn Marino       struct df_reg_info *reg_info;
573*e4b17023SJohn Marino 
574*e4b17023SJohn Marino       reg_info = (struct df_reg_info *) pool_alloc (problem_data->reg_pool);
575*e4b17023SJohn Marino       memset (reg_info, 0, sizeof (struct df_reg_info));
576*e4b17023SJohn Marino       df->def_regs[i] = reg_info;
577*e4b17023SJohn Marino       reg_info = (struct df_reg_info *) pool_alloc (problem_data->reg_pool);
578*e4b17023SJohn Marino       memset (reg_info, 0, sizeof (struct df_reg_info));
579*e4b17023SJohn Marino       df->use_regs[i] = reg_info;
580*e4b17023SJohn Marino       reg_info = (struct df_reg_info *) pool_alloc (problem_data->reg_pool);
581*e4b17023SJohn Marino       memset (reg_info, 0, sizeof (struct df_reg_info));
582*e4b17023SJohn Marino       df->eq_use_regs[i] = reg_info;
583*e4b17023SJohn Marino       df->def_info.begin[i] = 0;
584*e4b17023SJohn Marino       df->def_info.count[i] = 0;
585*e4b17023SJohn Marino       df->use_info.begin[i] = 0;
586*e4b17023SJohn Marino       df->use_info.count[i] = 0;
587*e4b17023SJohn Marino     }
588*e4b17023SJohn Marino 
589*e4b17023SJohn Marino   df->regs_inited = max_reg;
590*e4b17023SJohn Marino }
591*e4b17023SJohn Marino 
592*e4b17023SJohn Marino 
593*e4b17023SJohn Marino /* Grow the ref information.  */
594*e4b17023SJohn Marino 
595*e4b17023SJohn Marino static void
df_grow_ref_info(struct df_ref_info * ref_info,unsigned int new_size)596*e4b17023SJohn Marino df_grow_ref_info (struct df_ref_info *ref_info, unsigned int new_size)
597*e4b17023SJohn Marino {
598*e4b17023SJohn Marino   if (ref_info->refs_size < new_size)
599*e4b17023SJohn Marino     {
600*e4b17023SJohn Marino       ref_info->refs = XRESIZEVEC (df_ref, ref_info->refs, new_size);
601*e4b17023SJohn Marino       memset (ref_info->refs + ref_info->refs_size, 0,
602*e4b17023SJohn Marino 	      (new_size - ref_info->refs_size) *sizeof (df_ref));
603*e4b17023SJohn Marino       ref_info->refs_size = new_size;
604*e4b17023SJohn Marino     }
605*e4b17023SJohn Marino }
606*e4b17023SJohn Marino 
607*e4b17023SJohn Marino 
608*e4b17023SJohn Marino /* Check and grow the ref information if necessary.  This routine
609*e4b17023SJohn Marino    guarantees total_size + BITMAP_ADDEND amount of entries in refs
610*e4b17023SJohn Marino    array.  It updates ref_info->refs_size only and does not change
611*e4b17023SJohn Marino    ref_info->total_size.  */
612*e4b17023SJohn Marino 
613*e4b17023SJohn Marino static void
df_check_and_grow_ref_info(struct df_ref_info * ref_info,unsigned bitmap_addend)614*e4b17023SJohn Marino df_check_and_grow_ref_info (struct df_ref_info *ref_info,
615*e4b17023SJohn Marino 			    unsigned bitmap_addend)
616*e4b17023SJohn Marino {
617*e4b17023SJohn Marino   if (ref_info->refs_size < ref_info->total_size + bitmap_addend)
618*e4b17023SJohn Marino     {
619*e4b17023SJohn Marino       int new_size = ref_info->total_size + bitmap_addend;
620*e4b17023SJohn Marino       new_size += ref_info->total_size / 4;
621*e4b17023SJohn Marino       df_grow_ref_info (ref_info, new_size);
622*e4b17023SJohn Marino     }
623*e4b17023SJohn Marino }
624*e4b17023SJohn Marino 
625*e4b17023SJohn Marino 
626*e4b17023SJohn Marino /* Grow the ref information.  If the current size is less than the
627*e4b17023SJohn Marino    number of instructions, grow to 25% more than the number of
628*e4b17023SJohn Marino    instructions.  */
629*e4b17023SJohn Marino 
630*e4b17023SJohn Marino void
df_grow_insn_info(void)631*e4b17023SJohn Marino df_grow_insn_info (void)
632*e4b17023SJohn Marino {
633*e4b17023SJohn Marino   unsigned int new_size = get_max_uid () + 1;
634*e4b17023SJohn Marino   if (DF_INSN_SIZE () < new_size)
635*e4b17023SJohn Marino     {
636*e4b17023SJohn Marino       new_size += new_size / 4;
637*e4b17023SJohn Marino       df->insns = XRESIZEVEC (struct df_insn_info *, df->insns, new_size);
638*e4b17023SJohn Marino       memset (df->insns + df->insns_size, 0,
639*e4b17023SJohn Marino 	      (new_size - DF_INSN_SIZE ()) *sizeof (struct df_insn_info *));
640*e4b17023SJohn Marino       DF_INSN_SIZE () = new_size;
641*e4b17023SJohn Marino     }
642*e4b17023SJohn Marino }
643*e4b17023SJohn Marino 
644*e4b17023SJohn Marino 
645*e4b17023SJohn Marino 
646*e4b17023SJohn Marino 
647*e4b17023SJohn Marino /*----------------------------------------------------------------------------
648*e4b17023SJohn Marino    PUBLIC INTERFACES FOR SMALL GRAIN CHANGES TO SCANNING.
649*e4b17023SJohn Marino ----------------------------------------------------------------------------*/
650*e4b17023SJohn Marino 
651*e4b17023SJohn Marino /* Rescan all of the block_to_analyze or all of the blocks in the
652*e4b17023SJohn Marino    function if df_set_blocks if blocks_to_analyze is NULL;  */
653*e4b17023SJohn Marino 
654*e4b17023SJohn Marino void
df_scan_blocks(void)655*e4b17023SJohn Marino df_scan_blocks (void)
656*e4b17023SJohn Marino {
657*e4b17023SJohn Marino   basic_block bb;
658*e4b17023SJohn Marino 
659*e4b17023SJohn Marino   df->def_info.ref_order = DF_REF_ORDER_NO_TABLE;
660*e4b17023SJohn Marino   df->use_info.ref_order = DF_REF_ORDER_NO_TABLE;
661*e4b17023SJohn Marino 
662*e4b17023SJohn Marino   df_get_regular_block_artificial_uses (&df->regular_block_artificial_uses);
663*e4b17023SJohn Marino   df_get_eh_block_artificial_uses (&df->eh_block_artificial_uses);
664*e4b17023SJohn Marino 
665*e4b17023SJohn Marino   bitmap_ior_into (&df->eh_block_artificial_uses,
666*e4b17023SJohn Marino 		   &df->regular_block_artificial_uses);
667*e4b17023SJohn Marino 
668*e4b17023SJohn Marino   /* ENTRY and EXIT blocks have special defs/uses.  */
669*e4b17023SJohn Marino   df_get_entry_block_def_set (df->entry_block_defs);
670*e4b17023SJohn Marino   df_record_entry_block_defs (df->entry_block_defs);
671*e4b17023SJohn Marino   df_get_exit_block_use_set (df->exit_block_uses);
672*e4b17023SJohn Marino   df_record_exit_block_uses (df->exit_block_uses);
673*e4b17023SJohn Marino   df_set_bb_dirty (BASIC_BLOCK (ENTRY_BLOCK));
674*e4b17023SJohn Marino   df_set_bb_dirty (BASIC_BLOCK (EXIT_BLOCK));
675*e4b17023SJohn Marino 
676*e4b17023SJohn Marino   /* Regular blocks */
677*e4b17023SJohn Marino   FOR_EACH_BB (bb)
678*e4b17023SJohn Marino     {
679*e4b17023SJohn Marino       unsigned int bb_index = bb->index;
680*e4b17023SJohn Marino       df_bb_refs_record (bb_index, true);
681*e4b17023SJohn Marino     }
682*e4b17023SJohn Marino }
683*e4b17023SJohn Marino 
684*e4b17023SJohn Marino /* Create new refs under address LOC within INSN.  This function is
685*e4b17023SJohn Marino    only used externally.  REF_FLAGS must be either 0 or DF_REF_IN_NOTE,
686*e4b17023SJohn Marino    depending on whether LOC is inside PATTERN (INSN) or a note.  */
687*e4b17023SJohn Marino 
688*e4b17023SJohn Marino void
df_uses_create(rtx * loc,rtx insn,int ref_flags)689*e4b17023SJohn Marino df_uses_create (rtx *loc, rtx insn, int ref_flags)
690*e4b17023SJohn Marino {
691*e4b17023SJohn Marino   gcc_assert (!(ref_flags & ~DF_REF_IN_NOTE));
692*e4b17023SJohn Marino   df_uses_record (NULL, loc, DF_REF_REG_USE,
693*e4b17023SJohn Marino                   BLOCK_FOR_INSN (insn),
694*e4b17023SJohn Marino                   DF_INSN_INFO_GET (insn),
695*e4b17023SJohn Marino                   ref_flags);
696*e4b17023SJohn Marino }
697*e4b17023SJohn Marino 
698*e4b17023SJohn Marino /* Create a new ref of type DF_REF_TYPE for register REG at address
699*e4b17023SJohn Marino    LOC within INSN of BB.  This function is only used externally.  */
700*e4b17023SJohn Marino 
701*e4b17023SJohn Marino df_ref
df_ref_create(rtx reg,rtx * loc,rtx insn,basic_block bb,enum df_ref_type ref_type,int ref_flags)702*e4b17023SJohn Marino df_ref_create (rtx reg, rtx *loc, rtx insn,
703*e4b17023SJohn Marino 	       basic_block bb,
704*e4b17023SJohn Marino 	       enum df_ref_type ref_type,
705*e4b17023SJohn Marino 	       int ref_flags)
706*e4b17023SJohn Marino {
707*e4b17023SJohn Marino   enum df_ref_class cl;
708*e4b17023SJohn Marino 
709*e4b17023SJohn Marino   df_grow_reg_info ();
710*e4b17023SJohn Marino 
711*e4b17023SJohn Marino   /* You cannot hack artificial refs.  */
712*e4b17023SJohn Marino   gcc_assert (insn);
713*e4b17023SJohn Marino 
714*e4b17023SJohn Marino   if (loc)
715*e4b17023SJohn Marino     cl = DF_REF_REGULAR;
716*e4b17023SJohn Marino   else
717*e4b17023SJohn Marino     cl = DF_REF_BASE;
718*e4b17023SJohn Marino 
719*e4b17023SJohn Marino   return df_ref_create_structure (cl, NULL, reg, loc, bb,
720*e4b17023SJohn Marino                                   DF_INSN_INFO_GET (insn),
721*e4b17023SJohn Marino                                   ref_type, ref_flags);
722*e4b17023SJohn Marino }
723*e4b17023SJohn Marino 
724*e4b17023SJohn Marino static void
df_install_ref_incremental(df_ref ref)725*e4b17023SJohn Marino df_install_ref_incremental (df_ref ref)
726*e4b17023SJohn Marino {
727*e4b17023SJohn Marino   struct df_reg_info **reg_info;
728*e4b17023SJohn Marino   struct df_ref_info *ref_info;
729*e4b17023SJohn Marino   df_ref *ref_rec;
730*e4b17023SJohn Marino   df_ref **ref_rec_ptr;
731*e4b17023SJohn Marino   unsigned int count = 0;
732*e4b17023SJohn Marino   bool add_to_table;
733*e4b17023SJohn Marino 
734*e4b17023SJohn Marino   rtx insn = DF_REF_INSN (ref);
735*e4b17023SJohn Marino   basic_block bb = BLOCK_FOR_INSN (insn);
736*e4b17023SJohn Marino 
737*e4b17023SJohn Marino   if (DF_REF_REG_DEF_P (ref))
738*e4b17023SJohn Marino     {
739*e4b17023SJohn Marino       reg_info = df->def_regs;
740*e4b17023SJohn Marino       ref_info = &df->def_info;
741*e4b17023SJohn Marino       ref_rec_ptr = &DF_INSN_DEFS (insn);
742*e4b17023SJohn Marino       add_to_table = ref_info->ref_order != DF_REF_ORDER_NO_TABLE;
743*e4b17023SJohn Marino     }
744*e4b17023SJohn Marino   else if (DF_REF_FLAGS (ref) & DF_REF_IN_NOTE)
745*e4b17023SJohn Marino     {
746*e4b17023SJohn Marino       reg_info = df->eq_use_regs;
747*e4b17023SJohn Marino       ref_info = &df->use_info;
748*e4b17023SJohn Marino       ref_rec_ptr = &DF_INSN_EQ_USES (insn);
749*e4b17023SJohn Marino       switch (ref_info->ref_order)
750*e4b17023SJohn Marino 	{
751*e4b17023SJohn Marino 	case DF_REF_ORDER_UNORDERED_WITH_NOTES:
752*e4b17023SJohn Marino 	case DF_REF_ORDER_BY_REG_WITH_NOTES:
753*e4b17023SJohn Marino 	case DF_REF_ORDER_BY_INSN_WITH_NOTES:
754*e4b17023SJohn Marino 	  add_to_table = true;
755*e4b17023SJohn Marino 	  break;
756*e4b17023SJohn Marino 	default:
757*e4b17023SJohn Marino 	  add_to_table = false;
758*e4b17023SJohn Marino 	  break;
759*e4b17023SJohn Marino 	}
760*e4b17023SJohn Marino     }
761*e4b17023SJohn Marino   else
762*e4b17023SJohn Marino     {
763*e4b17023SJohn Marino       reg_info = df->use_regs;
764*e4b17023SJohn Marino       ref_info = &df->use_info;
765*e4b17023SJohn Marino       ref_rec_ptr = &DF_INSN_USES (insn);
766*e4b17023SJohn Marino       add_to_table = ref_info->ref_order != DF_REF_ORDER_NO_TABLE;
767*e4b17023SJohn Marino     }
768*e4b17023SJohn Marino 
769*e4b17023SJohn Marino   /* Do not add if ref is not in the right blocks.  */
770*e4b17023SJohn Marino   if (add_to_table && df->analyze_subset)
771*e4b17023SJohn Marino     add_to_table = bitmap_bit_p (df->blocks_to_analyze, bb->index);
772*e4b17023SJohn Marino 
773*e4b17023SJohn Marino   df_install_ref (ref, reg_info[DF_REF_REGNO (ref)], ref_info, add_to_table);
774*e4b17023SJohn Marino 
775*e4b17023SJohn Marino   if (add_to_table)
776*e4b17023SJohn Marino     switch (ref_info->ref_order)
777*e4b17023SJohn Marino       {
778*e4b17023SJohn Marino       case DF_REF_ORDER_UNORDERED_WITH_NOTES:
779*e4b17023SJohn Marino       case DF_REF_ORDER_BY_REG_WITH_NOTES:
780*e4b17023SJohn Marino       case DF_REF_ORDER_BY_INSN_WITH_NOTES:
781*e4b17023SJohn Marino 	ref_info->ref_order = DF_REF_ORDER_UNORDERED_WITH_NOTES;
782*e4b17023SJohn Marino 	break;
783*e4b17023SJohn Marino       default:
784*e4b17023SJohn Marino 	ref_info->ref_order = DF_REF_ORDER_UNORDERED;
785*e4b17023SJohn Marino 	break;
786*e4b17023SJohn Marino       }
787*e4b17023SJohn Marino 
788*e4b17023SJohn Marino   ref_rec = *ref_rec_ptr;
789*e4b17023SJohn Marino   while (*ref_rec)
790*e4b17023SJohn Marino     {
791*e4b17023SJohn Marino       count++;
792*e4b17023SJohn Marino       ref_rec++;
793*e4b17023SJohn Marino     }
794*e4b17023SJohn Marino 
795*e4b17023SJohn Marino   ref_rec = *ref_rec_ptr;
796*e4b17023SJohn Marino   if (count)
797*e4b17023SJohn Marino     {
798*e4b17023SJohn Marino       ref_rec = XRESIZEVEC (df_ref, ref_rec, count+2);
799*e4b17023SJohn Marino       *ref_rec_ptr = ref_rec;
800*e4b17023SJohn Marino       ref_rec[count] = ref;
801*e4b17023SJohn Marino       ref_rec[count+1] = NULL;
802*e4b17023SJohn Marino       qsort (ref_rec, count + 1, sizeof (df_ref), df_ref_compare);
803*e4b17023SJohn Marino     }
804*e4b17023SJohn Marino   else
805*e4b17023SJohn Marino     {
806*e4b17023SJohn Marino       df_ref *ref_rec = XNEWVEC (df_ref, 2);
807*e4b17023SJohn Marino       ref_rec[0] = ref;
808*e4b17023SJohn Marino       ref_rec[1] = NULL;
809*e4b17023SJohn Marino       *ref_rec_ptr = ref_rec;
810*e4b17023SJohn Marino     }
811*e4b17023SJohn Marino 
812*e4b17023SJohn Marino #if 0
813*e4b17023SJohn Marino   if (dump_file)
814*e4b17023SJohn Marino     {
815*e4b17023SJohn Marino       fprintf (dump_file, "adding ref ");
816*e4b17023SJohn Marino       df_ref_debug (ref, dump_file);
817*e4b17023SJohn Marino     }
818*e4b17023SJohn Marino #endif
819*e4b17023SJohn Marino   /* By adding the ref directly, df_insn_rescan my not find any
820*e4b17023SJohn Marino      differences even though the block will have changed.  So we need
821*e4b17023SJohn Marino      to mark the block dirty ourselves.  */
822*e4b17023SJohn Marino   if (!DEBUG_INSN_P (DF_REF_INSN (ref)))
823*e4b17023SJohn Marino     df_set_bb_dirty (bb);
824*e4b17023SJohn Marino }
825*e4b17023SJohn Marino 
826*e4b17023SJohn Marino 
827*e4b17023SJohn Marino 
828*e4b17023SJohn Marino /*----------------------------------------------------------------------------
829*e4b17023SJohn Marino    UTILITIES TO CREATE AND DESTROY REFS AND CHAINS.
830*e4b17023SJohn Marino ----------------------------------------------------------------------------*/
831*e4b17023SJohn Marino 
832*e4b17023SJohn Marino static void
df_free_ref(df_ref ref)833*e4b17023SJohn Marino df_free_ref (df_ref ref)
834*e4b17023SJohn Marino {
835*e4b17023SJohn Marino   struct df_scan_problem_data *problem_data
836*e4b17023SJohn Marino     = (struct df_scan_problem_data *) df_scan->problem_data;
837*e4b17023SJohn Marino 
838*e4b17023SJohn Marino   switch (DF_REF_CLASS (ref))
839*e4b17023SJohn Marino     {
840*e4b17023SJohn Marino     case DF_REF_BASE:
841*e4b17023SJohn Marino       pool_free (problem_data->ref_base_pool, ref);
842*e4b17023SJohn Marino       break;
843*e4b17023SJohn Marino 
844*e4b17023SJohn Marino     case DF_REF_ARTIFICIAL:
845*e4b17023SJohn Marino       pool_free (problem_data->ref_artificial_pool, ref);
846*e4b17023SJohn Marino       break;
847*e4b17023SJohn Marino 
848*e4b17023SJohn Marino     case DF_REF_REGULAR:
849*e4b17023SJohn Marino       pool_free (problem_data->ref_regular_pool, ref);
850*e4b17023SJohn Marino       break;
851*e4b17023SJohn Marino     }
852*e4b17023SJohn Marino }
853*e4b17023SJohn Marino 
854*e4b17023SJohn Marino 
855*e4b17023SJohn Marino /* Unlink and delete REF at the reg_use, reg_eq_use or reg_def chain.
856*e4b17023SJohn Marino    Also delete the def-use or use-def chain if it exists.  */
857*e4b17023SJohn Marino 
858*e4b17023SJohn Marino static void
df_reg_chain_unlink(df_ref ref)859*e4b17023SJohn Marino df_reg_chain_unlink (df_ref ref)
860*e4b17023SJohn Marino {
861*e4b17023SJohn Marino   df_ref next = DF_REF_NEXT_REG (ref);
862*e4b17023SJohn Marino   df_ref prev = DF_REF_PREV_REG (ref);
863*e4b17023SJohn Marino   int id = DF_REF_ID (ref);
864*e4b17023SJohn Marino   struct df_reg_info *reg_info;
865*e4b17023SJohn Marino   df_ref *refs = NULL;
866*e4b17023SJohn Marino 
867*e4b17023SJohn Marino   if (DF_REF_REG_DEF_P (ref))
868*e4b17023SJohn Marino     {
869*e4b17023SJohn Marino       int regno = DF_REF_REGNO (ref);
870*e4b17023SJohn Marino       reg_info = DF_REG_DEF_GET (regno);
871*e4b17023SJohn Marino       refs = df->def_info.refs;
872*e4b17023SJohn Marino     }
873*e4b17023SJohn Marino   else
874*e4b17023SJohn Marino     {
875*e4b17023SJohn Marino       if (DF_REF_FLAGS (ref) & DF_REF_IN_NOTE)
876*e4b17023SJohn Marino 	{
877*e4b17023SJohn Marino 	  reg_info = DF_REG_EQ_USE_GET (DF_REF_REGNO (ref));
878*e4b17023SJohn Marino 	  switch (df->use_info.ref_order)
879*e4b17023SJohn Marino 	    {
880*e4b17023SJohn Marino 	    case DF_REF_ORDER_UNORDERED_WITH_NOTES:
881*e4b17023SJohn Marino 	    case DF_REF_ORDER_BY_REG_WITH_NOTES:
882*e4b17023SJohn Marino 	    case DF_REF_ORDER_BY_INSN_WITH_NOTES:
883*e4b17023SJohn Marino 	      refs = df->use_info.refs;
884*e4b17023SJohn Marino 	      break;
885*e4b17023SJohn Marino 	    default:
886*e4b17023SJohn Marino 	      break;
887*e4b17023SJohn Marino 	    }
888*e4b17023SJohn Marino 	}
889*e4b17023SJohn Marino       else
890*e4b17023SJohn Marino 	{
891*e4b17023SJohn Marino 	  reg_info = DF_REG_USE_GET (DF_REF_REGNO (ref));
892*e4b17023SJohn Marino 	  refs = df->use_info.refs;
893*e4b17023SJohn Marino 	}
894*e4b17023SJohn Marino     }
895*e4b17023SJohn Marino 
896*e4b17023SJohn Marino   if (refs)
897*e4b17023SJohn Marino     {
898*e4b17023SJohn Marino       if (df->analyze_subset)
899*e4b17023SJohn Marino 	{
900*e4b17023SJohn Marino 	  if (bitmap_bit_p (df->blocks_to_analyze, DF_REF_BBNO (ref)))
901*e4b17023SJohn Marino 	    refs[id] = NULL;
902*e4b17023SJohn Marino 	}
903*e4b17023SJohn Marino       else
904*e4b17023SJohn Marino 	refs[id] = NULL;
905*e4b17023SJohn Marino     }
906*e4b17023SJohn Marino 
907*e4b17023SJohn Marino   /* Delete any def-use or use-def chains that start here. It is
908*e4b17023SJohn Marino      possible that there is trash in this field.  This happens for
909*e4b17023SJohn Marino      insns that have been deleted when rescanning has been deferred
910*e4b17023SJohn Marino      and the chain problem has also been deleted.  The chain tear down
911*e4b17023SJohn Marino      code skips deleted insns.  */
912*e4b17023SJohn Marino   if (df_chain && DF_REF_CHAIN (ref))
913*e4b17023SJohn Marino     df_chain_unlink (ref);
914*e4b17023SJohn Marino 
915*e4b17023SJohn Marino   reg_info->n_refs--;
916*e4b17023SJohn Marino   if (DF_REF_FLAGS_IS_SET (ref, DF_HARD_REG_LIVE))
917*e4b17023SJohn Marino     {
918*e4b17023SJohn Marino       gcc_assert (DF_REF_REGNO (ref) < FIRST_PSEUDO_REGISTER);
919*e4b17023SJohn Marino       df->hard_regs_live_count[DF_REF_REGNO (ref)]--;
920*e4b17023SJohn Marino     }
921*e4b17023SJohn Marino 
922*e4b17023SJohn Marino   /* Unlink from the reg chain.  If there is no prev, this is the
923*e4b17023SJohn Marino      first of the list.  If not, just join the next and prev.  */
924*e4b17023SJohn Marino   if (prev)
925*e4b17023SJohn Marino     DF_REF_NEXT_REG (prev) = next;
926*e4b17023SJohn Marino   else
927*e4b17023SJohn Marino     {
928*e4b17023SJohn Marino       gcc_assert (reg_info->reg_chain == ref);
929*e4b17023SJohn Marino       reg_info->reg_chain = next;
930*e4b17023SJohn Marino     }
931*e4b17023SJohn Marino   if (next)
932*e4b17023SJohn Marino     DF_REF_PREV_REG (next) = prev;
933*e4b17023SJohn Marino 
934*e4b17023SJohn Marino   df_free_ref (ref);
935*e4b17023SJohn Marino }
936*e4b17023SJohn Marino 
937*e4b17023SJohn Marino 
938*e4b17023SJohn Marino /* Remove REF from VEC.  */
939*e4b17023SJohn Marino 
940*e4b17023SJohn Marino static void
df_ref_compress_rec(df_ref ** vec_ptr,df_ref ref)941*e4b17023SJohn Marino df_ref_compress_rec (df_ref **vec_ptr, df_ref ref)
942*e4b17023SJohn Marino {
943*e4b17023SJohn Marino   df_ref *vec = *vec_ptr;
944*e4b17023SJohn Marino 
945*e4b17023SJohn Marino   if (vec[1])
946*e4b17023SJohn Marino     {
947*e4b17023SJohn Marino       while (*vec && *vec != ref)
948*e4b17023SJohn Marino 	vec++;
949*e4b17023SJohn Marino 
950*e4b17023SJohn Marino       while (*vec)
951*e4b17023SJohn Marino 	{
952*e4b17023SJohn Marino 	  *vec = *(vec+1);
953*e4b17023SJohn Marino 	  vec++;
954*e4b17023SJohn Marino 	}
955*e4b17023SJohn Marino     }
956*e4b17023SJohn Marino   else
957*e4b17023SJohn Marino     {
958*e4b17023SJohn Marino       free (vec);
959*e4b17023SJohn Marino       *vec_ptr = df_null_ref_rec;
960*e4b17023SJohn Marino     }
961*e4b17023SJohn Marino }
962*e4b17023SJohn Marino 
963*e4b17023SJohn Marino 
964*e4b17023SJohn Marino /* Unlink REF from all def-use/use-def chains, etc.  */
965*e4b17023SJohn Marino 
966*e4b17023SJohn Marino void
df_ref_remove(df_ref ref)967*e4b17023SJohn Marino df_ref_remove (df_ref ref)
968*e4b17023SJohn Marino {
969*e4b17023SJohn Marino #if 0
970*e4b17023SJohn Marino   if (dump_file)
971*e4b17023SJohn Marino     {
972*e4b17023SJohn Marino       fprintf (dump_file, "removing ref ");
973*e4b17023SJohn Marino       df_ref_debug (ref, dump_file);
974*e4b17023SJohn Marino     }
975*e4b17023SJohn Marino #endif
976*e4b17023SJohn Marino 
977*e4b17023SJohn Marino   if (DF_REF_REG_DEF_P (ref))
978*e4b17023SJohn Marino     {
979*e4b17023SJohn Marino       if (DF_REF_IS_ARTIFICIAL (ref))
980*e4b17023SJohn Marino 	{
981*e4b17023SJohn Marino 	  struct df_scan_bb_info *bb_info
982*e4b17023SJohn Marino 	    = df_scan_get_bb_info (DF_REF_BBNO (ref));
983*e4b17023SJohn Marino 	  df_ref_compress_rec (&bb_info->artificial_defs, ref);
984*e4b17023SJohn Marino 	}
985*e4b17023SJohn Marino       else
986*e4b17023SJohn Marino 	{
987*e4b17023SJohn Marino 	  unsigned int uid = DF_REF_INSN_UID (ref);
988*e4b17023SJohn Marino 	  struct df_insn_info *insn_rec = DF_INSN_UID_GET (uid);
989*e4b17023SJohn Marino 	  df_ref_compress_rec (&insn_rec->defs, ref);
990*e4b17023SJohn Marino 	}
991*e4b17023SJohn Marino     }
992*e4b17023SJohn Marino   else
993*e4b17023SJohn Marino     {
994*e4b17023SJohn Marino       if (DF_REF_IS_ARTIFICIAL (ref))
995*e4b17023SJohn Marino 	{
996*e4b17023SJohn Marino 	  struct df_scan_bb_info *bb_info
997*e4b17023SJohn Marino 	    = df_scan_get_bb_info (DF_REF_BBNO (ref));
998*e4b17023SJohn Marino 	  df_ref_compress_rec (&bb_info->artificial_uses, ref);
999*e4b17023SJohn Marino 	}
1000*e4b17023SJohn Marino       else
1001*e4b17023SJohn Marino 	{
1002*e4b17023SJohn Marino 	  unsigned int uid = DF_REF_INSN_UID (ref);
1003*e4b17023SJohn Marino 	  struct df_insn_info *insn_rec = DF_INSN_UID_GET (uid);
1004*e4b17023SJohn Marino 
1005*e4b17023SJohn Marino 	  if (DF_REF_FLAGS (ref) & DF_REF_IN_NOTE)
1006*e4b17023SJohn Marino 	    df_ref_compress_rec (&insn_rec->eq_uses, ref);
1007*e4b17023SJohn Marino 	  else
1008*e4b17023SJohn Marino 	    df_ref_compress_rec (&insn_rec->uses, ref);
1009*e4b17023SJohn Marino 	}
1010*e4b17023SJohn Marino     }
1011*e4b17023SJohn Marino 
1012*e4b17023SJohn Marino   /* By deleting the ref directly, df_insn_rescan my not find any
1013*e4b17023SJohn Marino      differences even though the block will have changed.  So we need
1014*e4b17023SJohn Marino      to mark the block dirty ourselves.  */
1015*e4b17023SJohn Marino   if (!DEBUG_INSN_P (DF_REF_INSN (ref)))
1016*e4b17023SJohn Marino     df_set_bb_dirty (DF_REF_BB (ref));
1017*e4b17023SJohn Marino   df_reg_chain_unlink (ref);
1018*e4b17023SJohn Marino }
1019*e4b17023SJohn Marino 
1020*e4b17023SJohn Marino 
1021*e4b17023SJohn Marino /* Create the insn record for INSN.  If there was one there, zero it
1022*e4b17023SJohn Marino    out.  */
1023*e4b17023SJohn Marino 
1024*e4b17023SJohn Marino struct df_insn_info *
df_insn_create_insn_record(rtx insn)1025*e4b17023SJohn Marino df_insn_create_insn_record (rtx insn)
1026*e4b17023SJohn Marino {
1027*e4b17023SJohn Marino   struct df_scan_problem_data *problem_data
1028*e4b17023SJohn Marino     = (struct df_scan_problem_data *) df_scan->problem_data;
1029*e4b17023SJohn Marino   struct df_insn_info *insn_rec;
1030*e4b17023SJohn Marino 
1031*e4b17023SJohn Marino   df_grow_insn_info ();
1032*e4b17023SJohn Marino   insn_rec = DF_INSN_INFO_GET (insn);
1033*e4b17023SJohn Marino   if (!insn_rec)
1034*e4b17023SJohn Marino     {
1035*e4b17023SJohn Marino       insn_rec = (struct df_insn_info *) pool_alloc (problem_data->insn_pool);
1036*e4b17023SJohn Marino       DF_INSN_INFO_SET (insn, insn_rec);
1037*e4b17023SJohn Marino     }
1038*e4b17023SJohn Marino   memset (insn_rec, 0, sizeof (struct df_insn_info));
1039*e4b17023SJohn Marino   insn_rec->insn = insn;
1040*e4b17023SJohn Marino   return insn_rec;
1041*e4b17023SJohn Marino }
1042*e4b17023SJohn Marino 
1043*e4b17023SJohn Marino 
1044*e4b17023SJohn Marino /* Delete all du chain (DF_REF_CHAIN()) of all refs in the ref chain.  */
1045*e4b17023SJohn Marino 
1046*e4b17023SJohn Marino static void
df_ref_chain_delete_du_chain(df_ref * ref_rec)1047*e4b17023SJohn Marino df_ref_chain_delete_du_chain (df_ref *ref_rec)
1048*e4b17023SJohn Marino {
1049*e4b17023SJohn Marino   while (*ref_rec)
1050*e4b17023SJohn Marino     {
1051*e4b17023SJohn Marino       df_ref ref = *ref_rec;
1052*e4b17023SJohn Marino       /* CHAIN is allocated by DF_CHAIN. So make sure to
1053*e4b17023SJohn Marino          pass df_scan instance for the problem.  */
1054*e4b17023SJohn Marino       if (DF_REF_CHAIN (ref))
1055*e4b17023SJohn Marino         df_chain_unlink (ref);
1056*e4b17023SJohn Marino       ref_rec++;
1057*e4b17023SJohn Marino     }
1058*e4b17023SJohn Marino }
1059*e4b17023SJohn Marino 
1060*e4b17023SJohn Marino 
1061*e4b17023SJohn Marino /* Delete all refs in the ref chain.  */
1062*e4b17023SJohn Marino 
1063*e4b17023SJohn Marino static void
df_ref_chain_delete(df_ref * ref_rec)1064*e4b17023SJohn Marino df_ref_chain_delete (df_ref *ref_rec)
1065*e4b17023SJohn Marino {
1066*e4b17023SJohn Marino   df_ref *start = ref_rec;
1067*e4b17023SJohn Marino   while (*ref_rec)
1068*e4b17023SJohn Marino     {
1069*e4b17023SJohn Marino       df_reg_chain_unlink (*ref_rec);
1070*e4b17023SJohn Marino       ref_rec++;
1071*e4b17023SJohn Marino     }
1072*e4b17023SJohn Marino 
1073*e4b17023SJohn Marino   /* If the list is empty, it has a special shared element that is not
1074*e4b17023SJohn Marino      to be deleted.  */
1075*e4b17023SJohn Marino   if (*start)
1076*e4b17023SJohn Marino     free (start);
1077*e4b17023SJohn Marino }
1078*e4b17023SJohn Marino 
1079*e4b17023SJohn Marino 
1080*e4b17023SJohn Marino /* Delete the hardreg chain.  */
1081*e4b17023SJohn Marino 
1082*e4b17023SJohn Marino static void
df_mw_hardreg_chain_delete(struct df_mw_hardreg ** hardregs)1083*e4b17023SJohn Marino df_mw_hardreg_chain_delete (struct df_mw_hardreg **hardregs)
1084*e4b17023SJohn Marino {
1085*e4b17023SJohn Marino   struct df_scan_problem_data *problem_data;
1086*e4b17023SJohn Marino 
1087*e4b17023SJohn Marino   if (!hardregs)
1088*e4b17023SJohn Marino     return;
1089*e4b17023SJohn Marino 
1090*e4b17023SJohn Marino   problem_data = (struct df_scan_problem_data *) df_scan->problem_data;
1091*e4b17023SJohn Marino 
1092*e4b17023SJohn Marino   while (*hardregs)
1093*e4b17023SJohn Marino     {
1094*e4b17023SJohn Marino       pool_free (problem_data->mw_reg_pool, *hardregs);
1095*e4b17023SJohn Marino       hardregs++;
1096*e4b17023SJohn Marino     }
1097*e4b17023SJohn Marino }
1098*e4b17023SJohn Marino 
1099*e4b17023SJohn Marino 
1100*e4b17023SJohn Marino /* Delete all of the refs information from INSN.  BB must be passed in
1101*e4b17023SJohn Marino    except when called from df_process_deferred_rescans to mark the block
1102*e4b17023SJohn Marino    as dirty.  */
1103*e4b17023SJohn Marino 
1104*e4b17023SJohn Marino void
df_insn_delete(basic_block bb,unsigned int uid)1105*e4b17023SJohn Marino df_insn_delete (basic_block bb, unsigned int uid)
1106*e4b17023SJohn Marino {
1107*e4b17023SJohn Marino   struct df_insn_info *insn_info = NULL;
1108*e4b17023SJohn Marino   if (!df)
1109*e4b17023SJohn Marino     return;
1110*e4b17023SJohn Marino 
1111*e4b17023SJohn Marino   df_grow_bb_info (df_scan);
1112*e4b17023SJohn Marino   df_grow_reg_info ();
1113*e4b17023SJohn Marino 
1114*e4b17023SJohn Marino   /* The block must be marked as dirty now, rather than later as in
1115*e4b17023SJohn Marino      df_insn_rescan and df_notes_rescan because it may not be there at
1116*e4b17023SJohn Marino      rescanning time and the mark would blow up.  */
1117*e4b17023SJohn Marino   if (bb)
1118*e4b17023SJohn Marino     df_set_bb_dirty (bb);
1119*e4b17023SJohn Marino 
1120*e4b17023SJohn Marino   insn_info = DF_INSN_UID_SAFE_GET (uid);
1121*e4b17023SJohn Marino 
1122*e4b17023SJohn Marino   /* The client has deferred rescanning.  */
1123*e4b17023SJohn Marino   if (df->changeable_flags & DF_DEFER_INSN_RESCAN)
1124*e4b17023SJohn Marino     {
1125*e4b17023SJohn Marino       if (insn_info)
1126*e4b17023SJohn Marino 	{
1127*e4b17023SJohn Marino 	  bitmap_clear_bit (&df->insns_to_rescan, uid);
1128*e4b17023SJohn Marino 	  bitmap_clear_bit (&df->insns_to_notes_rescan, uid);
1129*e4b17023SJohn Marino 	  bitmap_set_bit (&df->insns_to_delete, uid);
1130*e4b17023SJohn Marino 	}
1131*e4b17023SJohn Marino       if (dump_file)
1132*e4b17023SJohn Marino 	fprintf (dump_file, "deferring deletion of insn with uid = %d.\n", uid);
1133*e4b17023SJohn Marino       return;
1134*e4b17023SJohn Marino     }
1135*e4b17023SJohn Marino 
1136*e4b17023SJohn Marino   if (dump_file)
1137*e4b17023SJohn Marino     fprintf (dump_file, "deleting insn with uid = %d.\n", uid);
1138*e4b17023SJohn Marino 
1139*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_delete, uid);
1140*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_rescan, uid);
1141*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_notes_rescan, uid);
1142*e4b17023SJohn Marino   if (insn_info)
1143*e4b17023SJohn Marino     {
1144*e4b17023SJohn Marino       struct df_scan_problem_data *problem_data
1145*e4b17023SJohn Marino 	= (struct df_scan_problem_data *) df_scan->problem_data;
1146*e4b17023SJohn Marino 
1147*e4b17023SJohn Marino       /* In general, notes do not have the insn_info fields
1148*e4b17023SJohn Marino 	 initialized.  However, combine deletes insns by changing them
1149*e4b17023SJohn Marino 	 to notes.  How clever.  So we cannot just check if it is a
1150*e4b17023SJohn Marino 	 valid insn before short circuiting this code, we need to see
1151*e4b17023SJohn Marino 	 if we actually initialized it.  */
1152*e4b17023SJohn Marino       if (insn_info->defs)
1153*e4b17023SJohn Marino 	{
1154*e4b17023SJohn Marino 	  df_mw_hardreg_chain_delete (insn_info->mw_hardregs);
1155*e4b17023SJohn Marino 
1156*e4b17023SJohn Marino 	  if (df_chain)
1157*e4b17023SJohn Marino 	    {
1158*e4b17023SJohn Marino 	      df_ref_chain_delete_du_chain (insn_info->defs);
1159*e4b17023SJohn Marino 	      df_ref_chain_delete_du_chain (insn_info->uses);
1160*e4b17023SJohn Marino 	      df_ref_chain_delete_du_chain (insn_info->eq_uses);
1161*e4b17023SJohn Marino 	    }
1162*e4b17023SJohn Marino 
1163*e4b17023SJohn Marino 	  df_ref_chain_delete (insn_info->defs);
1164*e4b17023SJohn Marino 	  df_ref_chain_delete (insn_info->uses);
1165*e4b17023SJohn Marino 	  df_ref_chain_delete (insn_info->eq_uses);
1166*e4b17023SJohn Marino 	}
1167*e4b17023SJohn Marino       pool_free (problem_data->insn_pool, insn_info);
1168*e4b17023SJohn Marino       DF_INSN_UID_SET (uid, NULL);
1169*e4b17023SJohn Marino     }
1170*e4b17023SJohn Marino }
1171*e4b17023SJohn Marino 
1172*e4b17023SJohn Marino 
1173*e4b17023SJohn Marino /* Free all of the refs and the mw_hardregs in COLLECTION_REC.  */
1174*e4b17023SJohn Marino 
1175*e4b17023SJohn Marino static void
df_free_collection_rec(struct df_collection_rec * collection_rec)1176*e4b17023SJohn Marino df_free_collection_rec (struct df_collection_rec *collection_rec)
1177*e4b17023SJohn Marino {
1178*e4b17023SJohn Marino   unsigned int ix;
1179*e4b17023SJohn Marino   struct df_scan_problem_data *problem_data
1180*e4b17023SJohn Marino     = (struct df_scan_problem_data *) df_scan->problem_data;
1181*e4b17023SJohn Marino   df_ref ref;
1182*e4b17023SJohn Marino   struct df_mw_hardreg *mw;
1183*e4b17023SJohn Marino 
1184*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (df_ref, collection_rec->def_vec, ix, ref)
1185*e4b17023SJohn Marino     df_free_ref (ref);
1186*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (df_ref, collection_rec->use_vec, ix, ref)
1187*e4b17023SJohn Marino     df_free_ref (ref);
1188*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (df_ref, collection_rec->eq_use_vec, ix, ref)
1189*e4b17023SJohn Marino     df_free_ref (ref);
1190*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (df_mw_hardreg_ptr, collection_rec->mw_vec, ix, mw)
1191*e4b17023SJohn Marino     pool_free (problem_data->mw_reg_pool, mw);
1192*e4b17023SJohn Marino 
1193*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec->def_vec);
1194*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec->use_vec);
1195*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec->eq_use_vec);
1196*e4b17023SJohn Marino   VEC_free (df_mw_hardreg_ptr, stack, collection_rec->mw_vec);
1197*e4b17023SJohn Marino }
1198*e4b17023SJohn Marino 
1199*e4b17023SJohn Marino /* Rescan INSN.  Return TRUE if the rescanning produced any changes.  */
1200*e4b17023SJohn Marino 
1201*e4b17023SJohn Marino bool
df_insn_rescan(rtx insn)1202*e4b17023SJohn Marino df_insn_rescan (rtx insn)
1203*e4b17023SJohn Marino {
1204*e4b17023SJohn Marino   unsigned int uid = INSN_UID (insn);
1205*e4b17023SJohn Marino   struct df_insn_info *insn_info = NULL;
1206*e4b17023SJohn Marino   basic_block bb = BLOCK_FOR_INSN (insn);
1207*e4b17023SJohn Marino   struct df_collection_rec collection_rec;
1208*e4b17023SJohn Marino 
1209*e4b17023SJohn Marino   if ((!df) || (!INSN_P (insn)))
1210*e4b17023SJohn Marino     return false;
1211*e4b17023SJohn Marino 
1212*e4b17023SJohn Marino   if (!bb)
1213*e4b17023SJohn Marino     {
1214*e4b17023SJohn Marino       if (dump_file)
1215*e4b17023SJohn Marino 	fprintf (dump_file, "no bb for insn with uid = %d.\n", uid);
1216*e4b17023SJohn Marino       return false;
1217*e4b17023SJohn Marino     }
1218*e4b17023SJohn Marino 
1219*e4b17023SJohn Marino   /* The client has disabled rescanning and plans to do it itself.  */
1220*e4b17023SJohn Marino   if (df->changeable_flags & DF_NO_INSN_RESCAN)
1221*e4b17023SJohn Marino     return false;
1222*e4b17023SJohn Marino 
1223*e4b17023SJohn Marino   df_grow_bb_info (df_scan);
1224*e4b17023SJohn Marino   df_grow_reg_info ();
1225*e4b17023SJohn Marino 
1226*e4b17023SJohn Marino   insn_info = DF_INSN_UID_SAFE_GET (uid);
1227*e4b17023SJohn Marino 
1228*e4b17023SJohn Marino   /* The client has deferred rescanning.  */
1229*e4b17023SJohn Marino   if (df->changeable_flags & DF_DEFER_INSN_RESCAN)
1230*e4b17023SJohn Marino     {
1231*e4b17023SJohn Marino       if (!insn_info)
1232*e4b17023SJohn Marino 	{
1233*e4b17023SJohn Marino 	  insn_info = df_insn_create_insn_record (insn);
1234*e4b17023SJohn Marino 	  insn_info->defs = df_null_ref_rec;
1235*e4b17023SJohn Marino 	  insn_info->uses = df_null_ref_rec;
1236*e4b17023SJohn Marino 	  insn_info->eq_uses = df_null_ref_rec;
1237*e4b17023SJohn Marino 	  insn_info->mw_hardregs = df_null_mw_rec;
1238*e4b17023SJohn Marino 	}
1239*e4b17023SJohn Marino       if (dump_file)
1240*e4b17023SJohn Marino 	fprintf (dump_file, "deferring rescan insn with uid = %d.\n", uid);
1241*e4b17023SJohn Marino 
1242*e4b17023SJohn Marino       bitmap_clear_bit (&df->insns_to_delete, uid);
1243*e4b17023SJohn Marino       bitmap_clear_bit (&df->insns_to_notes_rescan, uid);
1244*e4b17023SJohn Marino       bitmap_set_bit (&df->insns_to_rescan, INSN_UID (insn));
1245*e4b17023SJohn Marino       return false;
1246*e4b17023SJohn Marino     }
1247*e4b17023SJohn Marino 
1248*e4b17023SJohn Marino   collection_rec.def_vec = VEC_alloc (df_ref, stack, 128);
1249*e4b17023SJohn Marino   collection_rec.use_vec = VEC_alloc (df_ref, stack, 32);
1250*e4b17023SJohn Marino   collection_rec.eq_use_vec = VEC_alloc (df_ref, stack, 32);
1251*e4b17023SJohn Marino   collection_rec.mw_vec = VEC_alloc (df_mw_hardreg_ptr, stack, 32);
1252*e4b17023SJohn Marino 
1253*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_delete, uid);
1254*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_rescan, uid);
1255*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_notes_rescan, uid);
1256*e4b17023SJohn Marino   if (insn_info)
1257*e4b17023SJohn Marino     {
1258*e4b17023SJohn Marino       int luid;
1259*e4b17023SJohn Marino       bool the_same = df_insn_refs_verify (&collection_rec, bb, insn, false);
1260*e4b17023SJohn Marino       /* If there's no change, return false. */
1261*e4b17023SJohn Marino       if (the_same)
1262*e4b17023SJohn Marino 	{
1263*e4b17023SJohn Marino 	  df_free_collection_rec (&collection_rec);
1264*e4b17023SJohn Marino 	  if (dump_file)
1265*e4b17023SJohn Marino 	    fprintf (dump_file, "verify found no changes in insn with uid = %d.\n", uid);
1266*e4b17023SJohn Marino 	  return false;
1267*e4b17023SJohn Marino 	}
1268*e4b17023SJohn Marino       if (dump_file)
1269*e4b17023SJohn Marino 	fprintf (dump_file, "rescanning insn with uid = %d.\n", uid);
1270*e4b17023SJohn Marino 
1271*e4b17023SJohn Marino       /* There's change - we need to delete the existing info.
1272*e4b17023SJohn Marino 	 Since the insn isn't moved, we can salvage its LUID.  */
1273*e4b17023SJohn Marino       luid = DF_INSN_LUID (insn);
1274*e4b17023SJohn Marino       df_insn_delete (NULL, uid);
1275*e4b17023SJohn Marino       df_insn_create_insn_record (insn);
1276*e4b17023SJohn Marino       DF_INSN_LUID (insn) = luid;
1277*e4b17023SJohn Marino     }
1278*e4b17023SJohn Marino   else
1279*e4b17023SJohn Marino     {
1280*e4b17023SJohn Marino       struct df_insn_info *insn_info = df_insn_create_insn_record (insn);
1281*e4b17023SJohn Marino       df_insn_refs_collect (&collection_rec, bb, insn_info);
1282*e4b17023SJohn Marino       if (dump_file)
1283*e4b17023SJohn Marino 	fprintf (dump_file, "scanning new insn with uid = %d.\n", uid);
1284*e4b17023SJohn Marino     }
1285*e4b17023SJohn Marino 
1286*e4b17023SJohn Marino   df_refs_add_to_chains (&collection_rec, bb, insn);
1287*e4b17023SJohn Marino   if (!DEBUG_INSN_P (insn))
1288*e4b17023SJohn Marino     df_set_bb_dirty (bb);
1289*e4b17023SJohn Marino 
1290*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec.def_vec);
1291*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec.use_vec);
1292*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec.eq_use_vec);
1293*e4b17023SJohn Marino   VEC_free (df_mw_hardreg_ptr, stack, collection_rec.mw_vec);
1294*e4b17023SJohn Marino 
1295*e4b17023SJohn Marino   return true;
1296*e4b17023SJohn Marino }
1297*e4b17023SJohn Marino 
1298*e4b17023SJohn Marino /* Same as df_insn_rescan, but don't mark the basic block as
1299*e4b17023SJohn Marino    dirty.  */
1300*e4b17023SJohn Marino 
1301*e4b17023SJohn Marino bool
df_insn_rescan_debug_internal(rtx insn)1302*e4b17023SJohn Marino df_insn_rescan_debug_internal (rtx insn)
1303*e4b17023SJohn Marino {
1304*e4b17023SJohn Marino   unsigned int uid = INSN_UID (insn);
1305*e4b17023SJohn Marino   struct df_insn_info *insn_info;
1306*e4b17023SJohn Marino 
1307*e4b17023SJohn Marino   gcc_assert (DEBUG_INSN_P (insn)
1308*e4b17023SJohn Marino 	      && VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn)));
1309*e4b17023SJohn Marino 
1310*e4b17023SJohn Marino   if (!df)
1311*e4b17023SJohn Marino     return false;
1312*e4b17023SJohn Marino 
1313*e4b17023SJohn Marino   insn_info = DF_INSN_UID_SAFE_GET (INSN_UID (insn));
1314*e4b17023SJohn Marino   if (!insn_info)
1315*e4b17023SJohn Marino     return false;
1316*e4b17023SJohn Marino 
1317*e4b17023SJohn Marino   if (dump_file)
1318*e4b17023SJohn Marino     fprintf (dump_file, "deleting debug_insn with uid = %d.\n", uid);
1319*e4b17023SJohn Marino 
1320*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_delete, uid);
1321*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_rescan, uid);
1322*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_notes_rescan, uid);
1323*e4b17023SJohn Marino 
1324*e4b17023SJohn Marino   if (!insn_info->defs)
1325*e4b17023SJohn Marino     return false;
1326*e4b17023SJohn Marino 
1327*e4b17023SJohn Marino   if (insn_info->defs == df_null_ref_rec
1328*e4b17023SJohn Marino       && insn_info->uses == df_null_ref_rec
1329*e4b17023SJohn Marino       && insn_info->eq_uses == df_null_ref_rec
1330*e4b17023SJohn Marino       && insn_info->mw_hardregs == df_null_mw_rec)
1331*e4b17023SJohn Marino     return false;
1332*e4b17023SJohn Marino 
1333*e4b17023SJohn Marino   df_mw_hardreg_chain_delete (insn_info->mw_hardregs);
1334*e4b17023SJohn Marino 
1335*e4b17023SJohn Marino   if (df_chain)
1336*e4b17023SJohn Marino     {
1337*e4b17023SJohn Marino       df_ref_chain_delete_du_chain (insn_info->defs);
1338*e4b17023SJohn Marino       df_ref_chain_delete_du_chain (insn_info->uses);
1339*e4b17023SJohn Marino       df_ref_chain_delete_du_chain (insn_info->eq_uses);
1340*e4b17023SJohn Marino     }
1341*e4b17023SJohn Marino 
1342*e4b17023SJohn Marino   df_ref_chain_delete (insn_info->defs);
1343*e4b17023SJohn Marino   df_ref_chain_delete (insn_info->uses);
1344*e4b17023SJohn Marino   df_ref_chain_delete (insn_info->eq_uses);
1345*e4b17023SJohn Marino 
1346*e4b17023SJohn Marino   insn_info->defs = df_null_ref_rec;
1347*e4b17023SJohn Marino   insn_info->uses = df_null_ref_rec;
1348*e4b17023SJohn Marino   insn_info->eq_uses = df_null_ref_rec;
1349*e4b17023SJohn Marino   insn_info->mw_hardregs = df_null_mw_rec;
1350*e4b17023SJohn Marino 
1351*e4b17023SJohn Marino   return true;
1352*e4b17023SJohn Marino }
1353*e4b17023SJohn Marino 
1354*e4b17023SJohn Marino 
1355*e4b17023SJohn Marino /* Rescan all of the insns in the function.  Note that the artificial
1356*e4b17023SJohn Marino    uses and defs are not touched.  This function will destroy def-se
1357*e4b17023SJohn Marino    or use-def chains.  */
1358*e4b17023SJohn Marino 
1359*e4b17023SJohn Marino void
df_insn_rescan_all(void)1360*e4b17023SJohn Marino df_insn_rescan_all (void)
1361*e4b17023SJohn Marino {
1362*e4b17023SJohn Marino   bool no_insn_rescan = false;
1363*e4b17023SJohn Marino   bool defer_insn_rescan = false;
1364*e4b17023SJohn Marino   basic_block bb;
1365*e4b17023SJohn Marino   bitmap_iterator bi;
1366*e4b17023SJohn Marino   unsigned int uid;
1367*e4b17023SJohn Marino   bitmap_head tmp;
1368*e4b17023SJohn Marino 
1369*e4b17023SJohn Marino   bitmap_initialize (&tmp, &df_bitmap_obstack);
1370*e4b17023SJohn Marino 
1371*e4b17023SJohn Marino   if (df->changeable_flags & DF_NO_INSN_RESCAN)
1372*e4b17023SJohn Marino     {
1373*e4b17023SJohn Marino       df_clear_flags (DF_NO_INSN_RESCAN);
1374*e4b17023SJohn Marino       no_insn_rescan = true;
1375*e4b17023SJohn Marino     }
1376*e4b17023SJohn Marino 
1377*e4b17023SJohn Marino   if (df->changeable_flags & DF_DEFER_INSN_RESCAN)
1378*e4b17023SJohn Marino     {
1379*e4b17023SJohn Marino       df_clear_flags (DF_DEFER_INSN_RESCAN);
1380*e4b17023SJohn Marino       defer_insn_rescan = true;
1381*e4b17023SJohn Marino     }
1382*e4b17023SJohn Marino 
1383*e4b17023SJohn Marino   bitmap_copy (&tmp, &df->insns_to_delete);
1384*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (&tmp, 0, uid, bi)
1385*e4b17023SJohn Marino     {
1386*e4b17023SJohn Marino       struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
1387*e4b17023SJohn Marino       if (insn_info)
1388*e4b17023SJohn Marino 	df_insn_delete (NULL, uid);
1389*e4b17023SJohn Marino     }
1390*e4b17023SJohn Marino 
1391*e4b17023SJohn Marino   bitmap_clear (&tmp);
1392*e4b17023SJohn Marino   bitmap_clear (&df->insns_to_delete);
1393*e4b17023SJohn Marino   bitmap_clear (&df->insns_to_rescan);
1394*e4b17023SJohn Marino   bitmap_clear (&df->insns_to_notes_rescan);
1395*e4b17023SJohn Marino 
1396*e4b17023SJohn Marino   FOR_EACH_BB (bb)
1397*e4b17023SJohn Marino     {
1398*e4b17023SJohn Marino       rtx insn;
1399*e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
1400*e4b17023SJohn Marino 	{
1401*e4b17023SJohn Marino 	  df_insn_rescan (insn);
1402*e4b17023SJohn Marino 	}
1403*e4b17023SJohn Marino     }
1404*e4b17023SJohn Marino 
1405*e4b17023SJohn Marino   if (no_insn_rescan)
1406*e4b17023SJohn Marino     df_set_flags (DF_NO_INSN_RESCAN);
1407*e4b17023SJohn Marino   if (defer_insn_rescan)
1408*e4b17023SJohn Marino     df_set_flags (DF_DEFER_INSN_RESCAN);
1409*e4b17023SJohn Marino }
1410*e4b17023SJohn Marino 
1411*e4b17023SJohn Marino 
1412*e4b17023SJohn Marino /* Process all of the deferred rescans or deletions.  */
1413*e4b17023SJohn Marino 
1414*e4b17023SJohn Marino void
df_process_deferred_rescans(void)1415*e4b17023SJohn Marino df_process_deferred_rescans (void)
1416*e4b17023SJohn Marino {
1417*e4b17023SJohn Marino   bool no_insn_rescan = false;
1418*e4b17023SJohn Marino   bool defer_insn_rescan = false;
1419*e4b17023SJohn Marino   bitmap_iterator bi;
1420*e4b17023SJohn Marino   unsigned int uid;
1421*e4b17023SJohn Marino   bitmap_head tmp;
1422*e4b17023SJohn Marino 
1423*e4b17023SJohn Marino   bitmap_initialize (&tmp, &df_bitmap_obstack);
1424*e4b17023SJohn Marino 
1425*e4b17023SJohn Marino   if (df->changeable_flags & DF_NO_INSN_RESCAN)
1426*e4b17023SJohn Marino     {
1427*e4b17023SJohn Marino       df_clear_flags (DF_NO_INSN_RESCAN);
1428*e4b17023SJohn Marino       no_insn_rescan = true;
1429*e4b17023SJohn Marino     }
1430*e4b17023SJohn Marino 
1431*e4b17023SJohn Marino   if (df->changeable_flags & DF_DEFER_INSN_RESCAN)
1432*e4b17023SJohn Marino     {
1433*e4b17023SJohn Marino       df_clear_flags (DF_DEFER_INSN_RESCAN);
1434*e4b17023SJohn Marino       defer_insn_rescan = true;
1435*e4b17023SJohn Marino     }
1436*e4b17023SJohn Marino 
1437*e4b17023SJohn Marino   if (dump_file)
1438*e4b17023SJohn Marino     fprintf (dump_file, "starting the processing of deferred insns\n");
1439*e4b17023SJohn Marino 
1440*e4b17023SJohn Marino   bitmap_copy (&tmp, &df->insns_to_delete);
1441*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (&tmp, 0, uid, bi)
1442*e4b17023SJohn Marino     {
1443*e4b17023SJohn Marino       struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
1444*e4b17023SJohn Marino       if (insn_info)
1445*e4b17023SJohn Marino 	df_insn_delete (NULL, uid);
1446*e4b17023SJohn Marino     }
1447*e4b17023SJohn Marino 
1448*e4b17023SJohn Marino   bitmap_copy (&tmp, &df->insns_to_rescan);
1449*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (&tmp, 0, uid, bi)
1450*e4b17023SJohn Marino     {
1451*e4b17023SJohn Marino       struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
1452*e4b17023SJohn Marino       if (insn_info)
1453*e4b17023SJohn Marino 	df_insn_rescan (insn_info->insn);
1454*e4b17023SJohn Marino     }
1455*e4b17023SJohn Marino 
1456*e4b17023SJohn Marino   bitmap_copy (&tmp, &df->insns_to_notes_rescan);
1457*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (&tmp, 0, uid, bi)
1458*e4b17023SJohn Marino     {
1459*e4b17023SJohn Marino       struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
1460*e4b17023SJohn Marino       if (insn_info)
1461*e4b17023SJohn Marino 	df_notes_rescan (insn_info->insn);
1462*e4b17023SJohn Marino     }
1463*e4b17023SJohn Marino 
1464*e4b17023SJohn Marino   if (dump_file)
1465*e4b17023SJohn Marino     fprintf (dump_file, "ending the processing of deferred insns\n");
1466*e4b17023SJohn Marino 
1467*e4b17023SJohn Marino   bitmap_clear (&tmp);
1468*e4b17023SJohn Marino   bitmap_clear (&df->insns_to_delete);
1469*e4b17023SJohn Marino   bitmap_clear (&df->insns_to_rescan);
1470*e4b17023SJohn Marino   bitmap_clear (&df->insns_to_notes_rescan);
1471*e4b17023SJohn Marino 
1472*e4b17023SJohn Marino   if (no_insn_rescan)
1473*e4b17023SJohn Marino     df_set_flags (DF_NO_INSN_RESCAN);
1474*e4b17023SJohn Marino   if (defer_insn_rescan)
1475*e4b17023SJohn Marino     df_set_flags (DF_DEFER_INSN_RESCAN);
1476*e4b17023SJohn Marino 
1477*e4b17023SJohn Marino   /* If someone changed regs_ever_live during this pass, fix up the
1478*e4b17023SJohn Marino      entry and exit blocks.  */
1479*e4b17023SJohn Marino   if (df->redo_entry_and_exit)
1480*e4b17023SJohn Marino     {
1481*e4b17023SJohn Marino       df_update_entry_exit_and_calls ();
1482*e4b17023SJohn Marino       df->redo_entry_and_exit = false;
1483*e4b17023SJohn Marino     }
1484*e4b17023SJohn Marino }
1485*e4b17023SJohn Marino 
1486*e4b17023SJohn Marino 
1487*e4b17023SJohn Marino /* Count the number of refs. Include the defs if INCLUDE_DEFS. Include
1488*e4b17023SJohn Marino    the uses if INCLUDE_USES. Include the eq_uses if
1489*e4b17023SJohn Marino    INCLUDE_EQ_USES.  */
1490*e4b17023SJohn Marino 
1491*e4b17023SJohn Marino static unsigned int
df_count_refs(bool include_defs,bool include_uses,bool include_eq_uses)1492*e4b17023SJohn Marino df_count_refs (bool include_defs, bool include_uses,
1493*e4b17023SJohn Marino 	       bool include_eq_uses)
1494*e4b17023SJohn Marino {
1495*e4b17023SJohn Marino   unsigned int regno;
1496*e4b17023SJohn Marino   int size = 0;
1497*e4b17023SJohn Marino   unsigned int m = df->regs_inited;
1498*e4b17023SJohn Marino 
1499*e4b17023SJohn Marino   for (regno = 0; regno < m; regno++)
1500*e4b17023SJohn Marino     {
1501*e4b17023SJohn Marino       if (include_defs)
1502*e4b17023SJohn Marino 	size += DF_REG_DEF_COUNT (regno);
1503*e4b17023SJohn Marino       if (include_uses)
1504*e4b17023SJohn Marino 	size += DF_REG_USE_COUNT (regno);
1505*e4b17023SJohn Marino       if (include_eq_uses)
1506*e4b17023SJohn Marino 	size += DF_REG_EQ_USE_COUNT (regno);
1507*e4b17023SJohn Marino     }
1508*e4b17023SJohn Marino   return size;
1509*e4b17023SJohn Marino }
1510*e4b17023SJohn Marino 
1511*e4b17023SJohn Marino 
1512*e4b17023SJohn Marino /* Take build ref table for either the uses or defs from the reg-use
1513*e4b17023SJohn Marino    or reg-def chains.  This version processes the refs in reg order
1514*e4b17023SJohn Marino    which is likely to be best if processing the whole function.  */
1515*e4b17023SJohn Marino 
1516*e4b17023SJohn Marino static void
df_reorganize_refs_by_reg_by_reg(struct df_ref_info * ref_info,bool include_defs,bool include_uses,bool include_eq_uses)1517*e4b17023SJohn Marino df_reorganize_refs_by_reg_by_reg (struct df_ref_info *ref_info,
1518*e4b17023SJohn Marino 				  bool include_defs,
1519*e4b17023SJohn Marino 				  bool include_uses,
1520*e4b17023SJohn Marino 				  bool include_eq_uses)
1521*e4b17023SJohn Marino {
1522*e4b17023SJohn Marino   unsigned int m = df->regs_inited;
1523*e4b17023SJohn Marino   unsigned int regno;
1524*e4b17023SJohn Marino   unsigned int offset = 0;
1525*e4b17023SJohn Marino   unsigned int start;
1526*e4b17023SJohn Marino 
1527*e4b17023SJohn Marino   if (df->changeable_flags & DF_NO_HARD_REGS)
1528*e4b17023SJohn Marino     {
1529*e4b17023SJohn Marino       start = FIRST_PSEUDO_REGISTER;
1530*e4b17023SJohn Marino       memset (ref_info->begin, 0, sizeof (int) * FIRST_PSEUDO_REGISTER);
1531*e4b17023SJohn Marino       memset (ref_info->count, 0, sizeof (int) * FIRST_PSEUDO_REGISTER);
1532*e4b17023SJohn Marino     }
1533*e4b17023SJohn Marino   else
1534*e4b17023SJohn Marino     start = 0;
1535*e4b17023SJohn Marino 
1536*e4b17023SJohn Marino   ref_info->total_size
1537*e4b17023SJohn Marino     = df_count_refs (include_defs, include_uses, include_eq_uses);
1538*e4b17023SJohn Marino 
1539*e4b17023SJohn Marino   df_check_and_grow_ref_info (ref_info, 1);
1540*e4b17023SJohn Marino 
1541*e4b17023SJohn Marino   for (regno = start; regno < m; regno++)
1542*e4b17023SJohn Marino     {
1543*e4b17023SJohn Marino       int count = 0;
1544*e4b17023SJohn Marino       ref_info->begin[regno] = offset;
1545*e4b17023SJohn Marino       if (include_defs)
1546*e4b17023SJohn Marino 	{
1547*e4b17023SJohn Marino 	  df_ref ref = DF_REG_DEF_CHAIN (regno);
1548*e4b17023SJohn Marino 	  while (ref)
1549*e4b17023SJohn Marino 	    {
1550*e4b17023SJohn Marino 	      ref_info->refs[offset] = ref;
1551*e4b17023SJohn Marino 	      DF_REF_ID (ref) = offset++;
1552*e4b17023SJohn Marino 	      count++;
1553*e4b17023SJohn Marino 	      ref = DF_REF_NEXT_REG (ref);
1554*e4b17023SJohn Marino 	      gcc_checking_assert (offset < ref_info->refs_size);
1555*e4b17023SJohn Marino 	    }
1556*e4b17023SJohn Marino 	}
1557*e4b17023SJohn Marino       if (include_uses)
1558*e4b17023SJohn Marino 	{
1559*e4b17023SJohn Marino 	  df_ref ref = DF_REG_USE_CHAIN (regno);
1560*e4b17023SJohn Marino 	  while (ref)
1561*e4b17023SJohn Marino 	    {
1562*e4b17023SJohn Marino 	      ref_info->refs[offset] = ref;
1563*e4b17023SJohn Marino 	      DF_REF_ID (ref) = offset++;
1564*e4b17023SJohn Marino 	      count++;
1565*e4b17023SJohn Marino 	      ref = DF_REF_NEXT_REG (ref);
1566*e4b17023SJohn Marino 	      gcc_checking_assert (offset < ref_info->refs_size);
1567*e4b17023SJohn Marino 	    }
1568*e4b17023SJohn Marino 	}
1569*e4b17023SJohn Marino       if (include_eq_uses)
1570*e4b17023SJohn Marino 	{
1571*e4b17023SJohn Marino 	  df_ref ref = DF_REG_EQ_USE_CHAIN (regno);
1572*e4b17023SJohn Marino 	  while (ref)
1573*e4b17023SJohn Marino 	    {
1574*e4b17023SJohn Marino 	      ref_info->refs[offset] = ref;
1575*e4b17023SJohn Marino 	      DF_REF_ID (ref) = offset++;
1576*e4b17023SJohn Marino 	      count++;
1577*e4b17023SJohn Marino 	      ref = DF_REF_NEXT_REG (ref);
1578*e4b17023SJohn Marino 	      gcc_checking_assert (offset < ref_info->refs_size);
1579*e4b17023SJohn Marino 	    }
1580*e4b17023SJohn Marino 	}
1581*e4b17023SJohn Marino       ref_info->count[regno] = count;
1582*e4b17023SJohn Marino     }
1583*e4b17023SJohn Marino 
1584*e4b17023SJohn Marino   /* The bitmap size is not decremented when refs are deleted.  So
1585*e4b17023SJohn Marino      reset it now that we have squished out all of the empty
1586*e4b17023SJohn Marino      slots.  */
1587*e4b17023SJohn Marino   ref_info->table_size = offset;
1588*e4b17023SJohn Marino }
1589*e4b17023SJohn Marino 
1590*e4b17023SJohn Marino 
1591*e4b17023SJohn Marino /* Take build ref table for either the uses or defs from the reg-use
1592*e4b17023SJohn Marino    or reg-def chains.  This version processes the refs in insn order
1593*e4b17023SJohn Marino    which is likely to be best if processing some segment of the
1594*e4b17023SJohn Marino    function.  */
1595*e4b17023SJohn Marino 
1596*e4b17023SJohn Marino static void
df_reorganize_refs_by_reg_by_insn(struct df_ref_info * ref_info,bool include_defs,bool include_uses,bool include_eq_uses)1597*e4b17023SJohn Marino df_reorganize_refs_by_reg_by_insn (struct df_ref_info *ref_info,
1598*e4b17023SJohn Marino 				   bool include_defs,
1599*e4b17023SJohn Marino 				   bool include_uses,
1600*e4b17023SJohn Marino 				   bool include_eq_uses)
1601*e4b17023SJohn Marino {
1602*e4b17023SJohn Marino   bitmap_iterator bi;
1603*e4b17023SJohn Marino   unsigned int bb_index;
1604*e4b17023SJohn Marino   unsigned int m = df->regs_inited;
1605*e4b17023SJohn Marino   unsigned int offset = 0;
1606*e4b17023SJohn Marino   unsigned int r;
1607*e4b17023SJohn Marino   unsigned int start
1608*e4b17023SJohn Marino     = (df->changeable_flags & DF_NO_HARD_REGS) ? FIRST_PSEUDO_REGISTER : 0;
1609*e4b17023SJohn Marino 
1610*e4b17023SJohn Marino   memset (ref_info->begin, 0, sizeof (int) * df->regs_inited);
1611*e4b17023SJohn Marino   memset (ref_info->count, 0, sizeof (int) * df->regs_inited);
1612*e4b17023SJohn Marino 
1613*e4b17023SJohn Marino   ref_info->total_size = df_count_refs (include_defs, include_uses, include_eq_uses);
1614*e4b17023SJohn Marino   df_check_and_grow_ref_info (ref_info, 1);
1615*e4b17023SJohn Marino 
1616*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (df->blocks_to_analyze, 0, bb_index, bi)
1617*e4b17023SJohn Marino     {
1618*e4b17023SJohn Marino       basic_block bb = BASIC_BLOCK (bb_index);
1619*e4b17023SJohn Marino       rtx insn;
1620*e4b17023SJohn Marino       df_ref *ref_rec;
1621*e4b17023SJohn Marino 
1622*e4b17023SJohn Marino       if (include_defs)
1623*e4b17023SJohn Marino 	for (ref_rec = df_get_artificial_defs (bb_index); *ref_rec; ref_rec++)
1624*e4b17023SJohn Marino 	  {
1625*e4b17023SJohn Marino 	    unsigned int regno = DF_REF_REGNO (*ref_rec);
1626*e4b17023SJohn Marino 	    ref_info->count[regno]++;
1627*e4b17023SJohn Marino 	  }
1628*e4b17023SJohn Marino       if (include_uses)
1629*e4b17023SJohn Marino 	for (ref_rec = df_get_artificial_uses (bb_index); *ref_rec; ref_rec++)
1630*e4b17023SJohn Marino 	  {
1631*e4b17023SJohn Marino 	    unsigned int regno = DF_REF_REGNO (*ref_rec);
1632*e4b17023SJohn Marino 	    ref_info->count[regno]++;
1633*e4b17023SJohn Marino 	  }
1634*e4b17023SJohn Marino 
1635*e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
1636*e4b17023SJohn Marino 	{
1637*e4b17023SJohn Marino 	  if (INSN_P (insn))
1638*e4b17023SJohn Marino 	    {
1639*e4b17023SJohn Marino 	      unsigned int uid = INSN_UID (insn);
1640*e4b17023SJohn Marino 
1641*e4b17023SJohn Marino 	      if (include_defs)
1642*e4b17023SJohn Marino 		for (ref_rec = DF_INSN_UID_DEFS (uid); *ref_rec; ref_rec++)
1643*e4b17023SJohn Marino 		  {
1644*e4b17023SJohn Marino 		    unsigned int regno = DF_REF_REGNO (*ref_rec);
1645*e4b17023SJohn Marino 		    ref_info->count[regno]++;
1646*e4b17023SJohn Marino 		  }
1647*e4b17023SJohn Marino 	      if (include_uses)
1648*e4b17023SJohn Marino 		for (ref_rec = DF_INSN_UID_USES (uid); *ref_rec; ref_rec++)
1649*e4b17023SJohn Marino 		  {
1650*e4b17023SJohn Marino 		    unsigned int regno = DF_REF_REGNO (*ref_rec);
1651*e4b17023SJohn Marino 		    ref_info->count[regno]++;
1652*e4b17023SJohn Marino 		  }
1653*e4b17023SJohn Marino 	      if (include_eq_uses)
1654*e4b17023SJohn Marino 		for (ref_rec = DF_INSN_UID_EQ_USES (uid); *ref_rec; ref_rec++)
1655*e4b17023SJohn Marino 		  {
1656*e4b17023SJohn Marino 		    unsigned int regno = DF_REF_REGNO (*ref_rec);
1657*e4b17023SJohn Marino 		    ref_info->count[regno]++;
1658*e4b17023SJohn Marino 		  }
1659*e4b17023SJohn Marino 	    }
1660*e4b17023SJohn Marino 	}
1661*e4b17023SJohn Marino     }
1662*e4b17023SJohn Marino 
1663*e4b17023SJohn Marino   for (r = start; r < m; r++)
1664*e4b17023SJohn Marino     {
1665*e4b17023SJohn Marino       ref_info->begin[r] = offset;
1666*e4b17023SJohn Marino       offset += ref_info->count[r];
1667*e4b17023SJohn Marino       ref_info->count[r] = 0;
1668*e4b17023SJohn Marino     }
1669*e4b17023SJohn Marino 
1670*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (df->blocks_to_analyze, 0, bb_index, bi)
1671*e4b17023SJohn Marino     {
1672*e4b17023SJohn Marino       basic_block bb = BASIC_BLOCK (bb_index);
1673*e4b17023SJohn Marino       rtx insn;
1674*e4b17023SJohn Marino       df_ref *ref_rec;
1675*e4b17023SJohn Marino 
1676*e4b17023SJohn Marino       if (include_defs)
1677*e4b17023SJohn Marino 	for (ref_rec = df_get_artificial_defs (bb_index); *ref_rec; ref_rec++)
1678*e4b17023SJohn Marino 	  {
1679*e4b17023SJohn Marino 	    df_ref ref = *ref_rec;
1680*e4b17023SJohn Marino 	    unsigned int regno = DF_REF_REGNO (ref);
1681*e4b17023SJohn Marino 	    if (regno >= start)
1682*e4b17023SJohn Marino 	      {
1683*e4b17023SJohn Marino 		unsigned int id
1684*e4b17023SJohn Marino 		  = ref_info->begin[regno] + ref_info->count[regno]++;
1685*e4b17023SJohn Marino 		DF_REF_ID (ref) = id;
1686*e4b17023SJohn Marino 		ref_info->refs[id] = ref;
1687*e4b17023SJohn Marino 	      }
1688*e4b17023SJohn Marino 	  }
1689*e4b17023SJohn Marino       if (include_uses)
1690*e4b17023SJohn Marino 	for (ref_rec = df_get_artificial_uses (bb_index); *ref_rec; ref_rec++)
1691*e4b17023SJohn Marino 	  {
1692*e4b17023SJohn Marino 	    df_ref ref = *ref_rec;
1693*e4b17023SJohn Marino 	    unsigned int regno = DF_REF_REGNO (ref);
1694*e4b17023SJohn Marino 	    if (regno >= start)
1695*e4b17023SJohn Marino 	      {
1696*e4b17023SJohn Marino 		unsigned int id
1697*e4b17023SJohn Marino 		  = ref_info->begin[regno] + ref_info->count[regno]++;
1698*e4b17023SJohn Marino 		DF_REF_ID (ref) = id;
1699*e4b17023SJohn Marino 		ref_info->refs[id] = ref;
1700*e4b17023SJohn Marino 	      }
1701*e4b17023SJohn Marino 	  }
1702*e4b17023SJohn Marino 
1703*e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
1704*e4b17023SJohn Marino 	{
1705*e4b17023SJohn Marino 	  if (INSN_P (insn))
1706*e4b17023SJohn Marino 	    {
1707*e4b17023SJohn Marino 	      unsigned int uid = INSN_UID (insn);
1708*e4b17023SJohn Marino 
1709*e4b17023SJohn Marino 	      if (include_defs)
1710*e4b17023SJohn Marino 		for (ref_rec = DF_INSN_UID_DEFS (uid); *ref_rec; ref_rec++)
1711*e4b17023SJohn Marino 		  {
1712*e4b17023SJohn Marino 		    df_ref ref = *ref_rec;
1713*e4b17023SJohn Marino 		    unsigned int regno = DF_REF_REGNO (ref);
1714*e4b17023SJohn Marino 		    if (regno >= start)
1715*e4b17023SJohn Marino 		      {
1716*e4b17023SJohn Marino 			unsigned int id
1717*e4b17023SJohn Marino 			  = ref_info->begin[regno] + ref_info->count[regno]++;
1718*e4b17023SJohn Marino 			DF_REF_ID (ref) = id;
1719*e4b17023SJohn Marino 			ref_info->refs[id] = ref;
1720*e4b17023SJohn Marino 		      }
1721*e4b17023SJohn Marino 		  }
1722*e4b17023SJohn Marino 	      if (include_uses)
1723*e4b17023SJohn Marino 		for (ref_rec = DF_INSN_UID_USES (uid); *ref_rec; ref_rec++)
1724*e4b17023SJohn Marino 		  {
1725*e4b17023SJohn Marino 		    df_ref ref = *ref_rec;
1726*e4b17023SJohn Marino 		    unsigned int regno = DF_REF_REGNO (ref);
1727*e4b17023SJohn Marino 		    if (regno >= start)
1728*e4b17023SJohn Marino 		      {
1729*e4b17023SJohn Marino 			unsigned int id
1730*e4b17023SJohn Marino 			  = ref_info->begin[regno] + ref_info->count[regno]++;
1731*e4b17023SJohn Marino 			DF_REF_ID (ref) = id;
1732*e4b17023SJohn Marino 			ref_info->refs[id] = ref;
1733*e4b17023SJohn Marino 		      }
1734*e4b17023SJohn Marino 		  }
1735*e4b17023SJohn Marino 	      if (include_eq_uses)
1736*e4b17023SJohn Marino 		for (ref_rec = DF_INSN_UID_EQ_USES (uid); *ref_rec; ref_rec++)
1737*e4b17023SJohn Marino 		  {
1738*e4b17023SJohn Marino 		    df_ref ref = *ref_rec;
1739*e4b17023SJohn Marino 		    unsigned int regno = DF_REF_REGNO (ref);
1740*e4b17023SJohn Marino 		    if (regno >= start)
1741*e4b17023SJohn Marino 		      {
1742*e4b17023SJohn Marino 			unsigned int id
1743*e4b17023SJohn Marino 			  = ref_info->begin[regno] + ref_info->count[regno]++;
1744*e4b17023SJohn Marino 			DF_REF_ID (ref) = id;
1745*e4b17023SJohn Marino 			ref_info->refs[id] = ref;
1746*e4b17023SJohn Marino 		      }
1747*e4b17023SJohn Marino 		  }
1748*e4b17023SJohn Marino 	    }
1749*e4b17023SJohn Marino 	}
1750*e4b17023SJohn Marino     }
1751*e4b17023SJohn Marino 
1752*e4b17023SJohn Marino   /* The bitmap size is not decremented when refs are deleted.  So
1753*e4b17023SJohn Marino      reset it now that we have squished out all of the empty
1754*e4b17023SJohn Marino      slots.  */
1755*e4b17023SJohn Marino 
1756*e4b17023SJohn Marino   ref_info->table_size = offset;
1757*e4b17023SJohn Marino }
1758*e4b17023SJohn Marino 
1759*e4b17023SJohn Marino /* Take build ref table for either the uses or defs from the reg-use
1760*e4b17023SJohn Marino    or reg-def chains.  */
1761*e4b17023SJohn Marino 
1762*e4b17023SJohn Marino static void
df_reorganize_refs_by_reg(struct df_ref_info * ref_info,bool include_defs,bool include_uses,bool include_eq_uses)1763*e4b17023SJohn Marino df_reorganize_refs_by_reg (struct df_ref_info *ref_info,
1764*e4b17023SJohn Marino 			   bool include_defs,
1765*e4b17023SJohn Marino 			   bool include_uses,
1766*e4b17023SJohn Marino 			   bool include_eq_uses)
1767*e4b17023SJohn Marino {
1768*e4b17023SJohn Marino   if (df->analyze_subset)
1769*e4b17023SJohn Marino     df_reorganize_refs_by_reg_by_insn (ref_info, include_defs,
1770*e4b17023SJohn Marino 				       include_uses, include_eq_uses);
1771*e4b17023SJohn Marino   else
1772*e4b17023SJohn Marino     df_reorganize_refs_by_reg_by_reg (ref_info, include_defs,
1773*e4b17023SJohn Marino 				       include_uses, include_eq_uses);
1774*e4b17023SJohn Marino }
1775*e4b17023SJohn Marino 
1776*e4b17023SJohn Marino 
1777*e4b17023SJohn Marino /* Add the refs in REF_VEC to the table in REF_INFO starting at OFFSET.  */
1778*e4b17023SJohn Marino static unsigned int
df_add_refs_to_table(unsigned int offset,struct df_ref_info * ref_info,df_ref * ref_vec)1779*e4b17023SJohn Marino df_add_refs_to_table (unsigned int offset,
1780*e4b17023SJohn Marino 		      struct df_ref_info *ref_info,
1781*e4b17023SJohn Marino 		      df_ref *ref_vec)
1782*e4b17023SJohn Marino {
1783*e4b17023SJohn Marino   while (*ref_vec)
1784*e4b17023SJohn Marino     {
1785*e4b17023SJohn Marino       df_ref ref = *ref_vec;
1786*e4b17023SJohn Marino       if ((!(df->changeable_flags & DF_NO_HARD_REGS))
1787*e4b17023SJohn Marino 	  || (DF_REF_REGNO (ref) >= FIRST_PSEUDO_REGISTER))
1788*e4b17023SJohn Marino 	{
1789*e4b17023SJohn Marino 	  ref_info->refs[offset] = ref;
1790*e4b17023SJohn Marino 	  DF_REF_ID (*ref_vec) = offset++;
1791*e4b17023SJohn Marino 	}
1792*e4b17023SJohn Marino       ref_vec++;
1793*e4b17023SJohn Marino     }
1794*e4b17023SJohn Marino   return offset;
1795*e4b17023SJohn Marino }
1796*e4b17023SJohn Marino 
1797*e4b17023SJohn Marino 
1798*e4b17023SJohn Marino /* Count the number of refs in all of the insns of BB. Include the
1799*e4b17023SJohn Marino    defs if INCLUDE_DEFS. Include the uses if INCLUDE_USES. Include the
1800*e4b17023SJohn Marino    eq_uses if INCLUDE_EQ_USES.  */
1801*e4b17023SJohn Marino 
1802*e4b17023SJohn Marino static unsigned int
df_reorganize_refs_by_insn_bb(basic_block bb,unsigned int offset,struct df_ref_info * ref_info,bool include_defs,bool include_uses,bool include_eq_uses)1803*e4b17023SJohn Marino df_reorganize_refs_by_insn_bb (basic_block bb, unsigned int offset,
1804*e4b17023SJohn Marino 			       struct df_ref_info *ref_info,
1805*e4b17023SJohn Marino 			       bool include_defs, bool include_uses,
1806*e4b17023SJohn Marino 			       bool include_eq_uses)
1807*e4b17023SJohn Marino {
1808*e4b17023SJohn Marino   rtx insn;
1809*e4b17023SJohn Marino 
1810*e4b17023SJohn Marino   if (include_defs)
1811*e4b17023SJohn Marino     offset = df_add_refs_to_table (offset, ref_info,
1812*e4b17023SJohn Marino 				   df_get_artificial_defs (bb->index));
1813*e4b17023SJohn Marino   if (include_uses)
1814*e4b17023SJohn Marino     offset = df_add_refs_to_table (offset, ref_info,
1815*e4b17023SJohn Marino 				   df_get_artificial_uses (bb->index));
1816*e4b17023SJohn Marino 
1817*e4b17023SJohn Marino   FOR_BB_INSNS (bb, insn)
1818*e4b17023SJohn Marino     if (INSN_P (insn))
1819*e4b17023SJohn Marino       {
1820*e4b17023SJohn Marino 	unsigned int uid = INSN_UID (insn);
1821*e4b17023SJohn Marino 	if (include_defs)
1822*e4b17023SJohn Marino 	  offset = df_add_refs_to_table (offset, ref_info,
1823*e4b17023SJohn Marino 					 DF_INSN_UID_DEFS (uid));
1824*e4b17023SJohn Marino 	if (include_uses)
1825*e4b17023SJohn Marino 	  offset = df_add_refs_to_table (offset, ref_info,
1826*e4b17023SJohn Marino 					 DF_INSN_UID_USES (uid));
1827*e4b17023SJohn Marino 	if (include_eq_uses)
1828*e4b17023SJohn Marino 	  offset = df_add_refs_to_table (offset, ref_info,
1829*e4b17023SJohn Marino 					 DF_INSN_UID_EQ_USES (uid));
1830*e4b17023SJohn Marino       }
1831*e4b17023SJohn Marino   return offset;
1832*e4b17023SJohn Marino }
1833*e4b17023SJohn Marino 
1834*e4b17023SJohn Marino 
1835*e4b17023SJohn Marino /* Organize the refs by insn into the table in REF_INFO.  If
1836*e4b17023SJohn Marino    blocks_to_analyze is defined, use that set, otherwise the entire
1837*e4b17023SJohn Marino    program.  Include the defs if INCLUDE_DEFS. Include the uses if
1838*e4b17023SJohn Marino    INCLUDE_USES. Include the eq_uses if INCLUDE_EQ_USES.  */
1839*e4b17023SJohn Marino 
1840*e4b17023SJohn Marino static void
df_reorganize_refs_by_insn(struct df_ref_info * ref_info,bool include_defs,bool include_uses,bool include_eq_uses)1841*e4b17023SJohn Marino df_reorganize_refs_by_insn (struct df_ref_info *ref_info,
1842*e4b17023SJohn Marino 			    bool include_defs, bool include_uses,
1843*e4b17023SJohn Marino 			    bool include_eq_uses)
1844*e4b17023SJohn Marino {
1845*e4b17023SJohn Marino   basic_block bb;
1846*e4b17023SJohn Marino   unsigned int offset = 0;
1847*e4b17023SJohn Marino 
1848*e4b17023SJohn Marino   ref_info->total_size = df_count_refs (include_defs, include_uses, include_eq_uses);
1849*e4b17023SJohn Marino   df_check_and_grow_ref_info (ref_info, 1);
1850*e4b17023SJohn Marino   if (df->blocks_to_analyze)
1851*e4b17023SJohn Marino     {
1852*e4b17023SJohn Marino       bitmap_iterator bi;
1853*e4b17023SJohn Marino       unsigned int index;
1854*e4b17023SJohn Marino 
1855*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (df->blocks_to_analyze, 0, index, bi)
1856*e4b17023SJohn Marino 	{
1857*e4b17023SJohn Marino 	  offset = df_reorganize_refs_by_insn_bb (BASIC_BLOCK (index), offset, ref_info,
1858*e4b17023SJohn Marino 						  include_defs, include_uses,
1859*e4b17023SJohn Marino 						  include_eq_uses);
1860*e4b17023SJohn Marino 	}
1861*e4b17023SJohn Marino 
1862*e4b17023SJohn Marino       ref_info->table_size = offset;
1863*e4b17023SJohn Marino     }
1864*e4b17023SJohn Marino   else
1865*e4b17023SJohn Marino     {
1866*e4b17023SJohn Marino       FOR_ALL_BB (bb)
1867*e4b17023SJohn Marino 	offset = df_reorganize_refs_by_insn_bb (bb, offset, ref_info,
1868*e4b17023SJohn Marino 						include_defs, include_uses,
1869*e4b17023SJohn Marino 						include_eq_uses);
1870*e4b17023SJohn Marino       ref_info->table_size = offset;
1871*e4b17023SJohn Marino     }
1872*e4b17023SJohn Marino }
1873*e4b17023SJohn Marino 
1874*e4b17023SJohn Marino 
1875*e4b17023SJohn Marino /* If the use refs in DF are not organized, reorganize them.  */
1876*e4b17023SJohn Marino 
1877*e4b17023SJohn Marino void
df_maybe_reorganize_use_refs(enum df_ref_order order)1878*e4b17023SJohn Marino df_maybe_reorganize_use_refs (enum df_ref_order order)
1879*e4b17023SJohn Marino {
1880*e4b17023SJohn Marino   if (order == df->use_info.ref_order)
1881*e4b17023SJohn Marino     return;
1882*e4b17023SJohn Marino 
1883*e4b17023SJohn Marino   switch (order)
1884*e4b17023SJohn Marino     {
1885*e4b17023SJohn Marino     case DF_REF_ORDER_BY_REG:
1886*e4b17023SJohn Marino       df_reorganize_refs_by_reg (&df->use_info, false, true, false);
1887*e4b17023SJohn Marino       break;
1888*e4b17023SJohn Marino 
1889*e4b17023SJohn Marino     case DF_REF_ORDER_BY_REG_WITH_NOTES:
1890*e4b17023SJohn Marino       df_reorganize_refs_by_reg (&df->use_info, false, true, true);
1891*e4b17023SJohn Marino       break;
1892*e4b17023SJohn Marino 
1893*e4b17023SJohn Marino     case DF_REF_ORDER_BY_INSN:
1894*e4b17023SJohn Marino       df_reorganize_refs_by_insn (&df->use_info, false, true, false);
1895*e4b17023SJohn Marino       break;
1896*e4b17023SJohn Marino 
1897*e4b17023SJohn Marino     case DF_REF_ORDER_BY_INSN_WITH_NOTES:
1898*e4b17023SJohn Marino       df_reorganize_refs_by_insn (&df->use_info, false, true, true);
1899*e4b17023SJohn Marino       break;
1900*e4b17023SJohn Marino 
1901*e4b17023SJohn Marino     case DF_REF_ORDER_NO_TABLE:
1902*e4b17023SJohn Marino       free (df->use_info.refs);
1903*e4b17023SJohn Marino       df->use_info.refs = NULL;
1904*e4b17023SJohn Marino       df->use_info.refs_size = 0;
1905*e4b17023SJohn Marino       break;
1906*e4b17023SJohn Marino 
1907*e4b17023SJohn Marino     case DF_REF_ORDER_UNORDERED:
1908*e4b17023SJohn Marino     case DF_REF_ORDER_UNORDERED_WITH_NOTES:
1909*e4b17023SJohn Marino       gcc_unreachable ();
1910*e4b17023SJohn Marino       break;
1911*e4b17023SJohn Marino     }
1912*e4b17023SJohn Marino 
1913*e4b17023SJohn Marino   df->use_info.ref_order = order;
1914*e4b17023SJohn Marino }
1915*e4b17023SJohn Marino 
1916*e4b17023SJohn Marino 
1917*e4b17023SJohn Marino /* If the def refs in DF are not organized, reorganize them.  */
1918*e4b17023SJohn Marino 
1919*e4b17023SJohn Marino void
df_maybe_reorganize_def_refs(enum df_ref_order order)1920*e4b17023SJohn Marino df_maybe_reorganize_def_refs (enum df_ref_order order)
1921*e4b17023SJohn Marino {
1922*e4b17023SJohn Marino   if (order == df->def_info.ref_order)
1923*e4b17023SJohn Marino     return;
1924*e4b17023SJohn Marino 
1925*e4b17023SJohn Marino   switch (order)
1926*e4b17023SJohn Marino     {
1927*e4b17023SJohn Marino     case DF_REF_ORDER_BY_REG:
1928*e4b17023SJohn Marino       df_reorganize_refs_by_reg (&df->def_info, true, false, false);
1929*e4b17023SJohn Marino       break;
1930*e4b17023SJohn Marino 
1931*e4b17023SJohn Marino     case DF_REF_ORDER_BY_INSN:
1932*e4b17023SJohn Marino       df_reorganize_refs_by_insn (&df->def_info, true, false, false);
1933*e4b17023SJohn Marino       break;
1934*e4b17023SJohn Marino 
1935*e4b17023SJohn Marino     case DF_REF_ORDER_NO_TABLE:
1936*e4b17023SJohn Marino       free (df->def_info.refs);
1937*e4b17023SJohn Marino       df->def_info.refs = NULL;
1938*e4b17023SJohn Marino       df->def_info.refs_size = 0;
1939*e4b17023SJohn Marino       break;
1940*e4b17023SJohn Marino 
1941*e4b17023SJohn Marino     case DF_REF_ORDER_BY_INSN_WITH_NOTES:
1942*e4b17023SJohn Marino     case DF_REF_ORDER_BY_REG_WITH_NOTES:
1943*e4b17023SJohn Marino     case DF_REF_ORDER_UNORDERED:
1944*e4b17023SJohn Marino     case DF_REF_ORDER_UNORDERED_WITH_NOTES:
1945*e4b17023SJohn Marino       gcc_unreachable ();
1946*e4b17023SJohn Marino       break;
1947*e4b17023SJohn Marino     }
1948*e4b17023SJohn Marino 
1949*e4b17023SJohn Marino   df->def_info.ref_order = order;
1950*e4b17023SJohn Marino }
1951*e4b17023SJohn Marino 
1952*e4b17023SJohn Marino 
1953*e4b17023SJohn Marino /* Change all of the basic block references in INSN to use the insn's
1954*e4b17023SJohn Marino    current basic block.  This function is called from routines that move
1955*e4b17023SJohn Marino    instructions from one block to another.  */
1956*e4b17023SJohn Marino 
1957*e4b17023SJohn Marino void
df_insn_change_bb(rtx insn,basic_block new_bb)1958*e4b17023SJohn Marino df_insn_change_bb (rtx insn, basic_block new_bb)
1959*e4b17023SJohn Marino {
1960*e4b17023SJohn Marino   basic_block old_bb = BLOCK_FOR_INSN (insn);
1961*e4b17023SJohn Marino   struct df_insn_info *insn_info;
1962*e4b17023SJohn Marino   unsigned int uid = INSN_UID (insn);
1963*e4b17023SJohn Marino 
1964*e4b17023SJohn Marino   if (old_bb == new_bb)
1965*e4b17023SJohn Marino     return;
1966*e4b17023SJohn Marino 
1967*e4b17023SJohn Marino   set_block_for_insn (insn, new_bb);
1968*e4b17023SJohn Marino 
1969*e4b17023SJohn Marino   if (!df)
1970*e4b17023SJohn Marino     return;
1971*e4b17023SJohn Marino 
1972*e4b17023SJohn Marino   if (dump_file)
1973*e4b17023SJohn Marino     fprintf (dump_file, "changing bb of uid %d\n", uid);
1974*e4b17023SJohn Marino 
1975*e4b17023SJohn Marino   insn_info = DF_INSN_UID_SAFE_GET (uid);
1976*e4b17023SJohn Marino   if (insn_info == NULL)
1977*e4b17023SJohn Marino     {
1978*e4b17023SJohn Marino       if (dump_file)
1979*e4b17023SJohn Marino 	fprintf (dump_file, "  unscanned insn\n");
1980*e4b17023SJohn Marino       df_insn_rescan (insn);
1981*e4b17023SJohn Marino       return;
1982*e4b17023SJohn Marino     }
1983*e4b17023SJohn Marino 
1984*e4b17023SJohn Marino   if (!INSN_P (insn))
1985*e4b17023SJohn Marino     return;
1986*e4b17023SJohn Marino 
1987*e4b17023SJohn Marino   df_set_bb_dirty (new_bb);
1988*e4b17023SJohn Marino   if (old_bb)
1989*e4b17023SJohn Marino     {
1990*e4b17023SJohn Marino       if (dump_file)
1991*e4b17023SJohn Marino 	fprintf (dump_file, "  from %d to %d\n",
1992*e4b17023SJohn Marino 		 old_bb->index, new_bb->index);
1993*e4b17023SJohn Marino       df_set_bb_dirty (old_bb);
1994*e4b17023SJohn Marino     }
1995*e4b17023SJohn Marino   else
1996*e4b17023SJohn Marino     if (dump_file)
1997*e4b17023SJohn Marino       fprintf (dump_file, "  to %d\n", new_bb->index);
1998*e4b17023SJohn Marino }
1999*e4b17023SJohn Marino 
2000*e4b17023SJohn Marino 
2001*e4b17023SJohn Marino /* Helper function for df_ref_change_reg_with_loc.  */
2002*e4b17023SJohn Marino 
2003*e4b17023SJohn Marino static void
df_ref_change_reg_with_loc_1(struct df_reg_info * old_df,struct df_reg_info * new_df,int new_regno,rtx loc)2004*e4b17023SJohn Marino df_ref_change_reg_with_loc_1 (struct df_reg_info *old_df,
2005*e4b17023SJohn Marino 			      struct df_reg_info *new_df,
2006*e4b17023SJohn Marino 			      int new_regno, rtx loc)
2007*e4b17023SJohn Marino {
2008*e4b17023SJohn Marino   df_ref the_ref = old_df->reg_chain;
2009*e4b17023SJohn Marino 
2010*e4b17023SJohn Marino   while (the_ref)
2011*e4b17023SJohn Marino     {
2012*e4b17023SJohn Marino       if ((!DF_REF_IS_ARTIFICIAL (the_ref))
2013*e4b17023SJohn Marino 	  && DF_REF_LOC (the_ref)
2014*e4b17023SJohn Marino 	  && (*DF_REF_LOC (the_ref) == loc))
2015*e4b17023SJohn Marino 	{
2016*e4b17023SJohn Marino 	  df_ref next_ref = DF_REF_NEXT_REG (the_ref);
2017*e4b17023SJohn Marino 	  df_ref prev_ref = DF_REF_PREV_REG (the_ref);
2018*e4b17023SJohn Marino 	  df_ref *ref_vec, *ref_vec_t;
2019*e4b17023SJohn Marino 	  struct df_insn_info *insn_info = DF_REF_INSN_INFO (the_ref);
2020*e4b17023SJohn Marino 	  unsigned int count = 0;
2021*e4b17023SJohn Marino 
2022*e4b17023SJohn Marino 	  DF_REF_REGNO (the_ref) = new_regno;
2023*e4b17023SJohn Marino 	  DF_REF_REG (the_ref) = regno_reg_rtx[new_regno];
2024*e4b17023SJohn Marino 
2025*e4b17023SJohn Marino 	  /* Pull the_ref out of the old regno chain.  */
2026*e4b17023SJohn Marino 	  if (prev_ref)
2027*e4b17023SJohn Marino 	    DF_REF_NEXT_REG (prev_ref) = next_ref;
2028*e4b17023SJohn Marino 	  else
2029*e4b17023SJohn Marino 	    old_df->reg_chain = next_ref;
2030*e4b17023SJohn Marino 	  if (next_ref)
2031*e4b17023SJohn Marino 	    DF_REF_PREV_REG (next_ref) = prev_ref;
2032*e4b17023SJohn Marino 	  old_df->n_refs--;
2033*e4b17023SJohn Marino 
2034*e4b17023SJohn Marino 	  /* Put the ref into the new regno chain.  */
2035*e4b17023SJohn Marino 	  DF_REF_PREV_REG (the_ref) = NULL;
2036*e4b17023SJohn Marino 	  DF_REF_NEXT_REG (the_ref) = new_df->reg_chain;
2037*e4b17023SJohn Marino 	  if (new_df->reg_chain)
2038*e4b17023SJohn Marino 	    DF_REF_PREV_REG (new_df->reg_chain) = the_ref;
2039*e4b17023SJohn Marino 	  new_df->reg_chain = the_ref;
2040*e4b17023SJohn Marino 	  new_df->n_refs++;
2041*e4b17023SJohn Marino 	  if (DF_REF_BB (the_ref))
2042*e4b17023SJohn Marino 	    df_set_bb_dirty (DF_REF_BB (the_ref));
2043*e4b17023SJohn Marino 
2044*e4b17023SJohn Marino 	  /* Need to sort the record again that the ref was in because
2045*e4b17023SJohn Marino 	     the regno is a sorting key.  First, find the right
2046*e4b17023SJohn Marino 	     record.  */
2047*e4b17023SJohn Marino 	  if (DF_REF_FLAGS (the_ref) & DF_REF_IN_NOTE)
2048*e4b17023SJohn Marino 	    ref_vec = insn_info->eq_uses;
2049*e4b17023SJohn Marino 	  else
2050*e4b17023SJohn Marino 	    ref_vec = insn_info->uses;
2051*e4b17023SJohn Marino 	  if (dump_file)
2052*e4b17023SJohn Marino 	    fprintf (dump_file, "changing reg in insn %d\n",
2053*e4b17023SJohn Marino 		     DF_REF_INSN_UID (the_ref));
2054*e4b17023SJohn Marino 
2055*e4b17023SJohn Marino 	  ref_vec_t = ref_vec;
2056*e4b17023SJohn Marino 
2057*e4b17023SJohn Marino 	  /* Find the length.  */
2058*e4b17023SJohn Marino 	  while (*ref_vec_t)
2059*e4b17023SJohn Marino 	    {
2060*e4b17023SJohn Marino 	      count++;
2061*e4b17023SJohn Marino 	      ref_vec_t++;
2062*e4b17023SJohn Marino 	    }
2063*e4b17023SJohn Marino 	  qsort (ref_vec, count, sizeof (df_ref ), df_ref_compare);
2064*e4b17023SJohn Marino 
2065*e4b17023SJohn Marino 	  the_ref = next_ref;
2066*e4b17023SJohn Marino 	}
2067*e4b17023SJohn Marino       else
2068*e4b17023SJohn Marino 	the_ref = DF_REF_NEXT_REG (the_ref);
2069*e4b17023SJohn Marino     }
2070*e4b17023SJohn Marino }
2071*e4b17023SJohn Marino 
2072*e4b17023SJohn Marino 
2073*e4b17023SJohn Marino /* Change the regno of all refs that contained LOC from OLD_REGNO to
2074*e4b17023SJohn Marino    NEW_REGNO.  Refs that do not match LOC are not changed which means
2075*e4b17023SJohn Marino    that artificial refs are not changed since they have no loc.  This
2076*e4b17023SJohn Marino    call is to support the SET_REGNO macro. */
2077*e4b17023SJohn Marino 
2078*e4b17023SJohn Marino void
df_ref_change_reg_with_loc(int old_regno,int new_regno,rtx loc)2079*e4b17023SJohn Marino df_ref_change_reg_with_loc (int old_regno, int new_regno, rtx loc)
2080*e4b17023SJohn Marino {
2081*e4b17023SJohn Marino   if ((!df) || (old_regno == -1) || (old_regno == new_regno))
2082*e4b17023SJohn Marino     return;
2083*e4b17023SJohn Marino 
2084*e4b17023SJohn Marino   df_grow_reg_info ();
2085*e4b17023SJohn Marino 
2086*e4b17023SJohn Marino   df_ref_change_reg_with_loc_1 (DF_REG_DEF_GET (old_regno),
2087*e4b17023SJohn Marino 				DF_REG_DEF_GET (new_regno), new_regno, loc);
2088*e4b17023SJohn Marino   df_ref_change_reg_with_loc_1 (DF_REG_USE_GET (old_regno),
2089*e4b17023SJohn Marino 				DF_REG_USE_GET (new_regno), new_regno, loc);
2090*e4b17023SJohn Marino   df_ref_change_reg_with_loc_1 (DF_REG_EQ_USE_GET (old_regno),
2091*e4b17023SJohn Marino 				DF_REG_EQ_USE_GET (new_regno), new_regno, loc);
2092*e4b17023SJohn Marino }
2093*e4b17023SJohn Marino 
2094*e4b17023SJohn Marino 
2095*e4b17023SJohn Marino /* Delete the mw_hardregs that point into the eq_notes.  */
2096*e4b17023SJohn Marino 
2097*e4b17023SJohn Marino static unsigned int
df_mw_hardreg_chain_delete_eq_uses(struct df_insn_info * insn_info)2098*e4b17023SJohn Marino df_mw_hardreg_chain_delete_eq_uses (struct df_insn_info *insn_info)
2099*e4b17023SJohn Marino {
2100*e4b17023SJohn Marino   struct df_mw_hardreg **mw_vec = insn_info->mw_hardregs;
2101*e4b17023SJohn Marino   unsigned int deleted = 0;
2102*e4b17023SJohn Marino   unsigned int count = 0;
2103*e4b17023SJohn Marino   struct df_scan_problem_data *problem_data
2104*e4b17023SJohn Marino     = (struct df_scan_problem_data *) df_scan->problem_data;
2105*e4b17023SJohn Marino 
2106*e4b17023SJohn Marino   if (!*mw_vec)
2107*e4b17023SJohn Marino     return 0;
2108*e4b17023SJohn Marino 
2109*e4b17023SJohn Marino   while (*mw_vec)
2110*e4b17023SJohn Marino     {
2111*e4b17023SJohn Marino       if ((*mw_vec)->flags & DF_REF_IN_NOTE)
2112*e4b17023SJohn Marino 	{
2113*e4b17023SJohn Marino 	  struct df_mw_hardreg **temp_vec = mw_vec;
2114*e4b17023SJohn Marino 
2115*e4b17023SJohn Marino 	  pool_free (problem_data->mw_reg_pool, *mw_vec);
2116*e4b17023SJohn Marino 	  temp_vec = mw_vec;
2117*e4b17023SJohn Marino 	  /* Shove the remaining ones down one to fill the gap.  While
2118*e4b17023SJohn Marino 	     this looks n**2, it is highly unusual to have any mw regs
2119*e4b17023SJohn Marino 	     in eq_notes and the chances of more than one are almost
2120*e4b17023SJohn Marino 	     non existent.  */
2121*e4b17023SJohn Marino 	  while (*temp_vec)
2122*e4b17023SJohn Marino 	    {
2123*e4b17023SJohn Marino 	      *temp_vec = *(temp_vec + 1);
2124*e4b17023SJohn Marino 	      temp_vec++;
2125*e4b17023SJohn Marino 	    }
2126*e4b17023SJohn Marino 	  deleted++;
2127*e4b17023SJohn Marino 	}
2128*e4b17023SJohn Marino       else
2129*e4b17023SJohn Marino 	{
2130*e4b17023SJohn Marino 	  mw_vec++;
2131*e4b17023SJohn Marino 	  count++;
2132*e4b17023SJohn Marino 	}
2133*e4b17023SJohn Marino     }
2134*e4b17023SJohn Marino 
2135*e4b17023SJohn Marino   if (count == 0)
2136*e4b17023SJohn Marino     {
2137*e4b17023SJohn Marino       df_scan_free_mws_vec (insn_info->mw_hardregs);
2138*e4b17023SJohn Marino       insn_info->mw_hardregs = df_null_mw_rec;
2139*e4b17023SJohn Marino       return 0;
2140*e4b17023SJohn Marino     }
2141*e4b17023SJohn Marino   return deleted;
2142*e4b17023SJohn Marino }
2143*e4b17023SJohn Marino 
2144*e4b17023SJohn Marino 
2145*e4b17023SJohn Marino /* Rescan only the REG_EQUIV/REG_EQUAL notes part of INSN.  */
2146*e4b17023SJohn Marino 
2147*e4b17023SJohn Marino void
df_notes_rescan(rtx insn)2148*e4b17023SJohn Marino df_notes_rescan (rtx insn)
2149*e4b17023SJohn Marino {
2150*e4b17023SJohn Marino   struct df_insn_info *insn_info;
2151*e4b17023SJohn Marino   unsigned int uid = INSN_UID (insn);
2152*e4b17023SJohn Marino 
2153*e4b17023SJohn Marino   if (!df)
2154*e4b17023SJohn Marino     return;
2155*e4b17023SJohn Marino 
2156*e4b17023SJohn Marino   /* The client has disabled rescanning and plans to do it itself.  */
2157*e4b17023SJohn Marino   if (df->changeable_flags & DF_NO_INSN_RESCAN)
2158*e4b17023SJohn Marino     return;
2159*e4b17023SJohn Marino 
2160*e4b17023SJohn Marino   /* Do nothing if the insn hasn't been emitted yet.  */
2161*e4b17023SJohn Marino   if (!BLOCK_FOR_INSN (insn))
2162*e4b17023SJohn Marino     return;
2163*e4b17023SJohn Marino 
2164*e4b17023SJohn Marino   df_grow_bb_info (df_scan);
2165*e4b17023SJohn Marino   df_grow_reg_info ();
2166*e4b17023SJohn Marino 
2167*e4b17023SJohn Marino   insn_info = DF_INSN_UID_SAFE_GET (INSN_UID(insn));
2168*e4b17023SJohn Marino 
2169*e4b17023SJohn Marino   /* The client has deferred rescanning.  */
2170*e4b17023SJohn Marino   if (df->changeable_flags & DF_DEFER_INSN_RESCAN)
2171*e4b17023SJohn Marino     {
2172*e4b17023SJohn Marino       if (!insn_info)
2173*e4b17023SJohn Marino 	{
2174*e4b17023SJohn Marino 	  insn_info = df_insn_create_insn_record (insn);
2175*e4b17023SJohn Marino 	  insn_info->defs = df_null_ref_rec;
2176*e4b17023SJohn Marino 	  insn_info->uses = df_null_ref_rec;
2177*e4b17023SJohn Marino 	  insn_info->eq_uses = df_null_ref_rec;
2178*e4b17023SJohn Marino 	  insn_info->mw_hardregs = df_null_mw_rec;
2179*e4b17023SJohn Marino 	}
2180*e4b17023SJohn Marino 
2181*e4b17023SJohn Marino       bitmap_clear_bit (&df->insns_to_delete, uid);
2182*e4b17023SJohn Marino       /* If the insn is set to be rescanned, it does not need to also
2183*e4b17023SJohn Marino 	 be notes rescanned.  */
2184*e4b17023SJohn Marino       if (!bitmap_bit_p (&df->insns_to_rescan, uid))
2185*e4b17023SJohn Marino 	bitmap_set_bit (&df->insns_to_notes_rescan, INSN_UID (insn));
2186*e4b17023SJohn Marino       return;
2187*e4b17023SJohn Marino     }
2188*e4b17023SJohn Marino 
2189*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_delete, uid);
2190*e4b17023SJohn Marino   bitmap_clear_bit (&df->insns_to_notes_rescan, uid);
2191*e4b17023SJohn Marino 
2192*e4b17023SJohn Marino   if (insn_info)
2193*e4b17023SJohn Marino     {
2194*e4b17023SJohn Marino       basic_block bb = BLOCK_FOR_INSN (insn);
2195*e4b17023SJohn Marino       rtx note;
2196*e4b17023SJohn Marino       struct df_collection_rec collection_rec;
2197*e4b17023SJohn Marino       unsigned int num_deleted;
2198*e4b17023SJohn Marino       unsigned int mw_len;
2199*e4b17023SJohn Marino 
2200*e4b17023SJohn Marino       memset (&collection_rec, 0, sizeof (struct df_collection_rec));
2201*e4b17023SJohn Marino       collection_rec.eq_use_vec = VEC_alloc (df_ref, stack, 32);
2202*e4b17023SJohn Marino       collection_rec.mw_vec = VEC_alloc (df_mw_hardreg_ptr, stack, 32);
2203*e4b17023SJohn Marino 
2204*e4b17023SJohn Marino       num_deleted = df_mw_hardreg_chain_delete_eq_uses (insn_info);
2205*e4b17023SJohn Marino       df_ref_chain_delete (insn_info->eq_uses);
2206*e4b17023SJohn Marino       insn_info->eq_uses = NULL;
2207*e4b17023SJohn Marino 
2208*e4b17023SJohn Marino       /* Process REG_EQUIV/REG_EQUAL notes */
2209*e4b17023SJohn Marino       for (note = REG_NOTES (insn); note;
2210*e4b17023SJohn Marino 	   note = XEXP (note, 1))
2211*e4b17023SJohn Marino 	{
2212*e4b17023SJohn Marino 	  switch (REG_NOTE_KIND (note))
2213*e4b17023SJohn Marino 	    {
2214*e4b17023SJohn Marino 	    case REG_EQUIV:
2215*e4b17023SJohn Marino 	    case REG_EQUAL:
2216*e4b17023SJohn Marino 	      df_uses_record (&collection_rec,
2217*e4b17023SJohn Marino 			      &XEXP (note, 0), DF_REF_REG_USE,
2218*e4b17023SJohn Marino 			      bb, insn_info, DF_REF_IN_NOTE);
2219*e4b17023SJohn Marino 	    default:
2220*e4b17023SJohn Marino 	      break;
2221*e4b17023SJohn Marino 	    }
2222*e4b17023SJohn Marino 	}
2223*e4b17023SJohn Marino 
2224*e4b17023SJohn Marino       /* Find some place to put any new mw_hardregs.  */
2225*e4b17023SJohn Marino       df_canonize_collection_rec (&collection_rec);
2226*e4b17023SJohn Marino       mw_len = VEC_length (df_mw_hardreg_ptr, collection_rec.mw_vec);
2227*e4b17023SJohn Marino       if (mw_len)
2228*e4b17023SJohn Marino 	{
2229*e4b17023SJohn Marino 	  unsigned int count = 0;
2230*e4b17023SJohn Marino 	  struct df_mw_hardreg **mw_rec = insn_info->mw_hardregs;
2231*e4b17023SJohn Marino 	  while (*mw_rec)
2232*e4b17023SJohn Marino 	    {
2233*e4b17023SJohn Marino 	      count++;
2234*e4b17023SJohn Marino 	      mw_rec++;
2235*e4b17023SJohn Marino 	    }
2236*e4b17023SJohn Marino 
2237*e4b17023SJohn Marino 	  if (count)
2238*e4b17023SJohn Marino 	    {
2239*e4b17023SJohn Marino 	      /* Append to the end of the existing record after
2240*e4b17023SJohn Marino 		 expanding it if necessary.  */
2241*e4b17023SJohn Marino 	      if (mw_len > num_deleted)
2242*e4b17023SJohn Marino 		{
2243*e4b17023SJohn Marino 		  insn_info->mw_hardregs =
2244*e4b17023SJohn Marino 		    XRESIZEVEC (struct df_mw_hardreg *,
2245*e4b17023SJohn Marino 				insn_info->mw_hardregs,
2246*e4b17023SJohn Marino 				count + 1 + mw_len);
2247*e4b17023SJohn Marino 		}
2248*e4b17023SJohn Marino 	      memcpy (&insn_info->mw_hardregs[count],
2249*e4b17023SJohn Marino 		      VEC_address (df_mw_hardreg_ptr, collection_rec.mw_vec),
2250*e4b17023SJohn Marino 		      mw_len * sizeof (struct df_mw_hardreg *));
2251*e4b17023SJohn Marino 	      insn_info->mw_hardregs[count + mw_len] = NULL;
2252*e4b17023SJohn Marino 	      qsort (insn_info->mw_hardregs, count + mw_len,
2253*e4b17023SJohn Marino 		     sizeof (struct df_mw_hardreg *), df_mw_compare);
2254*e4b17023SJohn Marino 	    }
2255*e4b17023SJohn Marino 	  else
2256*e4b17023SJohn Marino 	    {
2257*e4b17023SJohn Marino 	      /* No vector there. */
2258*e4b17023SJohn Marino 	      insn_info->mw_hardregs
2259*e4b17023SJohn Marino 		= XNEWVEC (struct df_mw_hardreg*, 1 + mw_len);
2260*e4b17023SJohn Marino 	      memcpy (insn_info->mw_hardregs,
2261*e4b17023SJohn Marino 		      VEC_address (df_mw_hardreg_ptr, collection_rec.mw_vec),
2262*e4b17023SJohn Marino 		      mw_len * sizeof (struct df_mw_hardreg *));
2263*e4b17023SJohn Marino 	      insn_info->mw_hardregs[mw_len] = NULL;
2264*e4b17023SJohn Marino 	    }
2265*e4b17023SJohn Marino 	}
2266*e4b17023SJohn Marino       /* Get rid of the mw_rec so that df_refs_add_to_chains will
2267*e4b17023SJohn Marino 	 ignore it.  */
2268*e4b17023SJohn Marino       VEC_free (df_mw_hardreg_ptr, stack, collection_rec.mw_vec);
2269*e4b17023SJohn Marino       df_refs_add_to_chains (&collection_rec, bb, insn);
2270*e4b17023SJohn Marino       VEC_free (df_ref, stack, collection_rec.eq_use_vec);
2271*e4b17023SJohn Marino     }
2272*e4b17023SJohn Marino   else
2273*e4b17023SJohn Marino     df_insn_rescan (insn);
2274*e4b17023SJohn Marino 
2275*e4b17023SJohn Marino }
2276*e4b17023SJohn Marino 
2277*e4b17023SJohn Marino 
2278*e4b17023SJohn Marino /*----------------------------------------------------------------------------
2279*e4b17023SJohn Marino    Hard core instruction scanning code.  No external interfaces here,
2280*e4b17023SJohn Marino    just a lot of routines that look inside insns.
2281*e4b17023SJohn Marino ----------------------------------------------------------------------------*/
2282*e4b17023SJohn Marino 
2283*e4b17023SJohn Marino 
2284*e4b17023SJohn Marino /* Return true if the contents of two df_ref's are identical.
2285*e4b17023SJohn Marino    It ignores DF_REF_MARKER.  */
2286*e4b17023SJohn Marino 
2287*e4b17023SJohn Marino static bool
df_ref_equal_p(df_ref ref1,df_ref ref2)2288*e4b17023SJohn Marino df_ref_equal_p (df_ref ref1, df_ref ref2)
2289*e4b17023SJohn Marino {
2290*e4b17023SJohn Marino   if (!ref2)
2291*e4b17023SJohn Marino     return false;
2292*e4b17023SJohn Marino 
2293*e4b17023SJohn Marino   if (ref1 == ref2)
2294*e4b17023SJohn Marino     return true;
2295*e4b17023SJohn Marino 
2296*e4b17023SJohn Marino   if (DF_REF_CLASS (ref1) != DF_REF_CLASS (ref2)
2297*e4b17023SJohn Marino       || DF_REF_REGNO (ref1) != DF_REF_REGNO (ref2)
2298*e4b17023SJohn Marino       || DF_REF_REG (ref1) != DF_REF_REG (ref2)
2299*e4b17023SJohn Marino       || DF_REF_TYPE (ref1) != DF_REF_TYPE (ref2)
2300*e4b17023SJohn Marino       || ((DF_REF_FLAGS (ref1) & ~(DF_REF_REG_MARKER + DF_REF_MW_HARDREG))
2301*e4b17023SJohn Marino 	  != (DF_REF_FLAGS (ref2) & ~(DF_REF_REG_MARKER + DF_REF_MW_HARDREG)))
2302*e4b17023SJohn Marino       || DF_REF_BB (ref1) != DF_REF_BB (ref2)
2303*e4b17023SJohn Marino       || DF_REF_INSN_INFO (ref1) != DF_REF_INSN_INFO (ref2))
2304*e4b17023SJohn Marino     return false;
2305*e4b17023SJohn Marino 
2306*e4b17023SJohn Marino   switch (DF_REF_CLASS (ref1))
2307*e4b17023SJohn Marino     {
2308*e4b17023SJohn Marino     case DF_REF_ARTIFICIAL:
2309*e4b17023SJohn Marino     case DF_REF_BASE:
2310*e4b17023SJohn Marino       return true;
2311*e4b17023SJohn Marino 
2312*e4b17023SJohn Marino     case DF_REF_REGULAR:
2313*e4b17023SJohn Marino       return DF_REF_LOC (ref1) == DF_REF_LOC (ref2);
2314*e4b17023SJohn Marino 
2315*e4b17023SJohn Marino     default:
2316*e4b17023SJohn Marino       gcc_unreachable ();
2317*e4b17023SJohn Marino     }
2318*e4b17023SJohn Marino   return false;
2319*e4b17023SJohn Marino }
2320*e4b17023SJohn Marino 
2321*e4b17023SJohn Marino 
2322*e4b17023SJohn Marino /* Compare REF1 and REF2 for sorting.  This is only called from places
2323*e4b17023SJohn Marino    where all of the refs are of the same type, in the same insn, and
2324*e4b17023SJohn Marino    have the same bb.  So these fields are not checked.  */
2325*e4b17023SJohn Marino 
2326*e4b17023SJohn Marino static int
df_ref_compare(const void * r1,const void * r2)2327*e4b17023SJohn Marino df_ref_compare (const void *r1, const void *r2)
2328*e4b17023SJohn Marino {
2329*e4b17023SJohn Marino   const df_ref ref1 = *(const df_ref *)r1;
2330*e4b17023SJohn Marino   const df_ref ref2 = *(const df_ref *)r2;
2331*e4b17023SJohn Marino 
2332*e4b17023SJohn Marino   if (ref1 == ref2)
2333*e4b17023SJohn Marino     return 0;
2334*e4b17023SJohn Marino 
2335*e4b17023SJohn Marino   if (DF_REF_CLASS (ref1) != DF_REF_CLASS (ref2))
2336*e4b17023SJohn Marino     return (int)DF_REF_CLASS (ref1) - (int)DF_REF_CLASS (ref2);
2337*e4b17023SJohn Marino 
2338*e4b17023SJohn Marino   if (DF_REF_REGNO (ref1) != DF_REF_REGNO (ref2))
2339*e4b17023SJohn Marino     return (int)DF_REF_REGNO (ref1) - (int)DF_REF_REGNO (ref2);
2340*e4b17023SJohn Marino 
2341*e4b17023SJohn Marino   if (DF_REF_TYPE (ref1) != DF_REF_TYPE (ref2))
2342*e4b17023SJohn Marino     return (int)DF_REF_TYPE (ref1) - (int)DF_REF_TYPE (ref2);
2343*e4b17023SJohn Marino 
2344*e4b17023SJohn Marino   if (DF_REF_REG (ref1) != DF_REF_REG (ref2))
2345*e4b17023SJohn Marino     return (int)DF_REF_ORDER (ref1) - (int)DF_REF_ORDER (ref2);
2346*e4b17023SJohn Marino 
2347*e4b17023SJohn Marino   /* Cannot look at the LOC field on artificial refs.  */
2348*e4b17023SJohn Marino   if (DF_REF_CLASS (ref1) != DF_REF_ARTIFICIAL
2349*e4b17023SJohn Marino       && DF_REF_LOC (ref1) != DF_REF_LOC (ref2))
2350*e4b17023SJohn Marino     return (int)DF_REF_ORDER (ref1) - (int)DF_REF_ORDER (ref2);
2351*e4b17023SJohn Marino 
2352*e4b17023SJohn Marino   if (DF_REF_FLAGS (ref1) != DF_REF_FLAGS (ref2))
2353*e4b17023SJohn Marino     {
2354*e4b17023SJohn Marino       /* If two refs are identical except that one of them has is from
2355*e4b17023SJohn Marino 	 a mw and one is not, we need to have the one with the mw
2356*e4b17023SJohn Marino 	 first.  */
2357*e4b17023SJohn Marino       if (DF_REF_FLAGS_IS_SET (ref1, DF_REF_MW_HARDREG) ==
2358*e4b17023SJohn Marino 	  DF_REF_FLAGS_IS_SET (ref2, DF_REF_MW_HARDREG))
2359*e4b17023SJohn Marino 	return DF_REF_FLAGS (ref1) - DF_REF_FLAGS (ref2);
2360*e4b17023SJohn Marino       else if (DF_REF_FLAGS_IS_SET (ref1, DF_REF_MW_HARDREG))
2361*e4b17023SJohn Marino 	return -1;
2362*e4b17023SJohn Marino       else
2363*e4b17023SJohn Marino 	return 1;
2364*e4b17023SJohn Marino     }
2365*e4b17023SJohn Marino 
2366*e4b17023SJohn Marino   return (int)DF_REF_ORDER (ref1) - (int)DF_REF_ORDER (ref2);
2367*e4b17023SJohn Marino }
2368*e4b17023SJohn Marino 
2369*e4b17023SJohn Marino static void
df_swap_refs(VEC (df_ref,stack)** ref_vec,int i,int j)2370*e4b17023SJohn Marino df_swap_refs (VEC(df_ref,stack) **ref_vec, int i, int j)
2371*e4b17023SJohn Marino {
2372*e4b17023SJohn Marino   df_ref tmp = VEC_index (df_ref, *ref_vec, i);
2373*e4b17023SJohn Marino   VEC_replace (df_ref, *ref_vec, i, VEC_index (df_ref, *ref_vec, j));
2374*e4b17023SJohn Marino   VEC_replace (df_ref, *ref_vec, j, tmp);
2375*e4b17023SJohn Marino }
2376*e4b17023SJohn Marino 
2377*e4b17023SJohn Marino /* Sort and compress a set of refs.  */
2378*e4b17023SJohn Marino 
2379*e4b17023SJohn Marino static void
df_sort_and_compress_refs(VEC (df_ref,stack)** ref_vec)2380*e4b17023SJohn Marino df_sort_and_compress_refs (VEC(df_ref,stack) **ref_vec)
2381*e4b17023SJohn Marino {
2382*e4b17023SJohn Marino   unsigned int count;
2383*e4b17023SJohn Marino   unsigned int i;
2384*e4b17023SJohn Marino   unsigned int dist = 0;
2385*e4b17023SJohn Marino 
2386*e4b17023SJohn Marino   count = VEC_length (df_ref, *ref_vec);
2387*e4b17023SJohn Marino 
2388*e4b17023SJohn Marino   /* If there are 1 or 0 elements, there is nothing to do.  */
2389*e4b17023SJohn Marino   if (count < 2)
2390*e4b17023SJohn Marino     return;
2391*e4b17023SJohn Marino   else if (count == 2)
2392*e4b17023SJohn Marino     {
2393*e4b17023SJohn Marino       df_ref r0 = VEC_index (df_ref, *ref_vec, 0);
2394*e4b17023SJohn Marino       df_ref r1 = VEC_index (df_ref, *ref_vec, 1);
2395*e4b17023SJohn Marino       if (df_ref_compare (&r0, &r1) > 0)
2396*e4b17023SJohn Marino         df_swap_refs (ref_vec, 0, 1);
2397*e4b17023SJohn Marino     }
2398*e4b17023SJohn Marino   else
2399*e4b17023SJohn Marino     {
2400*e4b17023SJohn Marino       for (i = 0; i < count - 1; i++)
2401*e4b17023SJohn Marino 	{
2402*e4b17023SJohn Marino 	  df_ref r0 = VEC_index (df_ref, *ref_vec, i);
2403*e4b17023SJohn Marino 	  df_ref r1 = VEC_index (df_ref, *ref_vec, i + 1);
2404*e4b17023SJohn Marino 	  if (df_ref_compare (&r0, &r1) >= 0)
2405*e4b17023SJohn Marino 	    break;
2406*e4b17023SJohn Marino 	}
2407*e4b17023SJohn Marino       /* If the array is already strictly ordered,
2408*e4b17023SJohn Marino          which is the most common case for large COUNT case
2409*e4b17023SJohn Marino          (which happens for CALL INSNs),
2410*e4b17023SJohn Marino          no need to sort and filter out duplicate.
2411*e4b17023SJohn Marino          Simply return the count.
2412*e4b17023SJohn Marino          Make sure DF_GET_ADD_REFS adds refs in the increasing order
2413*e4b17023SJohn Marino          of DF_REF_COMPARE.  */
2414*e4b17023SJohn Marino       if (i == count - 1)
2415*e4b17023SJohn Marino         return;
2416*e4b17023SJohn Marino       VEC_qsort (df_ref, *ref_vec, df_ref_compare);
2417*e4b17023SJohn Marino     }
2418*e4b17023SJohn Marino 
2419*e4b17023SJohn Marino   for (i=0; i<count-dist; i++)
2420*e4b17023SJohn Marino     {
2421*e4b17023SJohn Marino       /* Find the next ref that is not equal to the current ref.  */
2422*e4b17023SJohn Marino       while (i + dist + 1 < count
2423*e4b17023SJohn Marino 	     && df_ref_equal_p (VEC_index (df_ref, *ref_vec, i),
2424*e4b17023SJohn Marino 				VEC_index (df_ref, *ref_vec, i + dist + 1)))
2425*e4b17023SJohn Marino 	{
2426*e4b17023SJohn Marino 	  df_free_ref (VEC_index (df_ref, *ref_vec, i + dist + 1));
2427*e4b17023SJohn Marino 	  dist++;
2428*e4b17023SJohn Marino 	}
2429*e4b17023SJohn Marino       /* Copy it down to the next position.  */
2430*e4b17023SJohn Marino       if (dist && i + dist + 1 < count)
2431*e4b17023SJohn Marino 	VEC_replace (df_ref, *ref_vec, i + 1,
2432*e4b17023SJohn Marino 		     VEC_index (df_ref, *ref_vec, i + dist + 1));
2433*e4b17023SJohn Marino     }
2434*e4b17023SJohn Marino 
2435*e4b17023SJohn Marino   count -= dist;
2436*e4b17023SJohn Marino   VEC_truncate (df_ref, *ref_vec, count);
2437*e4b17023SJohn Marino }
2438*e4b17023SJohn Marino 
2439*e4b17023SJohn Marino 
2440*e4b17023SJohn Marino /* Return true if the contents of two df_ref's are identical.
2441*e4b17023SJohn Marino    It ignores DF_REF_MARKER.  */
2442*e4b17023SJohn Marino 
2443*e4b17023SJohn Marino static bool
df_mw_equal_p(struct df_mw_hardreg * mw1,struct df_mw_hardreg * mw2)2444*e4b17023SJohn Marino df_mw_equal_p (struct df_mw_hardreg *mw1, struct df_mw_hardreg *mw2)
2445*e4b17023SJohn Marino {
2446*e4b17023SJohn Marino   if (!mw2)
2447*e4b17023SJohn Marino     return false;
2448*e4b17023SJohn Marino   return (mw1 == mw2) ||
2449*e4b17023SJohn Marino     (mw1->mw_reg == mw2->mw_reg
2450*e4b17023SJohn Marino      && mw1->type == mw2->type
2451*e4b17023SJohn Marino      && mw1->flags == mw2->flags
2452*e4b17023SJohn Marino      && mw1->start_regno == mw2->start_regno
2453*e4b17023SJohn Marino      && mw1->end_regno == mw2->end_regno);
2454*e4b17023SJohn Marino }
2455*e4b17023SJohn Marino 
2456*e4b17023SJohn Marino 
2457*e4b17023SJohn Marino /* Compare MW1 and MW2 for sorting.  */
2458*e4b17023SJohn Marino 
2459*e4b17023SJohn Marino static int
df_mw_compare(const void * m1,const void * m2)2460*e4b17023SJohn Marino df_mw_compare (const void *m1, const void *m2)
2461*e4b17023SJohn Marino {
2462*e4b17023SJohn Marino   const struct df_mw_hardreg *const mw1 = *(const struct df_mw_hardreg *const*)m1;
2463*e4b17023SJohn Marino   const struct df_mw_hardreg *const mw2 = *(const struct df_mw_hardreg *const*)m2;
2464*e4b17023SJohn Marino 
2465*e4b17023SJohn Marino   if (mw1 == mw2)
2466*e4b17023SJohn Marino     return 0;
2467*e4b17023SJohn Marino 
2468*e4b17023SJohn Marino   if (mw1->type != mw2->type)
2469*e4b17023SJohn Marino     return mw1->type - mw2->type;
2470*e4b17023SJohn Marino 
2471*e4b17023SJohn Marino   if (mw1->flags != mw2->flags)
2472*e4b17023SJohn Marino     return mw1->flags - mw2->flags;
2473*e4b17023SJohn Marino 
2474*e4b17023SJohn Marino   if (mw1->start_regno != mw2->start_regno)
2475*e4b17023SJohn Marino     return mw1->start_regno - mw2->start_regno;
2476*e4b17023SJohn Marino 
2477*e4b17023SJohn Marino   if (mw1->end_regno != mw2->end_regno)
2478*e4b17023SJohn Marino     return mw1->end_regno - mw2->end_regno;
2479*e4b17023SJohn Marino 
2480*e4b17023SJohn Marino   if (mw1->mw_reg != mw2->mw_reg)
2481*e4b17023SJohn Marino     return mw1->mw_order - mw2->mw_order;
2482*e4b17023SJohn Marino 
2483*e4b17023SJohn Marino   return 0;
2484*e4b17023SJohn Marino }
2485*e4b17023SJohn Marino 
2486*e4b17023SJohn Marino 
2487*e4b17023SJohn Marino /* Sort and compress a set of refs.  */
2488*e4b17023SJohn Marino 
2489*e4b17023SJohn Marino static void
df_sort_and_compress_mws(VEC (df_mw_hardreg_ptr,stack)** mw_vec)2490*e4b17023SJohn Marino df_sort_and_compress_mws (VEC(df_mw_hardreg_ptr,stack) **mw_vec)
2491*e4b17023SJohn Marino {
2492*e4b17023SJohn Marino   unsigned int count;
2493*e4b17023SJohn Marino   struct df_scan_problem_data *problem_data
2494*e4b17023SJohn Marino     = (struct df_scan_problem_data *) df_scan->problem_data;
2495*e4b17023SJohn Marino   unsigned int i;
2496*e4b17023SJohn Marino   unsigned int dist = 0;
2497*e4b17023SJohn Marino 
2498*e4b17023SJohn Marino   count = VEC_length (df_mw_hardreg_ptr, *mw_vec);
2499*e4b17023SJohn Marino   if (count < 2)
2500*e4b17023SJohn Marino     return;
2501*e4b17023SJohn Marino   else if (count == 2)
2502*e4b17023SJohn Marino     {
2503*e4b17023SJohn Marino       struct df_mw_hardreg *m0 = VEC_index (df_mw_hardreg_ptr, *mw_vec, 0);
2504*e4b17023SJohn Marino       struct df_mw_hardreg *m1 = VEC_index (df_mw_hardreg_ptr, *mw_vec, 1);
2505*e4b17023SJohn Marino       if (df_mw_compare (&m0, &m1) > 0)
2506*e4b17023SJohn Marino         {
2507*e4b17023SJohn Marino           struct df_mw_hardreg *tmp = VEC_index (df_mw_hardreg_ptr,
2508*e4b17023SJohn Marino 						 *mw_vec, 0);
2509*e4b17023SJohn Marino 	  VEC_replace (df_mw_hardreg_ptr, *mw_vec, 0,
2510*e4b17023SJohn Marino 		       VEC_index (df_mw_hardreg_ptr, *mw_vec, 1));
2511*e4b17023SJohn Marino 	  VEC_replace (df_mw_hardreg_ptr, *mw_vec, 1, tmp);
2512*e4b17023SJohn Marino         }
2513*e4b17023SJohn Marino     }
2514*e4b17023SJohn Marino   else
2515*e4b17023SJohn Marino     VEC_qsort (df_mw_hardreg_ptr, *mw_vec, df_mw_compare);
2516*e4b17023SJohn Marino 
2517*e4b17023SJohn Marino   for (i=0; i<count-dist; i++)
2518*e4b17023SJohn Marino     {
2519*e4b17023SJohn Marino       /* Find the next ref that is not equal to the current ref.  */
2520*e4b17023SJohn Marino       while (i + dist + 1 < count
2521*e4b17023SJohn Marino 	     && df_mw_equal_p (VEC_index (df_mw_hardreg_ptr, *mw_vec, i),
2522*e4b17023SJohn Marino 			       VEC_index (df_mw_hardreg_ptr, *mw_vec,
2523*e4b17023SJohn Marino 					  i + dist + 1)))
2524*e4b17023SJohn Marino 	{
2525*e4b17023SJohn Marino 	  pool_free (problem_data->mw_reg_pool,
2526*e4b17023SJohn Marino 		     VEC_index (df_mw_hardreg_ptr, *mw_vec, i + dist + 1));
2527*e4b17023SJohn Marino 	  dist++;
2528*e4b17023SJohn Marino 	}
2529*e4b17023SJohn Marino       /* Copy it down to the next position.  */
2530*e4b17023SJohn Marino       if (dist && i + dist + 1 < count)
2531*e4b17023SJohn Marino 	VEC_replace (df_mw_hardreg_ptr, *mw_vec, i + 1,
2532*e4b17023SJohn Marino 		     VEC_index (df_mw_hardreg_ptr, *mw_vec, i + dist + 1));
2533*e4b17023SJohn Marino     }
2534*e4b17023SJohn Marino 
2535*e4b17023SJohn Marino   count -= dist;
2536*e4b17023SJohn Marino   VEC_truncate (df_mw_hardreg_ptr, *mw_vec, count);
2537*e4b17023SJohn Marino }
2538*e4b17023SJohn Marino 
2539*e4b17023SJohn Marino 
2540*e4b17023SJohn Marino /* Sort and remove duplicates from the COLLECTION_REC.  */
2541*e4b17023SJohn Marino 
2542*e4b17023SJohn Marino static void
df_canonize_collection_rec(struct df_collection_rec * collection_rec)2543*e4b17023SJohn Marino df_canonize_collection_rec (struct df_collection_rec *collection_rec)
2544*e4b17023SJohn Marino {
2545*e4b17023SJohn Marino   df_sort_and_compress_refs (&collection_rec->def_vec);
2546*e4b17023SJohn Marino   df_sort_and_compress_refs (&collection_rec->use_vec);
2547*e4b17023SJohn Marino   df_sort_and_compress_refs (&collection_rec->eq_use_vec);
2548*e4b17023SJohn Marino   df_sort_and_compress_mws (&collection_rec->mw_vec);
2549*e4b17023SJohn Marino }
2550*e4b17023SJohn Marino 
2551*e4b17023SJohn Marino 
2552*e4b17023SJohn Marino /* Add the new df_ref to appropriate reg_info/ref_info chains.  */
2553*e4b17023SJohn Marino 
2554*e4b17023SJohn Marino static void
df_install_ref(df_ref this_ref,struct df_reg_info * reg_info,struct df_ref_info * ref_info,bool add_to_table)2555*e4b17023SJohn Marino df_install_ref (df_ref this_ref,
2556*e4b17023SJohn Marino 		struct df_reg_info *reg_info,
2557*e4b17023SJohn Marino 		struct df_ref_info *ref_info,
2558*e4b17023SJohn Marino 		bool add_to_table)
2559*e4b17023SJohn Marino {
2560*e4b17023SJohn Marino   unsigned int regno = DF_REF_REGNO (this_ref);
2561*e4b17023SJohn Marino   /* Add the ref to the reg_{def,use,eq_use} chain.  */
2562*e4b17023SJohn Marino   df_ref head = reg_info->reg_chain;
2563*e4b17023SJohn Marino 
2564*e4b17023SJohn Marino   reg_info->reg_chain = this_ref;
2565*e4b17023SJohn Marino   reg_info->n_refs++;
2566*e4b17023SJohn Marino 
2567*e4b17023SJohn Marino   if (DF_REF_FLAGS_IS_SET (this_ref, DF_HARD_REG_LIVE))
2568*e4b17023SJohn Marino     {
2569*e4b17023SJohn Marino       gcc_assert (regno < FIRST_PSEUDO_REGISTER);
2570*e4b17023SJohn Marino       df->hard_regs_live_count[regno]++;
2571*e4b17023SJohn Marino     }
2572*e4b17023SJohn Marino 
2573*e4b17023SJohn Marino   gcc_checking_assert (DF_REF_NEXT_REG (this_ref) == NULL
2574*e4b17023SJohn Marino 		       && DF_REF_PREV_REG (this_ref) == NULL);
2575*e4b17023SJohn Marino 
2576*e4b17023SJohn Marino   DF_REF_NEXT_REG (this_ref) = head;
2577*e4b17023SJohn Marino 
2578*e4b17023SJohn Marino   /* We cannot actually link to the head of the chain.  */
2579*e4b17023SJohn Marino   DF_REF_PREV_REG (this_ref) = NULL;
2580*e4b17023SJohn Marino 
2581*e4b17023SJohn Marino   if (head)
2582*e4b17023SJohn Marino     DF_REF_PREV_REG (head) = this_ref;
2583*e4b17023SJohn Marino 
2584*e4b17023SJohn Marino   if (add_to_table)
2585*e4b17023SJohn Marino     {
2586*e4b17023SJohn Marino       gcc_assert (ref_info->ref_order != DF_REF_ORDER_NO_TABLE);
2587*e4b17023SJohn Marino       df_check_and_grow_ref_info (ref_info, 1);
2588*e4b17023SJohn Marino       DF_REF_ID (this_ref) = ref_info->table_size;
2589*e4b17023SJohn Marino       /* Add the ref to the big array of defs.  */
2590*e4b17023SJohn Marino       ref_info->refs[ref_info->table_size] = this_ref;
2591*e4b17023SJohn Marino       ref_info->table_size++;
2592*e4b17023SJohn Marino     }
2593*e4b17023SJohn Marino   else
2594*e4b17023SJohn Marino     DF_REF_ID (this_ref) = -1;
2595*e4b17023SJohn Marino 
2596*e4b17023SJohn Marino   ref_info->total_size++;
2597*e4b17023SJohn Marino }
2598*e4b17023SJohn Marino 
2599*e4b17023SJohn Marino 
2600*e4b17023SJohn Marino /* This function takes one of the groups of refs (defs, uses or
2601*e4b17023SJohn Marino    eq_uses) and installs the entire group into the insn.  It also adds
2602*e4b17023SJohn Marino    each of these refs into the appropriate chains.  */
2603*e4b17023SJohn Marino 
2604*e4b17023SJohn Marino static df_ref *
df_install_refs(basic_block bb,VEC (df_ref,stack)* old_vec,struct df_reg_info ** reg_info,struct df_ref_info * ref_info,bool is_notes)2605*e4b17023SJohn Marino df_install_refs (basic_block bb,
2606*e4b17023SJohn Marino 		 VEC(df_ref,stack)* old_vec,
2607*e4b17023SJohn Marino 		 struct df_reg_info **reg_info,
2608*e4b17023SJohn Marino 		 struct df_ref_info *ref_info,
2609*e4b17023SJohn Marino 		 bool is_notes)
2610*e4b17023SJohn Marino {
2611*e4b17023SJohn Marino   unsigned int count;
2612*e4b17023SJohn Marino 
2613*e4b17023SJohn Marino   count = VEC_length (df_ref, old_vec);
2614*e4b17023SJohn Marino   if (count)
2615*e4b17023SJohn Marino     {
2616*e4b17023SJohn Marino       df_ref *new_vec = XNEWVEC (df_ref, count + 1);
2617*e4b17023SJohn Marino       bool add_to_table;
2618*e4b17023SJohn Marino       df_ref this_ref;
2619*e4b17023SJohn Marino       unsigned int ix;
2620*e4b17023SJohn Marino 
2621*e4b17023SJohn Marino       switch (ref_info->ref_order)
2622*e4b17023SJohn Marino 	{
2623*e4b17023SJohn Marino 	case DF_REF_ORDER_UNORDERED_WITH_NOTES:
2624*e4b17023SJohn Marino 	case DF_REF_ORDER_BY_REG_WITH_NOTES:
2625*e4b17023SJohn Marino 	case DF_REF_ORDER_BY_INSN_WITH_NOTES:
2626*e4b17023SJohn Marino 	  ref_info->ref_order = DF_REF_ORDER_UNORDERED_WITH_NOTES;
2627*e4b17023SJohn Marino 	  add_to_table = true;
2628*e4b17023SJohn Marino 	  break;
2629*e4b17023SJohn Marino 	case DF_REF_ORDER_UNORDERED:
2630*e4b17023SJohn Marino 	case DF_REF_ORDER_BY_REG:
2631*e4b17023SJohn Marino 	case DF_REF_ORDER_BY_INSN:
2632*e4b17023SJohn Marino 	  ref_info->ref_order = DF_REF_ORDER_UNORDERED;
2633*e4b17023SJohn Marino 	  add_to_table = !is_notes;
2634*e4b17023SJohn Marino 	  break;
2635*e4b17023SJohn Marino 	default:
2636*e4b17023SJohn Marino 	  add_to_table = false;
2637*e4b17023SJohn Marino 	  break;
2638*e4b17023SJohn Marino 	}
2639*e4b17023SJohn Marino 
2640*e4b17023SJohn Marino       /* Do not add if ref is not in the right blocks.  */
2641*e4b17023SJohn Marino       if (add_to_table && df->analyze_subset)
2642*e4b17023SJohn Marino 	add_to_table = bitmap_bit_p (df->blocks_to_analyze, bb->index);
2643*e4b17023SJohn Marino 
2644*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (df_ref, old_vec, ix, this_ref)
2645*e4b17023SJohn Marino 	{
2646*e4b17023SJohn Marino 	  new_vec[ix] = this_ref;
2647*e4b17023SJohn Marino 	  df_install_ref (this_ref, reg_info[DF_REF_REGNO (this_ref)],
2648*e4b17023SJohn Marino 			  ref_info, add_to_table);
2649*e4b17023SJohn Marino 	}
2650*e4b17023SJohn Marino 
2651*e4b17023SJohn Marino       new_vec[count] = NULL;
2652*e4b17023SJohn Marino       return new_vec;
2653*e4b17023SJohn Marino     }
2654*e4b17023SJohn Marino   else
2655*e4b17023SJohn Marino     return df_null_ref_rec;
2656*e4b17023SJohn Marino }
2657*e4b17023SJohn Marino 
2658*e4b17023SJohn Marino 
2659*e4b17023SJohn Marino /* This function takes the mws installs the entire group into the
2660*e4b17023SJohn Marino    insn.  */
2661*e4b17023SJohn Marino 
2662*e4b17023SJohn Marino static struct df_mw_hardreg **
df_install_mws(VEC (df_mw_hardreg_ptr,stack)* old_vec)2663*e4b17023SJohn Marino df_install_mws (VEC(df_mw_hardreg_ptr,stack) *old_vec)
2664*e4b17023SJohn Marino {
2665*e4b17023SJohn Marino   unsigned int count;
2666*e4b17023SJohn Marino 
2667*e4b17023SJohn Marino   count = VEC_length (df_mw_hardreg_ptr, old_vec);
2668*e4b17023SJohn Marino   if (count)
2669*e4b17023SJohn Marino     {
2670*e4b17023SJohn Marino       struct df_mw_hardreg **new_vec
2671*e4b17023SJohn Marino 	= XNEWVEC (struct df_mw_hardreg*, count + 1);
2672*e4b17023SJohn Marino       memcpy (new_vec, VEC_address (df_mw_hardreg_ptr, old_vec),
2673*e4b17023SJohn Marino 	      sizeof (struct df_mw_hardreg*) * count);
2674*e4b17023SJohn Marino       new_vec[count] = NULL;
2675*e4b17023SJohn Marino       return new_vec;
2676*e4b17023SJohn Marino     }
2677*e4b17023SJohn Marino   else
2678*e4b17023SJohn Marino     return df_null_mw_rec;
2679*e4b17023SJohn Marino }
2680*e4b17023SJohn Marino 
2681*e4b17023SJohn Marino 
2682*e4b17023SJohn Marino /* Add a chain of df_refs to appropriate ref chain/reg_info/ref_info
2683*e4b17023SJohn Marino    chains and update other necessary information.  */
2684*e4b17023SJohn Marino 
2685*e4b17023SJohn Marino static void
df_refs_add_to_chains(struct df_collection_rec * collection_rec,basic_block bb,rtx insn)2686*e4b17023SJohn Marino df_refs_add_to_chains (struct df_collection_rec *collection_rec,
2687*e4b17023SJohn Marino 		       basic_block bb, rtx insn)
2688*e4b17023SJohn Marino {
2689*e4b17023SJohn Marino   if (insn)
2690*e4b17023SJohn Marino     {
2691*e4b17023SJohn Marino       struct df_insn_info *insn_rec = DF_INSN_INFO_GET (insn);
2692*e4b17023SJohn Marino       /* If there is a vector in the collection rec, add it to the
2693*e4b17023SJohn Marino 	 insn.  A null rec is a signal that the caller will handle the
2694*e4b17023SJohn Marino 	 chain specially.  */
2695*e4b17023SJohn Marino       if (collection_rec->def_vec)
2696*e4b17023SJohn Marino 	{
2697*e4b17023SJohn Marino 	  df_scan_free_ref_vec (insn_rec->defs);
2698*e4b17023SJohn Marino 	  insn_rec->defs
2699*e4b17023SJohn Marino 	    = df_install_refs (bb, collection_rec->def_vec,
2700*e4b17023SJohn Marino 			       df->def_regs,
2701*e4b17023SJohn Marino 			       &df->def_info, false);
2702*e4b17023SJohn Marino 	}
2703*e4b17023SJohn Marino       if (collection_rec->use_vec)
2704*e4b17023SJohn Marino 	{
2705*e4b17023SJohn Marino 	  df_scan_free_ref_vec (insn_rec->uses);
2706*e4b17023SJohn Marino 	  insn_rec->uses
2707*e4b17023SJohn Marino 	    = df_install_refs (bb, collection_rec->use_vec,
2708*e4b17023SJohn Marino 			       df->use_regs,
2709*e4b17023SJohn Marino 			       &df->use_info, false);
2710*e4b17023SJohn Marino 	}
2711*e4b17023SJohn Marino       if (collection_rec->eq_use_vec)
2712*e4b17023SJohn Marino 	{
2713*e4b17023SJohn Marino 	  df_scan_free_ref_vec (insn_rec->eq_uses);
2714*e4b17023SJohn Marino 	  insn_rec->eq_uses
2715*e4b17023SJohn Marino 	    = df_install_refs (bb, collection_rec->eq_use_vec,
2716*e4b17023SJohn Marino 			       df->eq_use_regs,
2717*e4b17023SJohn Marino 			       &df->use_info, true);
2718*e4b17023SJohn Marino 	}
2719*e4b17023SJohn Marino       if (collection_rec->mw_vec)
2720*e4b17023SJohn Marino 	{
2721*e4b17023SJohn Marino 	  df_scan_free_mws_vec (insn_rec->mw_hardregs);
2722*e4b17023SJohn Marino 	  insn_rec->mw_hardregs
2723*e4b17023SJohn Marino 	    = df_install_mws (collection_rec->mw_vec);
2724*e4b17023SJohn Marino 	}
2725*e4b17023SJohn Marino     }
2726*e4b17023SJohn Marino   else
2727*e4b17023SJohn Marino     {
2728*e4b17023SJohn Marino       struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb->index);
2729*e4b17023SJohn Marino 
2730*e4b17023SJohn Marino       df_scan_free_ref_vec (bb_info->artificial_defs);
2731*e4b17023SJohn Marino       bb_info->artificial_defs
2732*e4b17023SJohn Marino 	= df_install_refs (bb, collection_rec->def_vec,
2733*e4b17023SJohn Marino 			   df->def_regs,
2734*e4b17023SJohn Marino 			   &df->def_info, false);
2735*e4b17023SJohn Marino       df_scan_free_ref_vec (bb_info->artificial_uses);
2736*e4b17023SJohn Marino       bb_info->artificial_uses
2737*e4b17023SJohn Marino 	= df_install_refs (bb, collection_rec->use_vec,
2738*e4b17023SJohn Marino 			   df->use_regs,
2739*e4b17023SJohn Marino 			   &df->use_info, false);
2740*e4b17023SJohn Marino     }
2741*e4b17023SJohn Marino }
2742*e4b17023SJohn Marino 
2743*e4b17023SJohn Marino 
2744*e4b17023SJohn Marino /* Allocate a ref and initialize its fields.  */
2745*e4b17023SJohn Marino 
2746*e4b17023SJohn Marino static df_ref
df_ref_create_structure(enum df_ref_class cl,struct df_collection_rec * collection_rec,rtx reg,rtx * loc,basic_block bb,struct df_insn_info * info,enum df_ref_type ref_type,int ref_flags)2747*e4b17023SJohn Marino df_ref_create_structure (enum df_ref_class cl,
2748*e4b17023SJohn Marino 			 struct df_collection_rec *collection_rec,
2749*e4b17023SJohn Marino 			 rtx reg, rtx *loc,
2750*e4b17023SJohn Marino 			 basic_block bb, struct df_insn_info *info,
2751*e4b17023SJohn Marino 			 enum df_ref_type ref_type,
2752*e4b17023SJohn Marino 			 int ref_flags)
2753*e4b17023SJohn Marino {
2754*e4b17023SJohn Marino   df_ref this_ref = NULL;
2755*e4b17023SJohn Marino   int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
2756*e4b17023SJohn Marino   struct df_scan_problem_data *problem_data
2757*e4b17023SJohn Marino     = (struct df_scan_problem_data *) df_scan->problem_data;
2758*e4b17023SJohn Marino 
2759*e4b17023SJohn Marino   switch (cl)
2760*e4b17023SJohn Marino     {
2761*e4b17023SJohn Marino     case DF_REF_BASE:
2762*e4b17023SJohn Marino       this_ref = (df_ref) pool_alloc (problem_data->ref_base_pool);
2763*e4b17023SJohn Marino       gcc_checking_assert (loc == NULL);
2764*e4b17023SJohn Marino       break;
2765*e4b17023SJohn Marino 
2766*e4b17023SJohn Marino     case DF_REF_ARTIFICIAL:
2767*e4b17023SJohn Marino       this_ref = (df_ref) pool_alloc (problem_data->ref_artificial_pool);
2768*e4b17023SJohn Marino       this_ref->artificial_ref.bb = bb;
2769*e4b17023SJohn Marino       gcc_checking_assert (loc == NULL);
2770*e4b17023SJohn Marino       break;
2771*e4b17023SJohn Marino 
2772*e4b17023SJohn Marino     case DF_REF_REGULAR:
2773*e4b17023SJohn Marino       this_ref = (df_ref) pool_alloc (problem_data->ref_regular_pool);
2774*e4b17023SJohn Marino       this_ref->regular_ref.loc = loc;
2775*e4b17023SJohn Marino       gcc_checking_assert (loc);
2776*e4b17023SJohn Marino       break;
2777*e4b17023SJohn Marino     }
2778*e4b17023SJohn Marino 
2779*e4b17023SJohn Marino   DF_REF_CLASS (this_ref) = cl;
2780*e4b17023SJohn Marino   DF_REF_ID (this_ref) = -1;
2781*e4b17023SJohn Marino   DF_REF_REG (this_ref) = reg;
2782*e4b17023SJohn Marino   DF_REF_REGNO (this_ref) =  regno;
2783*e4b17023SJohn Marino   DF_REF_TYPE (this_ref) = ref_type;
2784*e4b17023SJohn Marino   DF_REF_INSN_INFO (this_ref) = info;
2785*e4b17023SJohn Marino   DF_REF_CHAIN (this_ref) = NULL;
2786*e4b17023SJohn Marino   DF_REF_FLAGS (this_ref) = ref_flags;
2787*e4b17023SJohn Marino   DF_REF_NEXT_REG (this_ref) = NULL;
2788*e4b17023SJohn Marino   DF_REF_PREV_REG (this_ref) = NULL;
2789*e4b17023SJohn Marino   DF_REF_ORDER (this_ref) = df->ref_order++;
2790*e4b17023SJohn Marino 
2791*e4b17023SJohn Marino   /* We need to clear this bit because fwprop, and in the future
2792*e4b17023SJohn Marino      possibly other optimizations sometimes create new refs using ond
2793*e4b17023SJohn Marino      refs as the model.  */
2794*e4b17023SJohn Marino   DF_REF_FLAGS_CLEAR (this_ref, DF_HARD_REG_LIVE);
2795*e4b17023SJohn Marino 
2796*e4b17023SJohn Marino   /* See if this ref needs to have DF_HARD_REG_LIVE bit set.  */
2797*e4b17023SJohn Marino   if (regno < FIRST_PSEUDO_REGISTER
2798*e4b17023SJohn Marino       && !DF_REF_IS_ARTIFICIAL (this_ref)
2799*e4b17023SJohn Marino       && !DEBUG_INSN_P (DF_REF_INSN (this_ref)))
2800*e4b17023SJohn Marino     {
2801*e4b17023SJohn Marino       if (DF_REF_REG_DEF_P (this_ref))
2802*e4b17023SJohn Marino 	{
2803*e4b17023SJohn Marino 	  if (!DF_REF_FLAGS_IS_SET (this_ref, DF_REF_MAY_CLOBBER))
2804*e4b17023SJohn Marino 	    DF_REF_FLAGS_SET (this_ref, DF_HARD_REG_LIVE);
2805*e4b17023SJohn Marino 	}
2806*e4b17023SJohn Marino       else if (!(TEST_HARD_REG_BIT (elim_reg_set, regno)
2807*e4b17023SJohn Marino 		 && (regno == FRAME_POINTER_REGNUM
2808*e4b17023SJohn Marino 		     || regno == ARG_POINTER_REGNUM)))
2809*e4b17023SJohn Marino 	DF_REF_FLAGS_SET (this_ref, DF_HARD_REG_LIVE);
2810*e4b17023SJohn Marino     }
2811*e4b17023SJohn Marino 
2812*e4b17023SJohn Marino   if (collection_rec)
2813*e4b17023SJohn Marino     {
2814*e4b17023SJohn Marino       if (DF_REF_REG_DEF_P (this_ref))
2815*e4b17023SJohn Marino 	VEC_safe_push (df_ref, stack, collection_rec->def_vec, this_ref);
2816*e4b17023SJohn Marino       else if (DF_REF_FLAGS (this_ref) & DF_REF_IN_NOTE)
2817*e4b17023SJohn Marino 	VEC_safe_push (df_ref, stack, collection_rec->eq_use_vec, this_ref);
2818*e4b17023SJohn Marino       else
2819*e4b17023SJohn Marino 	VEC_safe_push (df_ref, stack, collection_rec->use_vec, this_ref);
2820*e4b17023SJohn Marino     }
2821*e4b17023SJohn Marino   else
2822*e4b17023SJohn Marino     df_install_ref_incremental (this_ref);
2823*e4b17023SJohn Marino 
2824*e4b17023SJohn Marino   return this_ref;
2825*e4b17023SJohn Marino }
2826*e4b17023SJohn Marino 
2827*e4b17023SJohn Marino 
2828*e4b17023SJohn Marino /* Create new references of type DF_REF_TYPE for each part of register REG
2829*e4b17023SJohn Marino    at address LOC within INSN of BB.  */
2830*e4b17023SJohn Marino 
2831*e4b17023SJohn Marino 
2832*e4b17023SJohn Marino static void
df_ref_record(enum df_ref_class cl,struct df_collection_rec * collection_rec,rtx reg,rtx * loc,basic_block bb,struct df_insn_info * insn_info,enum df_ref_type ref_type,int ref_flags)2833*e4b17023SJohn Marino df_ref_record (enum df_ref_class cl,
2834*e4b17023SJohn Marino 	       struct df_collection_rec *collection_rec,
2835*e4b17023SJohn Marino                rtx reg, rtx *loc,
2836*e4b17023SJohn Marino 	       basic_block bb, struct df_insn_info *insn_info,
2837*e4b17023SJohn Marino 	       enum df_ref_type ref_type,
2838*e4b17023SJohn Marino 	       int ref_flags)
2839*e4b17023SJohn Marino {
2840*e4b17023SJohn Marino   unsigned int regno;
2841*e4b17023SJohn Marino 
2842*e4b17023SJohn Marino   gcc_checking_assert (REG_P (reg) || GET_CODE (reg) == SUBREG);
2843*e4b17023SJohn Marino 
2844*e4b17023SJohn Marino   regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
2845*e4b17023SJohn Marino   if (regno < FIRST_PSEUDO_REGISTER)
2846*e4b17023SJohn Marino     {
2847*e4b17023SJohn Marino       struct df_mw_hardreg *hardreg = NULL;
2848*e4b17023SJohn Marino       struct df_scan_problem_data *problem_data
2849*e4b17023SJohn Marino         = (struct df_scan_problem_data *) df_scan->problem_data;
2850*e4b17023SJohn Marino       unsigned int i;
2851*e4b17023SJohn Marino       unsigned int endregno;
2852*e4b17023SJohn Marino       df_ref ref;
2853*e4b17023SJohn Marino 
2854*e4b17023SJohn Marino       if (GET_CODE (reg) == SUBREG)
2855*e4b17023SJohn Marino 	{
2856*e4b17023SJohn Marino 	  regno += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
2857*e4b17023SJohn Marino 					SUBREG_BYTE (reg), GET_MODE (reg));
2858*e4b17023SJohn Marino 	  endregno = regno + subreg_nregs (reg);
2859*e4b17023SJohn Marino 	}
2860*e4b17023SJohn Marino       else
2861*e4b17023SJohn Marino 	endregno = END_HARD_REGNO (reg);
2862*e4b17023SJohn Marino 
2863*e4b17023SJohn Marino       /*  If this is a multiword hardreg, we create some extra
2864*e4b17023SJohn Marino 	  datastructures that will enable us to easily build REG_DEAD
2865*e4b17023SJohn Marino 	  and REG_UNUSED notes.  */
2866*e4b17023SJohn Marino       if (collection_rec
2867*e4b17023SJohn Marino 	  && (endregno != regno + 1) && insn_info)
2868*e4b17023SJohn Marino 	{
2869*e4b17023SJohn Marino 	  /* Sets to a subreg of a multiword register are partial.
2870*e4b17023SJohn Marino 	     Sets to a non-subreg of a multiword register are not.  */
2871*e4b17023SJohn Marino 	  if (GET_CODE (reg) == SUBREG)
2872*e4b17023SJohn Marino 	    ref_flags |= DF_REF_PARTIAL;
2873*e4b17023SJohn Marino 	  ref_flags |= DF_REF_MW_HARDREG;
2874*e4b17023SJohn Marino 
2875*e4b17023SJohn Marino 	  hardreg = (struct df_mw_hardreg *) pool_alloc (problem_data->mw_reg_pool);
2876*e4b17023SJohn Marino 	  hardreg->type = ref_type;
2877*e4b17023SJohn Marino 	  hardreg->flags = ref_flags;
2878*e4b17023SJohn Marino 	  hardreg->mw_reg = reg;
2879*e4b17023SJohn Marino 	  hardreg->start_regno = regno;
2880*e4b17023SJohn Marino 	  hardreg->end_regno = endregno - 1;
2881*e4b17023SJohn Marino 	  hardreg->mw_order = df->ref_order++;
2882*e4b17023SJohn Marino 	  VEC_safe_push (df_mw_hardreg_ptr, stack, collection_rec->mw_vec,
2883*e4b17023SJohn Marino 			 hardreg);
2884*e4b17023SJohn Marino 	}
2885*e4b17023SJohn Marino 
2886*e4b17023SJohn Marino       for (i = regno; i < endregno; i++)
2887*e4b17023SJohn Marino 	{
2888*e4b17023SJohn Marino 	  ref = df_ref_create_structure (cl, collection_rec, regno_reg_rtx[i], loc,
2889*e4b17023SJohn Marino 					 bb, insn_info, ref_type, ref_flags);
2890*e4b17023SJohn Marino 
2891*e4b17023SJohn Marino           gcc_assert (ORIGINAL_REGNO (DF_REF_REG (ref)) == i);
2892*e4b17023SJohn Marino 	}
2893*e4b17023SJohn Marino     }
2894*e4b17023SJohn Marino   else
2895*e4b17023SJohn Marino     {
2896*e4b17023SJohn Marino       df_ref_create_structure (cl, collection_rec, reg, loc, bb, insn_info,
2897*e4b17023SJohn Marino 			       ref_type, ref_flags);
2898*e4b17023SJohn Marino     }
2899*e4b17023SJohn Marino }
2900*e4b17023SJohn Marino 
2901*e4b17023SJohn Marino 
2902*e4b17023SJohn Marino /* A set to a non-paradoxical SUBREG for which the number of word_mode units
2903*e4b17023SJohn Marino    covered by the outer mode is smaller than that covered by the inner mode,
2904*e4b17023SJohn Marino    is a read-modify-write operation.
2905*e4b17023SJohn Marino    This function returns true iff the SUBREG X is such a SUBREG.  */
2906*e4b17023SJohn Marino 
2907*e4b17023SJohn Marino bool
df_read_modify_subreg_p(rtx x)2908*e4b17023SJohn Marino df_read_modify_subreg_p (rtx x)
2909*e4b17023SJohn Marino {
2910*e4b17023SJohn Marino   unsigned int isize, osize;
2911*e4b17023SJohn Marino   if (GET_CODE (x) != SUBREG)
2912*e4b17023SJohn Marino     return false;
2913*e4b17023SJohn Marino   isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
2914*e4b17023SJohn Marino   osize = GET_MODE_SIZE (GET_MODE (x));
2915*e4b17023SJohn Marino   return isize > osize
2916*e4b17023SJohn Marino 	 && isize > REGMODE_NATURAL_SIZE (GET_MODE (SUBREG_REG (x)));
2917*e4b17023SJohn Marino }
2918*e4b17023SJohn Marino 
2919*e4b17023SJohn Marino 
2920*e4b17023SJohn Marino /* Process all the registers defined in the rtx, X.
2921*e4b17023SJohn Marino    Autoincrement/decrement definitions will be picked up by
2922*e4b17023SJohn Marino    df_uses_record.  */
2923*e4b17023SJohn Marino 
2924*e4b17023SJohn Marino static void
df_def_record_1(struct df_collection_rec * collection_rec,rtx x,basic_block bb,struct df_insn_info * insn_info,int flags)2925*e4b17023SJohn Marino df_def_record_1 (struct df_collection_rec *collection_rec,
2926*e4b17023SJohn Marino                  rtx x, basic_block bb, struct df_insn_info *insn_info,
2927*e4b17023SJohn Marino 		 int flags)
2928*e4b17023SJohn Marino {
2929*e4b17023SJohn Marino   rtx *loc;
2930*e4b17023SJohn Marino   rtx dst;
2931*e4b17023SJohn Marino 
2932*e4b17023SJohn Marino  /* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL
2933*e4b17023SJohn Marino      construct.  */
2934*e4b17023SJohn Marino   if (GET_CODE (x) == EXPR_LIST || GET_CODE (x) == CLOBBER)
2935*e4b17023SJohn Marino     loc = &XEXP (x, 0);
2936*e4b17023SJohn Marino   else
2937*e4b17023SJohn Marino     loc = &SET_DEST (x);
2938*e4b17023SJohn Marino   dst = *loc;
2939*e4b17023SJohn Marino 
2940*e4b17023SJohn Marino   /* It is legal to have a set destination be a parallel. */
2941*e4b17023SJohn Marino   if (GET_CODE (dst) == PARALLEL)
2942*e4b17023SJohn Marino     {
2943*e4b17023SJohn Marino       int i;
2944*e4b17023SJohn Marino 
2945*e4b17023SJohn Marino       for (i = XVECLEN (dst, 0) - 1; i >= 0; i--)
2946*e4b17023SJohn Marino 	{
2947*e4b17023SJohn Marino 	  rtx temp = XVECEXP (dst, 0, i);
2948*e4b17023SJohn Marino 	  if (GET_CODE (temp) == EXPR_LIST || GET_CODE (temp) == CLOBBER
2949*e4b17023SJohn Marino 	      || GET_CODE (temp) == SET)
2950*e4b17023SJohn Marino 	    df_def_record_1 (collection_rec,
2951*e4b17023SJohn Marino                              temp, bb, insn_info,
2952*e4b17023SJohn Marino 			     GET_CODE (temp) == CLOBBER
2953*e4b17023SJohn Marino 			     ? flags | DF_REF_MUST_CLOBBER : flags);
2954*e4b17023SJohn Marino 	}
2955*e4b17023SJohn Marino       return;
2956*e4b17023SJohn Marino     }
2957*e4b17023SJohn Marino 
2958*e4b17023SJohn Marino   if (GET_CODE (dst) == STRICT_LOW_PART)
2959*e4b17023SJohn Marino     {
2960*e4b17023SJohn Marino       flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL | DF_REF_STRICT_LOW_PART;
2961*e4b17023SJohn Marino 
2962*e4b17023SJohn Marino       loc = &XEXP (dst, 0);
2963*e4b17023SJohn Marino       dst = *loc;
2964*e4b17023SJohn Marino     }
2965*e4b17023SJohn Marino 
2966*e4b17023SJohn Marino   if (GET_CODE (dst) == ZERO_EXTRACT)
2967*e4b17023SJohn Marino     {
2968*e4b17023SJohn Marino       flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL | DF_REF_ZERO_EXTRACT;
2969*e4b17023SJohn Marino 
2970*e4b17023SJohn Marino       loc = &XEXP (dst, 0);
2971*e4b17023SJohn Marino       dst = *loc;
2972*e4b17023SJohn Marino     }
2973*e4b17023SJohn Marino 
2974*e4b17023SJohn Marino   /* At this point if we do not have a reg or a subreg, just return.  */
2975*e4b17023SJohn Marino   if (REG_P (dst))
2976*e4b17023SJohn Marino     {
2977*e4b17023SJohn Marino       df_ref_record (DF_REF_REGULAR, collection_rec,
2978*e4b17023SJohn Marino 		     dst, loc, bb, insn_info, DF_REF_REG_DEF, flags);
2979*e4b17023SJohn Marino 
2980*e4b17023SJohn Marino       /* We want to keep sp alive everywhere - by making all
2981*e4b17023SJohn Marino 	 writes to sp also use of sp. */
2982*e4b17023SJohn Marino       if (REGNO (dst) == STACK_POINTER_REGNUM)
2983*e4b17023SJohn Marino 	df_ref_record (DF_REF_BASE, collection_rec,
2984*e4b17023SJohn Marino 		       dst, NULL, bb, insn_info, DF_REF_REG_USE, flags);
2985*e4b17023SJohn Marino     }
2986*e4b17023SJohn Marino   else if (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst)))
2987*e4b17023SJohn Marino     {
2988*e4b17023SJohn Marino       if (df_read_modify_subreg_p (dst))
2989*e4b17023SJohn Marino 	flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL;
2990*e4b17023SJohn Marino 
2991*e4b17023SJohn Marino       flags |= DF_REF_SUBREG;
2992*e4b17023SJohn Marino 
2993*e4b17023SJohn Marino       df_ref_record (DF_REF_REGULAR, collection_rec,
2994*e4b17023SJohn Marino 		     dst, loc, bb, insn_info, DF_REF_REG_DEF, flags);
2995*e4b17023SJohn Marino     }
2996*e4b17023SJohn Marino }
2997*e4b17023SJohn Marino 
2998*e4b17023SJohn Marino 
2999*e4b17023SJohn Marino /* Process all the registers defined in the pattern rtx, X.  */
3000*e4b17023SJohn Marino 
3001*e4b17023SJohn Marino static void
df_defs_record(struct df_collection_rec * collection_rec,rtx x,basic_block bb,struct df_insn_info * insn_info,int flags)3002*e4b17023SJohn Marino df_defs_record (struct df_collection_rec *collection_rec,
3003*e4b17023SJohn Marino                 rtx x, basic_block bb, struct df_insn_info *insn_info,
3004*e4b17023SJohn Marino 		int flags)
3005*e4b17023SJohn Marino {
3006*e4b17023SJohn Marino   RTX_CODE code = GET_CODE (x);
3007*e4b17023SJohn Marino 
3008*e4b17023SJohn Marino   if (code == SET || code == CLOBBER)
3009*e4b17023SJohn Marino     {
3010*e4b17023SJohn Marino       /* Mark the single def within the pattern.  */
3011*e4b17023SJohn Marino       int clobber_flags = flags;
3012*e4b17023SJohn Marino       clobber_flags |= (code == CLOBBER) ? DF_REF_MUST_CLOBBER : 0;
3013*e4b17023SJohn Marino       df_def_record_1 (collection_rec, x, bb, insn_info, clobber_flags);
3014*e4b17023SJohn Marino     }
3015*e4b17023SJohn Marino   else if (code == COND_EXEC)
3016*e4b17023SJohn Marino     {
3017*e4b17023SJohn Marino       df_defs_record (collection_rec, COND_EXEC_CODE (x),
3018*e4b17023SJohn Marino 		      bb, insn_info, DF_REF_CONDITIONAL);
3019*e4b17023SJohn Marino     }
3020*e4b17023SJohn Marino   else if (code == PARALLEL)
3021*e4b17023SJohn Marino     {
3022*e4b17023SJohn Marino       int i;
3023*e4b17023SJohn Marino 
3024*e4b17023SJohn Marino       /* Mark the multiple defs within the pattern.  */
3025*e4b17023SJohn Marino       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
3026*e4b17023SJohn Marino 	df_defs_record (collection_rec, XVECEXP (x, 0, i), bb, insn_info, flags);
3027*e4b17023SJohn Marino     }
3028*e4b17023SJohn Marino }
3029*e4b17023SJohn Marino 
3030*e4b17023SJohn Marino 
3031*e4b17023SJohn Marino /* Process all the registers used in the rtx at address LOC.  */
3032*e4b17023SJohn Marino 
3033*e4b17023SJohn Marino static void
df_uses_record(struct df_collection_rec * collection_rec,rtx * loc,enum df_ref_type ref_type,basic_block bb,struct df_insn_info * insn_info,int flags)3034*e4b17023SJohn Marino df_uses_record (struct df_collection_rec *collection_rec,
3035*e4b17023SJohn Marino                 rtx *loc, enum df_ref_type ref_type,
3036*e4b17023SJohn Marino 		basic_block bb, struct df_insn_info *insn_info,
3037*e4b17023SJohn Marino 		int flags)
3038*e4b17023SJohn Marino {
3039*e4b17023SJohn Marino   RTX_CODE code;
3040*e4b17023SJohn Marino   rtx x;
3041*e4b17023SJohn Marino 
3042*e4b17023SJohn Marino  retry:
3043*e4b17023SJohn Marino   x = *loc;
3044*e4b17023SJohn Marino   if (!x)
3045*e4b17023SJohn Marino     return;
3046*e4b17023SJohn Marino   code = GET_CODE (x);
3047*e4b17023SJohn Marino   switch (code)
3048*e4b17023SJohn Marino     {
3049*e4b17023SJohn Marino     case LABEL_REF:
3050*e4b17023SJohn Marino     case SYMBOL_REF:
3051*e4b17023SJohn Marino     case CONST_INT:
3052*e4b17023SJohn Marino     case CONST:
3053*e4b17023SJohn Marino     case CONST_DOUBLE:
3054*e4b17023SJohn Marino     case CONST_FIXED:
3055*e4b17023SJohn Marino     case CONST_VECTOR:
3056*e4b17023SJohn Marino     case PC:
3057*e4b17023SJohn Marino     case CC0:
3058*e4b17023SJohn Marino     case ADDR_VEC:
3059*e4b17023SJohn Marino     case ADDR_DIFF_VEC:
3060*e4b17023SJohn Marino       return;
3061*e4b17023SJohn Marino 
3062*e4b17023SJohn Marino     case CLOBBER:
3063*e4b17023SJohn Marino       /* If we are clobbering a MEM, mark any registers inside the address
3064*e4b17023SJohn Marino 	 as being used.  */
3065*e4b17023SJohn Marino       if (MEM_P (XEXP (x, 0)))
3066*e4b17023SJohn Marino 	df_uses_record (collection_rec,
3067*e4b17023SJohn Marino 			&XEXP (XEXP (x, 0), 0),
3068*e4b17023SJohn Marino 			DF_REF_REG_MEM_STORE,
3069*e4b17023SJohn Marino 		        bb, insn_info,
3070*e4b17023SJohn Marino 			flags);
3071*e4b17023SJohn Marino 
3072*e4b17023SJohn Marino       /* If we're clobbering a REG then we have a def so ignore.  */
3073*e4b17023SJohn Marino       return;
3074*e4b17023SJohn Marino 
3075*e4b17023SJohn Marino     case MEM:
3076*e4b17023SJohn Marino       df_uses_record (collection_rec,
3077*e4b17023SJohn Marino 		      &XEXP (x, 0), DF_REF_REG_MEM_LOAD,
3078*e4b17023SJohn Marino 		      bb, insn_info, flags & DF_REF_IN_NOTE);
3079*e4b17023SJohn Marino       return;
3080*e4b17023SJohn Marino 
3081*e4b17023SJohn Marino     case SUBREG:
3082*e4b17023SJohn Marino       /* While we're here, optimize this case.  */
3083*e4b17023SJohn Marino       flags |= DF_REF_PARTIAL;
3084*e4b17023SJohn Marino       /* In case the SUBREG is not of a REG, do not optimize.  */
3085*e4b17023SJohn Marino       if (!REG_P (SUBREG_REG (x)))
3086*e4b17023SJohn Marino 	{
3087*e4b17023SJohn Marino 	  loc = &SUBREG_REG (x);
3088*e4b17023SJohn Marino 	  df_uses_record (collection_rec, loc, ref_type, bb, insn_info, flags);
3089*e4b17023SJohn Marino 	  return;
3090*e4b17023SJohn Marino 	}
3091*e4b17023SJohn Marino       /* ... Fall through ...  */
3092*e4b17023SJohn Marino 
3093*e4b17023SJohn Marino     case REG:
3094*e4b17023SJohn Marino       df_ref_record (DF_REF_REGULAR, collection_rec,
3095*e4b17023SJohn Marino 		     x, loc, bb, insn_info,
3096*e4b17023SJohn Marino 		     ref_type, flags);
3097*e4b17023SJohn Marino       return;
3098*e4b17023SJohn Marino 
3099*e4b17023SJohn Marino     case SIGN_EXTRACT:
3100*e4b17023SJohn Marino     case ZERO_EXTRACT:
3101*e4b17023SJohn Marino       {
3102*e4b17023SJohn Marino         df_uses_record (collection_rec,
3103*e4b17023SJohn Marino                         &XEXP (x, 1), ref_type, bb, insn_info, flags);
3104*e4b17023SJohn Marino         df_uses_record (collection_rec,
3105*e4b17023SJohn Marino                         &XEXP (x, 2), ref_type, bb, insn_info, flags);
3106*e4b17023SJohn Marino 
3107*e4b17023SJohn Marino         /* If the parameters to the zero or sign extract are
3108*e4b17023SJohn Marino            constants, strip them off and recurse, otherwise there is
3109*e4b17023SJohn Marino            no information that we can gain from this operation.  */
3110*e4b17023SJohn Marino         if (code == ZERO_EXTRACT)
3111*e4b17023SJohn Marino           flags |= DF_REF_ZERO_EXTRACT;
3112*e4b17023SJohn Marino         else
3113*e4b17023SJohn Marino           flags |= DF_REF_SIGN_EXTRACT;
3114*e4b17023SJohn Marino 
3115*e4b17023SJohn Marino         df_uses_record (collection_rec,
3116*e4b17023SJohn Marino                         &XEXP (x, 0), ref_type, bb, insn_info, flags);
3117*e4b17023SJohn Marino         return;
3118*e4b17023SJohn Marino       }
3119*e4b17023SJohn Marino       break;
3120*e4b17023SJohn Marino 
3121*e4b17023SJohn Marino     case SET:
3122*e4b17023SJohn Marino       {
3123*e4b17023SJohn Marino 	rtx dst = SET_DEST (x);
3124*e4b17023SJohn Marino 	gcc_assert (!(flags & DF_REF_IN_NOTE));
3125*e4b17023SJohn Marino 	df_uses_record (collection_rec,
3126*e4b17023SJohn Marino 			&SET_SRC (x), DF_REF_REG_USE, bb, insn_info, flags);
3127*e4b17023SJohn Marino 
3128*e4b17023SJohn Marino 	switch (GET_CODE (dst))
3129*e4b17023SJohn Marino 	  {
3130*e4b17023SJohn Marino 	    case SUBREG:
3131*e4b17023SJohn Marino 	      if (df_read_modify_subreg_p (dst))
3132*e4b17023SJohn Marino 		{
3133*e4b17023SJohn Marino 		  df_uses_record (collection_rec, &SUBREG_REG (dst),
3134*e4b17023SJohn Marino 				  DF_REF_REG_USE, bb, insn_info,
3135*e4b17023SJohn Marino 				  flags | DF_REF_READ_WRITE | DF_REF_SUBREG);
3136*e4b17023SJohn Marino 		  break;
3137*e4b17023SJohn Marino 		}
3138*e4b17023SJohn Marino 	      /* Fall through.  */
3139*e4b17023SJohn Marino 	    case REG:
3140*e4b17023SJohn Marino 	    case PARALLEL:
3141*e4b17023SJohn Marino 	    case SCRATCH:
3142*e4b17023SJohn Marino 	    case PC:
3143*e4b17023SJohn Marino 	    case CC0:
3144*e4b17023SJohn Marino 		break;
3145*e4b17023SJohn Marino 	    case MEM:
3146*e4b17023SJohn Marino 	      df_uses_record (collection_rec, &XEXP (dst, 0),
3147*e4b17023SJohn Marino 			      DF_REF_REG_MEM_STORE, bb, insn_info, flags);
3148*e4b17023SJohn Marino 	      break;
3149*e4b17023SJohn Marino 	    case STRICT_LOW_PART:
3150*e4b17023SJohn Marino 	      {
3151*e4b17023SJohn Marino 		rtx *temp = &XEXP (dst, 0);
3152*e4b17023SJohn Marino 		/* A strict_low_part uses the whole REG and not just the
3153*e4b17023SJohn Marino 		 SUBREG.  */
3154*e4b17023SJohn Marino 		dst = XEXP (dst, 0);
3155*e4b17023SJohn Marino 		df_uses_record (collection_rec,
3156*e4b17023SJohn Marino 				(GET_CODE (dst) == SUBREG) ? &SUBREG_REG (dst) : temp,
3157*e4b17023SJohn Marino 				DF_REF_REG_USE, bb, insn_info,
3158*e4b17023SJohn Marino 				DF_REF_READ_WRITE | DF_REF_STRICT_LOW_PART);
3159*e4b17023SJohn Marino 	      }
3160*e4b17023SJohn Marino 	      break;
3161*e4b17023SJohn Marino 	    case ZERO_EXTRACT:
3162*e4b17023SJohn Marino 	      {
3163*e4b17023SJohn Marino 		df_uses_record (collection_rec, &XEXP (dst, 1),
3164*e4b17023SJohn Marino 				DF_REF_REG_USE, bb, insn_info, flags);
3165*e4b17023SJohn Marino 		df_uses_record (collection_rec, &XEXP (dst, 2),
3166*e4b17023SJohn Marino 				DF_REF_REG_USE, bb, insn_info, flags);
3167*e4b17023SJohn Marino                 if (GET_CODE (XEXP (dst,0)) == MEM)
3168*e4b17023SJohn Marino                   df_uses_record (collection_rec, &XEXP (dst, 0),
3169*e4b17023SJohn Marino                                   DF_REF_REG_USE, bb, insn_info,
3170*e4b17023SJohn Marino                                   flags);
3171*e4b17023SJohn Marino                 else
3172*e4b17023SJohn Marino                   df_uses_record (collection_rec, &XEXP (dst, 0),
3173*e4b17023SJohn Marino                                   DF_REF_REG_USE, bb, insn_info,
3174*e4b17023SJohn Marino                                   DF_REF_READ_WRITE | DF_REF_ZERO_EXTRACT);
3175*e4b17023SJohn Marino 	      }
3176*e4b17023SJohn Marino 	      break;
3177*e4b17023SJohn Marino 
3178*e4b17023SJohn Marino 	    default:
3179*e4b17023SJohn Marino 	      gcc_unreachable ();
3180*e4b17023SJohn Marino 	  }
3181*e4b17023SJohn Marino 	return;
3182*e4b17023SJohn Marino       }
3183*e4b17023SJohn Marino 
3184*e4b17023SJohn Marino     case RETURN:
3185*e4b17023SJohn Marino     case SIMPLE_RETURN:
3186*e4b17023SJohn Marino       break;
3187*e4b17023SJohn Marino 
3188*e4b17023SJohn Marino     case ASM_OPERANDS:
3189*e4b17023SJohn Marino     case UNSPEC_VOLATILE:
3190*e4b17023SJohn Marino     case TRAP_IF:
3191*e4b17023SJohn Marino     case ASM_INPUT:
3192*e4b17023SJohn Marino       {
3193*e4b17023SJohn Marino 	/* Traditional and volatile asm instructions must be
3194*e4b17023SJohn Marino 	   considered to use and clobber all hard registers, all
3195*e4b17023SJohn Marino 	   pseudo-registers and all of memory.  So must TRAP_IF and
3196*e4b17023SJohn Marino 	   UNSPEC_VOLATILE operations.
3197*e4b17023SJohn Marino 
3198*e4b17023SJohn Marino 	   Consider for instance a volatile asm that changes the fpu
3199*e4b17023SJohn Marino 	   rounding mode.  An insn should not be moved across this
3200*e4b17023SJohn Marino 	   even if it only uses pseudo-regs because it might give an
3201*e4b17023SJohn Marino 	   incorrectly rounded result.
3202*e4b17023SJohn Marino 
3203*e4b17023SJohn Marino 	   However, flow.c's liveness computation did *not* do this,
3204*e4b17023SJohn Marino 	   giving the reasoning as " ?!? Unfortunately, marking all
3205*e4b17023SJohn Marino 	   hard registers as live causes massive problems for the
3206*e4b17023SJohn Marino 	   register allocator and marking all pseudos as live creates
3207*e4b17023SJohn Marino 	   mountains of uninitialized variable warnings."
3208*e4b17023SJohn Marino 
3209*e4b17023SJohn Marino 	   In order to maintain the status quo with regard to liveness
3210*e4b17023SJohn Marino 	   and uses, we do what flow.c did and just mark any regs we
3211*e4b17023SJohn Marino 	   can find in ASM_OPERANDS as used.  In global asm insns are
3212*e4b17023SJohn Marino 	   scanned and regs_asm_clobbered is filled out.
3213*e4b17023SJohn Marino 
3214*e4b17023SJohn Marino 	   For all ASM_OPERANDS, we must traverse the vector of input
3215*e4b17023SJohn Marino 	   operands.  We can not just fall through here since then we
3216*e4b17023SJohn Marino 	   would be confused by the ASM_INPUT rtx inside ASM_OPERANDS,
3217*e4b17023SJohn Marino 	   which do not indicate traditional asms unlike their normal
3218*e4b17023SJohn Marino 	   usage.  */
3219*e4b17023SJohn Marino 	if (code == ASM_OPERANDS)
3220*e4b17023SJohn Marino 	  {
3221*e4b17023SJohn Marino 	    int j;
3222*e4b17023SJohn Marino 
3223*e4b17023SJohn Marino 	    for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++)
3224*e4b17023SJohn Marino 	      df_uses_record (collection_rec, &ASM_OPERANDS_INPUT (x, j),
3225*e4b17023SJohn Marino 			      DF_REF_REG_USE, bb, insn_info, flags);
3226*e4b17023SJohn Marino 	    return;
3227*e4b17023SJohn Marino 	  }
3228*e4b17023SJohn Marino 	break;
3229*e4b17023SJohn Marino       }
3230*e4b17023SJohn Marino 
3231*e4b17023SJohn Marino     case VAR_LOCATION:
3232*e4b17023SJohn Marino       df_uses_record (collection_rec,
3233*e4b17023SJohn Marino 		      &PAT_VAR_LOCATION_LOC (x),
3234*e4b17023SJohn Marino 		      DF_REF_REG_USE, bb, insn_info, flags);
3235*e4b17023SJohn Marino       return;
3236*e4b17023SJohn Marino 
3237*e4b17023SJohn Marino     case PRE_DEC:
3238*e4b17023SJohn Marino     case POST_DEC:
3239*e4b17023SJohn Marino     case PRE_INC:
3240*e4b17023SJohn Marino     case POST_INC:
3241*e4b17023SJohn Marino     case PRE_MODIFY:
3242*e4b17023SJohn Marino     case POST_MODIFY:
3243*e4b17023SJohn Marino       gcc_assert (!DEBUG_INSN_P (insn_info->insn));
3244*e4b17023SJohn Marino       /* Catch the def of the register being modified.  */
3245*e4b17023SJohn Marino       df_ref_record (DF_REF_REGULAR, collection_rec, XEXP (x, 0), &XEXP (x, 0),
3246*e4b17023SJohn Marino 		     bb, insn_info,
3247*e4b17023SJohn Marino 		     DF_REF_REG_DEF,
3248*e4b17023SJohn Marino                      flags | DF_REF_READ_WRITE | DF_REF_PRE_POST_MODIFY);
3249*e4b17023SJohn Marino 
3250*e4b17023SJohn Marino       /* ... Fall through to handle uses ...  */
3251*e4b17023SJohn Marino 
3252*e4b17023SJohn Marino     default:
3253*e4b17023SJohn Marino       break;
3254*e4b17023SJohn Marino     }
3255*e4b17023SJohn Marino 
3256*e4b17023SJohn Marino   /* Recursively scan the operands of this expression.  */
3257*e4b17023SJohn Marino   {
3258*e4b17023SJohn Marino     const char *fmt = GET_RTX_FORMAT (code);
3259*e4b17023SJohn Marino     int i;
3260*e4b17023SJohn Marino 
3261*e4b17023SJohn Marino     for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3262*e4b17023SJohn Marino       {
3263*e4b17023SJohn Marino 	if (fmt[i] == 'e')
3264*e4b17023SJohn Marino 	  {
3265*e4b17023SJohn Marino 	    /* Tail recursive case: save a function call level.  */
3266*e4b17023SJohn Marino 	    if (i == 0)
3267*e4b17023SJohn Marino 	      {
3268*e4b17023SJohn Marino 		loc = &XEXP (x, 0);
3269*e4b17023SJohn Marino 		goto retry;
3270*e4b17023SJohn Marino 	      }
3271*e4b17023SJohn Marino 	    df_uses_record (collection_rec, &XEXP (x, i), ref_type,
3272*e4b17023SJohn Marino 			    bb, insn_info, flags);
3273*e4b17023SJohn Marino 	  }
3274*e4b17023SJohn Marino 	else if (fmt[i] == 'E')
3275*e4b17023SJohn Marino 	  {
3276*e4b17023SJohn Marino 	    int j;
3277*e4b17023SJohn Marino 	    for (j = 0; j < XVECLEN (x, i); j++)
3278*e4b17023SJohn Marino 	      df_uses_record (collection_rec,
3279*e4b17023SJohn Marino 			      &XVECEXP (x, i, j), ref_type,
3280*e4b17023SJohn Marino 			      bb, insn_info, flags);
3281*e4b17023SJohn Marino 	  }
3282*e4b17023SJohn Marino       }
3283*e4b17023SJohn Marino   }
3284*e4b17023SJohn Marino 
3285*e4b17023SJohn Marino   return;
3286*e4b17023SJohn Marino }
3287*e4b17023SJohn Marino 
3288*e4b17023SJohn Marino 
3289*e4b17023SJohn Marino /* For all DF_REF_CONDITIONAL defs, add a corresponding uses.  */
3290*e4b17023SJohn Marino 
3291*e4b17023SJohn Marino static void
df_get_conditional_uses(struct df_collection_rec * collection_rec)3292*e4b17023SJohn Marino df_get_conditional_uses (struct df_collection_rec *collection_rec)
3293*e4b17023SJohn Marino {
3294*e4b17023SJohn Marino   unsigned int ix;
3295*e4b17023SJohn Marino   df_ref ref;
3296*e4b17023SJohn Marino 
3297*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (df_ref, collection_rec->def_vec, ix, ref)
3298*e4b17023SJohn Marino     {
3299*e4b17023SJohn Marino       if (DF_REF_FLAGS_IS_SET (ref, DF_REF_CONDITIONAL))
3300*e4b17023SJohn Marino         {
3301*e4b17023SJohn Marino           df_ref use;
3302*e4b17023SJohn Marino 
3303*e4b17023SJohn Marino           use = df_ref_create_structure (DF_REF_CLASS (ref), collection_rec, DF_REF_REG (ref),
3304*e4b17023SJohn Marino 					 DF_REF_LOC (ref), DF_REF_BB (ref),
3305*e4b17023SJohn Marino 					 DF_REF_INSN_INFO (ref), DF_REF_REG_USE,
3306*e4b17023SJohn Marino 					 DF_REF_FLAGS (ref) & ~DF_REF_CONDITIONAL);
3307*e4b17023SJohn Marino           DF_REF_REGNO (use) = DF_REF_REGNO (ref);
3308*e4b17023SJohn Marino         }
3309*e4b17023SJohn Marino     }
3310*e4b17023SJohn Marino }
3311*e4b17023SJohn Marino 
3312*e4b17023SJohn Marino 
3313*e4b17023SJohn Marino /* Get call's extra defs and uses. */
3314*e4b17023SJohn Marino 
3315*e4b17023SJohn Marino static void
df_get_call_refs(struct df_collection_rec * collection_rec,basic_block bb,struct df_insn_info * insn_info,int flags)3316*e4b17023SJohn Marino df_get_call_refs (struct df_collection_rec * collection_rec,
3317*e4b17023SJohn Marino                   basic_block bb,
3318*e4b17023SJohn Marino                   struct df_insn_info *insn_info,
3319*e4b17023SJohn Marino                   int flags)
3320*e4b17023SJohn Marino {
3321*e4b17023SJohn Marino   rtx note;
3322*e4b17023SJohn Marino   bitmap_iterator bi;
3323*e4b17023SJohn Marino   unsigned int ui;
3324*e4b17023SJohn Marino   bool is_sibling_call;
3325*e4b17023SJohn Marino   unsigned int i;
3326*e4b17023SJohn Marino   df_ref def;
3327*e4b17023SJohn Marino   bitmap_head defs_generated;
3328*e4b17023SJohn Marino 
3329*e4b17023SJohn Marino   bitmap_initialize (&defs_generated, &df_bitmap_obstack);
3330*e4b17023SJohn Marino 
3331*e4b17023SJohn Marino   /* Do not generate clobbers for registers that are the result of the
3332*e4b17023SJohn Marino      call.  This causes ordering problems in the chain building code
3333*e4b17023SJohn Marino      depending on which def is seen first.  */
3334*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (df_ref, collection_rec->def_vec, i, def)
3335*e4b17023SJohn Marino     bitmap_set_bit (&defs_generated, DF_REF_REGNO (def));
3336*e4b17023SJohn Marino 
3337*e4b17023SJohn Marino   /* Record the registers used to pass arguments, and explicitly
3338*e4b17023SJohn Marino      noted as clobbered.  */
3339*e4b17023SJohn Marino   for (note = CALL_INSN_FUNCTION_USAGE (insn_info->insn); note;
3340*e4b17023SJohn Marino        note = XEXP (note, 1))
3341*e4b17023SJohn Marino     {
3342*e4b17023SJohn Marino       if (GET_CODE (XEXP (note, 0)) == USE)
3343*e4b17023SJohn Marino         df_uses_record (collection_rec, &XEXP (XEXP (note, 0), 0),
3344*e4b17023SJohn Marino 			DF_REF_REG_USE, bb, insn_info, flags);
3345*e4b17023SJohn Marino       else if (GET_CODE (XEXP (note, 0)) == CLOBBER)
3346*e4b17023SJohn Marino 	{
3347*e4b17023SJohn Marino 	  if (REG_P (XEXP (XEXP (note, 0), 0)))
3348*e4b17023SJohn Marino 	    {
3349*e4b17023SJohn Marino 	      unsigned int regno = REGNO (XEXP (XEXP (note, 0), 0));
3350*e4b17023SJohn Marino 	      if (!bitmap_bit_p (&defs_generated, regno))
3351*e4b17023SJohn Marino 		df_defs_record (collection_rec, XEXP (note, 0), bb,
3352*e4b17023SJohn Marino 				insn_info, flags);
3353*e4b17023SJohn Marino 	    }
3354*e4b17023SJohn Marino 	  else
3355*e4b17023SJohn Marino 	    df_uses_record (collection_rec, &XEXP (note, 0),
3356*e4b17023SJohn Marino 		            DF_REF_REG_USE, bb, insn_info, flags);
3357*e4b17023SJohn Marino 	}
3358*e4b17023SJohn Marino     }
3359*e4b17023SJohn Marino 
3360*e4b17023SJohn Marino   /* The stack ptr is used (honorarily) by a CALL insn.  */
3361*e4b17023SJohn Marino   df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[STACK_POINTER_REGNUM],
3362*e4b17023SJohn Marino 		 NULL, bb, insn_info, DF_REF_REG_USE,
3363*e4b17023SJohn Marino 		 DF_REF_CALL_STACK_USAGE | flags);
3364*e4b17023SJohn Marino 
3365*e4b17023SJohn Marino   /* Calls to const functions cannot access any global registers and calls to
3366*e4b17023SJohn Marino      pure functions cannot set them.  All other calls may reference any of the
3367*e4b17023SJohn Marino      global registers, so they are recorded as used.  */
3368*e4b17023SJohn Marino   if (!RTL_CONST_CALL_P (insn_info->insn))
3369*e4b17023SJohn Marino     for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3370*e4b17023SJohn Marino       if (global_regs[i])
3371*e4b17023SJohn Marino 	{
3372*e4b17023SJohn Marino 	  df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[i],
3373*e4b17023SJohn Marino 			 NULL, bb, insn_info, DF_REF_REG_USE, flags);
3374*e4b17023SJohn Marino 	  if (!RTL_PURE_CALL_P (insn_info->insn))
3375*e4b17023SJohn Marino 	    df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[i],
3376*e4b17023SJohn Marino 			   NULL, bb, insn_info, DF_REF_REG_DEF, flags);
3377*e4b17023SJohn Marino 	}
3378*e4b17023SJohn Marino 
3379*e4b17023SJohn Marino   is_sibling_call = SIBLING_CALL_P (insn_info->insn);
3380*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (regs_invalidated_by_call_regset, 0, ui, bi)
3381*e4b17023SJohn Marino     {
3382*e4b17023SJohn Marino       if (!global_regs[ui]
3383*e4b17023SJohn Marino 	  && (!bitmap_bit_p (&defs_generated, ui))
3384*e4b17023SJohn Marino 	  && (!is_sibling_call
3385*e4b17023SJohn Marino 	      || !bitmap_bit_p (df->exit_block_uses, ui)
3386*e4b17023SJohn Marino 	      || refers_to_regno_p (ui, ui+1,
3387*e4b17023SJohn Marino 				    crtl->return_rtx, NULL)))
3388*e4b17023SJohn Marino         df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[ui],
3389*e4b17023SJohn Marino 		       NULL, bb, insn_info, DF_REF_REG_DEF,
3390*e4b17023SJohn Marino 		       DF_REF_MAY_CLOBBER | flags);
3391*e4b17023SJohn Marino     }
3392*e4b17023SJohn Marino 
3393*e4b17023SJohn Marino   bitmap_clear (&defs_generated);
3394*e4b17023SJohn Marino   return;
3395*e4b17023SJohn Marino }
3396*e4b17023SJohn Marino 
3397*e4b17023SJohn Marino /* Collect all refs in the INSN. This function is free of any
3398*e4b17023SJohn Marino    side-effect - it will create and return a lists of df_ref's in the
3399*e4b17023SJohn Marino    COLLECTION_REC without putting those refs into existing ref chains
3400*e4b17023SJohn Marino    and reg chains. */
3401*e4b17023SJohn Marino 
3402*e4b17023SJohn Marino static void
df_insn_refs_collect(struct df_collection_rec * collection_rec,basic_block bb,struct df_insn_info * insn_info)3403*e4b17023SJohn Marino df_insn_refs_collect (struct df_collection_rec* collection_rec,
3404*e4b17023SJohn Marino 		      basic_block bb, struct df_insn_info *insn_info)
3405*e4b17023SJohn Marino {
3406*e4b17023SJohn Marino   rtx note;
3407*e4b17023SJohn Marino   bool is_cond_exec = (GET_CODE (PATTERN (insn_info->insn)) == COND_EXEC);
3408*e4b17023SJohn Marino 
3409*e4b17023SJohn Marino   /* Clear out the collection record.  */
3410*e4b17023SJohn Marino   VEC_truncate (df_ref, collection_rec->def_vec, 0);
3411*e4b17023SJohn Marino   VEC_truncate (df_ref, collection_rec->use_vec, 0);
3412*e4b17023SJohn Marino   VEC_truncate (df_ref, collection_rec->eq_use_vec, 0);
3413*e4b17023SJohn Marino   VEC_truncate (df_mw_hardreg_ptr, collection_rec->mw_vec, 0);
3414*e4b17023SJohn Marino 
3415*e4b17023SJohn Marino   /* Record register defs.  */
3416*e4b17023SJohn Marino   df_defs_record (collection_rec, PATTERN (insn_info->insn), bb, insn_info, 0);
3417*e4b17023SJohn Marino 
3418*e4b17023SJohn Marino   /* Process REG_EQUIV/REG_EQUAL notes.  */
3419*e4b17023SJohn Marino   for (note = REG_NOTES (insn_info->insn); note;
3420*e4b17023SJohn Marino        note = XEXP (note, 1))
3421*e4b17023SJohn Marino     {
3422*e4b17023SJohn Marino       switch (REG_NOTE_KIND (note))
3423*e4b17023SJohn Marino         {
3424*e4b17023SJohn Marino         case REG_EQUIV:
3425*e4b17023SJohn Marino         case REG_EQUAL:
3426*e4b17023SJohn Marino           df_uses_record (collection_rec,
3427*e4b17023SJohn Marino                           &XEXP (note, 0), DF_REF_REG_USE,
3428*e4b17023SJohn Marino                           bb, insn_info, DF_REF_IN_NOTE);
3429*e4b17023SJohn Marino           break;
3430*e4b17023SJohn Marino         case REG_NON_LOCAL_GOTO:
3431*e4b17023SJohn Marino           /* The frame ptr is used by a non-local goto.  */
3432*e4b17023SJohn Marino           df_ref_record (DF_REF_BASE, collection_rec,
3433*e4b17023SJohn Marino                          regno_reg_rtx[FRAME_POINTER_REGNUM],
3434*e4b17023SJohn Marino                          NULL, bb, insn_info,
3435*e4b17023SJohn Marino                          DF_REF_REG_USE, 0);
3436*e4b17023SJohn Marino #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
3437*e4b17023SJohn Marino           df_ref_record (DF_REF_BASE, collection_rec,
3438*e4b17023SJohn Marino                          regno_reg_rtx[HARD_FRAME_POINTER_REGNUM],
3439*e4b17023SJohn Marino                          NULL, bb, insn_info,
3440*e4b17023SJohn Marino                          DF_REF_REG_USE, 0);
3441*e4b17023SJohn Marino #endif
3442*e4b17023SJohn Marino           break;
3443*e4b17023SJohn Marino         default:
3444*e4b17023SJohn Marino           break;
3445*e4b17023SJohn Marino         }
3446*e4b17023SJohn Marino     }
3447*e4b17023SJohn Marino 
3448*e4b17023SJohn Marino   if (CALL_P (insn_info->insn))
3449*e4b17023SJohn Marino     df_get_call_refs (collection_rec, bb, insn_info,
3450*e4b17023SJohn Marino 		      (is_cond_exec) ? DF_REF_CONDITIONAL : 0);
3451*e4b17023SJohn Marino 
3452*e4b17023SJohn Marino   /* Record the register uses.  */
3453*e4b17023SJohn Marino   df_uses_record (collection_rec,
3454*e4b17023SJohn Marino 		  &PATTERN (insn_info->insn), DF_REF_REG_USE, bb, insn_info, 0);
3455*e4b17023SJohn Marino 
3456*e4b17023SJohn Marino   /* DF_REF_CONDITIONAL needs corresponding USES. */
3457*e4b17023SJohn Marino   if (is_cond_exec)
3458*e4b17023SJohn Marino     df_get_conditional_uses (collection_rec);
3459*e4b17023SJohn Marino 
3460*e4b17023SJohn Marino   df_canonize_collection_rec (collection_rec);
3461*e4b17023SJohn Marino }
3462*e4b17023SJohn Marino 
3463*e4b17023SJohn Marino /* Recompute the luids for the insns in BB.  */
3464*e4b17023SJohn Marino 
3465*e4b17023SJohn Marino void
df_recompute_luids(basic_block bb)3466*e4b17023SJohn Marino df_recompute_luids (basic_block bb)
3467*e4b17023SJohn Marino {
3468*e4b17023SJohn Marino   rtx insn;
3469*e4b17023SJohn Marino   int luid = 0;
3470*e4b17023SJohn Marino 
3471*e4b17023SJohn Marino   df_grow_insn_info ();
3472*e4b17023SJohn Marino 
3473*e4b17023SJohn Marino   /* Scan the block an insn at a time from beginning to end.  */
3474*e4b17023SJohn Marino   FOR_BB_INSNS (bb, insn)
3475*e4b17023SJohn Marino     {
3476*e4b17023SJohn Marino       struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
3477*e4b17023SJohn Marino       /* Inserting labels does not always trigger the incremental
3478*e4b17023SJohn Marino 	 rescanning.  */
3479*e4b17023SJohn Marino       if (!insn_info)
3480*e4b17023SJohn Marino 	{
3481*e4b17023SJohn Marino 	  gcc_assert (!INSN_P (insn));
3482*e4b17023SJohn Marino 	  insn_info = df_insn_create_insn_record (insn);
3483*e4b17023SJohn Marino 	}
3484*e4b17023SJohn Marino 
3485*e4b17023SJohn Marino       DF_INSN_INFO_LUID (insn_info) = luid;
3486*e4b17023SJohn Marino       if (INSN_P (insn))
3487*e4b17023SJohn Marino 	luid++;
3488*e4b17023SJohn Marino     }
3489*e4b17023SJohn Marino }
3490*e4b17023SJohn Marino 
3491*e4b17023SJohn Marino 
3492*e4b17023SJohn Marino /* Collect all artificial refs at the block level for BB and add them
3493*e4b17023SJohn Marino    to COLLECTION_REC.  */
3494*e4b17023SJohn Marino 
3495*e4b17023SJohn Marino static void
df_bb_refs_collect(struct df_collection_rec * collection_rec,basic_block bb)3496*e4b17023SJohn Marino df_bb_refs_collect (struct df_collection_rec *collection_rec, basic_block bb)
3497*e4b17023SJohn Marino {
3498*e4b17023SJohn Marino   VEC_truncate (df_ref, collection_rec->def_vec, 0);
3499*e4b17023SJohn Marino   VEC_truncate (df_ref, collection_rec->use_vec, 0);
3500*e4b17023SJohn Marino   VEC_truncate (df_ref, collection_rec->eq_use_vec, 0);
3501*e4b17023SJohn Marino   VEC_truncate (df_mw_hardreg_ptr, collection_rec->mw_vec, 0);
3502*e4b17023SJohn Marino 
3503*e4b17023SJohn Marino   if (bb->index == ENTRY_BLOCK)
3504*e4b17023SJohn Marino     {
3505*e4b17023SJohn Marino       df_entry_block_defs_collect (collection_rec, df->entry_block_defs);
3506*e4b17023SJohn Marino       return;
3507*e4b17023SJohn Marino     }
3508*e4b17023SJohn Marino   else if (bb->index == EXIT_BLOCK)
3509*e4b17023SJohn Marino     {
3510*e4b17023SJohn Marino       df_exit_block_uses_collect (collection_rec, df->exit_block_uses);
3511*e4b17023SJohn Marino       return;
3512*e4b17023SJohn Marino     }
3513*e4b17023SJohn Marino 
3514*e4b17023SJohn Marino #ifdef EH_RETURN_DATA_REGNO
3515*e4b17023SJohn Marino   if (bb_has_eh_pred (bb))
3516*e4b17023SJohn Marino     {
3517*e4b17023SJohn Marino       unsigned int i;
3518*e4b17023SJohn Marino       /* Mark the registers that will contain data for the handler.  */
3519*e4b17023SJohn Marino       for (i = 0; ; ++i)
3520*e4b17023SJohn Marino 	{
3521*e4b17023SJohn Marino 	  unsigned regno = EH_RETURN_DATA_REGNO (i);
3522*e4b17023SJohn Marino 	  if (regno == INVALID_REGNUM)
3523*e4b17023SJohn Marino 	    break;
3524*e4b17023SJohn Marino 	  df_ref_record (DF_REF_ARTIFICIAL, collection_rec, regno_reg_rtx[regno], NULL,
3525*e4b17023SJohn Marino 			 bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP);
3526*e4b17023SJohn Marino 	}
3527*e4b17023SJohn Marino     }
3528*e4b17023SJohn Marino #endif
3529*e4b17023SJohn Marino 
3530*e4b17023SJohn Marino   /* Add the hard_frame_pointer if this block is the target of a
3531*e4b17023SJohn Marino      non-local goto.  */
3532*e4b17023SJohn Marino   if (bb->flags & BB_NON_LOCAL_GOTO_TARGET)
3533*e4b17023SJohn Marino     df_ref_record (DF_REF_ARTIFICIAL, collection_rec, hard_frame_pointer_rtx, NULL,
3534*e4b17023SJohn Marino 		   bb, NULL, DF_REF_REG_DEF, DF_REF_AT_TOP);
3535*e4b17023SJohn Marino 
3536*e4b17023SJohn Marino   /* Add the artificial uses.  */
3537*e4b17023SJohn Marino   if (bb->index >= NUM_FIXED_BLOCKS)
3538*e4b17023SJohn Marino     {
3539*e4b17023SJohn Marino       bitmap_iterator bi;
3540*e4b17023SJohn Marino       unsigned int regno;
3541*e4b17023SJohn Marino       bitmap au = bb_has_eh_pred (bb)
3542*e4b17023SJohn Marino 	? &df->eh_block_artificial_uses
3543*e4b17023SJohn Marino 	: &df->regular_block_artificial_uses;
3544*e4b17023SJohn Marino 
3545*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (au, 0, regno, bi)
3546*e4b17023SJohn Marino 	{
3547*e4b17023SJohn Marino 	  df_ref_record (DF_REF_ARTIFICIAL, collection_rec, regno_reg_rtx[regno], NULL,
3548*e4b17023SJohn Marino 			 bb, NULL, DF_REF_REG_USE, 0);
3549*e4b17023SJohn Marino 	}
3550*e4b17023SJohn Marino     }
3551*e4b17023SJohn Marino 
3552*e4b17023SJohn Marino   df_canonize_collection_rec (collection_rec);
3553*e4b17023SJohn Marino }
3554*e4b17023SJohn Marino 
3555*e4b17023SJohn Marino 
3556*e4b17023SJohn Marino /* Record all the refs within the basic block BB_INDEX and scan the instructions if SCAN_INSNS.  */
3557*e4b17023SJohn Marino 
3558*e4b17023SJohn Marino void
df_bb_refs_record(int bb_index,bool scan_insns)3559*e4b17023SJohn Marino df_bb_refs_record (int bb_index, bool scan_insns)
3560*e4b17023SJohn Marino {
3561*e4b17023SJohn Marino   basic_block bb = BASIC_BLOCK (bb_index);
3562*e4b17023SJohn Marino   rtx insn;
3563*e4b17023SJohn Marino   int luid = 0;
3564*e4b17023SJohn Marino   struct df_collection_rec collection_rec;
3565*e4b17023SJohn Marino 
3566*e4b17023SJohn Marino   if (!df)
3567*e4b17023SJohn Marino     return;
3568*e4b17023SJohn Marino 
3569*e4b17023SJohn Marino   df_grow_bb_info (df_scan);
3570*e4b17023SJohn Marino   collection_rec.def_vec = VEC_alloc (df_ref, stack, 128);
3571*e4b17023SJohn Marino   collection_rec.use_vec = VEC_alloc (df_ref, stack, 32);
3572*e4b17023SJohn Marino   collection_rec.eq_use_vec = VEC_alloc (df_ref, stack, 32);
3573*e4b17023SJohn Marino   collection_rec.mw_vec = VEC_alloc (df_mw_hardreg_ptr, stack, 32);
3574*e4b17023SJohn Marino 
3575*e4b17023SJohn Marino   if (scan_insns)
3576*e4b17023SJohn Marino     /* Scan the block an insn at a time from beginning to end.  */
3577*e4b17023SJohn Marino     FOR_BB_INSNS (bb, insn)
3578*e4b17023SJohn Marino       {
3579*e4b17023SJohn Marino 	struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
3580*e4b17023SJohn Marino 	gcc_assert (!insn_info);
3581*e4b17023SJohn Marino 
3582*e4b17023SJohn Marino 	insn_info = df_insn_create_insn_record (insn);
3583*e4b17023SJohn Marino 	if (INSN_P (insn))
3584*e4b17023SJohn Marino 	  {
3585*e4b17023SJohn Marino 	    /* Record refs within INSN.  */
3586*e4b17023SJohn Marino 	    DF_INSN_INFO_LUID (insn_info) = luid++;
3587*e4b17023SJohn Marino 	    df_insn_refs_collect (&collection_rec, bb, DF_INSN_INFO_GET (insn));
3588*e4b17023SJohn Marino 	    df_refs_add_to_chains (&collection_rec, bb, insn);
3589*e4b17023SJohn Marino 	  }
3590*e4b17023SJohn Marino 	DF_INSN_INFO_LUID (insn_info) = luid;
3591*e4b17023SJohn Marino       }
3592*e4b17023SJohn Marino 
3593*e4b17023SJohn Marino   /* Other block level artificial refs */
3594*e4b17023SJohn Marino   df_bb_refs_collect (&collection_rec, bb);
3595*e4b17023SJohn Marino   df_refs_add_to_chains (&collection_rec, bb, NULL);
3596*e4b17023SJohn Marino 
3597*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec.def_vec);
3598*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec.use_vec);
3599*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec.eq_use_vec);
3600*e4b17023SJohn Marino   VEC_free (df_mw_hardreg_ptr, stack, collection_rec.mw_vec);
3601*e4b17023SJohn Marino 
3602*e4b17023SJohn Marino   /* Now that the block has been processed, set the block as dirty so
3603*e4b17023SJohn Marino      LR and LIVE will get it processed.  */
3604*e4b17023SJohn Marino   df_set_bb_dirty (bb);
3605*e4b17023SJohn Marino }
3606*e4b17023SJohn Marino 
3607*e4b17023SJohn Marino 
3608*e4b17023SJohn Marino /* Get the artificial use set for a regular (i.e. non-exit/non-entry)
3609*e4b17023SJohn Marino    block. */
3610*e4b17023SJohn Marino 
3611*e4b17023SJohn Marino static void
df_get_regular_block_artificial_uses(bitmap regular_block_artificial_uses)3612*e4b17023SJohn Marino df_get_regular_block_artificial_uses (bitmap regular_block_artificial_uses)
3613*e4b17023SJohn Marino {
3614*e4b17023SJohn Marino #ifdef EH_USES
3615*e4b17023SJohn Marino   unsigned int i;
3616*e4b17023SJohn Marino #endif
3617*e4b17023SJohn Marino 
3618*e4b17023SJohn Marino   bitmap_clear (regular_block_artificial_uses);
3619*e4b17023SJohn Marino 
3620*e4b17023SJohn Marino   if (reload_completed)
3621*e4b17023SJohn Marino     {
3622*e4b17023SJohn Marino       if (frame_pointer_needed)
3623*e4b17023SJohn Marino 	bitmap_set_bit (regular_block_artificial_uses, HARD_FRAME_POINTER_REGNUM);
3624*e4b17023SJohn Marino     }
3625*e4b17023SJohn Marino   else
3626*e4b17023SJohn Marino     /* Before reload, there are a few registers that must be forced
3627*e4b17023SJohn Marino        live everywhere -- which might not already be the case for
3628*e4b17023SJohn Marino        blocks within infinite loops.  */
3629*e4b17023SJohn Marino     {
3630*e4b17023SJohn Marino       unsigned int picreg = PIC_OFFSET_TABLE_REGNUM;
3631*e4b17023SJohn Marino 
3632*e4b17023SJohn Marino       /* Any reference to any pseudo before reload is a potential
3633*e4b17023SJohn Marino 	 reference of the frame pointer.  */
3634*e4b17023SJohn Marino       bitmap_set_bit (regular_block_artificial_uses, FRAME_POINTER_REGNUM);
3635*e4b17023SJohn Marino 
3636*e4b17023SJohn Marino #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
3637*e4b17023SJohn Marino       bitmap_set_bit (regular_block_artificial_uses, HARD_FRAME_POINTER_REGNUM);
3638*e4b17023SJohn Marino #endif
3639*e4b17023SJohn Marino 
3640*e4b17023SJohn Marino #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
3641*e4b17023SJohn Marino       /* Pseudos with argument area equivalences may require
3642*e4b17023SJohn Marino 	 reloading via the argument pointer.  */
3643*e4b17023SJohn Marino       if (fixed_regs[ARG_POINTER_REGNUM])
3644*e4b17023SJohn Marino 	bitmap_set_bit (regular_block_artificial_uses, ARG_POINTER_REGNUM);
3645*e4b17023SJohn Marino #endif
3646*e4b17023SJohn Marino 
3647*e4b17023SJohn Marino       /* Any constant, or pseudo with constant equivalences, may
3648*e4b17023SJohn Marino 	 require reloading from memory using the pic register.  */
3649*e4b17023SJohn Marino       if (picreg != INVALID_REGNUM
3650*e4b17023SJohn Marino 	  && fixed_regs[picreg])
3651*e4b17023SJohn Marino 	bitmap_set_bit (regular_block_artificial_uses, picreg);
3652*e4b17023SJohn Marino     }
3653*e4b17023SJohn Marino   /* The all-important stack pointer must always be live.  */
3654*e4b17023SJohn Marino   bitmap_set_bit (regular_block_artificial_uses, STACK_POINTER_REGNUM);
3655*e4b17023SJohn Marino 
3656*e4b17023SJohn Marino #ifdef EH_USES
3657*e4b17023SJohn Marino   /* EH_USES registers are used:
3658*e4b17023SJohn Marino      1) at all insns that might throw (calls or with -fnon-call-exceptions
3659*e4b17023SJohn Marino 	trapping insns)
3660*e4b17023SJohn Marino      2) in all EH edges
3661*e4b17023SJohn Marino      3) to support backtraces and/or debugging, anywhere between their
3662*e4b17023SJohn Marino 	initialization and where they the saved registers are restored
3663*e4b17023SJohn Marino 	from them, including the cases where we don't reach the epilogue
3664*e4b17023SJohn Marino 	(noreturn call or infinite loop).  */
3665*e4b17023SJohn Marino   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3666*e4b17023SJohn Marino     if (EH_USES (i))
3667*e4b17023SJohn Marino       bitmap_set_bit (regular_block_artificial_uses, i);
3668*e4b17023SJohn Marino #endif
3669*e4b17023SJohn Marino }
3670*e4b17023SJohn Marino 
3671*e4b17023SJohn Marino 
3672*e4b17023SJohn Marino /* Get the artificial use set for an eh block. */
3673*e4b17023SJohn Marino 
3674*e4b17023SJohn Marino static void
df_get_eh_block_artificial_uses(bitmap eh_block_artificial_uses)3675*e4b17023SJohn Marino df_get_eh_block_artificial_uses (bitmap eh_block_artificial_uses)
3676*e4b17023SJohn Marino {
3677*e4b17023SJohn Marino   bitmap_clear (eh_block_artificial_uses);
3678*e4b17023SJohn Marino 
3679*e4b17023SJohn Marino   /* The following code (down thru the arg_pointer setting APPEARS
3680*e4b17023SJohn Marino      to be necessary because there is nothing that actually
3681*e4b17023SJohn Marino      describes what the exception handling code may actually need
3682*e4b17023SJohn Marino      to keep alive.  */
3683*e4b17023SJohn Marino   if (reload_completed)
3684*e4b17023SJohn Marino     {
3685*e4b17023SJohn Marino       if (frame_pointer_needed)
3686*e4b17023SJohn Marino 	{
3687*e4b17023SJohn Marino 	  bitmap_set_bit (eh_block_artificial_uses, FRAME_POINTER_REGNUM);
3688*e4b17023SJohn Marino #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
3689*e4b17023SJohn Marino 	  bitmap_set_bit (eh_block_artificial_uses, HARD_FRAME_POINTER_REGNUM);
3690*e4b17023SJohn Marino #endif
3691*e4b17023SJohn Marino 	}
3692*e4b17023SJohn Marino #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
3693*e4b17023SJohn Marino       if (fixed_regs[ARG_POINTER_REGNUM])
3694*e4b17023SJohn Marino 	bitmap_set_bit (eh_block_artificial_uses, ARG_POINTER_REGNUM);
3695*e4b17023SJohn Marino #endif
3696*e4b17023SJohn Marino     }
3697*e4b17023SJohn Marino }
3698*e4b17023SJohn Marino 
3699*e4b17023SJohn Marino 
3700*e4b17023SJohn Marino 
3701*e4b17023SJohn Marino /*----------------------------------------------------------------------------
3702*e4b17023SJohn Marino    Specialized hard register scanning functions.
3703*e4b17023SJohn Marino ----------------------------------------------------------------------------*/
3704*e4b17023SJohn Marino 
3705*e4b17023SJohn Marino 
3706*e4b17023SJohn Marino /* Mark a register in SET.  Hard registers in large modes get all
3707*e4b17023SJohn Marino    of their component registers set as well.  */
3708*e4b17023SJohn Marino 
3709*e4b17023SJohn Marino static void
df_mark_reg(rtx reg,void * vset)3710*e4b17023SJohn Marino df_mark_reg (rtx reg, void *vset)
3711*e4b17023SJohn Marino {
3712*e4b17023SJohn Marino   bitmap set = (bitmap) vset;
3713*e4b17023SJohn Marino   int regno = REGNO (reg);
3714*e4b17023SJohn Marino 
3715*e4b17023SJohn Marino   gcc_assert (GET_MODE (reg) != BLKmode);
3716*e4b17023SJohn Marino 
3717*e4b17023SJohn Marino   if (regno < FIRST_PSEUDO_REGISTER)
3718*e4b17023SJohn Marino     {
3719*e4b17023SJohn Marino       int n = hard_regno_nregs[regno][GET_MODE (reg)];
3720*e4b17023SJohn Marino       bitmap_set_range (set, regno, n);
3721*e4b17023SJohn Marino     }
3722*e4b17023SJohn Marino   else
3723*e4b17023SJohn Marino     bitmap_set_bit (set, regno);
3724*e4b17023SJohn Marino }
3725*e4b17023SJohn Marino 
3726*e4b17023SJohn Marino 
3727*e4b17023SJohn Marino /* Set the bit for regs that are considered being defined at the entry. */
3728*e4b17023SJohn Marino 
3729*e4b17023SJohn Marino static void
df_get_entry_block_def_set(bitmap entry_block_defs)3730*e4b17023SJohn Marino df_get_entry_block_def_set (bitmap entry_block_defs)
3731*e4b17023SJohn Marino {
3732*e4b17023SJohn Marino   rtx r;
3733*e4b17023SJohn Marino   int i;
3734*e4b17023SJohn Marino 
3735*e4b17023SJohn Marino   bitmap_clear (entry_block_defs);
3736*e4b17023SJohn Marino 
3737*e4b17023SJohn Marino   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3738*e4b17023SJohn Marino     if (FUNCTION_ARG_REGNO_P (i))
3739*e4b17023SJohn Marino       bitmap_set_bit (entry_block_defs, INCOMING_REGNO (i));
3740*e4b17023SJohn Marino 
3741*e4b17023SJohn Marino   /* The always important stack pointer.  */
3742*e4b17023SJohn Marino   bitmap_set_bit (entry_block_defs, STACK_POINTER_REGNUM);
3743*e4b17023SJohn Marino 
3744*e4b17023SJohn Marino   /* Once the prologue has been generated, all of these registers
3745*e4b17023SJohn Marino      should just show up in the first regular block.  */
3746*e4b17023SJohn Marino   if (HAVE_prologue && epilogue_completed)
3747*e4b17023SJohn Marino     {
3748*e4b17023SJohn Marino       /* Defs for the callee saved registers are inserted so that the
3749*e4b17023SJohn Marino 	 pushes have some defining location.  */
3750*e4b17023SJohn Marino       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3751*e4b17023SJohn Marino 	if ((call_used_regs[i] == 0) && (df_regs_ever_live_p (i)))
3752*e4b17023SJohn Marino 	  bitmap_set_bit (entry_block_defs, i);
3753*e4b17023SJohn Marino     }
3754*e4b17023SJohn Marino 
3755*e4b17023SJohn Marino   r = targetm.calls.struct_value_rtx (current_function_decl, true);
3756*e4b17023SJohn Marino   if (r && REG_P (r))
3757*e4b17023SJohn Marino     bitmap_set_bit (entry_block_defs, REGNO (r));
3758*e4b17023SJohn Marino 
3759*e4b17023SJohn Marino   /* If the function has an incoming STATIC_CHAIN, it has to show up
3760*e4b17023SJohn Marino      in the entry def set.  */
3761*e4b17023SJohn Marino   r = targetm.calls.static_chain (current_function_decl, true);
3762*e4b17023SJohn Marino   if (r && REG_P (r))
3763*e4b17023SJohn Marino     bitmap_set_bit (entry_block_defs, REGNO (r));
3764*e4b17023SJohn Marino 
3765*e4b17023SJohn Marino   if ((!reload_completed) || frame_pointer_needed)
3766*e4b17023SJohn Marino     {
3767*e4b17023SJohn Marino       /* Any reference to any pseudo before reload is a potential
3768*e4b17023SJohn Marino 	 reference of the frame pointer.  */
3769*e4b17023SJohn Marino       bitmap_set_bit (entry_block_defs, FRAME_POINTER_REGNUM);
3770*e4b17023SJohn Marino #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
3771*e4b17023SJohn Marino       /* If they are different, also mark the hard frame pointer as live.  */
3772*e4b17023SJohn Marino       if (!LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM))
3773*e4b17023SJohn Marino 	bitmap_set_bit (entry_block_defs, HARD_FRAME_POINTER_REGNUM);
3774*e4b17023SJohn Marino #endif
3775*e4b17023SJohn Marino     }
3776*e4b17023SJohn Marino 
3777*e4b17023SJohn Marino   /* These registers are live everywhere.  */
3778*e4b17023SJohn Marino   if (!reload_completed)
3779*e4b17023SJohn Marino     {
3780*e4b17023SJohn Marino #ifdef PIC_OFFSET_TABLE_REGNUM
3781*e4b17023SJohn Marino       unsigned int picreg = PIC_OFFSET_TABLE_REGNUM;
3782*e4b17023SJohn Marino #endif
3783*e4b17023SJohn Marino 
3784*e4b17023SJohn Marino #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
3785*e4b17023SJohn Marino       /* Pseudos with argument area equivalences may require
3786*e4b17023SJohn Marino 	 reloading via the argument pointer.  */
3787*e4b17023SJohn Marino       if (fixed_regs[ARG_POINTER_REGNUM])
3788*e4b17023SJohn Marino 	bitmap_set_bit (entry_block_defs, ARG_POINTER_REGNUM);
3789*e4b17023SJohn Marino #endif
3790*e4b17023SJohn Marino 
3791*e4b17023SJohn Marino #ifdef PIC_OFFSET_TABLE_REGNUM
3792*e4b17023SJohn Marino       /* Any constant, or pseudo with constant equivalences, may
3793*e4b17023SJohn Marino 	 require reloading from memory using the pic register.  */
3794*e4b17023SJohn Marino       if (picreg != INVALID_REGNUM
3795*e4b17023SJohn Marino 	  && fixed_regs[picreg])
3796*e4b17023SJohn Marino 	bitmap_set_bit (entry_block_defs, picreg);
3797*e4b17023SJohn Marino #endif
3798*e4b17023SJohn Marino     }
3799*e4b17023SJohn Marino 
3800*e4b17023SJohn Marino #ifdef INCOMING_RETURN_ADDR_RTX
3801*e4b17023SJohn Marino   if (REG_P (INCOMING_RETURN_ADDR_RTX))
3802*e4b17023SJohn Marino     bitmap_set_bit (entry_block_defs, REGNO (INCOMING_RETURN_ADDR_RTX));
3803*e4b17023SJohn Marino #endif
3804*e4b17023SJohn Marino 
3805*e4b17023SJohn Marino   targetm.extra_live_on_entry (entry_block_defs);
3806*e4b17023SJohn Marino }
3807*e4b17023SJohn Marino 
3808*e4b17023SJohn Marino 
3809*e4b17023SJohn Marino /* Return the (conservative) set of hard registers that are defined on
3810*e4b17023SJohn Marino    entry to the function.
3811*e4b17023SJohn Marino    It uses df->entry_block_defs to determine which register
3812*e4b17023SJohn Marino    reference to include.  */
3813*e4b17023SJohn Marino 
3814*e4b17023SJohn Marino static void
df_entry_block_defs_collect(struct df_collection_rec * collection_rec,bitmap entry_block_defs)3815*e4b17023SJohn Marino df_entry_block_defs_collect (struct df_collection_rec *collection_rec,
3816*e4b17023SJohn Marino 			     bitmap entry_block_defs)
3817*e4b17023SJohn Marino {
3818*e4b17023SJohn Marino   unsigned int i;
3819*e4b17023SJohn Marino   bitmap_iterator bi;
3820*e4b17023SJohn Marino 
3821*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (entry_block_defs, 0, i, bi)
3822*e4b17023SJohn Marino     {
3823*e4b17023SJohn Marino       df_ref_record (DF_REF_ARTIFICIAL, collection_rec, regno_reg_rtx[i], NULL,
3824*e4b17023SJohn Marino 		     ENTRY_BLOCK_PTR, NULL, DF_REF_REG_DEF, 0);
3825*e4b17023SJohn Marino     }
3826*e4b17023SJohn Marino 
3827*e4b17023SJohn Marino   df_canonize_collection_rec (collection_rec);
3828*e4b17023SJohn Marino }
3829*e4b17023SJohn Marino 
3830*e4b17023SJohn Marino 
3831*e4b17023SJohn Marino /* Record the (conservative) set of hard registers that are defined on
3832*e4b17023SJohn Marino    entry to the function.  */
3833*e4b17023SJohn Marino 
3834*e4b17023SJohn Marino static void
df_record_entry_block_defs(bitmap entry_block_defs)3835*e4b17023SJohn Marino df_record_entry_block_defs (bitmap entry_block_defs)
3836*e4b17023SJohn Marino {
3837*e4b17023SJohn Marino   struct df_collection_rec collection_rec;
3838*e4b17023SJohn Marino   memset (&collection_rec, 0, sizeof (struct df_collection_rec));
3839*e4b17023SJohn Marino   collection_rec.def_vec = VEC_alloc (df_ref, stack, FIRST_PSEUDO_REGISTER);
3840*e4b17023SJohn Marino   df_entry_block_defs_collect (&collection_rec, entry_block_defs);
3841*e4b17023SJohn Marino 
3842*e4b17023SJohn Marino   /* Process bb_refs chain */
3843*e4b17023SJohn Marino   df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (ENTRY_BLOCK), NULL);
3844*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec.def_vec);
3845*e4b17023SJohn Marino }
3846*e4b17023SJohn Marino 
3847*e4b17023SJohn Marino 
3848*e4b17023SJohn Marino /* Update the defs in the entry block.  */
3849*e4b17023SJohn Marino 
3850*e4b17023SJohn Marino void
df_update_entry_block_defs(void)3851*e4b17023SJohn Marino df_update_entry_block_defs (void)
3852*e4b17023SJohn Marino {
3853*e4b17023SJohn Marino   bitmap_head refs;
3854*e4b17023SJohn Marino   bool changed = false;
3855*e4b17023SJohn Marino 
3856*e4b17023SJohn Marino   bitmap_initialize (&refs, &df_bitmap_obstack);
3857*e4b17023SJohn Marino   df_get_entry_block_def_set (&refs);
3858*e4b17023SJohn Marino   if (df->entry_block_defs)
3859*e4b17023SJohn Marino     {
3860*e4b17023SJohn Marino       if (!bitmap_equal_p (df->entry_block_defs, &refs))
3861*e4b17023SJohn Marino 	{
3862*e4b17023SJohn Marino 	  struct df_scan_bb_info *bb_info = df_scan_get_bb_info (ENTRY_BLOCK);
3863*e4b17023SJohn Marino 	  df_ref_chain_delete_du_chain (bb_info->artificial_defs);
3864*e4b17023SJohn Marino 	  df_ref_chain_delete (bb_info->artificial_defs);
3865*e4b17023SJohn Marino 	  bb_info->artificial_defs = NULL;
3866*e4b17023SJohn Marino 	  changed = true;
3867*e4b17023SJohn Marino 	}
3868*e4b17023SJohn Marino     }
3869*e4b17023SJohn Marino   else
3870*e4b17023SJohn Marino     {
3871*e4b17023SJohn Marino       struct df_scan_problem_data *problem_data
3872*e4b17023SJohn Marino 	= (struct df_scan_problem_data *) df_scan->problem_data;
3873*e4b17023SJohn Marino 	gcc_unreachable ();
3874*e4b17023SJohn Marino       df->entry_block_defs = BITMAP_ALLOC (&problem_data->reg_bitmaps);
3875*e4b17023SJohn Marino       changed = true;
3876*e4b17023SJohn Marino     }
3877*e4b17023SJohn Marino 
3878*e4b17023SJohn Marino   if (changed)
3879*e4b17023SJohn Marino     {
3880*e4b17023SJohn Marino       df_record_entry_block_defs (&refs);
3881*e4b17023SJohn Marino       bitmap_copy (df->entry_block_defs, &refs);
3882*e4b17023SJohn Marino       df_set_bb_dirty (BASIC_BLOCK (ENTRY_BLOCK));
3883*e4b17023SJohn Marino     }
3884*e4b17023SJohn Marino   bitmap_clear (&refs);
3885*e4b17023SJohn Marino }
3886*e4b17023SJohn Marino 
3887*e4b17023SJohn Marino 
3888*e4b17023SJohn Marino /* Set the bit for regs that are considered being used at the exit. */
3889*e4b17023SJohn Marino 
3890*e4b17023SJohn Marino static void
df_get_exit_block_use_set(bitmap exit_block_uses)3891*e4b17023SJohn Marino df_get_exit_block_use_set (bitmap exit_block_uses)
3892*e4b17023SJohn Marino {
3893*e4b17023SJohn Marino   unsigned int i;
3894*e4b17023SJohn Marino   unsigned int picreg = PIC_OFFSET_TABLE_REGNUM;
3895*e4b17023SJohn Marino 
3896*e4b17023SJohn Marino   bitmap_clear (exit_block_uses);
3897*e4b17023SJohn Marino 
3898*e4b17023SJohn Marino   /* Stack pointer is always live at the exit.  */
3899*e4b17023SJohn Marino   bitmap_set_bit (exit_block_uses, STACK_POINTER_REGNUM);
3900*e4b17023SJohn Marino 
3901*e4b17023SJohn Marino   /* Mark the frame pointer if needed at the end of the function.
3902*e4b17023SJohn Marino      If we end up eliminating it, it will be removed from the live
3903*e4b17023SJohn Marino      list of each basic block by reload.  */
3904*e4b17023SJohn Marino 
3905*e4b17023SJohn Marino   if ((!reload_completed) || frame_pointer_needed)
3906*e4b17023SJohn Marino     {
3907*e4b17023SJohn Marino       bitmap_set_bit (exit_block_uses, FRAME_POINTER_REGNUM);
3908*e4b17023SJohn Marino #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
3909*e4b17023SJohn Marino       /* If they are different, also mark the hard frame pointer as live.  */
3910*e4b17023SJohn Marino       if (!LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM))
3911*e4b17023SJohn Marino 	bitmap_set_bit (exit_block_uses, HARD_FRAME_POINTER_REGNUM);
3912*e4b17023SJohn Marino #endif
3913*e4b17023SJohn Marino     }
3914*e4b17023SJohn Marino 
3915*e4b17023SJohn Marino   /* Many architectures have a GP register even without flag_pic.
3916*e4b17023SJohn Marino      Assume the pic register is not in use, or will be handled by
3917*e4b17023SJohn Marino      other means, if it is not fixed.  */
3918*e4b17023SJohn Marino   if (!PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
3919*e4b17023SJohn Marino       && picreg != INVALID_REGNUM
3920*e4b17023SJohn Marino       && fixed_regs[picreg])
3921*e4b17023SJohn Marino     bitmap_set_bit (exit_block_uses, picreg);
3922*e4b17023SJohn Marino 
3923*e4b17023SJohn Marino   /* Mark all global registers, and all registers used by the
3924*e4b17023SJohn Marino      epilogue as being live at the end of the function since they
3925*e4b17023SJohn Marino      may be referenced by our caller.  */
3926*e4b17023SJohn Marino   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3927*e4b17023SJohn Marino     if (global_regs[i] || EPILOGUE_USES (i))
3928*e4b17023SJohn Marino       bitmap_set_bit (exit_block_uses, i);
3929*e4b17023SJohn Marino 
3930*e4b17023SJohn Marino   if (HAVE_epilogue && epilogue_completed)
3931*e4b17023SJohn Marino     {
3932*e4b17023SJohn Marino       /* Mark all call-saved registers that we actually used.  */
3933*e4b17023SJohn Marino       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3934*e4b17023SJohn Marino 	if (df_regs_ever_live_p (i) && !LOCAL_REGNO (i)
3935*e4b17023SJohn Marino 	    && !TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
3936*e4b17023SJohn Marino 	  bitmap_set_bit (exit_block_uses, i);
3937*e4b17023SJohn Marino     }
3938*e4b17023SJohn Marino 
3939*e4b17023SJohn Marino #ifdef EH_RETURN_DATA_REGNO
3940*e4b17023SJohn Marino   /* Mark the registers that will contain data for the handler.  */
3941*e4b17023SJohn Marino   if (reload_completed && crtl->calls_eh_return)
3942*e4b17023SJohn Marino     for (i = 0; ; ++i)
3943*e4b17023SJohn Marino       {
3944*e4b17023SJohn Marino 	unsigned regno = EH_RETURN_DATA_REGNO (i);
3945*e4b17023SJohn Marino 	if (regno == INVALID_REGNUM)
3946*e4b17023SJohn Marino 	  break;
3947*e4b17023SJohn Marino 	bitmap_set_bit (exit_block_uses, regno);
3948*e4b17023SJohn Marino       }
3949*e4b17023SJohn Marino #endif
3950*e4b17023SJohn Marino 
3951*e4b17023SJohn Marino #ifdef EH_RETURN_STACKADJ_RTX
3952*e4b17023SJohn Marino   if ((!HAVE_epilogue || ! epilogue_completed)
3953*e4b17023SJohn Marino       && crtl->calls_eh_return)
3954*e4b17023SJohn Marino     {
3955*e4b17023SJohn Marino       rtx tmp = EH_RETURN_STACKADJ_RTX;
3956*e4b17023SJohn Marino       if (tmp && REG_P (tmp))
3957*e4b17023SJohn Marino 	df_mark_reg (tmp, exit_block_uses);
3958*e4b17023SJohn Marino     }
3959*e4b17023SJohn Marino #endif
3960*e4b17023SJohn Marino 
3961*e4b17023SJohn Marino #ifdef EH_RETURN_HANDLER_RTX
3962*e4b17023SJohn Marino   if ((!HAVE_epilogue || ! epilogue_completed)
3963*e4b17023SJohn Marino       && crtl->calls_eh_return)
3964*e4b17023SJohn Marino     {
3965*e4b17023SJohn Marino       rtx tmp = EH_RETURN_HANDLER_RTX;
3966*e4b17023SJohn Marino       if (tmp && REG_P (tmp))
3967*e4b17023SJohn Marino 	df_mark_reg (tmp, exit_block_uses);
3968*e4b17023SJohn Marino     }
3969*e4b17023SJohn Marino #endif
3970*e4b17023SJohn Marino 
3971*e4b17023SJohn Marino   /* Mark function return value.  */
3972*e4b17023SJohn Marino   diddle_return_value (df_mark_reg, (void*) exit_block_uses);
3973*e4b17023SJohn Marino }
3974*e4b17023SJohn Marino 
3975*e4b17023SJohn Marino 
3976*e4b17023SJohn Marino /* Return the refs of hard registers that are used in the exit block.
3977*e4b17023SJohn Marino    It uses df->exit_block_uses to determine register to include.  */
3978*e4b17023SJohn Marino 
3979*e4b17023SJohn Marino static void
df_exit_block_uses_collect(struct df_collection_rec * collection_rec,bitmap exit_block_uses)3980*e4b17023SJohn Marino df_exit_block_uses_collect (struct df_collection_rec *collection_rec, bitmap exit_block_uses)
3981*e4b17023SJohn Marino {
3982*e4b17023SJohn Marino   unsigned int i;
3983*e4b17023SJohn Marino   bitmap_iterator bi;
3984*e4b17023SJohn Marino 
3985*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (exit_block_uses, 0, i, bi)
3986*e4b17023SJohn Marino     df_ref_record (DF_REF_ARTIFICIAL, collection_rec, regno_reg_rtx[i], NULL,
3987*e4b17023SJohn Marino 		   EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0);
3988*e4b17023SJohn Marino 
3989*e4b17023SJohn Marino #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
3990*e4b17023SJohn Marino   /* It is deliberate that this is not put in the exit block uses but
3991*e4b17023SJohn Marino      I do not know why.  */
3992*e4b17023SJohn Marino   if (reload_completed
3993*e4b17023SJohn Marino       && !bitmap_bit_p (exit_block_uses, ARG_POINTER_REGNUM)
3994*e4b17023SJohn Marino       && bb_has_eh_pred (EXIT_BLOCK_PTR)
3995*e4b17023SJohn Marino       && fixed_regs[ARG_POINTER_REGNUM])
3996*e4b17023SJohn Marino     df_ref_record (DF_REF_ARTIFICIAL, collection_rec, regno_reg_rtx[ARG_POINTER_REGNUM], NULL,
3997*e4b17023SJohn Marino 		   EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0);
3998*e4b17023SJohn Marino #endif
3999*e4b17023SJohn Marino 
4000*e4b17023SJohn Marino   df_canonize_collection_rec (collection_rec);
4001*e4b17023SJohn Marino }
4002*e4b17023SJohn Marino 
4003*e4b17023SJohn Marino 
4004*e4b17023SJohn Marino /* Record the set of hard registers that are used in the exit block.
4005*e4b17023SJohn Marino    It uses df->exit_block_uses to determine which bit to include.  */
4006*e4b17023SJohn Marino 
4007*e4b17023SJohn Marino static void
df_record_exit_block_uses(bitmap exit_block_uses)4008*e4b17023SJohn Marino df_record_exit_block_uses (bitmap exit_block_uses)
4009*e4b17023SJohn Marino {
4010*e4b17023SJohn Marino   struct df_collection_rec collection_rec;
4011*e4b17023SJohn Marino   memset (&collection_rec, 0, sizeof (struct df_collection_rec));
4012*e4b17023SJohn Marino   collection_rec.use_vec = VEC_alloc (df_ref, stack, FIRST_PSEUDO_REGISTER);
4013*e4b17023SJohn Marino 
4014*e4b17023SJohn Marino   df_exit_block_uses_collect (&collection_rec, exit_block_uses);
4015*e4b17023SJohn Marino 
4016*e4b17023SJohn Marino   /* Process bb_refs chain */
4017*e4b17023SJohn Marino   df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (EXIT_BLOCK), NULL);
4018*e4b17023SJohn Marino   VEC_free (df_ref, stack, collection_rec.use_vec);
4019*e4b17023SJohn Marino }
4020*e4b17023SJohn Marino 
4021*e4b17023SJohn Marino 
4022*e4b17023SJohn Marino /* Update the uses in the exit block.  */
4023*e4b17023SJohn Marino 
4024*e4b17023SJohn Marino void
df_update_exit_block_uses(void)4025*e4b17023SJohn Marino df_update_exit_block_uses (void)
4026*e4b17023SJohn Marino {
4027*e4b17023SJohn Marino   bitmap_head refs;
4028*e4b17023SJohn Marino   bool changed = false;
4029*e4b17023SJohn Marino 
4030*e4b17023SJohn Marino   bitmap_initialize (&refs, &df_bitmap_obstack);
4031*e4b17023SJohn Marino   df_get_exit_block_use_set (&refs);
4032*e4b17023SJohn Marino   if (df->exit_block_uses)
4033*e4b17023SJohn Marino     {
4034*e4b17023SJohn Marino       if (!bitmap_equal_p (df->exit_block_uses, &refs))
4035*e4b17023SJohn Marino 	{
4036*e4b17023SJohn Marino 	  struct df_scan_bb_info *bb_info = df_scan_get_bb_info (EXIT_BLOCK);
4037*e4b17023SJohn Marino 	  df_ref_chain_delete_du_chain (bb_info->artificial_uses);
4038*e4b17023SJohn Marino 	  df_ref_chain_delete (bb_info->artificial_uses);
4039*e4b17023SJohn Marino 	  bb_info->artificial_uses = NULL;
4040*e4b17023SJohn Marino 	  changed = true;
4041*e4b17023SJohn Marino 	}
4042*e4b17023SJohn Marino     }
4043*e4b17023SJohn Marino   else
4044*e4b17023SJohn Marino     {
4045*e4b17023SJohn Marino       struct df_scan_problem_data *problem_data
4046*e4b17023SJohn Marino 	= (struct df_scan_problem_data *) df_scan->problem_data;
4047*e4b17023SJohn Marino 	gcc_unreachable ();
4048*e4b17023SJohn Marino       df->exit_block_uses = BITMAP_ALLOC (&problem_data->reg_bitmaps);
4049*e4b17023SJohn Marino       changed = true;
4050*e4b17023SJohn Marino     }
4051*e4b17023SJohn Marino 
4052*e4b17023SJohn Marino   if (changed)
4053*e4b17023SJohn Marino     {
4054*e4b17023SJohn Marino       df_record_exit_block_uses (&refs);
4055*e4b17023SJohn Marino       bitmap_copy (df->exit_block_uses,& refs);
4056*e4b17023SJohn Marino       df_set_bb_dirty (BASIC_BLOCK (EXIT_BLOCK));
4057*e4b17023SJohn Marino     }
4058*e4b17023SJohn Marino   bitmap_clear (&refs);
4059*e4b17023SJohn Marino }
4060*e4b17023SJohn Marino 
4061*e4b17023SJohn Marino static bool initialized = false;
4062*e4b17023SJohn Marino 
4063*e4b17023SJohn Marino 
4064*e4b17023SJohn Marino /* Initialize some platform specific structures.  */
4065*e4b17023SJohn Marino 
4066*e4b17023SJohn Marino void
df_hard_reg_init(void)4067*e4b17023SJohn Marino df_hard_reg_init (void)
4068*e4b17023SJohn Marino {
4069*e4b17023SJohn Marino #ifdef ELIMINABLE_REGS
4070*e4b17023SJohn Marino   int i;
4071*e4b17023SJohn Marino   static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
4072*e4b17023SJohn Marino #endif
4073*e4b17023SJohn Marino   if (initialized)
4074*e4b17023SJohn Marino     return;
4075*e4b17023SJohn Marino 
4076*e4b17023SJohn Marino   /* Record which registers will be eliminated.  We use this in
4077*e4b17023SJohn Marino      mark_used_regs.  */
4078*e4b17023SJohn Marino   CLEAR_HARD_REG_SET (elim_reg_set);
4079*e4b17023SJohn Marino 
4080*e4b17023SJohn Marino #ifdef ELIMINABLE_REGS
4081*e4b17023SJohn Marino   for (i = 0; i < (int) ARRAY_SIZE (eliminables); i++)
4082*e4b17023SJohn Marino     SET_HARD_REG_BIT (elim_reg_set, eliminables[i].from);
4083*e4b17023SJohn Marino #else
4084*e4b17023SJohn Marino   SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
4085*e4b17023SJohn Marino #endif
4086*e4b17023SJohn Marino 
4087*e4b17023SJohn Marino   initialized = true;
4088*e4b17023SJohn Marino }
4089*e4b17023SJohn Marino 
4090*e4b17023SJohn Marino 
4091*e4b17023SJohn Marino /* Recompute the parts of scanning that are based on regs_ever_live
4092*e4b17023SJohn Marino    because something changed in that array.  */
4093*e4b17023SJohn Marino 
4094*e4b17023SJohn Marino void
df_update_entry_exit_and_calls(void)4095*e4b17023SJohn Marino df_update_entry_exit_and_calls (void)
4096*e4b17023SJohn Marino {
4097*e4b17023SJohn Marino   basic_block bb;
4098*e4b17023SJohn Marino 
4099*e4b17023SJohn Marino   df_update_entry_block_defs ();
4100*e4b17023SJohn Marino   df_update_exit_block_uses ();
4101*e4b17023SJohn Marino 
4102*e4b17023SJohn Marino   /* The call insns need to be rescanned because there may be changes
4103*e4b17023SJohn Marino      in the set of registers clobbered across the call.  */
4104*e4b17023SJohn Marino   FOR_EACH_BB (bb)
4105*e4b17023SJohn Marino     {
4106*e4b17023SJohn Marino       rtx insn;
4107*e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
4108*e4b17023SJohn Marino 	{
4109*e4b17023SJohn Marino 	  if (INSN_P (insn) && CALL_P (insn))
4110*e4b17023SJohn Marino 	    df_insn_rescan (insn);
4111*e4b17023SJohn Marino 	}
4112*e4b17023SJohn Marino     }
4113*e4b17023SJohn Marino }
4114*e4b17023SJohn Marino 
4115*e4b17023SJohn Marino 
4116*e4b17023SJohn Marino /* Return true if hard REG is actually used in the some instruction.
4117*e4b17023SJohn Marino    There are a fair number of conditions that affect the setting of
4118*e4b17023SJohn Marino    this array.  See the comment in df.h for df->hard_regs_live_count
4119*e4b17023SJohn Marino    for the conditions that this array is set. */
4120*e4b17023SJohn Marino 
4121*e4b17023SJohn Marino bool
df_hard_reg_used_p(unsigned int reg)4122*e4b17023SJohn Marino df_hard_reg_used_p (unsigned int reg)
4123*e4b17023SJohn Marino {
4124*e4b17023SJohn Marino   return df->hard_regs_live_count[reg] != 0;
4125*e4b17023SJohn Marino }
4126*e4b17023SJohn Marino 
4127*e4b17023SJohn Marino 
4128*e4b17023SJohn Marino /* A count of the number of times REG is actually used in the some
4129*e4b17023SJohn Marino    instruction.  There are a fair number of conditions that affect the
4130*e4b17023SJohn Marino    setting of this array.  See the comment in df.h for
4131*e4b17023SJohn Marino    df->hard_regs_live_count for the conditions that this array is
4132*e4b17023SJohn Marino    set. */
4133*e4b17023SJohn Marino 
4134*e4b17023SJohn Marino 
4135*e4b17023SJohn Marino unsigned int
df_hard_reg_used_count(unsigned int reg)4136*e4b17023SJohn Marino df_hard_reg_used_count (unsigned int reg)
4137*e4b17023SJohn Marino {
4138*e4b17023SJohn Marino   return df->hard_regs_live_count[reg];
4139*e4b17023SJohn Marino }
4140*e4b17023SJohn Marino 
4141*e4b17023SJohn Marino 
4142*e4b17023SJohn Marino /* Get the value of regs_ever_live[REGNO].  */
4143*e4b17023SJohn Marino 
4144*e4b17023SJohn Marino bool
df_regs_ever_live_p(unsigned int regno)4145*e4b17023SJohn Marino df_regs_ever_live_p (unsigned int regno)
4146*e4b17023SJohn Marino {
4147*e4b17023SJohn Marino   return regs_ever_live[regno];
4148*e4b17023SJohn Marino }
4149*e4b17023SJohn Marino 
4150*e4b17023SJohn Marino 
4151*e4b17023SJohn Marino /* Set regs_ever_live[REGNO] to VALUE.  If this cause regs_ever_live
4152*e4b17023SJohn Marino    to change, schedule that change for the next update.  */
4153*e4b17023SJohn Marino 
4154*e4b17023SJohn Marino void
df_set_regs_ever_live(unsigned int regno,bool value)4155*e4b17023SJohn Marino df_set_regs_ever_live (unsigned int regno, bool value)
4156*e4b17023SJohn Marino {
4157*e4b17023SJohn Marino   if (regs_ever_live[regno] == value)
4158*e4b17023SJohn Marino     return;
4159*e4b17023SJohn Marino 
4160*e4b17023SJohn Marino   regs_ever_live[regno] = value;
4161*e4b17023SJohn Marino   if (df)
4162*e4b17023SJohn Marino     df->redo_entry_and_exit = true;
4163*e4b17023SJohn Marino }
4164*e4b17023SJohn Marino 
4165*e4b17023SJohn Marino 
4166*e4b17023SJohn Marino /* Compute "regs_ever_live" information from the underlying df
4167*e4b17023SJohn Marino    information.  Set the vector to all false if RESET.  */
4168*e4b17023SJohn Marino 
4169*e4b17023SJohn Marino void
df_compute_regs_ever_live(bool reset)4170*e4b17023SJohn Marino df_compute_regs_ever_live (bool reset)
4171*e4b17023SJohn Marino {
4172*e4b17023SJohn Marino   unsigned int i;
4173*e4b17023SJohn Marino   bool changed = df->redo_entry_and_exit;
4174*e4b17023SJohn Marino 
4175*e4b17023SJohn Marino   if (reset)
4176*e4b17023SJohn Marino     memset (regs_ever_live, 0, sizeof (regs_ever_live));
4177*e4b17023SJohn Marino 
4178*e4b17023SJohn Marino   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4179*e4b17023SJohn Marino     if ((!regs_ever_live[i]) && df_hard_reg_used_p (i))
4180*e4b17023SJohn Marino       {
4181*e4b17023SJohn Marino 	regs_ever_live[i] = true;
4182*e4b17023SJohn Marino 	changed = true;
4183*e4b17023SJohn Marino       }
4184*e4b17023SJohn Marino   if (changed)
4185*e4b17023SJohn Marino     df_update_entry_exit_and_calls ();
4186*e4b17023SJohn Marino   df->redo_entry_and_exit = false;
4187*e4b17023SJohn Marino }
4188*e4b17023SJohn Marino 
4189*e4b17023SJohn Marino 
4190*e4b17023SJohn Marino /*----------------------------------------------------------------------------
4191*e4b17023SJohn Marino   Dataflow ref information verification functions.
4192*e4b17023SJohn Marino 
4193*e4b17023SJohn Marino   df_reg_chain_mark (refs, regno, is_def, is_eq_use)
4194*e4b17023SJohn Marino   df_reg_chain_verify_unmarked (refs)
4195*e4b17023SJohn Marino   df_refs_verify (VEC(stack,df_ref)*, ref*, bool)
4196*e4b17023SJohn Marino   df_mws_verify (mw*, mw*, bool)
4197*e4b17023SJohn Marino   df_insn_refs_verify (collection_rec, bb, insn, bool)
4198*e4b17023SJohn Marino   df_bb_refs_verify (bb, refs, bool)
4199*e4b17023SJohn Marino   df_bb_verify (bb)
4200*e4b17023SJohn Marino   df_exit_block_bitmap_verify (bool)
4201*e4b17023SJohn Marino   df_entry_block_bitmap_verify (bool)
4202*e4b17023SJohn Marino   df_scan_verify ()
4203*e4b17023SJohn Marino ----------------------------------------------------------------------------*/
4204*e4b17023SJohn Marino 
4205*e4b17023SJohn Marino 
4206*e4b17023SJohn Marino /* Mark all refs in the reg chain.  Verify that all of the registers
4207*e4b17023SJohn Marino are in the correct chain.  */
4208*e4b17023SJohn Marino 
4209*e4b17023SJohn Marino static unsigned int
df_reg_chain_mark(df_ref refs,unsigned int regno,bool is_def,bool is_eq_use)4210*e4b17023SJohn Marino df_reg_chain_mark (df_ref refs, unsigned int regno,
4211*e4b17023SJohn Marino 		   bool is_def, bool is_eq_use)
4212*e4b17023SJohn Marino {
4213*e4b17023SJohn Marino   unsigned int count = 0;
4214*e4b17023SJohn Marino   df_ref ref;
4215*e4b17023SJohn Marino   for (ref = refs; ref; ref = DF_REF_NEXT_REG (ref))
4216*e4b17023SJohn Marino     {
4217*e4b17023SJohn Marino       gcc_assert (!DF_REF_IS_REG_MARKED (ref));
4218*e4b17023SJohn Marino 
4219*e4b17023SJohn Marino       /* If there are no def-use or use-def chains, make sure that all
4220*e4b17023SJohn Marino 	 of the chains are clear.  */
4221*e4b17023SJohn Marino       if (!df_chain)
4222*e4b17023SJohn Marino 	gcc_assert (!DF_REF_CHAIN (ref));
4223*e4b17023SJohn Marino 
4224*e4b17023SJohn Marino       /* Check to make sure the ref is in the correct chain.  */
4225*e4b17023SJohn Marino       gcc_assert (DF_REF_REGNO (ref) == regno);
4226*e4b17023SJohn Marino       if (is_def)
4227*e4b17023SJohn Marino 	gcc_assert (DF_REF_REG_DEF_P (ref));
4228*e4b17023SJohn Marino       else
4229*e4b17023SJohn Marino 	gcc_assert (!DF_REF_REG_DEF_P (ref));
4230*e4b17023SJohn Marino 
4231*e4b17023SJohn Marino       if (is_eq_use)
4232*e4b17023SJohn Marino 	gcc_assert ((DF_REF_FLAGS (ref) & DF_REF_IN_NOTE));
4233*e4b17023SJohn Marino       else
4234*e4b17023SJohn Marino 	gcc_assert ((DF_REF_FLAGS (ref) & DF_REF_IN_NOTE) == 0);
4235*e4b17023SJohn Marino 
4236*e4b17023SJohn Marino       if (DF_REF_NEXT_REG (ref))
4237*e4b17023SJohn Marino 	gcc_assert (DF_REF_PREV_REG (DF_REF_NEXT_REG (ref)) == ref);
4238*e4b17023SJohn Marino       count++;
4239*e4b17023SJohn Marino       DF_REF_REG_MARK (ref);
4240*e4b17023SJohn Marino     }
4241*e4b17023SJohn Marino   return count;
4242*e4b17023SJohn Marino }
4243*e4b17023SJohn Marino 
4244*e4b17023SJohn Marino 
4245*e4b17023SJohn Marino /* Verify that all of the registers in the chain are unmarked.  */
4246*e4b17023SJohn Marino 
4247*e4b17023SJohn Marino static void
df_reg_chain_verify_unmarked(df_ref refs)4248*e4b17023SJohn Marino df_reg_chain_verify_unmarked (df_ref refs)
4249*e4b17023SJohn Marino {
4250*e4b17023SJohn Marino   df_ref ref;
4251*e4b17023SJohn Marino   for (ref = refs; ref; ref = DF_REF_NEXT_REG (ref))
4252*e4b17023SJohn Marino     gcc_assert (!DF_REF_IS_REG_MARKED (ref));
4253*e4b17023SJohn Marino }
4254*e4b17023SJohn Marino 
4255*e4b17023SJohn Marino 
4256*e4b17023SJohn Marino /* Verify that NEW_REC and OLD_REC have exactly the same members. */
4257*e4b17023SJohn Marino 
4258*e4b17023SJohn Marino static bool
df_refs_verify(VEC (df_ref,stack)* new_rec,df_ref * old_rec,bool abort_if_fail)4259*e4b17023SJohn Marino df_refs_verify (VEC(df_ref,stack) *new_rec, df_ref *old_rec,
4260*e4b17023SJohn Marino 		bool abort_if_fail)
4261*e4b17023SJohn Marino {
4262*e4b17023SJohn Marino   unsigned int ix;
4263*e4b17023SJohn Marino   df_ref new_ref;
4264*e4b17023SJohn Marino 
4265*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (df_ref, new_rec, ix, new_ref)
4266*e4b17023SJohn Marino     {
4267*e4b17023SJohn Marino       if (*old_rec == NULL || !df_ref_equal_p (new_ref, *old_rec))
4268*e4b17023SJohn Marino 	{
4269*e4b17023SJohn Marino 	  if (abort_if_fail)
4270*e4b17023SJohn Marino 	    gcc_assert (0);
4271*e4b17023SJohn Marino 	  else
4272*e4b17023SJohn Marino 	    return false;
4273*e4b17023SJohn Marino 	}
4274*e4b17023SJohn Marino 
4275*e4b17023SJohn Marino       /* Abort if fail is called from the function level verifier.  If
4276*e4b17023SJohn Marino 	 that is the context, mark this reg as being seem.  */
4277*e4b17023SJohn Marino       if (abort_if_fail)
4278*e4b17023SJohn Marino 	{
4279*e4b17023SJohn Marino 	  gcc_assert (DF_REF_IS_REG_MARKED (*old_rec));
4280*e4b17023SJohn Marino 	  DF_REF_REG_UNMARK (*old_rec);
4281*e4b17023SJohn Marino 	}
4282*e4b17023SJohn Marino 
4283*e4b17023SJohn Marino       old_rec++;
4284*e4b17023SJohn Marino     }
4285*e4b17023SJohn Marino 
4286*e4b17023SJohn Marino   if (abort_if_fail)
4287*e4b17023SJohn Marino     gcc_assert (*old_rec == NULL);
4288*e4b17023SJohn Marino   else
4289*e4b17023SJohn Marino     return *old_rec == NULL;
4290*e4b17023SJohn Marino   return false;
4291*e4b17023SJohn Marino }
4292*e4b17023SJohn Marino 
4293*e4b17023SJohn Marino 
4294*e4b17023SJohn Marino /* Verify that NEW_REC and OLD_REC have exactly the same members. */
4295*e4b17023SJohn Marino 
4296*e4b17023SJohn Marino static bool
df_mws_verify(VEC (df_mw_hardreg_ptr,stack)* new_rec,struct df_mw_hardreg ** old_rec,bool abort_if_fail)4297*e4b17023SJohn Marino df_mws_verify (VEC(df_mw_hardreg_ptr,stack) *new_rec,
4298*e4b17023SJohn Marino 	       struct df_mw_hardreg **old_rec,
4299*e4b17023SJohn Marino 	       bool abort_if_fail)
4300*e4b17023SJohn Marino {
4301*e4b17023SJohn Marino   unsigned int ix;
4302*e4b17023SJohn Marino   struct df_mw_hardreg *new_reg;
4303*e4b17023SJohn Marino 
4304*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (df_mw_hardreg_ptr, new_rec, ix, new_reg)
4305*e4b17023SJohn Marino     {
4306*e4b17023SJohn Marino       if (*old_rec == NULL || !df_mw_equal_p (new_reg, *old_rec))
4307*e4b17023SJohn Marino 	{
4308*e4b17023SJohn Marino 	  if (abort_if_fail)
4309*e4b17023SJohn Marino 	    gcc_assert (0);
4310*e4b17023SJohn Marino 	  else
4311*e4b17023SJohn Marino 	    return false;
4312*e4b17023SJohn Marino 	}
4313*e4b17023SJohn Marino       old_rec++;
4314*e4b17023SJohn Marino     }
4315*e4b17023SJohn Marino 
4316*e4b17023SJohn Marino   if (abort_if_fail)
4317*e4b17023SJohn Marino     gcc_assert (*old_rec == NULL);
4318*e4b17023SJohn Marino   else
4319*e4b17023SJohn Marino     return *old_rec == NULL;
4320*e4b17023SJohn Marino   return false;
4321*e4b17023SJohn Marino }
4322*e4b17023SJohn Marino 
4323*e4b17023SJohn Marino 
4324*e4b17023SJohn Marino /* Return true if the existing insn refs information is complete and
4325*e4b17023SJohn Marino    correct. Otherwise (i.e. if there's any missing or extra refs),
4326*e4b17023SJohn Marino    return the correct df_ref chain in REFS_RETURN.
4327*e4b17023SJohn Marino 
4328*e4b17023SJohn Marino    If ABORT_IF_FAIL, leave the refs that are verified (already in the
4329*e4b17023SJohn Marino    ref chain) as DF_REF_MARKED(). If it's false, then it's a per-insn
4330*e4b17023SJohn Marino    verification mode instead of the whole function, so unmark
4331*e4b17023SJohn Marino    everything.
4332*e4b17023SJohn Marino 
4333*e4b17023SJohn Marino    If ABORT_IF_FAIL is set, this function never returns false.  */
4334*e4b17023SJohn Marino 
4335*e4b17023SJohn Marino static bool
df_insn_refs_verify(struct df_collection_rec * collection_rec,basic_block bb,rtx insn,bool abort_if_fail)4336*e4b17023SJohn Marino df_insn_refs_verify (struct df_collection_rec *collection_rec,
4337*e4b17023SJohn Marino 		     basic_block bb,
4338*e4b17023SJohn Marino                      rtx insn,
4339*e4b17023SJohn Marino 		     bool abort_if_fail)
4340*e4b17023SJohn Marino {
4341*e4b17023SJohn Marino   bool ret1, ret2, ret3, ret4;
4342*e4b17023SJohn Marino   unsigned int uid = INSN_UID (insn);
4343*e4b17023SJohn Marino   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
4344*e4b17023SJohn Marino 
4345*e4b17023SJohn Marino   df_insn_refs_collect (collection_rec, bb, insn_info);
4346*e4b17023SJohn Marino 
4347*e4b17023SJohn Marino   if (!DF_INSN_UID_DEFS (uid))
4348*e4b17023SJohn Marino     {
4349*e4b17023SJohn Marino       /* The insn_rec was created but it was never filled out.  */
4350*e4b17023SJohn Marino       if (abort_if_fail)
4351*e4b17023SJohn Marino 	gcc_assert (0);
4352*e4b17023SJohn Marino       else
4353*e4b17023SJohn Marino 	return false;
4354*e4b17023SJohn Marino     }
4355*e4b17023SJohn Marino 
4356*e4b17023SJohn Marino   /* Unfortunately we cannot opt out early if one of these is not
4357*e4b17023SJohn Marino      right because the marks will not get cleared.  */
4358*e4b17023SJohn Marino   ret1 = df_refs_verify (collection_rec->def_vec, DF_INSN_UID_DEFS (uid),
4359*e4b17023SJohn Marino 			 abort_if_fail);
4360*e4b17023SJohn Marino   ret2 = df_refs_verify (collection_rec->use_vec, DF_INSN_UID_USES (uid),
4361*e4b17023SJohn Marino 			 abort_if_fail);
4362*e4b17023SJohn Marino   ret3 = df_refs_verify (collection_rec->eq_use_vec, DF_INSN_UID_EQ_USES (uid),
4363*e4b17023SJohn Marino 			 abort_if_fail);
4364*e4b17023SJohn Marino   ret4 = df_mws_verify (collection_rec->mw_vec, DF_INSN_UID_MWS (uid),
4365*e4b17023SJohn Marino 		       abort_if_fail);
4366*e4b17023SJohn Marino   return (ret1 && ret2 && ret3 && ret4);
4367*e4b17023SJohn Marino }
4368*e4b17023SJohn Marino 
4369*e4b17023SJohn Marino 
4370*e4b17023SJohn Marino /* Return true if all refs in the basic block are correct and complete.
4371*e4b17023SJohn Marino    Due to df_ref_chain_verify, it will cause all refs
4372*e4b17023SJohn Marino    that are verified to have DF_REF_MARK bit set.  */
4373*e4b17023SJohn Marino 
4374*e4b17023SJohn Marino static bool
df_bb_verify(basic_block bb)4375*e4b17023SJohn Marino df_bb_verify (basic_block bb)
4376*e4b17023SJohn Marino {
4377*e4b17023SJohn Marino   rtx insn;
4378*e4b17023SJohn Marino   struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb->index);
4379*e4b17023SJohn Marino   struct df_collection_rec collection_rec;
4380*e4b17023SJohn Marino 
4381*e4b17023SJohn Marino   memset (&collection_rec, 0, sizeof (struct df_collection_rec));
4382*e4b17023SJohn Marino   collection_rec.def_vec = VEC_alloc (df_ref, stack, 128);
4383*e4b17023SJohn Marino   collection_rec.use_vec = VEC_alloc (df_ref, stack, 32);
4384*e4b17023SJohn Marino   collection_rec.eq_use_vec = VEC_alloc (df_ref, stack, 32);
4385*e4b17023SJohn Marino   collection_rec.mw_vec = VEC_alloc (df_mw_hardreg_ptr, stack, 32);
4386*e4b17023SJohn Marino 
4387*e4b17023SJohn Marino   gcc_assert (bb_info);
4388*e4b17023SJohn Marino 
4389*e4b17023SJohn Marino   /* Scan the block, one insn at a time, from beginning to end.  */
4390*e4b17023SJohn Marino   FOR_BB_INSNS_REVERSE (bb, insn)
4391*e4b17023SJohn Marino     {
4392*e4b17023SJohn Marino       if (!INSN_P (insn))
4393*e4b17023SJohn Marino         continue;
4394*e4b17023SJohn Marino       df_insn_refs_verify (&collection_rec, bb, insn, true);
4395*e4b17023SJohn Marino       df_free_collection_rec (&collection_rec);
4396*e4b17023SJohn Marino     }
4397*e4b17023SJohn Marino 
4398*e4b17023SJohn Marino   /* Do the artificial defs and uses.  */
4399*e4b17023SJohn Marino   df_bb_refs_collect (&collection_rec, bb);
4400*e4b17023SJohn Marino   df_refs_verify (collection_rec.def_vec, df_get_artificial_defs (bb->index), true);
4401*e4b17023SJohn Marino   df_refs_verify (collection_rec.use_vec, df_get_artificial_uses (bb->index), true);
4402*e4b17023SJohn Marino   df_free_collection_rec (&collection_rec);
4403*e4b17023SJohn Marino 
4404*e4b17023SJohn Marino   return true;
4405*e4b17023SJohn Marino }
4406*e4b17023SJohn Marino 
4407*e4b17023SJohn Marino 
4408*e4b17023SJohn Marino /* Returns true if the entry block has correct and complete df_ref set.
4409*e4b17023SJohn Marino    If not it either aborts if ABORT_IF_FAIL is true or returns false.  */
4410*e4b17023SJohn Marino 
4411*e4b17023SJohn Marino static bool
df_entry_block_bitmap_verify(bool abort_if_fail)4412*e4b17023SJohn Marino df_entry_block_bitmap_verify (bool abort_if_fail)
4413*e4b17023SJohn Marino {
4414*e4b17023SJohn Marino   bitmap_head entry_block_defs;
4415*e4b17023SJohn Marino   bool is_eq;
4416*e4b17023SJohn Marino 
4417*e4b17023SJohn Marino   bitmap_initialize (&entry_block_defs, &df_bitmap_obstack);
4418*e4b17023SJohn Marino   df_get_entry_block_def_set (&entry_block_defs);
4419*e4b17023SJohn Marino 
4420*e4b17023SJohn Marino   is_eq = bitmap_equal_p (&entry_block_defs, df->entry_block_defs);
4421*e4b17023SJohn Marino 
4422*e4b17023SJohn Marino   if (!is_eq && abort_if_fail)
4423*e4b17023SJohn Marino     {
4424*e4b17023SJohn Marino       print_current_pass (stderr);
4425*e4b17023SJohn Marino       fprintf (stderr, "entry_block_defs = ");
4426*e4b17023SJohn Marino       df_print_regset (stderr, &entry_block_defs);
4427*e4b17023SJohn Marino       fprintf (stderr, "df->entry_block_defs = ");
4428*e4b17023SJohn Marino       df_print_regset (stderr, df->entry_block_defs);
4429*e4b17023SJohn Marino       gcc_assert (0);
4430*e4b17023SJohn Marino     }
4431*e4b17023SJohn Marino 
4432*e4b17023SJohn Marino   bitmap_clear (&entry_block_defs);
4433*e4b17023SJohn Marino 
4434*e4b17023SJohn Marino   return is_eq;
4435*e4b17023SJohn Marino }
4436*e4b17023SJohn Marino 
4437*e4b17023SJohn Marino 
4438*e4b17023SJohn Marino /* Returns true if the exit block has correct and complete df_ref set.
4439*e4b17023SJohn Marino    If not it either aborts if ABORT_IF_FAIL is true or returns false. */
4440*e4b17023SJohn Marino 
4441*e4b17023SJohn Marino static bool
df_exit_block_bitmap_verify(bool abort_if_fail)4442*e4b17023SJohn Marino df_exit_block_bitmap_verify (bool abort_if_fail)
4443*e4b17023SJohn Marino {
4444*e4b17023SJohn Marino   bitmap_head exit_block_uses;
4445*e4b17023SJohn Marino   bool is_eq;
4446*e4b17023SJohn Marino 
4447*e4b17023SJohn Marino   bitmap_initialize (&exit_block_uses, &df_bitmap_obstack);
4448*e4b17023SJohn Marino   df_get_exit_block_use_set (&exit_block_uses);
4449*e4b17023SJohn Marino 
4450*e4b17023SJohn Marino   is_eq = bitmap_equal_p (&exit_block_uses, df->exit_block_uses);
4451*e4b17023SJohn Marino 
4452*e4b17023SJohn Marino   if (!is_eq && abort_if_fail)
4453*e4b17023SJohn Marino     {
4454*e4b17023SJohn Marino       print_current_pass (stderr);
4455*e4b17023SJohn Marino       fprintf (stderr, "exit_block_uses = ");
4456*e4b17023SJohn Marino       df_print_regset (stderr, &exit_block_uses);
4457*e4b17023SJohn Marino       fprintf (stderr, "df->exit_block_uses = ");
4458*e4b17023SJohn Marino       df_print_regset (stderr, df->exit_block_uses);
4459*e4b17023SJohn Marino       gcc_assert (0);
4460*e4b17023SJohn Marino     }
4461*e4b17023SJohn Marino 
4462*e4b17023SJohn Marino   bitmap_clear (&exit_block_uses);
4463*e4b17023SJohn Marino 
4464*e4b17023SJohn Marino   return is_eq;
4465*e4b17023SJohn Marino }
4466*e4b17023SJohn Marino 
4467*e4b17023SJohn Marino 
4468*e4b17023SJohn Marino /* Return true if df_ref information for all insns in all blocks are
4469*e4b17023SJohn Marino    correct and complete.  */
4470*e4b17023SJohn Marino 
4471*e4b17023SJohn Marino void
df_scan_verify(void)4472*e4b17023SJohn Marino df_scan_verify (void)
4473*e4b17023SJohn Marino {
4474*e4b17023SJohn Marino   unsigned int i;
4475*e4b17023SJohn Marino   basic_block bb;
4476*e4b17023SJohn Marino   bitmap_head regular_block_artificial_uses;
4477*e4b17023SJohn Marino   bitmap_head eh_block_artificial_uses;
4478*e4b17023SJohn Marino 
4479*e4b17023SJohn Marino   if (!df)
4480*e4b17023SJohn Marino     return;
4481*e4b17023SJohn Marino 
4482*e4b17023SJohn Marino   /* Verification is a 4 step process. */
4483*e4b17023SJohn Marino 
4484*e4b17023SJohn Marino   /* (1) All of the refs are marked by going thru the reg chains.  */
4485*e4b17023SJohn Marino   for (i = 0; i < DF_REG_SIZE (df); i++)
4486*e4b17023SJohn Marino     {
4487*e4b17023SJohn Marino       gcc_assert (df_reg_chain_mark (DF_REG_DEF_CHAIN (i), i, true, false)
4488*e4b17023SJohn Marino 		  == DF_REG_DEF_COUNT(i));
4489*e4b17023SJohn Marino       gcc_assert (df_reg_chain_mark (DF_REG_USE_CHAIN (i), i, false, false)
4490*e4b17023SJohn Marino 		  == DF_REG_USE_COUNT(i));
4491*e4b17023SJohn Marino       gcc_assert (df_reg_chain_mark (DF_REG_EQ_USE_CHAIN (i), i, false, true)
4492*e4b17023SJohn Marino 		  == DF_REG_EQ_USE_COUNT(i));
4493*e4b17023SJohn Marino     }
4494*e4b17023SJohn Marino 
4495*e4b17023SJohn Marino   /* (2) There are various bitmaps whose value may change over the
4496*e4b17023SJohn Marino      course of the compilation.  This step recomputes them to make
4497*e4b17023SJohn Marino      sure that they have not slipped out of date.  */
4498*e4b17023SJohn Marino   bitmap_initialize (&regular_block_artificial_uses, &df_bitmap_obstack);
4499*e4b17023SJohn Marino   bitmap_initialize (&eh_block_artificial_uses, &df_bitmap_obstack);
4500*e4b17023SJohn Marino 
4501*e4b17023SJohn Marino   df_get_regular_block_artificial_uses (&regular_block_artificial_uses);
4502*e4b17023SJohn Marino   df_get_eh_block_artificial_uses (&eh_block_artificial_uses);
4503*e4b17023SJohn Marino 
4504*e4b17023SJohn Marino   bitmap_ior_into (&eh_block_artificial_uses,
4505*e4b17023SJohn Marino 		   &regular_block_artificial_uses);
4506*e4b17023SJohn Marino 
4507*e4b17023SJohn Marino   /* Check artificial_uses bitmaps didn't change. */
4508*e4b17023SJohn Marino   gcc_assert (bitmap_equal_p (&regular_block_artificial_uses,
4509*e4b17023SJohn Marino 			      &df->regular_block_artificial_uses));
4510*e4b17023SJohn Marino   gcc_assert (bitmap_equal_p (&eh_block_artificial_uses,
4511*e4b17023SJohn Marino 			      &df->eh_block_artificial_uses));
4512*e4b17023SJohn Marino 
4513*e4b17023SJohn Marino   bitmap_clear (&regular_block_artificial_uses);
4514*e4b17023SJohn Marino   bitmap_clear (&eh_block_artificial_uses);
4515*e4b17023SJohn Marino 
4516*e4b17023SJohn Marino   /* Verify entry block and exit block. These only verify the bitmaps,
4517*e4b17023SJohn Marino      the refs are verified in df_bb_verify.  */
4518*e4b17023SJohn Marino   df_entry_block_bitmap_verify (true);
4519*e4b17023SJohn Marino   df_exit_block_bitmap_verify (true);
4520*e4b17023SJohn Marino 
4521*e4b17023SJohn Marino   /* (3) All of the insns in all of the blocks are traversed and the
4522*e4b17023SJohn Marino      marks are cleared both in the artificial refs attached to the
4523*e4b17023SJohn Marino      blocks and the real refs inside the insns.  It is a failure to
4524*e4b17023SJohn Marino      clear a mark that has not been set as this means that the ref in
4525*e4b17023SJohn Marino      the block or insn was not in the reg chain.  */
4526*e4b17023SJohn Marino 
4527*e4b17023SJohn Marino   FOR_ALL_BB (bb)
4528*e4b17023SJohn Marino     df_bb_verify (bb);
4529*e4b17023SJohn Marino 
4530*e4b17023SJohn Marino   /* (4) See if all reg chains are traversed a second time.  This time
4531*e4b17023SJohn Marino      a check is made that the marks are clear. A set mark would be a
4532*e4b17023SJohn Marino      from a reg that is not in any insn or basic block.  */
4533*e4b17023SJohn Marino 
4534*e4b17023SJohn Marino   for (i = 0; i < DF_REG_SIZE (df); i++)
4535*e4b17023SJohn Marino     {
4536*e4b17023SJohn Marino       df_reg_chain_verify_unmarked (DF_REG_DEF_CHAIN (i));
4537*e4b17023SJohn Marino       df_reg_chain_verify_unmarked (DF_REG_USE_CHAIN (i));
4538*e4b17023SJohn Marino       df_reg_chain_verify_unmarked (DF_REG_EQ_USE_CHAIN (i));
4539*e4b17023SJohn Marino     }
4540*e4b17023SJohn Marino }
4541