xref: /dflybsd-src/contrib/gcc-4.7/gcc/cfglayout.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Basic block reordering routines for the GNU compiler.
2*e4b17023SJohn Marino    Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3*e4b17023SJohn Marino    2011 Free Software Foundation, Inc.
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
8*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
9*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
10*e4b17023SJohn Marino version.
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15*e4b17023SJohn Marino for more details.
16*e4b17023SJohn Marino 
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino #include "config.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "tree.h"
26*e4b17023SJohn Marino #include "rtl.h"
27*e4b17023SJohn Marino #include "hard-reg-set.h"
28*e4b17023SJohn Marino #include "obstack.h"
29*e4b17023SJohn Marino #include "basic-block.h"
30*e4b17023SJohn Marino #include "insn-config.h"
31*e4b17023SJohn Marino #include "output.h"
32*e4b17023SJohn Marino #include "function.h"
33*e4b17023SJohn Marino #include "cfglayout.h"
34*e4b17023SJohn Marino #include "cfgloop.h"
35*e4b17023SJohn Marino #include "target.h"
36*e4b17023SJohn Marino #include "common/common-target.h"
37*e4b17023SJohn Marino #include "ggc.h"
38*e4b17023SJohn Marino #include "alloc-pool.h"
39*e4b17023SJohn Marino #include "flags.h"
40*e4b17023SJohn Marino #include "tree-pass.h"
41*e4b17023SJohn Marino #include "df.h"
42*e4b17023SJohn Marino #include "vecprim.h"
43*e4b17023SJohn Marino #include "emit-rtl.h"
44*e4b17023SJohn Marino 
45*e4b17023SJohn Marino /* Holds the interesting trailing notes for the function.  */
46*e4b17023SJohn Marino rtx cfg_layout_function_footer;
47*e4b17023SJohn Marino rtx cfg_layout_function_header;
48*e4b17023SJohn Marino 
49*e4b17023SJohn Marino static rtx skip_insns_after_block (basic_block);
50*e4b17023SJohn Marino static void record_effective_endpoints (void);
51*e4b17023SJohn Marino static rtx label_for_bb (basic_block);
52*e4b17023SJohn Marino static void fixup_reorder_chain (void);
53*e4b17023SJohn Marino 
54*e4b17023SJohn Marino static void change_scope (rtx, tree, tree);
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino void verify_insn_chain (void);
57*e4b17023SJohn Marino static void fixup_fallthru_exit_predecessor (void);
58*e4b17023SJohn Marino 
59*e4b17023SJohn Marino rtx
unlink_insn_chain(rtx first,rtx last)60*e4b17023SJohn Marino unlink_insn_chain (rtx first, rtx last)
61*e4b17023SJohn Marino {
62*e4b17023SJohn Marino   rtx prevfirst = PREV_INSN (first);
63*e4b17023SJohn Marino   rtx nextlast = NEXT_INSN (last);
64*e4b17023SJohn Marino 
65*e4b17023SJohn Marino   PREV_INSN (first) = NULL;
66*e4b17023SJohn Marino   NEXT_INSN (last) = NULL;
67*e4b17023SJohn Marino   if (prevfirst)
68*e4b17023SJohn Marino     NEXT_INSN (prevfirst) = nextlast;
69*e4b17023SJohn Marino   if (nextlast)
70*e4b17023SJohn Marino     PREV_INSN (nextlast) = prevfirst;
71*e4b17023SJohn Marino   else
72*e4b17023SJohn Marino     set_last_insn (prevfirst);
73*e4b17023SJohn Marino   if (!prevfirst)
74*e4b17023SJohn Marino     set_first_insn (nextlast);
75*e4b17023SJohn Marino   return first;
76*e4b17023SJohn Marino }
77*e4b17023SJohn Marino 
78*e4b17023SJohn Marino /* Skip over inter-block insns occurring after BB which are typically
79*e4b17023SJohn Marino    associated with BB (e.g., barriers). If there are any such insns,
80*e4b17023SJohn Marino    we return the last one. Otherwise, we return the end of BB.  */
81*e4b17023SJohn Marino 
82*e4b17023SJohn Marino static rtx
skip_insns_after_block(basic_block bb)83*e4b17023SJohn Marino skip_insns_after_block (basic_block bb)
84*e4b17023SJohn Marino {
85*e4b17023SJohn Marino   rtx insn, last_insn, next_head, prev;
86*e4b17023SJohn Marino 
87*e4b17023SJohn Marino   next_head = NULL_RTX;
88*e4b17023SJohn Marino   if (bb->next_bb != EXIT_BLOCK_PTR)
89*e4b17023SJohn Marino     next_head = BB_HEAD (bb->next_bb);
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino   for (last_insn = insn = BB_END (bb); (insn = NEXT_INSN (insn)) != 0; )
92*e4b17023SJohn Marino     {
93*e4b17023SJohn Marino       if (insn == next_head)
94*e4b17023SJohn Marino 	break;
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino       switch (GET_CODE (insn))
97*e4b17023SJohn Marino 	{
98*e4b17023SJohn Marino 	case BARRIER:
99*e4b17023SJohn Marino 	  last_insn = insn;
100*e4b17023SJohn Marino 	  continue;
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino 	case NOTE:
103*e4b17023SJohn Marino 	  switch (NOTE_KIND (insn))
104*e4b17023SJohn Marino 	    {
105*e4b17023SJohn Marino 	    case NOTE_INSN_BLOCK_END:
106*e4b17023SJohn Marino 	      gcc_unreachable ();
107*e4b17023SJohn Marino 	      continue;
108*e4b17023SJohn Marino 	    default:
109*e4b17023SJohn Marino 	      continue;
110*e4b17023SJohn Marino 	      break;
111*e4b17023SJohn Marino 	    }
112*e4b17023SJohn Marino 	  break;
113*e4b17023SJohn Marino 
114*e4b17023SJohn Marino 	case CODE_LABEL:
115*e4b17023SJohn Marino 	  if (NEXT_INSN (insn)
116*e4b17023SJohn Marino 	      && JUMP_TABLE_DATA_P (NEXT_INSN (insn)))
117*e4b17023SJohn Marino 	    {
118*e4b17023SJohn Marino 	      insn = NEXT_INSN (insn);
119*e4b17023SJohn Marino 	      last_insn = insn;
120*e4b17023SJohn Marino 	      continue;
121*e4b17023SJohn Marino 	    }
122*e4b17023SJohn Marino 	  break;
123*e4b17023SJohn Marino 
124*e4b17023SJohn Marino 	default:
125*e4b17023SJohn Marino 	  break;
126*e4b17023SJohn Marino 	}
127*e4b17023SJohn Marino 
128*e4b17023SJohn Marino       break;
129*e4b17023SJohn Marino     }
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino   /* It is possible to hit contradictory sequence.  For instance:
132*e4b17023SJohn Marino 
133*e4b17023SJohn Marino      jump_insn
134*e4b17023SJohn Marino      NOTE_INSN_BLOCK_BEG
135*e4b17023SJohn Marino      barrier
136*e4b17023SJohn Marino 
137*e4b17023SJohn Marino      Where barrier belongs to jump_insn, but the note does not.  This can be
138*e4b17023SJohn Marino      created by removing the basic block originally following
139*e4b17023SJohn Marino      NOTE_INSN_BLOCK_BEG.  In such case reorder the notes.  */
140*e4b17023SJohn Marino 
141*e4b17023SJohn Marino   for (insn = last_insn; insn != BB_END (bb); insn = prev)
142*e4b17023SJohn Marino     {
143*e4b17023SJohn Marino       prev = PREV_INSN (insn);
144*e4b17023SJohn Marino       if (NOTE_P (insn))
145*e4b17023SJohn Marino 	switch (NOTE_KIND (insn))
146*e4b17023SJohn Marino 	  {
147*e4b17023SJohn Marino 	  case NOTE_INSN_BLOCK_END:
148*e4b17023SJohn Marino 	    gcc_unreachable ();
149*e4b17023SJohn Marino 	    break;
150*e4b17023SJohn Marino 	  case NOTE_INSN_DELETED:
151*e4b17023SJohn Marino 	  case NOTE_INSN_DELETED_LABEL:
152*e4b17023SJohn Marino 	  case NOTE_INSN_DELETED_DEBUG_LABEL:
153*e4b17023SJohn Marino 	    continue;
154*e4b17023SJohn Marino 	  default:
155*e4b17023SJohn Marino 	    reorder_insns (insn, insn, last_insn);
156*e4b17023SJohn Marino 	  }
157*e4b17023SJohn Marino     }
158*e4b17023SJohn Marino 
159*e4b17023SJohn Marino   return last_insn;
160*e4b17023SJohn Marino }
161*e4b17023SJohn Marino 
162*e4b17023SJohn Marino /* Locate or create a label for a given basic block.  */
163*e4b17023SJohn Marino 
164*e4b17023SJohn Marino static rtx
label_for_bb(basic_block bb)165*e4b17023SJohn Marino label_for_bb (basic_block bb)
166*e4b17023SJohn Marino {
167*e4b17023SJohn Marino   rtx label = BB_HEAD (bb);
168*e4b17023SJohn Marino 
169*e4b17023SJohn Marino   if (!LABEL_P (label))
170*e4b17023SJohn Marino     {
171*e4b17023SJohn Marino       if (dump_file)
172*e4b17023SJohn Marino 	fprintf (dump_file, "Emitting label for block %d\n", bb->index);
173*e4b17023SJohn Marino 
174*e4b17023SJohn Marino       label = block_label (bb);
175*e4b17023SJohn Marino     }
176*e4b17023SJohn Marino 
177*e4b17023SJohn Marino   return label;
178*e4b17023SJohn Marino }
179*e4b17023SJohn Marino 
180*e4b17023SJohn Marino /* Locate the effective beginning and end of the insn chain for each
181*e4b17023SJohn Marino    block, as defined by skip_insns_after_block above.  */
182*e4b17023SJohn Marino 
183*e4b17023SJohn Marino static void
record_effective_endpoints(void)184*e4b17023SJohn Marino record_effective_endpoints (void)
185*e4b17023SJohn Marino {
186*e4b17023SJohn Marino   rtx next_insn;
187*e4b17023SJohn Marino   basic_block bb;
188*e4b17023SJohn Marino   rtx insn;
189*e4b17023SJohn Marino 
190*e4b17023SJohn Marino   for (insn = get_insns ();
191*e4b17023SJohn Marino        insn
192*e4b17023SJohn Marino        && NOTE_P (insn)
193*e4b17023SJohn Marino        && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK;
194*e4b17023SJohn Marino        insn = NEXT_INSN (insn))
195*e4b17023SJohn Marino     continue;
196*e4b17023SJohn Marino   /* No basic blocks at all?  */
197*e4b17023SJohn Marino   gcc_assert (insn);
198*e4b17023SJohn Marino 
199*e4b17023SJohn Marino   if (PREV_INSN (insn))
200*e4b17023SJohn Marino     cfg_layout_function_header =
201*e4b17023SJohn Marino 	    unlink_insn_chain (get_insns (), PREV_INSN (insn));
202*e4b17023SJohn Marino   else
203*e4b17023SJohn Marino     cfg_layout_function_header = NULL_RTX;
204*e4b17023SJohn Marino 
205*e4b17023SJohn Marino   next_insn = get_insns ();
206*e4b17023SJohn Marino   FOR_EACH_BB (bb)
207*e4b17023SJohn Marino     {
208*e4b17023SJohn Marino       rtx end;
209*e4b17023SJohn Marino 
210*e4b17023SJohn Marino       if (PREV_INSN (BB_HEAD (bb)) && next_insn != BB_HEAD (bb))
211*e4b17023SJohn Marino 	bb->il.rtl->header = unlink_insn_chain (next_insn,
212*e4b17023SJohn Marino 					      PREV_INSN (BB_HEAD (bb)));
213*e4b17023SJohn Marino       end = skip_insns_after_block (bb);
214*e4b17023SJohn Marino       if (NEXT_INSN (BB_END (bb)) && BB_END (bb) != end)
215*e4b17023SJohn Marino 	bb->il.rtl->footer = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end);
216*e4b17023SJohn Marino       next_insn = NEXT_INSN (BB_END (bb));
217*e4b17023SJohn Marino     }
218*e4b17023SJohn Marino 
219*e4b17023SJohn Marino   cfg_layout_function_footer = next_insn;
220*e4b17023SJohn Marino   if (cfg_layout_function_footer)
221*e4b17023SJohn Marino     cfg_layout_function_footer = unlink_insn_chain (cfg_layout_function_footer, get_last_insn ());
222*e4b17023SJohn Marino }
223*e4b17023SJohn Marino 
224*e4b17023SJohn Marino /* Data structures representing mapping of INSN_LOCATOR into scope blocks, line
225*e4b17023SJohn Marino    numbers and files.  In order to be GGC friendly we need to use separate
226*e4b17023SJohn Marino    varrays.  This also slightly improve the memory locality in binary search.
227*e4b17023SJohn Marino    The _locs array contains locators where the given property change.  The
228*e4b17023SJohn Marino    block_locators_blocks contains the scope block that is used for all insn
229*e4b17023SJohn Marino    locator greater than corresponding block_locators_locs value and smaller
230*e4b17023SJohn Marino    than the following one.  Similarly for the other properties.  */
231*e4b17023SJohn Marino static VEC(int,heap) *block_locators_locs;
232*e4b17023SJohn Marino static GTY(()) VEC(tree,gc) *block_locators_blocks;
233*e4b17023SJohn Marino static VEC(int,heap) *locations_locators_locs;
234*e4b17023SJohn Marino DEF_VEC_O(location_t);
235*e4b17023SJohn Marino DEF_VEC_ALLOC_O(location_t,heap);
236*e4b17023SJohn Marino static VEC(location_t,heap) *locations_locators_vals;
237*e4b17023SJohn Marino int prologue_locator;
238*e4b17023SJohn Marino int epilogue_locator;
239*e4b17023SJohn Marino 
240*e4b17023SJohn Marino /* Hold current location information and last location information, so the
241*e4b17023SJohn Marino    datastructures are built lazily only when some instructions in given
242*e4b17023SJohn Marino    place are needed.  */
243*e4b17023SJohn Marino static location_t curr_location, last_location;
244*e4b17023SJohn Marino static tree curr_block, last_block;
245*e4b17023SJohn Marino static int curr_rtl_loc = -1;
246*e4b17023SJohn Marino 
247*e4b17023SJohn Marino /* Allocate insn locator datastructure.  */
248*e4b17023SJohn Marino void
insn_locators_alloc(void)249*e4b17023SJohn Marino insn_locators_alloc (void)
250*e4b17023SJohn Marino {
251*e4b17023SJohn Marino   prologue_locator = epilogue_locator = 0;
252*e4b17023SJohn Marino 
253*e4b17023SJohn Marino   block_locators_locs = VEC_alloc (int, heap, 32);
254*e4b17023SJohn Marino   block_locators_blocks = VEC_alloc (tree, gc, 32);
255*e4b17023SJohn Marino   locations_locators_locs = VEC_alloc (int, heap, 32);
256*e4b17023SJohn Marino   locations_locators_vals = VEC_alloc (location_t, heap, 32);
257*e4b17023SJohn Marino 
258*e4b17023SJohn Marino   curr_location = UNKNOWN_LOCATION;
259*e4b17023SJohn Marino   last_location = UNKNOWN_LOCATION;
260*e4b17023SJohn Marino   curr_block = NULL;
261*e4b17023SJohn Marino   last_block = NULL;
262*e4b17023SJohn Marino   curr_rtl_loc = 0;
263*e4b17023SJohn Marino }
264*e4b17023SJohn Marino 
265*e4b17023SJohn Marino /* At the end of emit stage, clear current location.  */
266*e4b17023SJohn Marino void
insn_locators_finalize(void)267*e4b17023SJohn Marino insn_locators_finalize (void)
268*e4b17023SJohn Marino {
269*e4b17023SJohn Marino   if (curr_rtl_loc >= 0)
270*e4b17023SJohn Marino     epilogue_locator = curr_insn_locator ();
271*e4b17023SJohn Marino   curr_rtl_loc = -1;
272*e4b17023SJohn Marino }
273*e4b17023SJohn Marino 
274*e4b17023SJohn Marino /* Allocate insn locator datastructure.  */
275*e4b17023SJohn Marino void
insn_locators_free(void)276*e4b17023SJohn Marino insn_locators_free (void)
277*e4b17023SJohn Marino {
278*e4b17023SJohn Marino   prologue_locator = epilogue_locator = 0;
279*e4b17023SJohn Marino 
280*e4b17023SJohn Marino   VEC_free (int, heap, block_locators_locs);
281*e4b17023SJohn Marino   VEC_free (tree,gc, block_locators_blocks);
282*e4b17023SJohn Marino   VEC_free (int, heap, locations_locators_locs);
283*e4b17023SJohn Marino   VEC_free (location_t, heap, locations_locators_vals);
284*e4b17023SJohn Marino }
285*e4b17023SJohn Marino 
286*e4b17023SJohn Marino 
287*e4b17023SJohn Marino /* Set current location.  */
288*e4b17023SJohn Marino void
set_curr_insn_source_location(location_t location)289*e4b17023SJohn Marino set_curr_insn_source_location (location_t location)
290*e4b17023SJohn Marino {
291*e4b17023SJohn Marino   /* IV opts calls into RTL expansion to compute costs of operations.  At this
292*e4b17023SJohn Marino      time locators are not initialized.  */
293*e4b17023SJohn Marino   if (curr_rtl_loc == -1)
294*e4b17023SJohn Marino     return;
295*e4b17023SJohn Marino   curr_location = location;
296*e4b17023SJohn Marino }
297*e4b17023SJohn Marino 
298*e4b17023SJohn Marino /* Get current location.  */
299*e4b17023SJohn Marino location_t
get_curr_insn_source_location(void)300*e4b17023SJohn Marino get_curr_insn_source_location (void)
301*e4b17023SJohn Marino {
302*e4b17023SJohn Marino   return curr_location;
303*e4b17023SJohn Marino }
304*e4b17023SJohn Marino 
305*e4b17023SJohn Marino /* Set current scope block.  */
306*e4b17023SJohn Marino void
set_curr_insn_block(tree b)307*e4b17023SJohn Marino set_curr_insn_block (tree b)
308*e4b17023SJohn Marino {
309*e4b17023SJohn Marino   /* IV opts calls into RTL expansion to compute costs of operations.  At this
310*e4b17023SJohn Marino      time locators are not initialized.  */
311*e4b17023SJohn Marino   if (curr_rtl_loc == -1)
312*e4b17023SJohn Marino     return;
313*e4b17023SJohn Marino   if (b)
314*e4b17023SJohn Marino     curr_block = b;
315*e4b17023SJohn Marino }
316*e4b17023SJohn Marino 
317*e4b17023SJohn Marino /* Get current scope block.  */
318*e4b17023SJohn Marino tree
get_curr_insn_block(void)319*e4b17023SJohn Marino get_curr_insn_block (void)
320*e4b17023SJohn Marino {
321*e4b17023SJohn Marino   return curr_block;
322*e4b17023SJohn Marino }
323*e4b17023SJohn Marino 
324*e4b17023SJohn Marino /* Return current insn locator.  */
325*e4b17023SJohn Marino int
curr_insn_locator(void)326*e4b17023SJohn Marino curr_insn_locator (void)
327*e4b17023SJohn Marino {
328*e4b17023SJohn Marino   if (curr_rtl_loc == -1 || curr_location == UNKNOWN_LOCATION)
329*e4b17023SJohn Marino     return 0;
330*e4b17023SJohn Marino   if (last_block != curr_block)
331*e4b17023SJohn Marino     {
332*e4b17023SJohn Marino       curr_rtl_loc++;
333*e4b17023SJohn Marino       VEC_safe_push (int, heap, block_locators_locs, curr_rtl_loc);
334*e4b17023SJohn Marino       VEC_safe_push (tree, gc, block_locators_blocks, curr_block);
335*e4b17023SJohn Marino       last_block = curr_block;
336*e4b17023SJohn Marino     }
337*e4b17023SJohn Marino   if (last_location != curr_location)
338*e4b17023SJohn Marino     {
339*e4b17023SJohn Marino       curr_rtl_loc++;
340*e4b17023SJohn Marino       VEC_safe_push (int, heap, locations_locators_locs, curr_rtl_loc);
341*e4b17023SJohn Marino       VEC_safe_push (location_t, heap, locations_locators_vals, &curr_location);
342*e4b17023SJohn Marino       last_location = curr_location;
343*e4b17023SJohn Marino     }
344*e4b17023SJohn Marino   return curr_rtl_loc;
345*e4b17023SJohn Marino }
346*e4b17023SJohn Marino 
347*e4b17023SJohn Marino static unsigned int
into_cfg_layout_mode(void)348*e4b17023SJohn Marino into_cfg_layout_mode (void)
349*e4b17023SJohn Marino {
350*e4b17023SJohn Marino   cfg_layout_initialize (0);
351*e4b17023SJohn Marino   return 0;
352*e4b17023SJohn Marino }
353*e4b17023SJohn Marino 
354*e4b17023SJohn Marino static unsigned int
outof_cfg_layout_mode(void)355*e4b17023SJohn Marino outof_cfg_layout_mode (void)
356*e4b17023SJohn Marino {
357*e4b17023SJohn Marino   basic_block bb;
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino   FOR_EACH_BB (bb)
360*e4b17023SJohn Marino     if (bb->next_bb != EXIT_BLOCK_PTR)
361*e4b17023SJohn Marino       bb->aux = bb->next_bb;
362*e4b17023SJohn Marino 
363*e4b17023SJohn Marino   cfg_layout_finalize ();
364*e4b17023SJohn Marino 
365*e4b17023SJohn Marino   return 0;
366*e4b17023SJohn Marino }
367*e4b17023SJohn Marino 
368*e4b17023SJohn Marino struct rtl_opt_pass pass_into_cfg_layout_mode =
369*e4b17023SJohn Marino {
370*e4b17023SJohn Marino  {
371*e4b17023SJohn Marino   RTL_PASS,
372*e4b17023SJohn Marino   "into_cfglayout",                     /* name */
373*e4b17023SJohn Marino   NULL,                                 /* gate */
374*e4b17023SJohn Marino   into_cfg_layout_mode,                 /* execute */
375*e4b17023SJohn Marino   NULL,                                 /* sub */
376*e4b17023SJohn Marino   NULL,                                 /* next */
377*e4b17023SJohn Marino   0,                                    /* static_pass_number */
378*e4b17023SJohn Marino   TV_CFG,                               /* tv_id */
379*e4b17023SJohn Marino   0,                                    /* properties_required */
380*e4b17023SJohn Marino   PROP_cfglayout,                       /* properties_provided */
381*e4b17023SJohn Marino   0,                                    /* properties_destroyed */
382*e4b17023SJohn Marino   0,                                    /* todo_flags_start */
383*e4b17023SJohn Marino   0                                     /* todo_flags_finish */
384*e4b17023SJohn Marino  }
385*e4b17023SJohn Marino };
386*e4b17023SJohn Marino 
387*e4b17023SJohn Marino struct rtl_opt_pass pass_outof_cfg_layout_mode =
388*e4b17023SJohn Marino {
389*e4b17023SJohn Marino  {
390*e4b17023SJohn Marino   RTL_PASS,
391*e4b17023SJohn Marino   "outof_cfglayout",                    /* name */
392*e4b17023SJohn Marino   NULL,                                 /* gate */
393*e4b17023SJohn Marino   outof_cfg_layout_mode,                /* execute */
394*e4b17023SJohn Marino   NULL,                                 /* sub */
395*e4b17023SJohn Marino   NULL,                                 /* next */
396*e4b17023SJohn Marino   0,                                    /* static_pass_number */
397*e4b17023SJohn Marino   TV_CFG,                               /* tv_id */
398*e4b17023SJohn Marino   0,                                    /* properties_required */
399*e4b17023SJohn Marino   0,                                    /* properties_provided */
400*e4b17023SJohn Marino   PROP_cfglayout,                       /* properties_destroyed */
401*e4b17023SJohn Marino   0,                                    /* todo_flags_start */
402*e4b17023SJohn Marino   0                                     /* todo_flags_finish */
403*e4b17023SJohn Marino  }
404*e4b17023SJohn Marino };
405*e4b17023SJohn Marino 
406*e4b17023SJohn Marino /* Return scope resulting from combination of S1 and S2.  */
407*e4b17023SJohn Marino static tree
choose_inner_scope(tree s1,tree s2)408*e4b17023SJohn Marino choose_inner_scope (tree s1, tree s2)
409*e4b17023SJohn Marino {
410*e4b17023SJohn Marino    if (!s1)
411*e4b17023SJohn Marino      return s2;
412*e4b17023SJohn Marino    if (!s2)
413*e4b17023SJohn Marino      return s1;
414*e4b17023SJohn Marino    if (BLOCK_NUMBER (s1) > BLOCK_NUMBER (s2))
415*e4b17023SJohn Marino      return s1;
416*e4b17023SJohn Marino    return s2;
417*e4b17023SJohn Marino }
418*e4b17023SJohn Marino 
419*e4b17023SJohn Marino /* Emit lexical block notes needed to change scope from S1 to S2.  */
420*e4b17023SJohn Marino 
421*e4b17023SJohn Marino static void
change_scope(rtx orig_insn,tree s1,tree s2)422*e4b17023SJohn Marino change_scope (rtx orig_insn, tree s1, tree s2)
423*e4b17023SJohn Marino {
424*e4b17023SJohn Marino   rtx insn = orig_insn;
425*e4b17023SJohn Marino   tree com = NULL_TREE;
426*e4b17023SJohn Marino   tree ts1 = s1, ts2 = s2;
427*e4b17023SJohn Marino   tree s;
428*e4b17023SJohn Marino 
429*e4b17023SJohn Marino   while (ts1 != ts2)
430*e4b17023SJohn Marino     {
431*e4b17023SJohn Marino       gcc_assert (ts1 && ts2);
432*e4b17023SJohn Marino       if (BLOCK_NUMBER (ts1) > BLOCK_NUMBER (ts2))
433*e4b17023SJohn Marino 	ts1 = BLOCK_SUPERCONTEXT (ts1);
434*e4b17023SJohn Marino       else if (BLOCK_NUMBER (ts1) < BLOCK_NUMBER (ts2))
435*e4b17023SJohn Marino 	ts2 = BLOCK_SUPERCONTEXT (ts2);
436*e4b17023SJohn Marino       else
437*e4b17023SJohn Marino 	{
438*e4b17023SJohn Marino 	  ts1 = BLOCK_SUPERCONTEXT (ts1);
439*e4b17023SJohn Marino 	  ts2 = BLOCK_SUPERCONTEXT (ts2);
440*e4b17023SJohn Marino 	}
441*e4b17023SJohn Marino     }
442*e4b17023SJohn Marino   com = ts1;
443*e4b17023SJohn Marino 
444*e4b17023SJohn Marino   /* Close scopes.  */
445*e4b17023SJohn Marino   s = s1;
446*e4b17023SJohn Marino   while (s != com)
447*e4b17023SJohn Marino     {
448*e4b17023SJohn Marino       rtx note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
449*e4b17023SJohn Marino       NOTE_BLOCK (note) = s;
450*e4b17023SJohn Marino       s = BLOCK_SUPERCONTEXT (s);
451*e4b17023SJohn Marino     }
452*e4b17023SJohn Marino 
453*e4b17023SJohn Marino   /* Open scopes.  */
454*e4b17023SJohn Marino   s = s2;
455*e4b17023SJohn Marino   while (s != com)
456*e4b17023SJohn Marino     {
457*e4b17023SJohn Marino       insn = emit_note_before (NOTE_INSN_BLOCK_BEG, insn);
458*e4b17023SJohn Marino       NOTE_BLOCK (insn) = s;
459*e4b17023SJohn Marino       s = BLOCK_SUPERCONTEXT (s);
460*e4b17023SJohn Marino     }
461*e4b17023SJohn Marino }
462*e4b17023SJohn Marino 
463*e4b17023SJohn Marino /* Return lexical scope block locator belongs to.  */
464*e4b17023SJohn Marino static tree
locator_scope(int loc)465*e4b17023SJohn Marino locator_scope (int loc)
466*e4b17023SJohn Marino {
467*e4b17023SJohn Marino   int max = VEC_length (int, block_locators_locs);
468*e4b17023SJohn Marino   int min = 0;
469*e4b17023SJohn Marino 
470*e4b17023SJohn Marino   /* When block_locators_locs was initialized, the pro- and epilogue
471*e4b17023SJohn Marino      insns didn't exist yet and can therefore not be found this way.
472*e4b17023SJohn Marino      But we know that they belong to the outer most block of the
473*e4b17023SJohn Marino      current function.
474*e4b17023SJohn Marino      Without this test, the prologue would be put inside the block of
475*e4b17023SJohn Marino      the first valid instruction in the function and when that first
476*e4b17023SJohn Marino      insn is part of an inlined function then the low_pc of that
477*e4b17023SJohn Marino      inlined function is messed up.  Likewise for the epilogue and
478*e4b17023SJohn Marino      the last valid instruction.  */
479*e4b17023SJohn Marino   if (loc == prologue_locator || loc == epilogue_locator)
480*e4b17023SJohn Marino     return DECL_INITIAL (cfun->decl);
481*e4b17023SJohn Marino 
482*e4b17023SJohn Marino   if (!max || !loc)
483*e4b17023SJohn Marino     return NULL;
484*e4b17023SJohn Marino   while (1)
485*e4b17023SJohn Marino     {
486*e4b17023SJohn Marino       int pos = (min + max) / 2;
487*e4b17023SJohn Marino       int tmp = VEC_index (int, block_locators_locs, pos);
488*e4b17023SJohn Marino 
489*e4b17023SJohn Marino       if (tmp <= loc && min != pos)
490*e4b17023SJohn Marino 	min = pos;
491*e4b17023SJohn Marino       else if (tmp > loc && max != pos)
492*e4b17023SJohn Marino 	max = pos;
493*e4b17023SJohn Marino       else
494*e4b17023SJohn Marino 	{
495*e4b17023SJohn Marino 	  min = pos;
496*e4b17023SJohn Marino 	  break;
497*e4b17023SJohn Marino 	}
498*e4b17023SJohn Marino     }
499*e4b17023SJohn Marino   return VEC_index (tree, block_locators_blocks, min);
500*e4b17023SJohn Marino }
501*e4b17023SJohn Marino 
502*e4b17023SJohn Marino /* Return lexical scope block insn belongs to.  */
503*e4b17023SJohn Marino tree
insn_scope(const_rtx insn)504*e4b17023SJohn Marino insn_scope (const_rtx insn)
505*e4b17023SJohn Marino {
506*e4b17023SJohn Marino   return locator_scope (INSN_LOCATOR (insn));
507*e4b17023SJohn Marino }
508*e4b17023SJohn Marino 
509*e4b17023SJohn Marino /* Return line number of the statement specified by the locator.  */
510*e4b17023SJohn Marino location_t
locator_location(int loc)511*e4b17023SJohn Marino locator_location (int loc)
512*e4b17023SJohn Marino {
513*e4b17023SJohn Marino   int max = VEC_length (int, locations_locators_locs);
514*e4b17023SJohn Marino   int min = 0;
515*e4b17023SJohn Marino 
516*e4b17023SJohn Marino   while (1)
517*e4b17023SJohn Marino     {
518*e4b17023SJohn Marino       int pos = (min + max) / 2;
519*e4b17023SJohn Marino       int tmp = VEC_index (int, locations_locators_locs, pos);
520*e4b17023SJohn Marino 
521*e4b17023SJohn Marino       if (tmp <= loc && min != pos)
522*e4b17023SJohn Marino 	min = pos;
523*e4b17023SJohn Marino       else if (tmp > loc && max != pos)
524*e4b17023SJohn Marino 	max = pos;
525*e4b17023SJohn Marino       else
526*e4b17023SJohn Marino 	{
527*e4b17023SJohn Marino 	  min = pos;
528*e4b17023SJohn Marino 	  break;
529*e4b17023SJohn Marino 	}
530*e4b17023SJohn Marino     }
531*e4b17023SJohn Marino   return *VEC_index (location_t, locations_locators_vals, min);
532*e4b17023SJohn Marino }
533*e4b17023SJohn Marino 
534*e4b17023SJohn Marino /* Return source line of the statement that produced this insn.  */
535*e4b17023SJohn Marino int
locator_line(int loc)536*e4b17023SJohn Marino locator_line (int loc)
537*e4b17023SJohn Marino {
538*e4b17023SJohn Marino   expanded_location xloc;
539*e4b17023SJohn Marino   if (!loc)
540*e4b17023SJohn Marino     return 0;
541*e4b17023SJohn Marino   else
542*e4b17023SJohn Marino     xloc = expand_location (locator_location (loc));
543*e4b17023SJohn Marino   return xloc.line;
544*e4b17023SJohn Marino }
545*e4b17023SJohn Marino 
546*e4b17023SJohn Marino /* Return line number of the statement that produced this insn.  */
547*e4b17023SJohn Marino int
insn_line(const_rtx insn)548*e4b17023SJohn Marino insn_line (const_rtx insn)
549*e4b17023SJohn Marino {
550*e4b17023SJohn Marino   return locator_line (INSN_LOCATOR (insn));
551*e4b17023SJohn Marino }
552*e4b17023SJohn Marino 
553*e4b17023SJohn Marino /* Return source file of the statement specified by LOC.  */
554*e4b17023SJohn Marino const char *
locator_file(int loc)555*e4b17023SJohn Marino locator_file (int loc)
556*e4b17023SJohn Marino {
557*e4b17023SJohn Marino   expanded_location xloc;
558*e4b17023SJohn Marino   if (!loc)
559*e4b17023SJohn Marino     return 0;
560*e4b17023SJohn Marino   else
561*e4b17023SJohn Marino     xloc = expand_location (locator_location (loc));
562*e4b17023SJohn Marino   return xloc.file;
563*e4b17023SJohn Marino }
564*e4b17023SJohn Marino 
565*e4b17023SJohn Marino /* Return source file of the statement that produced this insn.  */
566*e4b17023SJohn Marino const char *
insn_file(const_rtx insn)567*e4b17023SJohn Marino insn_file (const_rtx insn)
568*e4b17023SJohn Marino {
569*e4b17023SJohn Marino   return locator_file (INSN_LOCATOR (insn));
570*e4b17023SJohn Marino }
571*e4b17023SJohn Marino 
572*e4b17023SJohn Marino /* Return true if LOC1 and LOC2 locators have the same location and scope.  */
573*e4b17023SJohn Marino bool
locator_eq(int loc1,int loc2)574*e4b17023SJohn Marino locator_eq (int loc1, int loc2)
575*e4b17023SJohn Marino {
576*e4b17023SJohn Marino   if (loc1 == loc2)
577*e4b17023SJohn Marino     return true;
578*e4b17023SJohn Marino   if (locator_location (loc1) != locator_location (loc2))
579*e4b17023SJohn Marino     return false;
580*e4b17023SJohn Marino   return locator_scope (loc1) == locator_scope (loc2);
581*e4b17023SJohn Marino }
582*e4b17023SJohn Marino 
583*e4b17023SJohn Marino /* Rebuild all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes based
584*e4b17023SJohn Marino    on the scope tree and the newly reordered instructions.  */
585*e4b17023SJohn Marino 
586*e4b17023SJohn Marino void
reemit_insn_block_notes(void)587*e4b17023SJohn Marino reemit_insn_block_notes (void)
588*e4b17023SJohn Marino {
589*e4b17023SJohn Marino   tree cur_block = DECL_INITIAL (cfun->decl);
590*e4b17023SJohn Marino   rtx insn, note;
591*e4b17023SJohn Marino 
592*e4b17023SJohn Marino   insn = get_insns ();
593*e4b17023SJohn Marino   if (!active_insn_p (insn))
594*e4b17023SJohn Marino     insn = next_active_insn (insn);
595*e4b17023SJohn Marino   for (; insn; insn = next_active_insn (insn))
596*e4b17023SJohn Marino     {
597*e4b17023SJohn Marino       tree this_block;
598*e4b17023SJohn Marino 
599*e4b17023SJohn Marino       /* Avoid putting scope notes between jump table and its label.  */
600*e4b17023SJohn Marino       if (JUMP_TABLE_DATA_P (insn))
601*e4b17023SJohn Marino 	continue;
602*e4b17023SJohn Marino 
603*e4b17023SJohn Marino       this_block = insn_scope (insn);
604*e4b17023SJohn Marino       /* For sequences compute scope resulting from merging all scopes
605*e4b17023SJohn Marino 	 of instructions nested inside.  */
606*e4b17023SJohn Marino       if (GET_CODE (PATTERN (insn)) == SEQUENCE)
607*e4b17023SJohn Marino 	{
608*e4b17023SJohn Marino 	  int i;
609*e4b17023SJohn Marino 	  rtx body = PATTERN (insn);
610*e4b17023SJohn Marino 
611*e4b17023SJohn Marino 	  this_block = NULL;
612*e4b17023SJohn Marino 	  for (i = 0; i < XVECLEN (body, 0); i++)
613*e4b17023SJohn Marino 	    this_block = choose_inner_scope (this_block,
614*e4b17023SJohn Marino 					 insn_scope (XVECEXP (body, 0, i)));
615*e4b17023SJohn Marino 	}
616*e4b17023SJohn Marino       if (! this_block)
617*e4b17023SJohn Marino 	continue;
618*e4b17023SJohn Marino 
619*e4b17023SJohn Marino       if (this_block != cur_block)
620*e4b17023SJohn Marino 	{
621*e4b17023SJohn Marino 	  change_scope (insn, cur_block, this_block);
622*e4b17023SJohn Marino 	  cur_block = this_block;
623*e4b17023SJohn Marino 	}
624*e4b17023SJohn Marino     }
625*e4b17023SJohn Marino 
626*e4b17023SJohn Marino   /* change_scope emits before the insn, not after.  */
627*e4b17023SJohn Marino   note = emit_note (NOTE_INSN_DELETED);
628*e4b17023SJohn Marino   change_scope (note, cur_block, DECL_INITIAL (cfun->decl));
629*e4b17023SJohn Marino   delete_insn (note);
630*e4b17023SJohn Marino 
631*e4b17023SJohn Marino   reorder_blocks ();
632*e4b17023SJohn Marino }
633*e4b17023SJohn Marino 
634*e4b17023SJohn Marino 
635*e4b17023SJohn Marino /* Link the basic blocks in the correct order, compacting the basic
636*e4b17023SJohn Marino    block queue while at it.  This also clears the visited flag on
637*e4b17023SJohn Marino    all basic blocks.  If STAY_IN_CFGLAYOUT_MODE is false, this function
638*e4b17023SJohn Marino    also clears the basic block header and footer fields.
639*e4b17023SJohn Marino 
640*e4b17023SJohn Marino    This function is usually called after a pass (e.g. tracer) finishes
641*e4b17023SJohn Marino    some transformations while in cfglayout mode.  The required sequence
642*e4b17023SJohn Marino    of the basic blocks is in a linked list along the bb->aux field.
643*e4b17023SJohn Marino    This functions re-links the basic block prev_bb and next_bb pointers
644*e4b17023SJohn Marino    accordingly, and it compacts and renumbers the blocks.  */
645*e4b17023SJohn Marino 
646*e4b17023SJohn Marino void
relink_block_chain(bool stay_in_cfglayout_mode)647*e4b17023SJohn Marino relink_block_chain (bool stay_in_cfglayout_mode)
648*e4b17023SJohn Marino {
649*e4b17023SJohn Marino   basic_block bb, prev_bb;
650*e4b17023SJohn Marino   int index;
651*e4b17023SJohn Marino 
652*e4b17023SJohn Marino   /* Maybe dump the re-ordered sequence.  */
653*e4b17023SJohn Marino   if (dump_file)
654*e4b17023SJohn Marino     {
655*e4b17023SJohn Marino       fprintf (dump_file, "Reordered sequence:\n");
656*e4b17023SJohn Marino       for (bb = ENTRY_BLOCK_PTR->next_bb, index = NUM_FIXED_BLOCKS;
657*e4b17023SJohn Marino 	   bb;
658*e4b17023SJohn Marino 	   bb = (basic_block) bb->aux, index++)
659*e4b17023SJohn Marino 	{
660*e4b17023SJohn Marino 	  fprintf (dump_file, " %i ", index);
661*e4b17023SJohn Marino 	  if (get_bb_original (bb))
662*e4b17023SJohn Marino 	    fprintf (dump_file, "duplicate of %i ",
663*e4b17023SJohn Marino 		     get_bb_original (bb)->index);
664*e4b17023SJohn Marino 	  else if (forwarder_block_p (bb)
665*e4b17023SJohn Marino 		   && !LABEL_P (BB_HEAD (bb)))
666*e4b17023SJohn Marino 	    fprintf (dump_file, "compensation ");
667*e4b17023SJohn Marino 	  else
668*e4b17023SJohn Marino 	    fprintf (dump_file, "bb %i ", bb->index);
669*e4b17023SJohn Marino 	  fprintf (dump_file, " [%i]\n", bb->frequency);
670*e4b17023SJohn Marino 	}
671*e4b17023SJohn Marino     }
672*e4b17023SJohn Marino 
673*e4b17023SJohn Marino   /* Now reorder the blocks.  */
674*e4b17023SJohn Marino   prev_bb = ENTRY_BLOCK_PTR;
675*e4b17023SJohn Marino   bb = ENTRY_BLOCK_PTR->next_bb;
676*e4b17023SJohn Marino   for (; bb; prev_bb = bb, bb = (basic_block) bb->aux)
677*e4b17023SJohn Marino     {
678*e4b17023SJohn Marino       bb->prev_bb = prev_bb;
679*e4b17023SJohn Marino       prev_bb->next_bb = bb;
680*e4b17023SJohn Marino     }
681*e4b17023SJohn Marino   prev_bb->next_bb = EXIT_BLOCK_PTR;
682*e4b17023SJohn Marino   EXIT_BLOCK_PTR->prev_bb = prev_bb;
683*e4b17023SJohn Marino 
684*e4b17023SJohn Marino   /* Then, clean up the aux and visited fields.  */
685*e4b17023SJohn Marino   FOR_ALL_BB (bb)
686*e4b17023SJohn Marino     {
687*e4b17023SJohn Marino       bb->aux = NULL;
688*e4b17023SJohn Marino       bb->il.rtl->visited = 0;
689*e4b17023SJohn Marino       if (!stay_in_cfglayout_mode)
690*e4b17023SJohn Marino 	bb->il.rtl->header = bb->il.rtl->footer = NULL;
691*e4b17023SJohn Marino     }
692*e4b17023SJohn Marino 
693*e4b17023SJohn Marino   /* Maybe reset the original copy tables, they are not valid anymore
694*e4b17023SJohn Marino      when we renumber the basic blocks in compact_blocks.  If we are
695*e4b17023SJohn Marino      are going out of cfglayout mode, don't re-allocate the tables.  */
696*e4b17023SJohn Marino   free_original_copy_tables ();
697*e4b17023SJohn Marino   if (stay_in_cfglayout_mode)
698*e4b17023SJohn Marino     initialize_original_copy_tables ();
699*e4b17023SJohn Marino 
700*e4b17023SJohn Marino   /* Finally, put basic_block_info in the new order.  */
701*e4b17023SJohn Marino   compact_blocks ();
702*e4b17023SJohn Marino }
703*e4b17023SJohn Marino 
704*e4b17023SJohn Marino 
705*e4b17023SJohn Marino /* Given a reorder chain, rearrange the code to match.  */
706*e4b17023SJohn Marino 
707*e4b17023SJohn Marino static void
fixup_reorder_chain(void)708*e4b17023SJohn Marino fixup_reorder_chain (void)
709*e4b17023SJohn Marino {
710*e4b17023SJohn Marino   basic_block bb;
711*e4b17023SJohn Marino   rtx insn = NULL;
712*e4b17023SJohn Marino 
713*e4b17023SJohn Marino   if (cfg_layout_function_header)
714*e4b17023SJohn Marino     {
715*e4b17023SJohn Marino       set_first_insn (cfg_layout_function_header);
716*e4b17023SJohn Marino       insn = cfg_layout_function_header;
717*e4b17023SJohn Marino       while (NEXT_INSN (insn))
718*e4b17023SJohn Marino 	insn = NEXT_INSN (insn);
719*e4b17023SJohn Marino     }
720*e4b17023SJohn Marino 
721*e4b17023SJohn Marino   /* First do the bulk reordering -- rechain the blocks without regard to
722*e4b17023SJohn Marino      the needed changes to jumps and labels.  */
723*e4b17023SJohn Marino 
724*e4b17023SJohn Marino   for (bb = ENTRY_BLOCK_PTR->next_bb; bb; bb = (basic_block) bb->aux)
725*e4b17023SJohn Marino     {
726*e4b17023SJohn Marino       if (bb->il.rtl->header)
727*e4b17023SJohn Marino 	{
728*e4b17023SJohn Marino 	  if (insn)
729*e4b17023SJohn Marino 	    NEXT_INSN (insn) = bb->il.rtl->header;
730*e4b17023SJohn Marino 	  else
731*e4b17023SJohn Marino 	    set_first_insn (bb->il.rtl->header);
732*e4b17023SJohn Marino 	  PREV_INSN (bb->il.rtl->header) = insn;
733*e4b17023SJohn Marino 	  insn = bb->il.rtl->header;
734*e4b17023SJohn Marino 	  while (NEXT_INSN (insn))
735*e4b17023SJohn Marino 	    insn = NEXT_INSN (insn);
736*e4b17023SJohn Marino 	}
737*e4b17023SJohn Marino       if (insn)
738*e4b17023SJohn Marino 	NEXT_INSN (insn) = BB_HEAD (bb);
739*e4b17023SJohn Marino       else
740*e4b17023SJohn Marino 	set_first_insn (BB_HEAD (bb));
741*e4b17023SJohn Marino       PREV_INSN (BB_HEAD (bb)) = insn;
742*e4b17023SJohn Marino       insn = BB_END (bb);
743*e4b17023SJohn Marino       if (bb->il.rtl->footer)
744*e4b17023SJohn Marino 	{
745*e4b17023SJohn Marino 	  NEXT_INSN (insn) = bb->il.rtl->footer;
746*e4b17023SJohn Marino 	  PREV_INSN (bb->il.rtl->footer) = insn;
747*e4b17023SJohn Marino 	  while (NEXT_INSN (insn))
748*e4b17023SJohn Marino 	    insn = NEXT_INSN (insn);
749*e4b17023SJohn Marino 	}
750*e4b17023SJohn Marino     }
751*e4b17023SJohn Marino 
752*e4b17023SJohn Marino   NEXT_INSN (insn) = cfg_layout_function_footer;
753*e4b17023SJohn Marino   if (cfg_layout_function_footer)
754*e4b17023SJohn Marino     PREV_INSN (cfg_layout_function_footer) = insn;
755*e4b17023SJohn Marino 
756*e4b17023SJohn Marino   while (NEXT_INSN (insn))
757*e4b17023SJohn Marino     insn = NEXT_INSN (insn);
758*e4b17023SJohn Marino 
759*e4b17023SJohn Marino   set_last_insn (insn);
760*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
761*e4b17023SJohn Marino   verify_insn_chain ();
762*e4b17023SJohn Marino #endif
763*e4b17023SJohn Marino 
764*e4b17023SJohn Marino   /* Now add jumps and labels as needed to match the blocks new
765*e4b17023SJohn Marino      outgoing edges.  */
766*e4b17023SJohn Marino 
767*e4b17023SJohn Marino   for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = (basic_block) bb->aux)
768*e4b17023SJohn Marino     {
769*e4b17023SJohn Marino       edge e_fall, e_taken, e;
770*e4b17023SJohn Marino       rtx bb_end_insn;
771*e4b17023SJohn Marino       rtx ret_label = NULL_RTX;
772*e4b17023SJohn Marino       basic_block nb, src_bb;
773*e4b17023SJohn Marino       edge_iterator ei;
774*e4b17023SJohn Marino 
775*e4b17023SJohn Marino       if (EDGE_COUNT (bb->succs) == 0)
776*e4b17023SJohn Marino 	continue;
777*e4b17023SJohn Marino 
778*e4b17023SJohn Marino       /* Find the old fallthru edge, and another non-EH edge for
779*e4b17023SJohn Marino 	 a taken jump.  */
780*e4b17023SJohn Marino       e_taken = e_fall = NULL;
781*e4b17023SJohn Marino 
782*e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->succs)
783*e4b17023SJohn Marino 	if (e->flags & EDGE_FALLTHRU)
784*e4b17023SJohn Marino 	  e_fall = e;
785*e4b17023SJohn Marino 	else if (! (e->flags & EDGE_EH))
786*e4b17023SJohn Marino 	  e_taken = e;
787*e4b17023SJohn Marino 
788*e4b17023SJohn Marino       bb_end_insn = BB_END (bb);
789*e4b17023SJohn Marino       if (JUMP_P (bb_end_insn))
790*e4b17023SJohn Marino 	{
791*e4b17023SJohn Marino 	  ret_label = JUMP_LABEL (bb_end_insn);
792*e4b17023SJohn Marino 	  if (any_condjump_p (bb_end_insn))
793*e4b17023SJohn Marino 	    {
794*e4b17023SJohn Marino 	      /* This might happen if the conditional jump has side
795*e4b17023SJohn Marino 		 effects and could therefore not be optimized away.
796*e4b17023SJohn Marino 		 Make the basic block to end with a barrier in order
797*e4b17023SJohn Marino 		 to prevent rtl_verify_flow_info from complaining.  */
798*e4b17023SJohn Marino 	      if (!e_fall)
799*e4b17023SJohn Marino 		{
800*e4b17023SJohn Marino 		  gcc_assert (!onlyjump_p (bb_end_insn)
801*e4b17023SJohn Marino 			      || returnjump_p (bb_end_insn));
802*e4b17023SJohn Marino 		  bb->il.rtl->footer = emit_barrier_after (bb_end_insn);
803*e4b17023SJohn Marino 		  continue;
804*e4b17023SJohn Marino 		}
805*e4b17023SJohn Marino 
806*e4b17023SJohn Marino 	      /* If the old fallthru is still next, nothing to do.  */
807*e4b17023SJohn Marino 	      if (bb->aux == e_fall->dest
808*e4b17023SJohn Marino 		  || e_fall->dest == EXIT_BLOCK_PTR)
809*e4b17023SJohn Marino 		continue;
810*e4b17023SJohn Marino 
811*e4b17023SJohn Marino 	      /* The degenerated case of conditional jump jumping to the next
812*e4b17023SJohn Marino 		 instruction can happen for jumps with side effects.  We need
813*e4b17023SJohn Marino 		 to construct a forwarder block and this will be done just
814*e4b17023SJohn Marino 		 fine by force_nonfallthru below.  */
815*e4b17023SJohn Marino 	      if (!e_taken)
816*e4b17023SJohn Marino 		;
817*e4b17023SJohn Marino 
818*e4b17023SJohn Marino 	      /* There is another special case: if *neither* block is next,
819*e4b17023SJohn Marino 		 such as happens at the very end of a function, then we'll
820*e4b17023SJohn Marino 		 need to add a new unconditional jump.  Choose the taken
821*e4b17023SJohn Marino 		 edge based on known or assumed probability.  */
822*e4b17023SJohn Marino 	      else if (bb->aux != e_taken->dest)
823*e4b17023SJohn Marino 		{
824*e4b17023SJohn Marino 		  rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
825*e4b17023SJohn Marino 
826*e4b17023SJohn Marino 		  if (note
827*e4b17023SJohn Marino 		      && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
828*e4b17023SJohn Marino 		      && invert_jump (bb_end_insn,
829*e4b17023SJohn Marino 				      (e_fall->dest == EXIT_BLOCK_PTR
830*e4b17023SJohn Marino 				       ? NULL_RTX
831*e4b17023SJohn Marino 				       : label_for_bb (e_fall->dest)), 0))
832*e4b17023SJohn Marino 		    {
833*e4b17023SJohn Marino 		      e_fall->flags &= ~EDGE_FALLTHRU;
834*e4b17023SJohn Marino 		      gcc_checking_assert (could_fall_through
835*e4b17023SJohn Marino 					   (e_taken->src, e_taken->dest));
836*e4b17023SJohn Marino 		      e_taken->flags |= EDGE_FALLTHRU;
837*e4b17023SJohn Marino 		      update_br_prob_note (bb);
838*e4b17023SJohn Marino 		      e = e_fall, e_fall = e_taken, e_taken = e;
839*e4b17023SJohn Marino 		    }
840*e4b17023SJohn Marino 		}
841*e4b17023SJohn Marino 
842*e4b17023SJohn Marino 	      /* If the "jumping" edge is a crossing edge, and the fall
843*e4b17023SJohn Marino 		 through edge is non-crossing, leave things as they are.  */
844*e4b17023SJohn Marino 	      else if ((e_taken->flags & EDGE_CROSSING)
845*e4b17023SJohn Marino 		       && !(e_fall->flags & EDGE_CROSSING))
846*e4b17023SJohn Marino 		continue;
847*e4b17023SJohn Marino 
848*e4b17023SJohn Marino 	      /* Otherwise we can try to invert the jump.  This will
849*e4b17023SJohn Marino 		 basically never fail, however, keep up the pretense.  */
850*e4b17023SJohn Marino 	      else if (invert_jump (bb_end_insn,
851*e4b17023SJohn Marino 				    (e_fall->dest == EXIT_BLOCK_PTR
852*e4b17023SJohn Marino 				     ? NULL_RTX
853*e4b17023SJohn Marino 				     : label_for_bb (e_fall->dest)), 0))
854*e4b17023SJohn Marino 		{
855*e4b17023SJohn Marino 		  e_fall->flags &= ~EDGE_FALLTHRU;
856*e4b17023SJohn Marino 		  gcc_checking_assert (could_fall_through
857*e4b17023SJohn Marino 				       (e_taken->src, e_taken->dest));
858*e4b17023SJohn Marino 		  e_taken->flags |= EDGE_FALLTHRU;
859*e4b17023SJohn Marino 		  update_br_prob_note (bb);
860*e4b17023SJohn Marino 		  continue;
861*e4b17023SJohn Marino 		}
862*e4b17023SJohn Marino 	    }
863*e4b17023SJohn Marino 	  else if (extract_asm_operands (PATTERN (bb_end_insn)) != NULL)
864*e4b17023SJohn Marino 	    {
865*e4b17023SJohn Marino 	      /* If the old fallthru is still next or if
866*e4b17023SJohn Marino 		 asm goto doesn't have a fallthru (e.g. when followed by
867*e4b17023SJohn Marino 		 __builtin_unreachable ()), nothing to do.  */
868*e4b17023SJohn Marino 	      if (! e_fall
869*e4b17023SJohn Marino 		  || bb->aux == e_fall->dest
870*e4b17023SJohn Marino 		  || e_fall->dest == EXIT_BLOCK_PTR)
871*e4b17023SJohn Marino 		continue;
872*e4b17023SJohn Marino 
873*e4b17023SJohn Marino 	      /* Otherwise we'll have to use the fallthru fixup below.  */
874*e4b17023SJohn Marino 	    }
875*e4b17023SJohn Marino 	  else
876*e4b17023SJohn Marino 	    {
877*e4b17023SJohn Marino 	      /* Otherwise we have some return, switch or computed
878*e4b17023SJohn Marino 		 jump.  In the 99% case, there should not have been a
879*e4b17023SJohn Marino 		 fallthru edge.  */
880*e4b17023SJohn Marino 	      gcc_assert (returnjump_p (bb_end_insn) || !e_fall);
881*e4b17023SJohn Marino 	      continue;
882*e4b17023SJohn Marino 	    }
883*e4b17023SJohn Marino 	}
884*e4b17023SJohn Marino       else
885*e4b17023SJohn Marino 	{
886*e4b17023SJohn Marino 	  /* No fallthru implies a noreturn function with EH edges, or
887*e4b17023SJohn Marino 	     something similarly bizarre.  In any case, we don't need to
888*e4b17023SJohn Marino 	     do anything.  */
889*e4b17023SJohn Marino 	  if (! e_fall)
890*e4b17023SJohn Marino 	    continue;
891*e4b17023SJohn Marino 
892*e4b17023SJohn Marino 	  /* If the fallthru block is still next, nothing to do.  */
893*e4b17023SJohn Marino 	  if (bb->aux == e_fall->dest)
894*e4b17023SJohn Marino 	    continue;
895*e4b17023SJohn Marino 
896*e4b17023SJohn Marino 	  /* A fallthru to exit block.  */
897*e4b17023SJohn Marino 	  if (e_fall->dest == EXIT_BLOCK_PTR)
898*e4b17023SJohn Marino 	    continue;
899*e4b17023SJohn Marino 	}
900*e4b17023SJohn Marino 
901*e4b17023SJohn Marino       /* We got here if we need to add a new jump insn.
902*e4b17023SJohn Marino 	 Note force_nonfallthru can delete E_FALL and thus we have to
903*e4b17023SJohn Marino 	 save E_FALL->src prior to the call to force_nonfallthru.  */
904*e4b17023SJohn Marino       src_bb = e_fall->src;
905*e4b17023SJohn Marino       nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label);
906*e4b17023SJohn Marino       if (nb)
907*e4b17023SJohn Marino 	{
908*e4b17023SJohn Marino 	  nb->il.rtl->visited = 1;
909*e4b17023SJohn Marino 	  nb->aux = bb->aux;
910*e4b17023SJohn Marino 	  bb->aux = nb;
911*e4b17023SJohn Marino 	  /* Don't process this new block.  */
912*e4b17023SJohn Marino 	  bb = nb;
913*e4b17023SJohn Marino 
914*e4b17023SJohn Marino 	  /* Make sure new bb is tagged for correct section (same as
915*e4b17023SJohn Marino 	     fall-thru source, since you cannot fall-thru across
916*e4b17023SJohn Marino 	     section boundaries).  */
917*e4b17023SJohn Marino 	  BB_COPY_PARTITION (src_bb, single_pred (bb));
918*e4b17023SJohn Marino 	  if (flag_reorder_blocks_and_partition
919*e4b17023SJohn Marino 	      && targetm_common.have_named_sections
920*e4b17023SJohn Marino 	      && JUMP_P (BB_END (bb))
921*e4b17023SJohn Marino 	      && !any_condjump_p (BB_END (bb))
922*e4b17023SJohn Marino 	      && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING))
923*e4b17023SJohn Marino 	    add_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX);
924*e4b17023SJohn Marino 	}
925*e4b17023SJohn Marino     }
926*e4b17023SJohn Marino 
927*e4b17023SJohn Marino   relink_block_chain (/*stay_in_cfglayout_mode=*/false);
928*e4b17023SJohn Marino 
929*e4b17023SJohn Marino   /* Annoying special case - jump around dead jumptables left in the code.  */
930*e4b17023SJohn Marino   FOR_EACH_BB (bb)
931*e4b17023SJohn Marino     {
932*e4b17023SJohn Marino       edge e = find_fallthru_edge (bb->succs);
933*e4b17023SJohn Marino 
934*e4b17023SJohn Marino       if (e && !can_fallthru (e->src, e->dest))
935*e4b17023SJohn Marino 	force_nonfallthru (e);
936*e4b17023SJohn Marino     }
937*e4b17023SJohn Marino 
938*e4b17023SJohn Marino   /* Ensure goto_locus from edges has some instructions with that locus
939*e4b17023SJohn Marino      in RTL.  */
940*e4b17023SJohn Marino   if (!optimize)
941*e4b17023SJohn Marino     FOR_EACH_BB (bb)
942*e4b17023SJohn Marino       {
943*e4b17023SJohn Marino         edge e;
944*e4b17023SJohn Marino         edge_iterator ei;
945*e4b17023SJohn Marino 
946*e4b17023SJohn Marino         FOR_EACH_EDGE (e, ei, bb->succs)
947*e4b17023SJohn Marino 	  if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
948*e4b17023SJohn Marino 	    {
949*e4b17023SJohn Marino 	      edge e2;
950*e4b17023SJohn Marino 	      edge_iterator ei2;
951*e4b17023SJohn Marino 	      basic_block dest, nb;
952*e4b17023SJohn Marino 	      rtx end;
953*e4b17023SJohn Marino 
954*e4b17023SJohn Marino 	      insn = BB_END (e->src);
955*e4b17023SJohn Marino 	      end = PREV_INSN (BB_HEAD (e->src));
956*e4b17023SJohn Marino 	      while (insn != end
957*e4b17023SJohn Marino 		     && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
958*e4b17023SJohn Marino 		insn = PREV_INSN (insn);
959*e4b17023SJohn Marino 	      if (insn != end
960*e4b17023SJohn Marino 		  && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
961*e4b17023SJohn Marino 		continue;
962*e4b17023SJohn Marino 	      if (simplejump_p (BB_END (e->src))
963*e4b17023SJohn Marino 		  && INSN_LOCATOR (BB_END (e->src)) == 0)
964*e4b17023SJohn Marino 		{
965*e4b17023SJohn Marino 		  INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
966*e4b17023SJohn Marino 		  continue;
967*e4b17023SJohn Marino 		}
968*e4b17023SJohn Marino 	      dest = e->dest;
969*e4b17023SJohn Marino 	      if (dest == EXIT_BLOCK_PTR)
970*e4b17023SJohn Marino 		{
971*e4b17023SJohn Marino 		  /* Non-fallthru edges to the exit block cannot be split.  */
972*e4b17023SJohn Marino 		  if (!(e->flags & EDGE_FALLTHRU))
973*e4b17023SJohn Marino 		    continue;
974*e4b17023SJohn Marino 		}
975*e4b17023SJohn Marino 	      else
976*e4b17023SJohn Marino 		{
977*e4b17023SJohn Marino 		  insn = BB_HEAD (dest);
978*e4b17023SJohn Marino 		  end = NEXT_INSN (BB_END (dest));
979*e4b17023SJohn Marino 		  while (insn != end && !NONDEBUG_INSN_P (insn))
980*e4b17023SJohn Marino 		    insn = NEXT_INSN (insn);
981*e4b17023SJohn Marino 		  if (insn != end && INSN_LOCATOR (insn)
982*e4b17023SJohn Marino 		      && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
983*e4b17023SJohn Marino 		    continue;
984*e4b17023SJohn Marino 		}
985*e4b17023SJohn Marino 	      nb = split_edge (e);
986*e4b17023SJohn Marino 	      if (!INSN_P (BB_END (nb)))
987*e4b17023SJohn Marino 		BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb),
988*e4b17023SJohn Marino 						     nb);
989*e4b17023SJohn Marino 	      INSN_LOCATOR (BB_END (nb)) = e->goto_locus;
990*e4b17023SJohn Marino 
991*e4b17023SJohn Marino 	      /* If there are other incoming edges to the destination block
992*e4b17023SJohn Marino 		 with the same goto locus, redirect them to the new block as
993*e4b17023SJohn Marino 		 well, this can prevent other such blocks from being created
994*e4b17023SJohn Marino 		 in subsequent iterations of the loop.  */
995*e4b17023SJohn Marino 	      for (ei2 = ei_start (dest->preds); (e2 = ei_safe_edge (ei2)); )
996*e4b17023SJohn Marino 		if (e2->goto_locus
997*e4b17023SJohn Marino 		    && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
998*e4b17023SJohn Marino 		    && locator_eq (e->goto_locus, e2->goto_locus))
999*e4b17023SJohn Marino 		  redirect_edge_and_branch (e2, nb);
1000*e4b17023SJohn Marino 		else
1001*e4b17023SJohn Marino 		  ei_next (&ei2);
1002*e4b17023SJohn Marino 	    }
1003*e4b17023SJohn Marino       }
1004*e4b17023SJohn Marino }
1005*e4b17023SJohn Marino 
1006*e4b17023SJohn Marino /* Perform sanity checks on the insn chain.
1007*e4b17023SJohn Marino    1. Check that next/prev pointers are consistent in both the forward and
1008*e4b17023SJohn Marino       reverse direction.
1009*e4b17023SJohn Marino    2. Count insns in chain, going both directions, and check if equal.
1010*e4b17023SJohn Marino    3. Check that get_last_insn () returns the actual end of chain.  */
1011*e4b17023SJohn Marino 
1012*e4b17023SJohn Marino DEBUG_FUNCTION void
verify_insn_chain(void)1013*e4b17023SJohn Marino verify_insn_chain (void)
1014*e4b17023SJohn Marino {
1015*e4b17023SJohn Marino   rtx x, prevx, nextx;
1016*e4b17023SJohn Marino   int insn_cnt1, insn_cnt2;
1017*e4b17023SJohn Marino 
1018*e4b17023SJohn Marino   for (prevx = NULL, insn_cnt1 = 1, x = get_insns ();
1019*e4b17023SJohn Marino        x != 0;
1020*e4b17023SJohn Marino        prevx = x, insn_cnt1++, x = NEXT_INSN (x))
1021*e4b17023SJohn Marino     gcc_assert (PREV_INSN (x) == prevx);
1022*e4b17023SJohn Marino 
1023*e4b17023SJohn Marino   gcc_assert (prevx == get_last_insn ());
1024*e4b17023SJohn Marino 
1025*e4b17023SJohn Marino   for (nextx = NULL, insn_cnt2 = 1, x = get_last_insn ();
1026*e4b17023SJohn Marino        x != 0;
1027*e4b17023SJohn Marino        nextx = x, insn_cnt2++, x = PREV_INSN (x))
1028*e4b17023SJohn Marino     gcc_assert (NEXT_INSN (x) == nextx);
1029*e4b17023SJohn Marino 
1030*e4b17023SJohn Marino   gcc_assert (insn_cnt1 == insn_cnt2);
1031*e4b17023SJohn Marino }
1032*e4b17023SJohn Marino 
1033*e4b17023SJohn Marino /* If we have assembler epilogues, the block falling through to exit must
1034*e4b17023SJohn Marino    be the last one in the reordered chain when we reach final.  Ensure
1035*e4b17023SJohn Marino    that this condition is met.  */
1036*e4b17023SJohn Marino static void
fixup_fallthru_exit_predecessor(void)1037*e4b17023SJohn Marino fixup_fallthru_exit_predecessor (void)
1038*e4b17023SJohn Marino {
1039*e4b17023SJohn Marino   edge e;
1040*e4b17023SJohn Marino   basic_block bb = NULL;
1041*e4b17023SJohn Marino 
1042*e4b17023SJohn Marino   /* This transformation is not valid before reload, because we might
1043*e4b17023SJohn Marino      separate a call from the instruction that copies the return
1044*e4b17023SJohn Marino      value.  */
1045*e4b17023SJohn Marino   gcc_assert (reload_completed);
1046*e4b17023SJohn Marino 
1047*e4b17023SJohn Marino   e = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
1048*e4b17023SJohn Marino   if (e)
1049*e4b17023SJohn Marino     bb = e->src;
1050*e4b17023SJohn Marino 
1051*e4b17023SJohn Marino   if (bb && bb->aux)
1052*e4b17023SJohn Marino     {
1053*e4b17023SJohn Marino       basic_block c = ENTRY_BLOCK_PTR->next_bb;
1054*e4b17023SJohn Marino 
1055*e4b17023SJohn Marino       /* If the very first block is the one with the fall-through exit
1056*e4b17023SJohn Marino 	 edge, we have to split that block.  */
1057*e4b17023SJohn Marino       if (c == bb)
1058*e4b17023SJohn Marino 	{
1059*e4b17023SJohn Marino 	  bb = split_block (bb, NULL)->dest;
1060*e4b17023SJohn Marino 	  bb->aux = c->aux;
1061*e4b17023SJohn Marino 	  c->aux = bb;
1062*e4b17023SJohn Marino 	  bb->il.rtl->footer = c->il.rtl->footer;
1063*e4b17023SJohn Marino 	  c->il.rtl->footer = NULL;
1064*e4b17023SJohn Marino 	}
1065*e4b17023SJohn Marino 
1066*e4b17023SJohn Marino       while (c->aux != bb)
1067*e4b17023SJohn Marino 	c = (basic_block) c->aux;
1068*e4b17023SJohn Marino 
1069*e4b17023SJohn Marino       c->aux = bb->aux;
1070*e4b17023SJohn Marino       while (c->aux)
1071*e4b17023SJohn Marino 	c = (basic_block) c->aux;
1072*e4b17023SJohn Marino 
1073*e4b17023SJohn Marino       c->aux = bb;
1074*e4b17023SJohn Marino       bb->aux = NULL;
1075*e4b17023SJohn Marino     }
1076*e4b17023SJohn Marino }
1077*e4b17023SJohn Marino 
1078*e4b17023SJohn Marino /* In case there are more than one fallthru predecessors of exit, force that
1079*e4b17023SJohn Marino    there is only one.  */
1080*e4b17023SJohn Marino 
1081*e4b17023SJohn Marino static void
force_one_exit_fallthru(void)1082*e4b17023SJohn Marino force_one_exit_fallthru (void)
1083*e4b17023SJohn Marino {
1084*e4b17023SJohn Marino   edge e, predecessor = NULL;
1085*e4b17023SJohn Marino   bool more = false;
1086*e4b17023SJohn Marino   edge_iterator ei;
1087*e4b17023SJohn Marino   basic_block forwarder, bb;
1088*e4b17023SJohn Marino 
1089*e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
1090*e4b17023SJohn Marino     if (e->flags & EDGE_FALLTHRU)
1091*e4b17023SJohn Marino       {
1092*e4b17023SJohn Marino 	if (predecessor == NULL)
1093*e4b17023SJohn Marino 	  predecessor = e;
1094*e4b17023SJohn Marino 	else
1095*e4b17023SJohn Marino 	  {
1096*e4b17023SJohn Marino 	    more = true;
1097*e4b17023SJohn Marino 	    break;
1098*e4b17023SJohn Marino 	  }
1099*e4b17023SJohn Marino       }
1100*e4b17023SJohn Marino 
1101*e4b17023SJohn Marino   if (!more)
1102*e4b17023SJohn Marino     return;
1103*e4b17023SJohn Marino 
1104*e4b17023SJohn Marino   /* Exit has several fallthru predecessors.  Create a forwarder block for
1105*e4b17023SJohn Marino      them.  */
1106*e4b17023SJohn Marino   forwarder = split_edge (predecessor);
1107*e4b17023SJohn Marino   for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
1108*e4b17023SJohn Marino     {
1109*e4b17023SJohn Marino       if (e->src == forwarder
1110*e4b17023SJohn Marino 	  || !(e->flags & EDGE_FALLTHRU))
1111*e4b17023SJohn Marino 	ei_next (&ei);
1112*e4b17023SJohn Marino       else
1113*e4b17023SJohn Marino 	redirect_edge_and_branch_force (e, forwarder);
1114*e4b17023SJohn Marino     }
1115*e4b17023SJohn Marino 
1116*e4b17023SJohn Marino   /* Fix up the chain of blocks -- make FORWARDER immediately precede the
1117*e4b17023SJohn Marino      exit block.  */
1118*e4b17023SJohn Marino   FOR_EACH_BB (bb)
1119*e4b17023SJohn Marino     {
1120*e4b17023SJohn Marino       if (bb->aux == NULL && bb != forwarder)
1121*e4b17023SJohn Marino 	{
1122*e4b17023SJohn Marino 	  bb->aux = forwarder;
1123*e4b17023SJohn Marino 	  break;
1124*e4b17023SJohn Marino 	}
1125*e4b17023SJohn Marino     }
1126*e4b17023SJohn Marino }
1127*e4b17023SJohn Marino 
1128*e4b17023SJohn Marino /* Return true in case it is possible to duplicate the basic block BB.  */
1129*e4b17023SJohn Marino 
1130*e4b17023SJohn Marino /* We do not want to declare the function in a header file, since it should
1131*e4b17023SJohn Marino    only be used through the cfghooks interface, and we do not want to move
1132*e4b17023SJohn Marino    it to cfgrtl.c since it would require also moving quite a lot of related
1133*e4b17023SJohn Marino    code.  */
1134*e4b17023SJohn Marino extern bool cfg_layout_can_duplicate_bb_p (const_basic_block);
1135*e4b17023SJohn Marino 
1136*e4b17023SJohn Marino bool
cfg_layout_can_duplicate_bb_p(const_basic_block bb)1137*e4b17023SJohn Marino cfg_layout_can_duplicate_bb_p (const_basic_block bb)
1138*e4b17023SJohn Marino {
1139*e4b17023SJohn Marino   /* Do not attempt to duplicate tablejumps, as we need to unshare
1140*e4b17023SJohn Marino      the dispatch table.  This is difficult to do, as the instructions
1141*e4b17023SJohn Marino      computing jump destination may be hoisted outside the basic block.  */
1142*e4b17023SJohn Marino   if (tablejump_p (BB_END (bb), NULL, NULL))
1143*e4b17023SJohn Marino     return false;
1144*e4b17023SJohn Marino 
1145*e4b17023SJohn Marino   /* Do not duplicate blocks containing insns that can't be copied.  */
1146*e4b17023SJohn Marino   if (targetm.cannot_copy_insn_p)
1147*e4b17023SJohn Marino     {
1148*e4b17023SJohn Marino       rtx insn = BB_HEAD (bb);
1149*e4b17023SJohn Marino       while (1)
1150*e4b17023SJohn Marino 	{
1151*e4b17023SJohn Marino 	  if (INSN_P (insn) && targetm.cannot_copy_insn_p (insn))
1152*e4b17023SJohn Marino 	    return false;
1153*e4b17023SJohn Marino 	  if (insn == BB_END (bb))
1154*e4b17023SJohn Marino 	    break;
1155*e4b17023SJohn Marino 	  insn = NEXT_INSN (insn);
1156*e4b17023SJohn Marino 	}
1157*e4b17023SJohn Marino     }
1158*e4b17023SJohn Marino 
1159*e4b17023SJohn Marino   return true;
1160*e4b17023SJohn Marino }
1161*e4b17023SJohn Marino 
1162*e4b17023SJohn Marino rtx
duplicate_insn_chain(rtx from,rtx to)1163*e4b17023SJohn Marino duplicate_insn_chain (rtx from, rtx to)
1164*e4b17023SJohn Marino {
1165*e4b17023SJohn Marino   rtx insn, last, copy;
1166*e4b17023SJohn Marino 
1167*e4b17023SJohn Marino   /* Avoid updating of boundaries of previous basic block.  The
1168*e4b17023SJohn Marino      note will get removed from insn stream in fixup.  */
1169*e4b17023SJohn Marino   last = emit_note (NOTE_INSN_DELETED);
1170*e4b17023SJohn Marino 
1171*e4b17023SJohn Marino   /* Create copy at the end of INSN chain.  The chain will
1172*e4b17023SJohn Marino      be reordered later.  */
1173*e4b17023SJohn Marino   for (insn = from; insn != NEXT_INSN (to); insn = NEXT_INSN (insn))
1174*e4b17023SJohn Marino     {
1175*e4b17023SJohn Marino       switch (GET_CODE (insn))
1176*e4b17023SJohn Marino 	{
1177*e4b17023SJohn Marino 	case DEBUG_INSN:
1178*e4b17023SJohn Marino 	  /* Don't duplicate label debug insns.  */
1179*e4b17023SJohn Marino 	  if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL)
1180*e4b17023SJohn Marino 	    break;
1181*e4b17023SJohn Marino 	  /* FALLTHRU */
1182*e4b17023SJohn Marino 	case INSN:
1183*e4b17023SJohn Marino 	case CALL_INSN:
1184*e4b17023SJohn Marino 	case JUMP_INSN:
1185*e4b17023SJohn Marino 	  /* Avoid copying of dispatch tables.  We never duplicate
1186*e4b17023SJohn Marino 	     tablejumps, so this can hit only in case the table got
1187*e4b17023SJohn Marino 	     moved far from original jump.  */
1188*e4b17023SJohn Marino 	  if (GET_CODE (PATTERN (insn)) == ADDR_VEC
1189*e4b17023SJohn Marino 	      || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
1190*e4b17023SJohn Marino 	    {
1191*e4b17023SJohn Marino 	      /* Avoid copying following barrier as well if any
1192*e4b17023SJohn Marino 		 (and debug insns in between).  */
1193*e4b17023SJohn Marino 	      rtx next;
1194*e4b17023SJohn Marino 
1195*e4b17023SJohn Marino 	      for (next = NEXT_INSN (insn);
1196*e4b17023SJohn Marino 		   next != NEXT_INSN (to);
1197*e4b17023SJohn Marino 		   next = NEXT_INSN (next))
1198*e4b17023SJohn Marino 		if (!DEBUG_INSN_P (next))
1199*e4b17023SJohn Marino 		  break;
1200*e4b17023SJohn Marino 	      if (next != NEXT_INSN (to) && BARRIER_P (next))
1201*e4b17023SJohn Marino 		insn = next;
1202*e4b17023SJohn Marino 	      break;
1203*e4b17023SJohn Marino 	    }
1204*e4b17023SJohn Marino 	  copy = emit_copy_of_insn_after (insn, get_last_insn ());
1205*e4b17023SJohn Marino 	  if (JUMP_P (insn) && JUMP_LABEL (insn) != NULL_RTX
1206*e4b17023SJohn Marino 	      && ANY_RETURN_P (JUMP_LABEL (insn)))
1207*e4b17023SJohn Marino 	    JUMP_LABEL (copy) = JUMP_LABEL (insn);
1208*e4b17023SJohn Marino           maybe_copy_prologue_epilogue_insn (insn, copy);
1209*e4b17023SJohn Marino 	  break;
1210*e4b17023SJohn Marino 
1211*e4b17023SJohn Marino 	case CODE_LABEL:
1212*e4b17023SJohn Marino 	  break;
1213*e4b17023SJohn Marino 
1214*e4b17023SJohn Marino 	case BARRIER:
1215*e4b17023SJohn Marino 	  emit_barrier ();
1216*e4b17023SJohn Marino 	  break;
1217*e4b17023SJohn Marino 
1218*e4b17023SJohn Marino 	case NOTE:
1219*e4b17023SJohn Marino 	  switch (NOTE_KIND (insn))
1220*e4b17023SJohn Marino 	    {
1221*e4b17023SJohn Marino 	      /* In case prologue is empty and function contain label
1222*e4b17023SJohn Marino 		 in first BB, we may want to copy the block.  */
1223*e4b17023SJohn Marino 	    case NOTE_INSN_PROLOGUE_END:
1224*e4b17023SJohn Marino 
1225*e4b17023SJohn Marino 	    case NOTE_INSN_DELETED:
1226*e4b17023SJohn Marino 	    case NOTE_INSN_DELETED_LABEL:
1227*e4b17023SJohn Marino 	    case NOTE_INSN_DELETED_DEBUG_LABEL:
1228*e4b17023SJohn Marino 	      /* No problem to strip these.  */
1229*e4b17023SJohn Marino 	    case NOTE_INSN_FUNCTION_BEG:
1230*e4b17023SJohn Marino 	      /* There is always just single entry to function.  */
1231*e4b17023SJohn Marino 	    case NOTE_INSN_BASIC_BLOCK:
1232*e4b17023SJohn Marino 	      break;
1233*e4b17023SJohn Marino 
1234*e4b17023SJohn Marino 	    case NOTE_INSN_EPILOGUE_BEG:
1235*e4b17023SJohn Marino 	    case NOTE_INSN_SWITCH_TEXT_SECTIONS:
1236*e4b17023SJohn Marino 	      emit_note_copy (insn);
1237*e4b17023SJohn Marino 	      break;
1238*e4b17023SJohn Marino 
1239*e4b17023SJohn Marino 	    default:
1240*e4b17023SJohn Marino 	      /* All other notes should have already been eliminated.  */
1241*e4b17023SJohn Marino 	      gcc_unreachable ();
1242*e4b17023SJohn Marino 	    }
1243*e4b17023SJohn Marino 	  break;
1244*e4b17023SJohn Marino 	default:
1245*e4b17023SJohn Marino 	  gcc_unreachable ();
1246*e4b17023SJohn Marino 	}
1247*e4b17023SJohn Marino     }
1248*e4b17023SJohn Marino   insn = NEXT_INSN (last);
1249*e4b17023SJohn Marino   delete_insn (last);
1250*e4b17023SJohn Marino   return insn;
1251*e4b17023SJohn Marino }
1252*e4b17023SJohn Marino /* Create a duplicate of the basic block BB.  */
1253*e4b17023SJohn Marino 
1254*e4b17023SJohn Marino /* We do not want to declare the function in a header file, since it should
1255*e4b17023SJohn Marino    only be used through the cfghooks interface, and we do not want to move
1256*e4b17023SJohn Marino    it to cfgrtl.c since it would require also moving quite a lot of related
1257*e4b17023SJohn Marino    code.  */
1258*e4b17023SJohn Marino extern basic_block cfg_layout_duplicate_bb (basic_block);
1259*e4b17023SJohn Marino 
1260*e4b17023SJohn Marino basic_block
cfg_layout_duplicate_bb(basic_block bb)1261*e4b17023SJohn Marino cfg_layout_duplicate_bb (basic_block bb)
1262*e4b17023SJohn Marino {
1263*e4b17023SJohn Marino   rtx insn;
1264*e4b17023SJohn Marino   basic_block new_bb;
1265*e4b17023SJohn Marino 
1266*e4b17023SJohn Marino   insn = duplicate_insn_chain (BB_HEAD (bb), BB_END (bb));
1267*e4b17023SJohn Marino   new_bb = create_basic_block (insn,
1268*e4b17023SJohn Marino 			       insn ? get_last_insn () : NULL,
1269*e4b17023SJohn Marino 			       EXIT_BLOCK_PTR->prev_bb);
1270*e4b17023SJohn Marino 
1271*e4b17023SJohn Marino   BB_COPY_PARTITION (new_bb, bb);
1272*e4b17023SJohn Marino   if (bb->il.rtl->header)
1273*e4b17023SJohn Marino     {
1274*e4b17023SJohn Marino       insn = bb->il.rtl->header;
1275*e4b17023SJohn Marino       while (NEXT_INSN (insn))
1276*e4b17023SJohn Marino 	insn = NEXT_INSN (insn);
1277*e4b17023SJohn Marino       insn = duplicate_insn_chain (bb->il.rtl->header, insn);
1278*e4b17023SJohn Marino       if (insn)
1279*e4b17023SJohn Marino 	new_bb->il.rtl->header = unlink_insn_chain (insn, get_last_insn ());
1280*e4b17023SJohn Marino     }
1281*e4b17023SJohn Marino 
1282*e4b17023SJohn Marino   if (bb->il.rtl->footer)
1283*e4b17023SJohn Marino     {
1284*e4b17023SJohn Marino       insn = bb->il.rtl->footer;
1285*e4b17023SJohn Marino       while (NEXT_INSN (insn))
1286*e4b17023SJohn Marino 	insn = NEXT_INSN (insn);
1287*e4b17023SJohn Marino       insn = duplicate_insn_chain (bb->il.rtl->footer, insn);
1288*e4b17023SJohn Marino       if (insn)
1289*e4b17023SJohn Marino 	new_bb->il.rtl->footer = unlink_insn_chain (insn, get_last_insn ());
1290*e4b17023SJohn Marino     }
1291*e4b17023SJohn Marino 
1292*e4b17023SJohn Marino   return new_bb;
1293*e4b17023SJohn Marino }
1294*e4b17023SJohn Marino 
1295*e4b17023SJohn Marino 
1296*e4b17023SJohn Marino /* Main entry point to this module - initialize the datastructures for
1297*e4b17023SJohn Marino    CFG layout changes.  It keeps LOOPS up-to-date if not null.
1298*e4b17023SJohn Marino 
1299*e4b17023SJohn Marino    FLAGS is a set of additional flags to pass to cleanup_cfg().  */
1300*e4b17023SJohn Marino 
1301*e4b17023SJohn Marino void
cfg_layout_initialize(unsigned int flags)1302*e4b17023SJohn Marino cfg_layout_initialize (unsigned int flags)
1303*e4b17023SJohn Marino {
1304*e4b17023SJohn Marino   rtx x;
1305*e4b17023SJohn Marino   basic_block bb;
1306*e4b17023SJohn Marino 
1307*e4b17023SJohn Marino   initialize_original_copy_tables ();
1308*e4b17023SJohn Marino 
1309*e4b17023SJohn Marino   cfg_layout_rtl_register_cfg_hooks ();
1310*e4b17023SJohn Marino 
1311*e4b17023SJohn Marino   record_effective_endpoints ();
1312*e4b17023SJohn Marino 
1313*e4b17023SJohn Marino   /* Make sure that the targets of non local gotos are marked.  */
1314*e4b17023SJohn Marino   for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
1315*e4b17023SJohn Marino     {
1316*e4b17023SJohn Marino       bb = BLOCK_FOR_INSN (XEXP (x, 0));
1317*e4b17023SJohn Marino       bb->flags |= BB_NON_LOCAL_GOTO_TARGET;
1318*e4b17023SJohn Marino     }
1319*e4b17023SJohn Marino 
1320*e4b17023SJohn Marino   cleanup_cfg (CLEANUP_CFGLAYOUT | flags);
1321*e4b17023SJohn Marino }
1322*e4b17023SJohn Marino 
1323*e4b17023SJohn Marino /* Splits superblocks.  */
1324*e4b17023SJohn Marino void
break_superblocks(void)1325*e4b17023SJohn Marino break_superblocks (void)
1326*e4b17023SJohn Marino {
1327*e4b17023SJohn Marino   sbitmap superblocks;
1328*e4b17023SJohn Marino   bool need = false;
1329*e4b17023SJohn Marino   basic_block bb;
1330*e4b17023SJohn Marino 
1331*e4b17023SJohn Marino   superblocks = sbitmap_alloc (last_basic_block);
1332*e4b17023SJohn Marino   sbitmap_zero (superblocks);
1333*e4b17023SJohn Marino 
1334*e4b17023SJohn Marino   FOR_EACH_BB (bb)
1335*e4b17023SJohn Marino     if (bb->flags & BB_SUPERBLOCK)
1336*e4b17023SJohn Marino       {
1337*e4b17023SJohn Marino 	bb->flags &= ~BB_SUPERBLOCK;
1338*e4b17023SJohn Marino 	SET_BIT (superblocks, bb->index);
1339*e4b17023SJohn Marino 	need = true;
1340*e4b17023SJohn Marino       }
1341*e4b17023SJohn Marino 
1342*e4b17023SJohn Marino   if (need)
1343*e4b17023SJohn Marino     {
1344*e4b17023SJohn Marino       rebuild_jump_labels (get_insns ());
1345*e4b17023SJohn Marino       find_many_sub_basic_blocks (superblocks);
1346*e4b17023SJohn Marino     }
1347*e4b17023SJohn Marino 
1348*e4b17023SJohn Marino   free (superblocks);
1349*e4b17023SJohn Marino }
1350*e4b17023SJohn Marino 
1351*e4b17023SJohn Marino /* Finalize the changes: reorder insn list according to the sequence specified
1352*e4b17023SJohn Marino    by aux pointers, enter compensation code, rebuild scope forest.  */
1353*e4b17023SJohn Marino 
1354*e4b17023SJohn Marino void
cfg_layout_finalize(void)1355*e4b17023SJohn Marino cfg_layout_finalize (void)
1356*e4b17023SJohn Marino {
1357*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1358*e4b17023SJohn Marino   verify_flow_info ();
1359*e4b17023SJohn Marino #endif
1360*e4b17023SJohn Marino   force_one_exit_fallthru ();
1361*e4b17023SJohn Marino   rtl_register_cfg_hooks ();
1362*e4b17023SJohn Marino   if (reload_completed
1363*e4b17023SJohn Marino #ifdef HAVE_epilogue
1364*e4b17023SJohn Marino       && !HAVE_epilogue
1365*e4b17023SJohn Marino #endif
1366*e4b17023SJohn Marino       )
1367*e4b17023SJohn Marino     fixup_fallthru_exit_predecessor ();
1368*e4b17023SJohn Marino   fixup_reorder_chain ();
1369*e4b17023SJohn Marino 
1370*e4b17023SJohn Marino   rebuild_jump_labels (get_insns ());
1371*e4b17023SJohn Marino   delete_dead_jumptables ();
1372*e4b17023SJohn Marino 
1373*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1374*e4b17023SJohn Marino   verify_insn_chain ();
1375*e4b17023SJohn Marino   verify_flow_info ();
1376*e4b17023SJohn Marino #endif
1377*e4b17023SJohn Marino }
1378*e4b17023SJohn Marino 
1379*e4b17023SJohn Marino /* Checks whether all N blocks in BBS array can be copied.  */
1380*e4b17023SJohn Marino bool
can_copy_bbs_p(basic_block * bbs,unsigned n)1381*e4b17023SJohn Marino can_copy_bbs_p (basic_block *bbs, unsigned n)
1382*e4b17023SJohn Marino {
1383*e4b17023SJohn Marino   unsigned i;
1384*e4b17023SJohn Marino   edge e;
1385*e4b17023SJohn Marino   int ret = true;
1386*e4b17023SJohn Marino 
1387*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1388*e4b17023SJohn Marino     bbs[i]->flags |= BB_DUPLICATED;
1389*e4b17023SJohn Marino 
1390*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1391*e4b17023SJohn Marino     {
1392*e4b17023SJohn Marino       /* In case we should redirect abnormal edge during duplication, fail.  */
1393*e4b17023SJohn Marino       edge_iterator ei;
1394*e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bbs[i]->succs)
1395*e4b17023SJohn Marino 	if ((e->flags & EDGE_ABNORMAL)
1396*e4b17023SJohn Marino 	    && (e->dest->flags & BB_DUPLICATED))
1397*e4b17023SJohn Marino 	  {
1398*e4b17023SJohn Marino 	    ret = false;
1399*e4b17023SJohn Marino 	    goto end;
1400*e4b17023SJohn Marino 	  }
1401*e4b17023SJohn Marino 
1402*e4b17023SJohn Marino       if (!can_duplicate_block_p (bbs[i]))
1403*e4b17023SJohn Marino 	{
1404*e4b17023SJohn Marino 	  ret = false;
1405*e4b17023SJohn Marino 	  break;
1406*e4b17023SJohn Marino 	}
1407*e4b17023SJohn Marino     }
1408*e4b17023SJohn Marino 
1409*e4b17023SJohn Marino end:
1410*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1411*e4b17023SJohn Marino     bbs[i]->flags &= ~BB_DUPLICATED;
1412*e4b17023SJohn Marino 
1413*e4b17023SJohn Marino   return ret;
1414*e4b17023SJohn Marino }
1415*e4b17023SJohn Marino 
1416*e4b17023SJohn Marino /* Duplicates N basic blocks stored in array BBS.  Newly created basic blocks
1417*e4b17023SJohn Marino    are placed into array NEW_BBS in the same order.  Edges from basic blocks
1418*e4b17023SJohn Marino    in BBS are also duplicated and copies of those of them
1419*e4b17023SJohn Marino    that lead into BBS are redirected to appropriate newly created block.  The
1420*e4b17023SJohn Marino    function assigns bbs into loops (copy of basic block bb is assigned to
1421*e4b17023SJohn Marino    bb->loop_father->copy loop, so this must be set up correctly in advance)
1422*e4b17023SJohn Marino    and updates dominators locally (LOOPS structure that contains the information
1423*e4b17023SJohn Marino    about dominators is passed to enable this).
1424*e4b17023SJohn Marino 
1425*e4b17023SJohn Marino    BASE is the superloop to that basic block belongs; if its header or latch
1426*e4b17023SJohn Marino    is copied, we do not set the new blocks as header or latch.
1427*e4b17023SJohn Marino 
1428*e4b17023SJohn Marino    Created copies of N_EDGES edges in array EDGES are stored in array NEW_EDGES,
1429*e4b17023SJohn Marino    also in the same order.
1430*e4b17023SJohn Marino 
1431*e4b17023SJohn Marino    Newly created basic blocks are put after the basic block AFTER in the
1432*e4b17023SJohn Marino    instruction stream, and the order of the blocks in BBS array is preserved.  */
1433*e4b17023SJohn Marino 
1434*e4b17023SJohn Marino void
copy_bbs(basic_block * bbs,unsigned n,basic_block * new_bbs,edge * edges,unsigned num_edges,edge * new_edges,struct loop * base,basic_block after)1435*e4b17023SJohn Marino copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs,
1436*e4b17023SJohn Marino 	  edge *edges, unsigned num_edges, edge *new_edges,
1437*e4b17023SJohn Marino 	  struct loop *base, basic_block after)
1438*e4b17023SJohn Marino {
1439*e4b17023SJohn Marino   unsigned i, j;
1440*e4b17023SJohn Marino   basic_block bb, new_bb, dom_bb;
1441*e4b17023SJohn Marino   edge e;
1442*e4b17023SJohn Marino 
1443*e4b17023SJohn Marino   /* Duplicate bbs, update dominators, assign bbs to loops.  */
1444*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1445*e4b17023SJohn Marino     {
1446*e4b17023SJohn Marino       /* Duplicate.  */
1447*e4b17023SJohn Marino       bb = bbs[i];
1448*e4b17023SJohn Marino       new_bb = new_bbs[i] = duplicate_block (bb, NULL, after);
1449*e4b17023SJohn Marino       after = new_bb;
1450*e4b17023SJohn Marino       bb->flags |= BB_DUPLICATED;
1451*e4b17023SJohn Marino       /* Possibly set loop header.  */
1452*e4b17023SJohn Marino       if (bb->loop_father->header == bb && bb->loop_father != base)
1453*e4b17023SJohn Marino 	new_bb->loop_father->header = new_bb;
1454*e4b17023SJohn Marino       /* Or latch.  */
1455*e4b17023SJohn Marino       if (bb->loop_father->latch == bb && bb->loop_father != base)
1456*e4b17023SJohn Marino 	new_bb->loop_father->latch = new_bb;
1457*e4b17023SJohn Marino     }
1458*e4b17023SJohn Marino 
1459*e4b17023SJohn Marino   /* Set dominators.  */
1460*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1461*e4b17023SJohn Marino     {
1462*e4b17023SJohn Marino       bb = bbs[i];
1463*e4b17023SJohn Marino       new_bb = new_bbs[i];
1464*e4b17023SJohn Marino 
1465*e4b17023SJohn Marino       dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb);
1466*e4b17023SJohn Marino       if (dom_bb->flags & BB_DUPLICATED)
1467*e4b17023SJohn Marino 	{
1468*e4b17023SJohn Marino 	  dom_bb = get_bb_copy (dom_bb);
1469*e4b17023SJohn Marino 	  set_immediate_dominator (CDI_DOMINATORS, new_bb, dom_bb);
1470*e4b17023SJohn Marino 	}
1471*e4b17023SJohn Marino     }
1472*e4b17023SJohn Marino 
1473*e4b17023SJohn Marino   /* Redirect edges.  */
1474*e4b17023SJohn Marino   for (j = 0; j < num_edges; j++)
1475*e4b17023SJohn Marino     new_edges[j] = NULL;
1476*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1477*e4b17023SJohn Marino     {
1478*e4b17023SJohn Marino       edge_iterator ei;
1479*e4b17023SJohn Marino       new_bb = new_bbs[i];
1480*e4b17023SJohn Marino       bb = bbs[i];
1481*e4b17023SJohn Marino 
1482*e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, new_bb->succs)
1483*e4b17023SJohn Marino 	{
1484*e4b17023SJohn Marino 	  for (j = 0; j < num_edges; j++)
1485*e4b17023SJohn Marino 	    if (edges[j] && edges[j]->src == bb && edges[j]->dest == e->dest)
1486*e4b17023SJohn Marino 	      new_edges[j] = e;
1487*e4b17023SJohn Marino 
1488*e4b17023SJohn Marino 	  if (!(e->dest->flags & BB_DUPLICATED))
1489*e4b17023SJohn Marino 	    continue;
1490*e4b17023SJohn Marino 	  redirect_edge_and_branch_force (e, get_bb_copy (e->dest));
1491*e4b17023SJohn Marino 	}
1492*e4b17023SJohn Marino     }
1493*e4b17023SJohn Marino 
1494*e4b17023SJohn Marino   /* Clear information about duplicates.  */
1495*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1496*e4b17023SJohn Marino     bbs[i]->flags &= ~BB_DUPLICATED;
1497*e4b17023SJohn Marino }
1498*e4b17023SJohn Marino 
1499*e4b17023SJohn Marino #include "gt-cfglayout.h"
1500