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 (®ular_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 (®ular_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 ®ular_block_artificial_uses);
4506*e4b17023SJohn Marino
4507*e4b17023SJohn Marino /* Check artificial_uses bitmaps didn't change. */
4508*e4b17023SJohn Marino gcc_assert (bitmap_equal_p (®ular_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 (®ular_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