xref: /dflybsd-src/contrib/gcc-4.7/gcc/bb-reorder.c (revision 0a8dc9fc45f4d0b236341a473fac4a486375f60c)
1e4b17023SJohn Marino /* Basic block reordering routines for the GNU compiler.
2e4b17023SJohn Marino    Copyright (C) 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011,
3e4b17023SJohn Marino    2012 Free Software Foundation, Inc.
4e4b17023SJohn Marino 
5e4b17023SJohn Marino    This file is part of GCC.
6e4b17023SJohn Marino 
7e4b17023SJohn Marino    GCC is free software; you can redistribute it and/or modify it
8e4b17023SJohn Marino    under the terms of the GNU General Public License as published by
9e4b17023SJohn Marino    the Free Software Foundation; either version 3, or (at your option)
10e4b17023SJohn Marino    any later version.
11e4b17023SJohn Marino 
12e4b17023SJohn Marino    GCC is distributed in the hope that it will be useful, but WITHOUT
13e4b17023SJohn Marino    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14e4b17023SJohn Marino    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15e4b17023SJohn Marino    License for more details.
16e4b17023SJohn Marino 
17e4b17023SJohn Marino    You should have received a copy of the GNU General Public License
18e4b17023SJohn Marino    along with GCC; see the file COPYING3.  If not see
19e4b17023SJohn Marino    <http://www.gnu.org/licenses/>.  */
20e4b17023SJohn Marino 
21e4b17023SJohn Marino /* This (greedy) algorithm constructs traces in several rounds.
22e4b17023SJohn Marino    The construction starts from "seeds".  The seed for the first round
23e4b17023SJohn Marino    is the entry point of function.  When there are more than one seed
24e4b17023SJohn Marino    that one is selected first that has the lowest key in the heap
25e4b17023SJohn Marino    (see function bb_to_key).  Then the algorithm repeatedly adds the most
26e4b17023SJohn Marino    probable successor to the end of a trace.  Finally it connects the traces.
27e4b17023SJohn Marino 
28e4b17023SJohn Marino    There are two parameters: Branch Threshold and Exec Threshold.
29e4b17023SJohn Marino    If the edge to a successor of the actual basic block is lower than
30e4b17023SJohn Marino    Branch Threshold or the frequency of the successor is lower than
31e4b17023SJohn Marino    Exec Threshold the successor will be the seed in one of the next rounds.
32e4b17023SJohn Marino    Each round has these parameters lower than the previous one.
33e4b17023SJohn Marino    The last round has to have these parameters set to zero
34e4b17023SJohn Marino    so that the remaining blocks are picked up.
35e4b17023SJohn Marino 
36e4b17023SJohn Marino    The algorithm selects the most probable successor from all unvisited
37e4b17023SJohn Marino    successors and successors that have been added to this trace.
38e4b17023SJohn Marino    The other successors (that has not been "sent" to the next round) will be
39e4b17023SJohn Marino    other seeds for this round and the secondary traces will start in them.
40e4b17023SJohn Marino    If the successor has not been visited in this trace it is added to the trace
41e4b17023SJohn Marino    (however, there is some heuristic for simple branches).
42e4b17023SJohn Marino    If the successor has been visited in this trace the loop has been found.
43e4b17023SJohn Marino    If the loop has many iterations the loop is rotated so that the
44e4b17023SJohn Marino    source block of the most probable edge going out from the loop
45e4b17023SJohn Marino    is the last block of the trace.
46e4b17023SJohn Marino    If the loop has few iterations and there is no edge from the last block of
47e4b17023SJohn Marino    the loop going out from loop the loop header is duplicated.
48e4b17023SJohn Marino    Finally, the construction of the trace is terminated.
49e4b17023SJohn Marino 
50e4b17023SJohn Marino    When connecting traces it first checks whether there is an edge from the
51e4b17023SJohn Marino    last block of one trace to the first block of another trace.
52e4b17023SJohn Marino    When there are still some unconnected traces it checks whether there exists
53e4b17023SJohn Marino    a basic block BB such that BB is a successor of the last bb of one trace
54e4b17023SJohn Marino    and BB is a predecessor of the first block of another trace. In this case,
55e4b17023SJohn Marino    BB is duplicated and the traces are connected through this duplicate.
56e4b17023SJohn Marino    The rest of traces are simply connected so there will be a jump to the
57e4b17023SJohn Marino    beginning of the rest of trace.
58e4b17023SJohn Marino 
59e4b17023SJohn Marino 
60e4b17023SJohn Marino    References:
61e4b17023SJohn Marino 
62e4b17023SJohn Marino    "Software Trace Cache"
63e4b17023SJohn Marino    A. Ramirez, J. Larriba-Pey, C. Navarro, J. Torrellas and M. Valero; 1999
64e4b17023SJohn Marino    http://citeseer.nj.nec.com/15361.html
65e4b17023SJohn Marino 
66e4b17023SJohn Marino */
67e4b17023SJohn Marino 
68e4b17023SJohn Marino #include "config.h"
69e4b17023SJohn Marino #include "system.h"
70e4b17023SJohn Marino #include "coretypes.h"
71e4b17023SJohn Marino #include "tm.h"
72e4b17023SJohn Marino #include "rtl.h"
73e4b17023SJohn Marino #include "regs.h"
74e4b17023SJohn Marino #include "flags.h"
75e4b17023SJohn Marino #include "timevar.h"
76e4b17023SJohn Marino #include "output.h"
77e4b17023SJohn Marino #include "cfglayout.h"
78e4b17023SJohn Marino #include "fibheap.h"
79e4b17023SJohn Marino #include "target.h"
80e4b17023SJohn Marino #include "function.h"
81e4b17023SJohn Marino #include "tm_p.h"
82e4b17023SJohn Marino #include "obstack.h"
83e4b17023SJohn Marino #include "expr.h"
84e4b17023SJohn Marino #include "params.h"
85e4b17023SJohn Marino #include "diagnostic-core.h"
86e4b17023SJohn Marino #include "toplev.h" /* user_defined_section_attribute */
87e4b17023SJohn Marino #include "tree-pass.h"
88e4b17023SJohn Marino #include "df.h"
89e4b17023SJohn Marino #include "bb-reorder.h"
90e4b17023SJohn Marino #include "except.h"
91e4b17023SJohn Marino 
92e4b17023SJohn Marino /* The number of rounds.  In most cases there will only be 4 rounds, but
93e4b17023SJohn Marino    when partitioning hot and cold basic blocks into separate sections of
94e4b17023SJohn Marino    the .o file there will be an extra round.*/
95e4b17023SJohn Marino #define N_ROUNDS 5
96e4b17023SJohn Marino 
97e4b17023SJohn Marino /* Stubs in case we don't have a return insn.
98e4b17023SJohn Marino    We have to check at runtime too, not only compiletime.  */
99e4b17023SJohn Marino 
100e4b17023SJohn Marino #ifndef HAVE_return
101e4b17023SJohn Marino #define HAVE_return 0
102e4b17023SJohn Marino #define gen_return() NULL_RTX
103e4b17023SJohn Marino #endif
104e4b17023SJohn Marino 
105e4b17023SJohn Marino 
106e4b17023SJohn Marino struct target_bb_reorder default_target_bb_reorder;
107e4b17023SJohn Marino #if SWITCHABLE_TARGET
108e4b17023SJohn Marino struct target_bb_reorder *this_target_bb_reorder = &default_target_bb_reorder;
109e4b17023SJohn Marino #endif
110e4b17023SJohn Marino 
111e4b17023SJohn Marino #define uncond_jump_length \
112e4b17023SJohn Marino   (this_target_bb_reorder->x_uncond_jump_length)
113e4b17023SJohn Marino 
114e4b17023SJohn Marino /* Branch thresholds in thousandths (per mille) of the REG_BR_PROB_BASE.  */
115e4b17023SJohn Marino static int branch_threshold[N_ROUNDS] = {400, 200, 100, 0, 0};
116e4b17023SJohn Marino 
117e4b17023SJohn Marino /* Exec thresholds in thousandths (per mille) of the frequency of bb 0.  */
118e4b17023SJohn Marino static int exec_threshold[N_ROUNDS] = {500, 200, 50, 0, 0};
119e4b17023SJohn Marino 
120e4b17023SJohn Marino /* If edge frequency is lower than DUPLICATION_THRESHOLD per mille of entry
121e4b17023SJohn Marino    block the edge destination is not duplicated while connecting traces.  */
122e4b17023SJohn Marino #define DUPLICATION_THRESHOLD 100
123e4b17023SJohn Marino 
124e4b17023SJohn Marino /* Structure to hold needed information for each basic block.  */
125e4b17023SJohn Marino typedef struct bbro_basic_block_data_def
126e4b17023SJohn Marino {
127e4b17023SJohn Marino   /* Which trace is the bb start of (-1 means it is not a start of a trace).  */
128e4b17023SJohn Marino   int start_of_trace;
129e4b17023SJohn Marino 
130e4b17023SJohn Marino   /* Which trace is the bb end of (-1 means it is not an end of a trace).  */
131e4b17023SJohn Marino   int end_of_trace;
132e4b17023SJohn Marino 
133e4b17023SJohn Marino   /* Which trace is the bb in?  */
134e4b17023SJohn Marino   int in_trace;
135e4b17023SJohn Marino 
136e4b17023SJohn Marino   /* Which heap is BB in (if any)?  */
137e4b17023SJohn Marino   fibheap_t heap;
138e4b17023SJohn Marino 
139e4b17023SJohn Marino   /* Which heap node is BB in (if any)?  */
140e4b17023SJohn Marino   fibnode_t node;
141e4b17023SJohn Marino } bbro_basic_block_data;
142e4b17023SJohn Marino 
143e4b17023SJohn Marino /* The current size of the following dynamic array.  */
144e4b17023SJohn Marino static int array_size;
145e4b17023SJohn Marino 
146e4b17023SJohn Marino /* The array which holds needed information for basic blocks.  */
147e4b17023SJohn Marino static bbro_basic_block_data *bbd;
148e4b17023SJohn Marino 
149e4b17023SJohn Marino /* To avoid frequent reallocation the size of arrays is greater than needed,
150e4b17023SJohn Marino    the number of elements is (not less than) 1.25 * size_wanted.  */
151e4b17023SJohn Marino #define GET_ARRAY_SIZE(X) ((((X) / 4) + 1) * 5)
152e4b17023SJohn Marino 
153e4b17023SJohn Marino /* Free the memory and set the pointer to NULL.  */
154e4b17023SJohn Marino #define FREE(P) (gcc_assert (P), free (P), P = 0)
155e4b17023SJohn Marino 
156e4b17023SJohn Marino /* Structure for holding information about a trace.  */
157e4b17023SJohn Marino struct trace
158e4b17023SJohn Marino {
159e4b17023SJohn Marino   /* First and last basic block of the trace.  */
160e4b17023SJohn Marino   basic_block first, last;
161e4b17023SJohn Marino 
162e4b17023SJohn Marino   /* The round of the STC creation which this trace was found in.  */
163e4b17023SJohn Marino   int round;
164e4b17023SJohn Marino 
165e4b17023SJohn Marino   /* The length (i.e. the number of basic blocks) of the trace.  */
166e4b17023SJohn Marino   int length;
167e4b17023SJohn Marino };
168e4b17023SJohn Marino 
169e4b17023SJohn Marino /* Maximum frequency and count of one of the entry blocks.  */
170e4b17023SJohn Marino static int max_entry_frequency;
171e4b17023SJohn Marino static gcov_type max_entry_count;
172e4b17023SJohn Marino 
173e4b17023SJohn Marino /* Local function prototypes.  */
174e4b17023SJohn Marino static void find_traces (int *, struct trace *);
175e4b17023SJohn Marino static basic_block rotate_loop (edge, struct trace *, int);
176e4b17023SJohn Marino static void mark_bb_visited (basic_block, int);
177e4b17023SJohn Marino static void find_traces_1_round (int, int, gcov_type, struct trace *, int *,
178e4b17023SJohn Marino 				 int, fibheap_t *, int);
179e4b17023SJohn Marino static basic_block copy_bb (basic_block, edge, basic_block, int);
180e4b17023SJohn Marino static fibheapkey_t bb_to_key (basic_block);
181e4b17023SJohn Marino static bool better_edge_p (const_basic_block, const_edge, int, int, int, int, const_edge);
182e4b17023SJohn Marino static void connect_traces (int, struct trace *);
183e4b17023SJohn Marino static bool copy_bb_p (const_basic_block, int);
184e4b17023SJohn Marino static bool push_to_next_round_p (const_basic_block, int, int, int, gcov_type);
185e4b17023SJohn Marino 
186e4b17023SJohn Marino /* Check to see if bb should be pushed into the next round of trace
187e4b17023SJohn Marino    collections or not.  Reasons for pushing the block forward are 1).
188e4b17023SJohn Marino    If the block is cold, we are doing partitioning, and there will be
189e4b17023SJohn Marino    another round (cold partition blocks are not supposed to be
190e4b17023SJohn Marino    collected into traces until the very last round); or 2). There will
191e4b17023SJohn Marino    be another round, and the basic block is not "hot enough" for the
192e4b17023SJohn Marino    current round of trace collection.  */
193e4b17023SJohn Marino 
194e4b17023SJohn Marino static bool
push_to_next_round_p(const_basic_block bb,int round,int number_of_rounds,int exec_th,gcov_type count_th)195e4b17023SJohn Marino push_to_next_round_p (const_basic_block bb, int round, int number_of_rounds,
196e4b17023SJohn Marino 		      int exec_th, gcov_type count_th)
197e4b17023SJohn Marino {
198e4b17023SJohn Marino   bool there_exists_another_round;
199e4b17023SJohn Marino   bool block_not_hot_enough;
200e4b17023SJohn Marino 
201e4b17023SJohn Marino   there_exists_another_round = round < number_of_rounds - 1;
202e4b17023SJohn Marino 
203e4b17023SJohn Marino   block_not_hot_enough = (bb->frequency < exec_th
204e4b17023SJohn Marino 			  || bb->count < count_th
205e4b17023SJohn Marino 			  || probably_never_executed_bb_p (bb));
206e4b17023SJohn Marino 
207e4b17023SJohn Marino   if (there_exists_another_round
208e4b17023SJohn Marino       && block_not_hot_enough)
209e4b17023SJohn Marino     return true;
210e4b17023SJohn Marino   else
211e4b17023SJohn Marino     return false;
212e4b17023SJohn Marino }
213e4b17023SJohn Marino 
214e4b17023SJohn Marino /* Find the traces for Software Trace Cache.  Chain each trace through
215e4b17023SJohn Marino    RBI()->next.  Store the number of traces to N_TRACES and description of
216e4b17023SJohn Marino    traces to TRACES.  */
217e4b17023SJohn Marino 
218e4b17023SJohn Marino static void
find_traces(int * n_traces,struct trace * traces)219e4b17023SJohn Marino find_traces (int *n_traces, struct trace *traces)
220e4b17023SJohn Marino {
221e4b17023SJohn Marino   int i;
222e4b17023SJohn Marino   int number_of_rounds;
223e4b17023SJohn Marino   edge e;
224e4b17023SJohn Marino   edge_iterator ei;
225e4b17023SJohn Marino   fibheap_t heap;
226e4b17023SJohn Marino 
227e4b17023SJohn Marino   /* Add one extra round of trace collection when partitioning hot/cold
228e4b17023SJohn Marino      basic blocks into separate sections.  The last round is for all the
229e4b17023SJohn Marino      cold blocks (and ONLY the cold blocks).  */
230e4b17023SJohn Marino 
231e4b17023SJohn Marino   number_of_rounds = N_ROUNDS - 1;
232e4b17023SJohn Marino 
233e4b17023SJohn Marino   /* Insert entry points of function into heap.  */
234e4b17023SJohn Marino   heap = fibheap_new ();
235e4b17023SJohn Marino   max_entry_frequency = 0;
236e4b17023SJohn Marino   max_entry_count = 0;
237e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
238e4b17023SJohn Marino     {
239e4b17023SJohn Marino       bbd[e->dest->index].heap = heap;
240e4b17023SJohn Marino       bbd[e->dest->index].node = fibheap_insert (heap, bb_to_key (e->dest),
241e4b17023SJohn Marino 						    e->dest);
242e4b17023SJohn Marino       if (e->dest->frequency > max_entry_frequency)
243e4b17023SJohn Marino 	max_entry_frequency = e->dest->frequency;
244e4b17023SJohn Marino       if (e->dest->count > max_entry_count)
245e4b17023SJohn Marino 	max_entry_count = e->dest->count;
246e4b17023SJohn Marino     }
247e4b17023SJohn Marino 
248e4b17023SJohn Marino   /* Find the traces.  */
249e4b17023SJohn Marino   for (i = 0; i < number_of_rounds; i++)
250e4b17023SJohn Marino     {
251e4b17023SJohn Marino       gcov_type count_threshold;
252e4b17023SJohn Marino 
253e4b17023SJohn Marino       if (dump_file)
254e4b17023SJohn Marino 	fprintf (dump_file, "STC - round %d\n", i + 1);
255e4b17023SJohn Marino 
256e4b17023SJohn Marino       if (max_entry_count < INT_MAX / 1000)
257e4b17023SJohn Marino 	count_threshold = max_entry_count * exec_threshold[i] / 1000;
258e4b17023SJohn Marino       else
259e4b17023SJohn Marino 	count_threshold = max_entry_count / 1000 * exec_threshold[i];
260e4b17023SJohn Marino 
261e4b17023SJohn Marino       find_traces_1_round (REG_BR_PROB_BASE * branch_threshold[i] / 1000,
262e4b17023SJohn Marino 			   max_entry_frequency * exec_threshold[i] / 1000,
263e4b17023SJohn Marino 			   count_threshold, traces, n_traces, i, &heap,
264e4b17023SJohn Marino 			   number_of_rounds);
265e4b17023SJohn Marino     }
266e4b17023SJohn Marino   fibheap_delete (heap);
267e4b17023SJohn Marino 
268e4b17023SJohn Marino   if (dump_file)
269e4b17023SJohn Marino     {
270e4b17023SJohn Marino       for (i = 0; i < *n_traces; i++)
271e4b17023SJohn Marino 	{
272e4b17023SJohn Marino 	  basic_block bb;
273e4b17023SJohn Marino 	  fprintf (dump_file, "Trace %d (round %d):  ", i + 1,
274e4b17023SJohn Marino 		   traces[i].round + 1);
275e4b17023SJohn Marino 	  for (bb = traces[i].first; bb != traces[i].last; bb = (basic_block) bb->aux)
276e4b17023SJohn Marino 	    fprintf (dump_file, "%d [%d] ", bb->index, bb->frequency);
277e4b17023SJohn Marino 	  fprintf (dump_file, "%d [%d]\n", bb->index, bb->frequency);
278e4b17023SJohn Marino 	}
279e4b17023SJohn Marino       fflush (dump_file);
280e4b17023SJohn Marino     }
281e4b17023SJohn Marino }
282e4b17023SJohn Marino 
283e4b17023SJohn Marino /* Rotate loop whose back edge is BACK_EDGE in the tail of trace TRACE
284e4b17023SJohn Marino    (with sequential number TRACE_N).  */
285e4b17023SJohn Marino 
286e4b17023SJohn Marino static basic_block
rotate_loop(edge back_edge,struct trace * trace,int trace_n)287e4b17023SJohn Marino rotate_loop (edge back_edge, struct trace *trace, int trace_n)
288e4b17023SJohn Marino {
289e4b17023SJohn Marino   basic_block bb;
290e4b17023SJohn Marino 
291e4b17023SJohn Marino   /* Information about the best end (end after rotation) of the loop.  */
292e4b17023SJohn Marino   basic_block best_bb = NULL;
293e4b17023SJohn Marino   edge best_edge = NULL;
294e4b17023SJohn Marino   int best_freq = -1;
295e4b17023SJohn Marino   gcov_type best_count = -1;
296e4b17023SJohn Marino   /* The best edge is preferred when its destination is not visited yet
297e4b17023SJohn Marino      or is a start block of some trace.  */
298e4b17023SJohn Marino   bool is_preferred = false;
299e4b17023SJohn Marino 
300e4b17023SJohn Marino   /* Find the most frequent edge that goes out from current trace.  */
301e4b17023SJohn Marino   bb = back_edge->dest;
302e4b17023SJohn Marino   do
303e4b17023SJohn Marino     {
304e4b17023SJohn Marino       edge e;
305e4b17023SJohn Marino       edge_iterator ei;
306e4b17023SJohn Marino 
307e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->succs)
308e4b17023SJohn Marino 	if (e->dest != EXIT_BLOCK_PTR
309e4b17023SJohn Marino 	    && e->dest->il.rtl->visited != trace_n
310e4b17023SJohn Marino 	    && (e->flags & EDGE_CAN_FALLTHRU)
311e4b17023SJohn Marino 	    && !(e->flags & EDGE_COMPLEX))
312e4b17023SJohn Marino 	{
313e4b17023SJohn Marino 	  if (is_preferred)
314e4b17023SJohn Marino 	    {
315e4b17023SJohn Marino 	      /* The best edge is preferred.  */
316e4b17023SJohn Marino 	      if (!e->dest->il.rtl->visited
317e4b17023SJohn Marino 		  || bbd[e->dest->index].start_of_trace >= 0)
318e4b17023SJohn Marino 		{
319e4b17023SJohn Marino 		  /* The current edge E is also preferred.  */
320e4b17023SJohn Marino 		  int freq = EDGE_FREQUENCY (e);
321e4b17023SJohn Marino 		  if (freq > best_freq || e->count > best_count)
322e4b17023SJohn Marino 		    {
323e4b17023SJohn Marino 		      best_freq = freq;
324e4b17023SJohn Marino 		      best_count = e->count;
325e4b17023SJohn Marino 		      best_edge = e;
326e4b17023SJohn Marino 		      best_bb = bb;
327e4b17023SJohn Marino 		    }
328e4b17023SJohn Marino 		}
329e4b17023SJohn Marino 	    }
330e4b17023SJohn Marino 	  else
331e4b17023SJohn Marino 	    {
332e4b17023SJohn Marino 	      if (!e->dest->il.rtl->visited
333e4b17023SJohn Marino 		  || bbd[e->dest->index].start_of_trace >= 0)
334e4b17023SJohn Marino 		{
335e4b17023SJohn Marino 		  /* The current edge E is preferred.  */
336e4b17023SJohn Marino 		  is_preferred = true;
337e4b17023SJohn Marino 		  best_freq = EDGE_FREQUENCY (e);
338e4b17023SJohn Marino 		  best_count = e->count;
339e4b17023SJohn Marino 		  best_edge = e;
340e4b17023SJohn Marino 		  best_bb = bb;
341e4b17023SJohn Marino 		}
342e4b17023SJohn Marino 	      else
343e4b17023SJohn Marino 		{
344e4b17023SJohn Marino 		  int freq = EDGE_FREQUENCY (e);
345e4b17023SJohn Marino 		  if (!best_edge || freq > best_freq || e->count > best_count)
346e4b17023SJohn Marino 		    {
347e4b17023SJohn Marino 		      best_freq = freq;
348e4b17023SJohn Marino 		      best_count = e->count;
349e4b17023SJohn Marino 		      best_edge = e;
350e4b17023SJohn Marino 		      best_bb = bb;
351e4b17023SJohn Marino 		    }
352e4b17023SJohn Marino 		}
353e4b17023SJohn Marino 	    }
354e4b17023SJohn Marino 	}
355e4b17023SJohn Marino       bb = (basic_block) bb->aux;
356e4b17023SJohn Marino     }
357e4b17023SJohn Marino   while (bb != back_edge->dest);
358e4b17023SJohn Marino 
359e4b17023SJohn Marino   if (best_bb)
360e4b17023SJohn Marino     {
361e4b17023SJohn Marino       /* Rotate the loop so that the BEST_EDGE goes out from the last block of
362e4b17023SJohn Marino 	 the trace.  */
363e4b17023SJohn Marino       if (back_edge->dest == trace->first)
364e4b17023SJohn Marino 	{
365e4b17023SJohn Marino 	  trace->first = (basic_block) best_bb->aux;
366e4b17023SJohn Marino 	}
367e4b17023SJohn Marino       else
368e4b17023SJohn Marino 	{
369e4b17023SJohn Marino 	  basic_block prev_bb;
370e4b17023SJohn Marino 
371e4b17023SJohn Marino 	  for (prev_bb = trace->first;
372e4b17023SJohn Marino 	       prev_bb->aux != back_edge->dest;
373e4b17023SJohn Marino 	       prev_bb = (basic_block) prev_bb->aux)
374e4b17023SJohn Marino 	    ;
375e4b17023SJohn Marino 	  prev_bb->aux = best_bb->aux;
376e4b17023SJohn Marino 
377e4b17023SJohn Marino 	  /* Try to get rid of uncond jump to cond jump.  */
378e4b17023SJohn Marino 	  if (single_succ_p (prev_bb))
379e4b17023SJohn Marino 	    {
380e4b17023SJohn Marino 	      basic_block header = single_succ (prev_bb);
381e4b17023SJohn Marino 
382e4b17023SJohn Marino 	      /* Duplicate HEADER if it is a small block containing cond jump
383e4b17023SJohn Marino 		 in the end.  */
384e4b17023SJohn Marino 	      if (any_condjump_p (BB_END (header)) && copy_bb_p (header, 0)
385e4b17023SJohn Marino 		  && !find_reg_note (BB_END (header), REG_CROSSING_JUMP,
386e4b17023SJohn Marino 				     NULL_RTX))
387e4b17023SJohn Marino 		copy_bb (header, single_succ_edge (prev_bb), prev_bb, trace_n);
388e4b17023SJohn Marino 	    }
389e4b17023SJohn Marino 	}
390e4b17023SJohn Marino     }
391e4b17023SJohn Marino   else
392e4b17023SJohn Marino     {
393e4b17023SJohn Marino       /* We have not found suitable loop tail so do no rotation.  */
394e4b17023SJohn Marino       best_bb = back_edge->src;
395e4b17023SJohn Marino     }
396e4b17023SJohn Marino   best_bb->aux = NULL;
397e4b17023SJohn Marino   return best_bb;
398e4b17023SJohn Marino }
399e4b17023SJohn Marino 
400e4b17023SJohn Marino /* This function marks BB that it was visited in trace number TRACE.  */
401e4b17023SJohn Marino 
402e4b17023SJohn Marino static void
mark_bb_visited(basic_block bb,int trace)403e4b17023SJohn Marino mark_bb_visited (basic_block bb, int trace)
404e4b17023SJohn Marino {
405e4b17023SJohn Marino   bb->il.rtl->visited = trace;
406e4b17023SJohn Marino   if (bbd[bb->index].heap)
407e4b17023SJohn Marino     {
408e4b17023SJohn Marino       fibheap_delete_node (bbd[bb->index].heap, bbd[bb->index].node);
409e4b17023SJohn Marino       bbd[bb->index].heap = NULL;
410e4b17023SJohn Marino       bbd[bb->index].node = NULL;
411e4b17023SJohn Marino     }
412e4b17023SJohn Marino }
413e4b17023SJohn Marino 
414e4b17023SJohn Marino /* One round of finding traces. Find traces for BRANCH_TH and EXEC_TH i.e. do
415e4b17023SJohn Marino    not include basic blocks their probability is lower than BRANCH_TH or their
416e4b17023SJohn Marino    frequency is lower than EXEC_TH into traces (or count is lower than
417e4b17023SJohn Marino    COUNT_TH).  It stores the new traces into TRACES and modifies the number of
418e4b17023SJohn Marino    traces *N_TRACES. Sets the round (which the trace belongs to) to ROUND. It
419e4b17023SJohn Marino    expects that starting basic blocks are in *HEAP and at the end it deletes
420e4b17023SJohn Marino    *HEAP and stores starting points for the next round into new *HEAP.  */
421e4b17023SJohn Marino 
422e4b17023SJohn Marino static void
find_traces_1_round(int branch_th,int exec_th,gcov_type count_th,struct trace * traces,int * n_traces,int round,fibheap_t * heap,int number_of_rounds)423e4b17023SJohn Marino find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
424e4b17023SJohn Marino 		     struct trace *traces, int *n_traces, int round,
425e4b17023SJohn Marino 		     fibheap_t *heap, int number_of_rounds)
426e4b17023SJohn Marino {
427e4b17023SJohn Marino   /* Heap for discarded basic blocks which are possible starting points for
428e4b17023SJohn Marino      the next round.  */
429e4b17023SJohn Marino   fibheap_t new_heap = fibheap_new ();
430e4b17023SJohn Marino 
431e4b17023SJohn Marino   while (!fibheap_empty (*heap))
432e4b17023SJohn Marino     {
433e4b17023SJohn Marino       basic_block bb;
434e4b17023SJohn Marino       struct trace *trace;
435e4b17023SJohn Marino       edge best_edge, e;
436e4b17023SJohn Marino       fibheapkey_t key;
437e4b17023SJohn Marino       edge_iterator ei;
438e4b17023SJohn Marino 
439e4b17023SJohn Marino       bb = (basic_block) fibheap_extract_min (*heap);
440e4b17023SJohn Marino       bbd[bb->index].heap = NULL;
441e4b17023SJohn Marino       bbd[bb->index].node = NULL;
442e4b17023SJohn Marino 
443e4b17023SJohn Marino       if (dump_file)
444e4b17023SJohn Marino 	fprintf (dump_file, "Getting bb %d\n", bb->index);
445e4b17023SJohn Marino 
446e4b17023SJohn Marino       /* If the BB's frequency is too low send BB to the next round.  When
447e4b17023SJohn Marino 	 partitioning hot/cold blocks into separate sections, make sure all
448e4b17023SJohn Marino 	 the cold blocks (and ONLY the cold blocks) go into the (extra) final
449e4b17023SJohn Marino 	 round.  */
450e4b17023SJohn Marino 
451e4b17023SJohn Marino       if (push_to_next_round_p (bb, round, number_of_rounds, exec_th,
452e4b17023SJohn Marino 				count_th))
453e4b17023SJohn Marino 	{
454e4b17023SJohn Marino 	  int key = bb_to_key (bb);
455e4b17023SJohn Marino 	  bbd[bb->index].heap = new_heap;
456e4b17023SJohn Marino 	  bbd[bb->index].node = fibheap_insert (new_heap, key, bb);
457e4b17023SJohn Marino 
458e4b17023SJohn Marino 	  if (dump_file)
459e4b17023SJohn Marino 	    fprintf (dump_file,
460e4b17023SJohn Marino 		     "  Possible start point of next round: %d (key: %d)\n",
461e4b17023SJohn Marino 		     bb->index, key);
462e4b17023SJohn Marino 	  continue;
463e4b17023SJohn Marino 	}
464e4b17023SJohn Marino 
465e4b17023SJohn Marino       trace = traces + *n_traces;
466e4b17023SJohn Marino       trace->first = bb;
467e4b17023SJohn Marino       trace->round = round;
468e4b17023SJohn Marino       trace->length = 0;
469e4b17023SJohn Marino       bbd[bb->index].in_trace = *n_traces;
470e4b17023SJohn Marino       (*n_traces)++;
471e4b17023SJohn Marino 
472e4b17023SJohn Marino       do
473e4b17023SJohn Marino 	{
474e4b17023SJohn Marino 	  int prob, freq;
475e4b17023SJohn Marino 	  bool ends_in_call;
476e4b17023SJohn Marino 
477e4b17023SJohn Marino 	  /* The probability and frequency of the best edge.  */
478e4b17023SJohn Marino 	  int best_prob = INT_MIN / 2;
479e4b17023SJohn Marino 	  int best_freq = INT_MIN / 2;
480e4b17023SJohn Marino 
481e4b17023SJohn Marino 	  best_edge = NULL;
482e4b17023SJohn Marino 	  mark_bb_visited (bb, *n_traces);
483e4b17023SJohn Marino 	  trace->length++;
484e4b17023SJohn Marino 
485e4b17023SJohn Marino 	  if (dump_file)
486e4b17023SJohn Marino 	    fprintf (dump_file, "Basic block %d was visited in trace %d\n",
487e4b17023SJohn Marino 		     bb->index, *n_traces - 1);
488e4b17023SJohn Marino 
489e4b17023SJohn Marino 	  ends_in_call = block_ends_with_call_p (bb);
490e4b17023SJohn Marino 
491e4b17023SJohn Marino 	  /* Select the successor that will be placed after BB.  */
492e4b17023SJohn Marino 	  FOR_EACH_EDGE (e, ei, bb->succs)
493e4b17023SJohn Marino 	    {
494e4b17023SJohn Marino 	      gcc_assert (!(e->flags & EDGE_FAKE));
495e4b17023SJohn Marino 
496e4b17023SJohn Marino 	      if (e->dest == EXIT_BLOCK_PTR)
497e4b17023SJohn Marino 		continue;
498e4b17023SJohn Marino 
499e4b17023SJohn Marino 	      if (e->dest->il.rtl->visited
500e4b17023SJohn Marino 		  && e->dest->il.rtl->visited != *n_traces)
501e4b17023SJohn Marino 		continue;
502e4b17023SJohn Marino 
503e4b17023SJohn Marino 	      if (BB_PARTITION (e->dest) != BB_PARTITION (bb))
504e4b17023SJohn Marino 		continue;
505e4b17023SJohn Marino 
506e4b17023SJohn Marino 	      prob = e->probability;
507e4b17023SJohn Marino 	      freq = e->dest->frequency;
508e4b17023SJohn Marino 
509e4b17023SJohn Marino 	      /* The only sensible preference for a call instruction is the
510e4b17023SJohn Marino 		 fallthru edge.  Don't bother selecting anything else.  */
511e4b17023SJohn Marino 	      if (ends_in_call)
512e4b17023SJohn Marino 		{
513e4b17023SJohn Marino 		  if (e->flags & EDGE_CAN_FALLTHRU)
514e4b17023SJohn Marino 		    {
515e4b17023SJohn Marino 		      best_edge = e;
516e4b17023SJohn Marino 		      best_prob = prob;
517e4b17023SJohn Marino 		      best_freq = freq;
518e4b17023SJohn Marino 		    }
519e4b17023SJohn Marino 		  continue;
520e4b17023SJohn Marino 		}
521e4b17023SJohn Marino 
522e4b17023SJohn Marino 	      /* Edge that cannot be fallthru or improbable or infrequent
523e4b17023SJohn Marino 		 successor (i.e. it is unsuitable successor).  */
524e4b17023SJohn Marino 	      if (!(e->flags & EDGE_CAN_FALLTHRU) || (e->flags & EDGE_COMPLEX)
525e4b17023SJohn Marino 		  || prob < branch_th || EDGE_FREQUENCY (e) < exec_th
526e4b17023SJohn Marino 		  || e->count < count_th)
527e4b17023SJohn Marino 		continue;
528e4b17023SJohn Marino 
529e4b17023SJohn Marino 	      /* If partitioning hot/cold basic blocks, don't consider edges
530e4b17023SJohn Marino 		 that cross section boundaries.  */
531e4b17023SJohn Marino 
532e4b17023SJohn Marino 	      if (better_edge_p (bb, e, prob, freq, best_prob, best_freq,
533e4b17023SJohn Marino 				 best_edge))
534e4b17023SJohn Marino 		{
535e4b17023SJohn Marino 		  best_edge = e;
536e4b17023SJohn Marino 		  best_prob = prob;
537e4b17023SJohn Marino 		  best_freq = freq;
538e4b17023SJohn Marino 		}
539e4b17023SJohn Marino 	    }
540e4b17023SJohn Marino 
541e4b17023SJohn Marino 	  /* If the best destination has multiple predecessors, and can be
542e4b17023SJohn Marino 	     duplicated cheaper than a jump, don't allow it to be added
543e4b17023SJohn Marino 	     to a trace.  We'll duplicate it when connecting traces.  */
544e4b17023SJohn Marino 	  if (best_edge && EDGE_COUNT (best_edge->dest->preds) >= 2
545e4b17023SJohn Marino 	      && copy_bb_p (best_edge->dest, 0))
546e4b17023SJohn Marino 	    best_edge = NULL;
547e4b17023SJohn Marino 
548e4b17023SJohn Marino 	  /* Add all non-selected successors to the heaps.  */
549e4b17023SJohn Marino 	  FOR_EACH_EDGE (e, ei, bb->succs)
550e4b17023SJohn Marino 	    {
551e4b17023SJohn Marino 	      if (e == best_edge
552e4b17023SJohn Marino 		  || e->dest == EXIT_BLOCK_PTR
553e4b17023SJohn Marino 		  || e->dest->il.rtl->visited)
554e4b17023SJohn Marino 		continue;
555e4b17023SJohn Marino 
556e4b17023SJohn Marino 	      key = bb_to_key (e->dest);
557e4b17023SJohn Marino 
558e4b17023SJohn Marino 	      if (bbd[e->dest->index].heap)
559e4b17023SJohn Marino 		{
560e4b17023SJohn Marino 		  /* E->DEST is already in some heap.  */
561e4b17023SJohn Marino 		  if (key != bbd[e->dest->index].node->key)
562e4b17023SJohn Marino 		    {
563e4b17023SJohn Marino 		      if (dump_file)
564e4b17023SJohn Marino 			{
565e4b17023SJohn Marino 			  fprintf (dump_file,
566e4b17023SJohn Marino 				   "Changing key for bb %d from %ld to %ld.\n",
567e4b17023SJohn Marino 				   e->dest->index,
568e4b17023SJohn Marino 				   (long) bbd[e->dest->index].node->key,
569e4b17023SJohn Marino 				   key);
570e4b17023SJohn Marino 			}
571e4b17023SJohn Marino 		      fibheap_replace_key (bbd[e->dest->index].heap,
572e4b17023SJohn Marino 					   bbd[e->dest->index].node, key);
573e4b17023SJohn Marino 		    }
574e4b17023SJohn Marino 		}
575e4b17023SJohn Marino 	      else
576e4b17023SJohn Marino 		{
577e4b17023SJohn Marino 		  fibheap_t which_heap = *heap;
578e4b17023SJohn Marino 
579e4b17023SJohn Marino 		  prob = e->probability;
580e4b17023SJohn Marino 		  freq = EDGE_FREQUENCY (e);
581e4b17023SJohn Marino 
582e4b17023SJohn Marino 		  if (!(e->flags & EDGE_CAN_FALLTHRU)
583e4b17023SJohn Marino 		      || (e->flags & EDGE_COMPLEX)
584e4b17023SJohn Marino 		      || prob < branch_th || freq < exec_th
585e4b17023SJohn Marino 		      || e->count < count_th)
586e4b17023SJohn Marino 		    {
587e4b17023SJohn Marino 		      /* When partitioning hot/cold basic blocks, make sure
588e4b17023SJohn Marino 			 the cold blocks (and only the cold blocks) all get
589e4b17023SJohn Marino 			 pushed to the last round of trace collection.  */
590e4b17023SJohn Marino 
591e4b17023SJohn Marino 		      if (push_to_next_round_p (e->dest, round,
592e4b17023SJohn Marino 						number_of_rounds,
593e4b17023SJohn Marino 						exec_th, count_th))
594e4b17023SJohn Marino 			which_heap = new_heap;
595e4b17023SJohn Marino 		    }
596e4b17023SJohn Marino 
597e4b17023SJohn Marino 		  bbd[e->dest->index].heap = which_heap;
598e4b17023SJohn Marino 		  bbd[e->dest->index].node = fibheap_insert (which_heap,
599e4b17023SJohn Marino 								key, e->dest);
600e4b17023SJohn Marino 
601e4b17023SJohn Marino 		  if (dump_file)
602e4b17023SJohn Marino 		    {
603e4b17023SJohn Marino 		      fprintf (dump_file,
604e4b17023SJohn Marino 			       "  Possible start of %s round: %d (key: %ld)\n",
605e4b17023SJohn Marino 			       (which_heap == new_heap) ? "next" : "this",
606e4b17023SJohn Marino 			       e->dest->index, (long) key);
607e4b17023SJohn Marino 		    }
608e4b17023SJohn Marino 
609e4b17023SJohn Marino 		}
610e4b17023SJohn Marino 	    }
611e4b17023SJohn Marino 
612e4b17023SJohn Marino 	  if (best_edge) /* Suitable successor was found.  */
613e4b17023SJohn Marino 	    {
614e4b17023SJohn Marino 	      if (best_edge->dest->il.rtl->visited == *n_traces)
615e4b17023SJohn Marino 		{
616e4b17023SJohn Marino 		  /* We do nothing with one basic block loops.  */
617e4b17023SJohn Marino 		  if (best_edge->dest != bb)
618e4b17023SJohn Marino 		    {
619e4b17023SJohn Marino 		      if (EDGE_FREQUENCY (best_edge)
620e4b17023SJohn Marino 			  > 4 * best_edge->dest->frequency / 5)
621e4b17023SJohn Marino 			{
622e4b17023SJohn Marino 			  /* The loop has at least 4 iterations.  If the loop
623e4b17023SJohn Marino 			     header is not the first block of the function
624e4b17023SJohn Marino 			     we can rotate the loop.  */
625e4b17023SJohn Marino 
626e4b17023SJohn Marino 			  if (best_edge->dest != ENTRY_BLOCK_PTR->next_bb)
627e4b17023SJohn Marino 			    {
628e4b17023SJohn Marino 			      if (dump_file)
629e4b17023SJohn Marino 				{
630e4b17023SJohn Marino 				  fprintf (dump_file,
631e4b17023SJohn Marino 					   "Rotating loop %d - %d\n",
632e4b17023SJohn Marino 					   best_edge->dest->index, bb->index);
633e4b17023SJohn Marino 				}
634e4b17023SJohn Marino 			      bb->aux = best_edge->dest;
635e4b17023SJohn Marino 			      bbd[best_edge->dest->index].in_trace =
636e4b17023SJohn Marino 							     (*n_traces) - 1;
637e4b17023SJohn Marino 			      bb = rotate_loop (best_edge, trace, *n_traces);
638e4b17023SJohn Marino 			    }
639e4b17023SJohn Marino 			}
640e4b17023SJohn Marino 		      else
641e4b17023SJohn Marino 			{
642e4b17023SJohn Marino 			  /* The loop has less than 4 iterations.  */
643e4b17023SJohn Marino 
644e4b17023SJohn Marino 			  if (single_succ_p (bb)
645e4b17023SJohn Marino 			      && copy_bb_p (best_edge->dest,
646e4b17023SJohn Marino 			      		    optimize_edge_for_speed_p (best_edge)))
647e4b17023SJohn Marino 			    {
648e4b17023SJohn Marino 			      bb = copy_bb (best_edge->dest, best_edge, bb,
649e4b17023SJohn Marino 					    *n_traces);
650e4b17023SJohn Marino 			      trace->length++;
651e4b17023SJohn Marino 			    }
652e4b17023SJohn Marino 			}
653e4b17023SJohn Marino 		    }
654e4b17023SJohn Marino 
655e4b17023SJohn Marino 		  /* Terminate the trace.  */
656e4b17023SJohn Marino 		  break;
657e4b17023SJohn Marino 		}
658e4b17023SJohn Marino 	      else
659e4b17023SJohn Marino 		{
660e4b17023SJohn Marino 		  /* Check for a situation
661e4b17023SJohn Marino 
662e4b17023SJohn Marino 		    A
663e4b17023SJohn Marino 		   /|
664e4b17023SJohn Marino 		  B |
665e4b17023SJohn Marino 		   \|
666e4b17023SJohn Marino 		    C
667e4b17023SJohn Marino 
668e4b17023SJohn Marino 		  where
669e4b17023SJohn Marino 		  EDGE_FREQUENCY (AB) + EDGE_FREQUENCY (BC)
670e4b17023SJohn Marino 		    >= EDGE_FREQUENCY (AC).
671e4b17023SJohn Marino 		  (i.e. 2 * B->frequency >= EDGE_FREQUENCY (AC) )
672e4b17023SJohn Marino 		  Best ordering is then A B C.
673e4b17023SJohn Marino 
674e4b17023SJohn Marino 		  This situation is created for example by:
675e4b17023SJohn Marino 
676e4b17023SJohn Marino 		  if (A) B;
677e4b17023SJohn Marino 		  C;
678e4b17023SJohn Marino 
679e4b17023SJohn Marino 		  */
680e4b17023SJohn Marino 
681e4b17023SJohn Marino 		  FOR_EACH_EDGE (e, ei, bb->succs)
682e4b17023SJohn Marino 		    if (e != best_edge
683e4b17023SJohn Marino 			&& (e->flags & EDGE_CAN_FALLTHRU)
684e4b17023SJohn Marino 			&& !(e->flags & EDGE_COMPLEX)
685e4b17023SJohn Marino 			&& !e->dest->il.rtl->visited
686e4b17023SJohn Marino 			&& single_pred_p (e->dest)
687e4b17023SJohn Marino 			&& !(e->flags & EDGE_CROSSING)
688e4b17023SJohn Marino 			&& single_succ_p (e->dest)
689e4b17023SJohn Marino 			&& (single_succ_edge (e->dest)->flags
690e4b17023SJohn Marino 			    & EDGE_CAN_FALLTHRU)
691e4b17023SJohn Marino 			&& !(single_succ_edge (e->dest)->flags & EDGE_COMPLEX)
692e4b17023SJohn Marino 			&& single_succ (e->dest) == best_edge->dest
693e4b17023SJohn Marino 			&& 2 * e->dest->frequency >= EDGE_FREQUENCY (best_edge))
694e4b17023SJohn Marino 		      {
695e4b17023SJohn Marino 			best_edge = e;
696e4b17023SJohn Marino 			if (dump_file)
697e4b17023SJohn Marino 			  fprintf (dump_file, "Selecting BB %d\n",
698e4b17023SJohn Marino 				   best_edge->dest->index);
699e4b17023SJohn Marino 			break;
700e4b17023SJohn Marino 		      }
701e4b17023SJohn Marino 
702e4b17023SJohn Marino 		  bb->aux = best_edge->dest;
703e4b17023SJohn Marino 		  bbd[best_edge->dest->index].in_trace = (*n_traces) - 1;
704e4b17023SJohn Marino 		  bb = best_edge->dest;
705e4b17023SJohn Marino 		}
706e4b17023SJohn Marino 	    }
707e4b17023SJohn Marino 	}
708e4b17023SJohn Marino       while (best_edge);
709e4b17023SJohn Marino       trace->last = bb;
710e4b17023SJohn Marino       bbd[trace->first->index].start_of_trace = *n_traces - 1;
711e4b17023SJohn Marino       bbd[trace->last->index].end_of_trace = *n_traces - 1;
712e4b17023SJohn Marino 
713e4b17023SJohn Marino       /* The trace is terminated so we have to recount the keys in heap
714e4b17023SJohn Marino 	 (some block can have a lower key because now one of its predecessors
715e4b17023SJohn Marino 	 is an end of the trace).  */
716e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->succs)
717e4b17023SJohn Marino 	{
718e4b17023SJohn Marino 	  if (e->dest == EXIT_BLOCK_PTR
719e4b17023SJohn Marino 	      || e->dest->il.rtl->visited)
720e4b17023SJohn Marino 	    continue;
721e4b17023SJohn Marino 
722e4b17023SJohn Marino 	  if (bbd[e->dest->index].heap)
723e4b17023SJohn Marino 	    {
724e4b17023SJohn Marino 	      key = bb_to_key (e->dest);
725e4b17023SJohn Marino 	      if (key != bbd[e->dest->index].node->key)
726e4b17023SJohn Marino 		{
727e4b17023SJohn Marino 		  if (dump_file)
728e4b17023SJohn Marino 		    {
729e4b17023SJohn Marino 		      fprintf (dump_file,
730e4b17023SJohn Marino 			       "Changing key for bb %d from %ld to %ld.\n",
731e4b17023SJohn Marino 			       e->dest->index,
732e4b17023SJohn Marino 			       (long) bbd[e->dest->index].node->key, key);
733e4b17023SJohn Marino 		    }
734e4b17023SJohn Marino 		  fibheap_replace_key (bbd[e->dest->index].heap,
735e4b17023SJohn Marino 				       bbd[e->dest->index].node,
736e4b17023SJohn Marino 				       key);
737e4b17023SJohn Marino 		}
738e4b17023SJohn Marino 	    }
739e4b17023SJohn Marino 	}
740e4b17023SJohn Marino     }
741e4b17023SJohn Marino 
742e4b17023SJohn Marino   fibheap_delete (*heap);
743e4b17023SJohn Marino 
744e4b17023SJohn Marino   /* "Return" the new heap.  */
745e4b17023SJohn Marino   *heap = new_heap;
746e4b17023SJohn Marino }
747e4b17023SJohn Marino 
748e4b17023SJohn Marino /* Create a duplicate of the basic block OLD_BB and redirect edge E to it, add
749e4b17023SJohn Marino    it to trace after BB, mark OLD_BB visited and update pass' data structures
750e4b17023SJohn Marino    (TRACE is a number of trace which OLD_BB is duplicated to).  */
751e4b17023SJohn Marino 
752e4b17023SJohn Marino static basic_block
copy_bb(basic_block old_bb,edge e,basic_block bb,int trace)753e4b17023SJohn Marino copy_bb (basic_block old_bb, edge e, basic_block bb, int trace)
754e4b17023SJohn Marino {
755e4b17023SJohn Marino   basic_block new_bb;
756e4b17023SJohn Marino 
757e4b17023SJohn Marino   new_bb = duplicate_block (old_bb, e, bb);
758e4b17023SJohn Marino   BB_COPY_PARTITION (new_bb, old_bb);
759e4b17023SJohn Marino 
760e4b17023SJohn Marino   gcc_assert (e->dest == new_bb);
761e4b17023SJohn Marino   gcc_assert (!e->dest->il.rtl->visited);
762e4b17023SJohn Marino 
763e4b17023SJohn Marino   if (dump_file)
764e4b17023SJohn Marino     fprintf (dump_file,
765e4b17023SJohn Marino 	     "Duplicated bb %d (created bb %d)\n",
766e4b17023SJohn Marino 	     old_bb->index, new_bb->index);
767e4b17023SJohn Marino   new_bb->il.rtl->visited = trace;
768e4b17023SJohn Marino   new_bb->aux = bb->aux;
769e4b17023SJohn Marino   bb->aux = new_bb;
770e4b17023SJohn Marino 
771e4b17023SJohn Marino   if (new_bb->index >= array_size || last_basic_block > array_size)
772e4b17023SJohn Marino     {
773e4b17023SJohn Marino       int i;
774e4b17023SJohn Marino       int new_size;
775e4b17023SJohn Marino 
776e4b17023SJohn Marino       new_size = MAX (last_basic_block, new_bb->index + 1);
777e4b17023SJohn Marino       new_size = GET_ARRAY_SIZE (new_size);
778e4b17023SJohn Marino       bbd = XRESIZEVEC (bbro_basic_block_data, bbd, new_size);
779e4b17023SJohn Marino       for (i = array_size; i < new_size; i++)
780e4b17023SJohn Marino 	{
781e4b17023SJohn Marino 	  bbd[i].start_of_trace = -1;
782e4b17023SJohn Marino 	  bbd[i].in_trace = -1;
783e4b17023SJohn Marino 	  bbd[i].end_of_trace = -1;
784e4b17023SJohn Marino 	  bbd[i].heap = NULL;
785e4b17023SJohn Marino 	  bbd[i].node = NULL;
786e4b17023SJohn Marino 	}
787e4b17023SJohn Marino       array_size = new_size;
788e4b17023SJohn Marino 
789e4b17023SJohn Marino       if (dump_file)
790e4b17023SJohn Marino 	{
791e4b17023SJohn Marino 	  fprintf (dump_file,
792e4b17023SJohn Marino 		   "Growing the dynamic array to %d elements.\n",
793e4b17023SJohn Marino 		   array_size);
794e4b17023SJohn Marino 	}
795e4b17023SJohn Marino     }
796e4b17023SJohn Marino 
797e4b17023SJohn Marino   bbd[new_bb->index].in_trace = trace;
798e4b17023SJohn Marino 
799e4b17023SJohn Marino   return new_bb;
800e4b17023SJohn Marino }
801e4b17023SJohn Marino 
802e4b17023SJohn Marino /* Compute and return the key (for the heap) of the basic block BB.  */
803e4b17023SJohn Marino 
804e4b17023SJohn Marino static fibheapkey_t
bb_to_key(basic_block bb)805e4b17023SJohn Marino bb_to_key (basic_block bb)
806e4b17023SJohn Marino {
807e4b17023SJohn Marino   edge e;
808e4b17023SJohn Marino   edge_iterator ei;
809e4b17023SJohn Marino   int priority = 0;
810e4b17023SJohn Marino 
811e4b17023SJohn Marino   /* Do not start in probably never executed blocks.  */
812e4b17023SJohn Marino 
813e4b17023SJohn Marino   if (BB_PARTITION (bb) == BB_COLD_PARTITION
814e4b17023SJohn Marino       || probably_never_executed_bb_p (bb))
815e4b17023SJohn Marino     return BB_FREQ_MAX;
816e4b17023SJohn Marino 
817e4b17023SJohn Marino   /* Prefer blocks whose predecessor is an end of some trace
818e4b17023SJohn Marino      or whose predecessor edge is EDGE_DFS_BACK.  */
819e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, bb->preds)
820e4b17023SJohn Marino     {
821e4b17023SJohn Marino       if ((e->src != ENTRY_BLOCK_PTR && bbd[e->src->index].end_of_trace >= 0)
822e4b17023SJohn Marino 	  || (e->flags & EDGE_DFS_BACK))
823e4b17023SJohn Marino 	{
824e4b17023SJohn Marino 	  int edge_freq = EDGE_FREQUENCY (e);
825e4b17023SJohn Marino 
826e4b17023SJohn Marino 	  if (edge_freq > priority)
827e4b17023SJohn Marino 	    priority = edge_freq;
828e4b17023SJohn Marino 	}
829e4b17023SJohn Marino     }
830e4b17023SJohn Marino 
831e4b17023SJohn Marino   if (priority)
832e4b17023SJohn Marino     /* The block with priority should have significantly lower key.  */
833e4b17023SJohn Marino     return -(100 * BB_FREQ_MAX + 100 * priority + bb->frequency);
834e4b17023SJohn Marino   return -bb->frequency;
835e4b17023SJohn Marino }
836e4b17023SJohn Marino 
837e4b17023SJohn Marino /* Return true when the edge E from basic block BB is better than the temporary
838e4b17023SJohn Marino    best edge (details are in function).  The probability of edge E is PROB. The
839e4b17023SJohn Marino    frequency of the successor is FREQ.  The current best probability is
840e4b17023SJohn Marino    BEST_PROB, the best frequency is BEST_FREQ.
841e4b17023SJohn Marino    The edge is considered to be equivalent when PROB does not differ much from
842e4b17023SJohn Marino    BEST_PROB; similarly for frequency.  */
843e4b17023SJohn Marino 
844e4b17023SJohn Marino static bool
better_edge_p(const_basic_block bb,const_edge e,int prob,int freq,int best_prob,int best_freq,const_edge cur_best_edge)845e4b17023SJohn Marino better_edge_p (const_basic_block bb, const_edge e, int prob, int freq, int best_prob,
846e4b17023SJohn Marino 	       int best_freq, const_edge cur_best_edge)
847e4b17023SJohn Marino {
848e4b17023SJohn Marino   bool is_better_edge;
849e4b17023SJohn Marino 
850e4b17023SJohn Marino   /* The BEST_* values do not have to be best, but can be a bit smaller than
851e4b17023SJohn Marino      maximum values.  */
852e4b17023SJohn Marino   int diff_prob = best_prob / 10;
853e4b17023SJohn Marino   int diff_freq = best_freq / 10;
854e4b17023SJohn Marino 
855e4b17023SJohn Marino   if (prob > best_prob + diff_prob)
856e4b17023SJohn Marino     /* The edge has higher probability than the temporary best edge.  */
857e4b17023SJohn Marino     is_better_edge = true;
858e4b17023SJohn Marino   else if (prob < best_prob - diff_prob)
859e4b17023SJohn Marino     /* The edge has lower probability than the temporary best edge.  */
860e4b17023SJohn Marino     is_better_edge = false;
861e4b17023SJohn Marino   else if (freq < best_freq - diff_freq)
862e4b17023SJohn Marino     /* The edge and the temporary best edge  have almost equivalent
863e4b17023SJohn Marino        probabilities.  The higher frequency of a successor now means
864e4b17023SJohn Marino        that there is another edge going into that successor.
865e4b17023SJohn Marino        This successor has lower frequency so it is better.  */
866e4b17023SJohn Marino     is_better_edge = true;
867e4b17023SJohn Marino   else if (freq > best_freq + diff_freq)
868e4b17023SJohn Marino     /* This successor has higher frequency so it is worse.  */
869e4b17023SJohn Marino     is_better_edge = false;
870e4b17023SJohn Marino   else if (e->dest->prev_bb == bb)
871e4b17023SJohn Marino     /* The edges have equivalent probabilities and the successors
872e4b17023SJohn Marino        have equivalent frequencies.  Select the previous successor.  */
873e4b17023SJohn Marino     is_better_edge = true;
874e4b17023SJohn Marino   else
875e4b17023SJohn Marino     is_better_edge = false;
876e4b17023SJohn Marino 
877e4b17023SJohn Marino   /* If we are doing hot/cold partitioning, make sure that we always favor
878e4b17023SJohn Marino      non-crossing edges over crossing edges.  */
879e4b17023SJohn Marino 
880e4b17023SJohn Marino   if (!is_better_edge
881e4b17023SJohn Marino       && flag_reorder_blocks_and_partition
882e4b17023SJohn Marino       && cur_best_edge
883e4b17023SJohn Marino       && (cur_best_edge->flags & EDGE_CROSSING)
884e4b17023SJohn Marino       && !(e->flags & EDGE_CROSSING))
885e4b17023SJohn Marino     is_better_edge = true;
886e4b17023SJohn Marino 
887e4b17023SJohn Marino   return is_better_edge;
888e4b17023SJohn Marino }
889e4b17023SJohn Marino 
890e4b17023SJohn Marino /* Connect traces in array TRACES, N_TRACES is the count of traces.  */
891e4b17023SJohn Marino 
892e4b17023SJohn Marino static void
connect_traces(int n_traces,struct trace * traces)893e4b17023SJohn Marino connect_traces (int n_traces, struct trace *traces)
894e4b17023SJohn Marino {
895e4b17023SJohn Marino   int i;
896e4b17023SJohn Marino   bool *connected;
897e4b17023SJohn Marino   bool two_passes;
898e4b17023SJohn Marino   int last_trace;
899e4b17023SJohn Marino   int current_pass;
900e4b17023SJohn Marino   int current_partition;
901e4b17023SJohn Marino   int freq_threshold;
902e4b17023SJohn Marino   gcov_type count_threshold;
903e4b17023SJohn Marino 
904e4b17023SJohn Marino   freq_threshold = max_entry_frequency * DUPLICATION_THRESHOLD / 1000;
905e4b17023SJohn Marino   if (max_entry_count < INT_MAX / 1000)
906e4b17023SJohn Marino     count_threshold = max_entry_count * DUPLICATION_THRESHOLD / 1000;
907e4b17023SJohn Marino   else
908e4b17023SJohn Marino     count_threshold = max_entry_count / 1000 * DUPLICATION_THRESHOLD;
909e4b17023SJohn Marino 
910e4b17023SJohn Marino   connected = XCNEWVEC (bool, n_traces);
911e4b17023SJohn Marino   last_trace = -1;
912e4b17023SJohn Marino   current_pass = 1;
913e4b17023SJohn Marino   current_partition = BB_PARTITION (traces[0].first);
914e4b17023SJohn Marino   two_passes = false;
915e4b17023SJohn Marino 
916e4b17023SJohn Marino   if (flag_reorder_blocks_and_partition)
917e4b17023SJohn Marino     for (i = 0; i < n_traces && !two_passes; i++)
918e4b17023SJohn Marino       if (BB_PARTITION (traces[0].first)
919e4b17023SJohn Marino 	  != BB_PARTITION (traces[i].first))
920e4b17023SJohn Marino 	two_passes = true;
921e4b17023SJohn Marino 
922e4b17023SJohn Marino   for (i = 0; i < n_traces || (two_passes && current_pass == 1) ; i++)
923e4b17023SJohn Marino     {
924e4b17023SJohn Marino       int t = i;
925e4b17023SJohn Marino       int t2;
926e4b17023SJohn Marino       edge e, best;
927e4b17023SJohn Marino       int best_len;
928e4b17023SJohn Marino 
929e4b17023SJohn Marino       if (i >= n_traces)
930e4b17023SJohn Marino 	{
931e4b17023SJohn Marino 	  gcc_assert (two_passes && current_pass == 1);
932e4b17023SJohn Marino 	  i = 0;
933e4b17023SJohn Marino 	  t = i;
934e4b17023SJohn Marino 	  current_pass = 2;
935e4b17023SJohn Marino 	  if (current_partition == BB_HOT_PARTITION)
936e4b17023SJohn Marino 	    current_partition = BB_COLD_PARTITION;
937e4b17023SJohn Marino 	  else
938e4b17023SJohn Marino 	    current_partition = BB_HOT_PARTITION;
939e4b17023SJohn Marino 	}
940e4b17023SJohn Marino 
941e4b17023SJohn Marino       if (connected[t])
942e4b17023SJohn Marino 	continue;
943e4b17023SJohn Marino 
944e4b17023SJohn Marino       if (two_passes
945e4b17023SJohn Marino 	  && BB_PARTITION (traces[t].first) != current_partition)
946e4b17023SJohn Marino 	continue;
947e4b17023SJohn Marino 
948e4b17023SJohn Marino       connected[t] = true;
949e4b17023SJohn Marino 
950e4b17023SJohn Marino       /* Find the predecessor traces.  */
951e4b17023SJohn Marino       for (t2 = t; t2 > 0;)
952e4b17023SJohn Marino 	{
953e4b17023SJohn Marino 	  edge_iterator ei;
954e4b17023SJohn Marino 	  best = NULL;
955e4b17023SJohn Marino 	  best_len = 0;
956e4b17023SJohn Marino 	  FOR_EACH_EDGE (e, ei, traces[t2].first->preds)
957e4b17023SJohn Marino 	    {
958e4b17023SJohn Marino 	      int si = e->src->index;
959e4b17023SJohn Marino 
960e4b17023SJohn Marino 	      if (e->src != ENTRY_BLOCK_PTR
961e4b17023SJohn Marino 		  && (e->flags & EDGE_CAN_FALLTHRU)
962e4b17023SJohn Marino 		  && !(e->flags & EDGE_COMPLEX)
963e4b17023SJohn Marino 		  && bbd[si].end_of_trace >= 0
964e4b17023SJohn Marino 		  && !connected[bbd[si].end_of_trace]
965e4b17023SJohn Marino 		  && (BB_PARTITION (e->src) == current_partition)
966e4b17023SJohn Marino 		  && (!best
967e4b17023SJohn Marino 		      || e->probability > best->probability
968e4b17023SJohn Marino 		      || (e->probability == best->probability
969e4b17023SJohn Marino 			  && traces[bbd[si].end_of_trace].length > best_len)))
970e4b17023SJohn Marino 		{
971e4b17023SJohn Marino 		  best = e;
972e4b17023SJohn Marino 		  best_len = traces[bbd[si].end_of_trace].length;
973e4b17023SJohn Marino 		}
974e4b17023SJohn Marino 	    }
975e4b17023SJohn Marino 	  if (best)
976e4b17023SJohn Marino 	    {
977e4b17023SJohn Marino 	      best->src->aux = best->dest;
978e4b17023SJohn Marino 	      t2 = bbd[best->src->index].end_of_trace;
979e4b17023SJohn Marino 	      connected[t2] = true;
980e4b17023SJohn Marino 
981e4b17023SJohn Marino 	      if (dump_file)
982e4b17023SJohn Marino 		{
983e4b17023SJohn Marino 		  fprintf (dump_file, "Connection: %d %d\n",
984e4b17023SJohn Marino 			   best->src->index, best->dest->index);
985e4b17023SJohn Marino 		}
986e4b17023SJohn Marino 	    }
987e4b17023SJohn Marino 	  else
988e4b17023SJohn Marino 	    break;
989e4b17023SJohn Marino 	}
990e4b17023SJohn Marino 
991e4b17023SJohn Marino       if (last_trace >= 0)
992e4b17023SJohn Marino 	traces[last_trace].last->aux = traces[t2].first;
993e4b17023SJohn Marino       last_trace = t;
994e4b17023SJohn Marino 
995e4b17023SJohn Marino       /* Find the successor traces.  */
996e4b17023SJohn Marino       while (1)
997e4b17023SJohn Marino 	{
998e4b17023SJohn Marino 	  /* Find the continuation of the chain.  */
999e4b17023SJohn Marino 	  edge_iterator ei;
1000e4b17023SJohn Marino 	  best = NULL;
1001e4b17023SJohn Marino 	  best_len = 0;
1002e4b17023SJohn Marino 	  FOR_EACH_EDGE (e, ei, traces[t].last->succs)
1003e4b17023SJohn Marino 	    {
1004e4b17023SJohn Marino 	      int di = e->dest->index;
1005e4b17023SJohn Marino 
1006e4b17023SJohn Marino 	      if (e->dest != EXIT_BLOCK_PTR
1007e4b17023SJohn Marino 		  && (e->flags & EDGE_CAN_FALLTHRU)
1008e4b17023SJohn Marino 		  && !(e->flags & EDGE_COMPLEX)
1009e4b17023SJohn Marino 		  && bbd[di].start_of_trace >= 0
1010e4b17023SJohn Marino 		  && !connected[bbd[di].start_of_trace]
1011e4b17023SJohn Marino 		  && (BB_PARTITION (e->dest) == current_partition)
1012e4b17023SJohn Marino 		  && (!best
1013e4b17023SJohn Marino 		      || e->probability > best->probability
1014e4b17023SJohn Marino 		      || (e->probability == best->probability
1015e4b17023SJohn Marino 			  && traces[bbd[di].start_of_trace].length > best_len)))
1016e4b17023SJohn Marino 		{
1017e4b17023SJohn Marino 		  best = e;
1018e4b17023SJohn Marino 		  best_len = traces[bbd[di].start_of_trace].length;
1019e4b17023SJohn Marino 		}
1020e4b17023SJohn Marino 	    }
1021e4b17023SJohn Marino 
1022e4b17023SJohn Marino 	  if (best)
1023e4b17023SJohn Marino 	    {
1024e4b17023SJohn Marino 	      if (dump_file)
1025e4b17023SJohn Marino 		{
1026e4b17023SJohn Marino 		  fprintf (dump_file, "Connection: %d %d\n",
1027e4b17023SJohn Marino 			   best->src->index, best->dest->index);
1028e4b17023SJohn Marino 		}
1029e4b17023SJohn Marino 	      t = bbd[best->dest->index].start_of_trace;
1030e4b17023SJohn Marino 	      traces[last_trace].last->aux = traces[t].first;
1031e4b17023SJohn Marino 	      connected[t] = true;
1032e4b17023SJohn Marino 	      last_trace = t;
1033e4b17023SJohn Marino 	    }
1034e4b17023SJohn Marino 	  else
1035e4b17023SJohn Marino 	    {
1036e4b17023SJohn Marino 	      /* Try to connect the traces by duplication of 1 block.  */
1037e4b17023SJohn Marino 	      edge e2;
1038e4b17023SJohn Marino 	      basic_block next_bb = NULL;
1039e4b17023SJohn Marino 	      bool try_copy = false;
1040e4b17023SJohn Marino 
1041e4b17023SJohn Marino 	      FOR_EACH_EDGE (e, ei, traces[t].last->succs)
1042e4b17023SJohn Marino 		if (e->dest != EXIT_BLOCK_PTR
1043e4b17023SJohn Marino 		    && (e->flags & EDGE_CAN_FALLTHRU)
1044e4b17023SJohn Marino 		    && !(e->flags & EDGE_COMPLEX)
1045e4b17023SJohn Marino 		    && (!best || e->probability > best->probability))
1046e4b17023SJohn Marino 		  {
1047e4b17023SJohn Marino 		    edge_iterator ei;
1048e4b17023SJohn Marino 		    edge best2 = NULL;
1049e4b17023SJohn Marino 		    int best2_len = 0;
1050e4b17023SJohn Marino 
1051e4b17023SJohn Marino 		    /* If the destination is a start of a trace which is only
1052e4b17023SJohn Marino 		       one block long, then no need to search the successor
1053e4b17023SJohn Marino 		       blocks of the trace.  Accept it.  */
1054e4b17023SJohn Marino 		    if (bbd[e->dest->index].start_of_trace >= 0
1055e4b17023SJohn Marino 			&& traces[bbd[e->dest->index].start_of_trace].length
1056e4b17023SJohn Marino 			   == 1)
1057e4b17023SJohn Marino 		      {
1058e4b17023SJohn Marino 			best = e;
1059e4b17023SJohn Marino 			try_copy = true;
1060e4b17023SJohn Marino 			continue;
1061e4b17023SJohn Marino 		      }
1062e4b17023SJohn Marino 
1063e4b17023SJohn Marino 		    FOR_EACH_EDGE (e2, ei, e->dest->succs)
1064e4b17023SJohn Marino 		      {
1065e4b17023SJohn Marino 			int di = e2->dest->index;
1066e4b17023SJohn Marino 
1067e4b17023SJohn Marino 			if (e2->dest == EXIT_BLOCK_PTR
1068e4b17023SJohn Marino 			    || ((e2->flags & EDGE_CAN_FALLTHRU)
1069e4b17023SJohn Marino 				&& !(e2->flags & EDGE_COMPLEX)
1070e4b17023SJohn Marino 				&& bbd[di].start_of_trace >= 0
1071e4b17023SJohn Marino 				&& !connected[bbd[di].start_of_trace]
1072e4b17023SJohn Marino 				&& (BB_PARTITION (e2->dest) == current_partition)
1073e4b17023SJohn Marino 				&& (EDGE_FREQUENCY (e2) >= freq_threshold)
1074e4b17023SJohn Marino 				&& (e2->count >= count_threshold)
1075e4b17023SJohn Marino 				&& (!best2
1076e4b17023SJohn Marino 				    || e2->probability > best2->probability
1077e4b17023SJohn Marino 				    || (e2->probability == best2->probability
1078e4b17023SJohn Marino 					&& traces[bbd[di].start_of_trace].length
1079e4b17023SJohn Marino 					   > best2_len))))
1080e4b17023SJohn Marino 			  {
1081e4b17023SJohn Marino 			    best = e;
1082e4b17023SJohn Marino 			    best2 = e2;
1083e4b17023SJohn Marino 			    if (e2->dest != EXIT_BLOCK_PTR)
1084e4b17023SJohn Marino 			      best2_len = traces[bbd[di].start_of_trace].length;
1085e4b17023SJohn Marino 			    else
1086e4b17023SJohn Marino 			      best2_len = INT_MAX;
1087e4b17023SJohn Marino 			    next_bb = e2->dest;
1088e4b17023SJohn Marino 			    try_copy = true;
1089e4b17023SJohn Marino 			  }
1090e4b17023SJohn Marino 		      }
1091e4b17023SJohn Marino 		  }
1092e4b17023SJohn Marino 
1093e4b17023SJohn Marino 	      if (flag_reorder_blocks_and_partition)
1094e4b17023SJohn Marino 		try_copy = false;
1095e4b17023SJohn Marino 
1096e4b17023SJohn Marino 	      /* Copy tiny blocks always; copy larger blocks only when the
1097e4b17023SJohn Marino 		 edge is traversed frequently enough.  */
1098e4b17023SJohn Marino 	      if (try_copy
1099e4b17023SJohn Marino 		  && copy_bb_p (best->dest,
1100e4b17023SJohn Marino 				optimize_edge_for_speed_p (best)
1101e4b17023SJohn Marino 				&& EDGE_FREQUENCY (best) >= freq_threshold
1102e4b17023SJohn Marino 				&& best->count >= count_threshold))
1103e4b17023SJohn Marino 		{
1104e4b17023SJohn Marino 		  basic_block new_bb;
1105e4b17023SJohn Marino 
1106e4b17023SJohn Marino 		  if (dump_file)
1107e4b17023SJohn Marino 		    {
1108e4b17023SJohn Marino 		      fprintf (dump_file, "Connection: %d %d ",
1109e4b17023SJohn Marino 			       traces[t].last->index, best->dest->index);
1110e4b17023SJohn Marino 		      if (!next_bb)
1111e4b17023SJohn Marino 			fputc ('\n', dump_file);
1112e4b17023SJohn Marino 		      else if (next_bb == EXIT_BLOCK_PTR)
1113e4b17023SJohn Marino 			fprintf (dump_file, "exit\n");
1114e4b17023SJohn Marino 		      else
1115e4b17023SJohn Marino 			fprintf (dump_file, "%d\n", next_bb->index);
1116e4b17023SJohn Marino 		    }
1117e4b17023SJohn Marino 
1118e4b17023SJohn Marino 		  new_bb = copy_bb (best->dest, best, traces[t].last, t);
1119e4b17023SJohn Marino 		  traces[t].last = new_bb;
1120e4b17023SJohn Marino 		  if (next_bb && next_bb != EXIT_BLOCK_PTR)
1121e4b17023SJohn Marino 		    {
1122e4b17023SJohn Marino 		      t = bbd[next_bb->index].start_of_trace;
1123e4b17023SJohn Marino 		      traces[last_trace].last->aux = traces[t].first;
1124e4b17023SJohn Marino 		      connected[t] = true;
1125e4b17023SJohn Marino 		      last_trace = t;
1126e4b17023SJohn Marino 		    }
1127e4b17023SJohn Marino 		  else
1128e4b17023SJohn Marino 		    break;	/* Stop finding the successor traces.  */
1129e4b17023SJohn Marino 		}
1130e4b17023SJohn Marino 	      else
1131e4b17023SJohn Marino 		break;	/* Stop finding the successor traces.  */
1132e4b17023SJohn Marino 	    }
1133e4b17023SJohn Marino 	}
1134e4b17023SJohn Marino     }
1135e4b17023SJohn Marino 
1136e4b17023SJohn Marino   if (dump_file)
1137e4b17023SJohn Marino     {
1138e4b17023SJohn Marino       basic_block bb;
1139e4b17023SJohn Marino 
1140e4b17023SJohn Marino       fprintf (dump_file, "Final order:\n");
1141e4b17023SJohn Marino       for (bb = traces[0].first; bb; bb = (basic_block) bb->aux)
1142e4b17023SJohn Marino 	fprintf (dump_file, "%d ", bb->index);
1143e4b17023SJohn Marino       fprintf (dump_file, "\n");
1144e4b17023SJohn Marino       fflush (dump_file);
1145e4b17023SJohn Marino     }
1146e4b17023SJohn Marino 
1147e4b17023SJohn Marino   FREE (connected);
1148e4b17023SJohn Marino }
1149e4b17023SJohn Marino 
1150e4b17023SJohn Marino /* Return true when BB can and should be copied. CODE_MAY_GROW is true
1151e4b17023SJohn Marino    when code size is allowed to grow by duplication.  */
1152e4b17023SJohn Marino 
1153e4b17023SJohn Marino static bool
copy_bb_p(const_basic_block bb,int code_may_grow)1154e4b17023SJohn Marino copy_bb_p (const_basic_block bb, int code_may_grow)
1155e4b17023SJohn Marino {
1156e4b17023SJohn Marino   int size = 0;
1157e4b17023SJohn Marino   int max_size = uncond_jump_length;
1158e4b17023SJohn Marino   rtx insn;
1159e4b17023SJohn Marino 
1160e4b17023SJohn Marino   if (!bb->frequency)
1161e4b17023SJohn Marino     return false;
1162e4b17023SJohn Marino   if (EDGE_COUNT (bb->preds) < 2)
1163e4b17023SJohn Marino     return false;
1164e4b17023SJohn Marino   if (!can_duplicate_block_p (bb))
1165e4b17023SJohn Marino     return false;
1166e4b17023SJohn Marino 
1167e4b17023SJohn Marino   /* Avoid duplicating blocks which have many successors (PR/13430).  */
1168e4b17023SJohn Marino   if (EDGE_COUNT (bb->succs) > 8)
1169e4b17023SJohn Marino     return false;
1170e4b17023SJohn Marino 
1171e4b17023SJohn Marino   if (code_may_grow && optimize_bb_for_speed_p (bb))
1172e4b17023SJohn Marino     max_size *= PARAM_VALUE (PARAM_MAX_GROW_COPY_BB_INSNS);
1173e4b17023SJohn Marino 
1174e4b17023SJohn Marino   FOR_BB_INSNS (bb, insn)
1175e4b17023SJohn Marino     {
1176e4b17023SJohn Marino       if (INSN_P (insn))
1177e4b17023SJohn Marino 	size += get_attr_min_length (insn);
1178e4b17023SJohn Marino     }
1179e4b17023SJohn Marino 
1180e4b17023SJohn Marino   if (size <= max_size)
1181e4b17023SJohn Marino     return true;
1182e4b17023SJohn Marino 
1183e4b17023SJohn Marino   if (dump_file)
1184e4b17023SJohn Marino     {
1185e4b17023SJohn Marino       fprintf (dump_file,
1186e4b17023SJohn Marino 	       "Block %d can't be copied because its size = %d.\n",
1187e4b17023SJohn Marino 	       bb->index, size);
1188e4b17023SJohn Marino     }
1189e4b17023SJohn Marino 
1190e4b17023SJohn Marino   return false;
1191e4b17023SJohn Marino }
1192e4b17023SJohn Marino 
1193e4b17023SJohn Marino /* Return the length of unconditional jump instruction.  */
1194e4b17023SJohn Marino 
1195e4b17023SJohn Marino int
get_uncond_jump_length(void)1196e4b17023SJohn Marino get_uncond_jump_length (void)
1197e4b17023SJohn Marino {
1198e4b17023SJohn Marino   rtx label, jump;
1199e4b17023SJohn Marino   int length;
1200e4b17023SJohn Marino 
1201e4b17023SJohn Marino   label = emit_label_before (gen_label_rtx (), get_insns ());
1202e4b17023SJohn Marino   jump = emit_jump_insn (gen_jump (label));
1203e4b17023SJohn Marino 
1204e4b17023SJohn Marino   length = get_attr_min_length (jump);
1205e4b17023SJohn Marino 
1206e4b17023SJohn Marino   delete_insn (jump);
1207e4b17023SJohn Marino   delete_insn (label);
1208e4b17023SJohn Marino   return length;
1209e4b17023SJohn Marino }
1210e4b17023SJohn Marino 
1211e4b17023SJohn Marino /* Emit a barrier into the footer of BB.  */
1212e4b17023SJohn Marino 
1213e4b17023SJohn Marino static void
emit_barrier_after_bb(basic_block bb)1214e4b17023SJohn Marino emit_barrier_after_bb (basic_block bb)
1215e4b17023SJohn Marino {
1216e4b17023SJohn Marino   rtx barrier = emit_barrier_after (BB_END (bb));
1217e4b17023SJohn Marino   bb->il.rtl->footer = unlink_insn_chain (barrier, barrier);
1218e4b17023SJohn Marino }
1219e4b17023SJohn Marino 
1220e4b17023SJohn Marino /* The landing pad OLD_LP, in block OLD_BB, has edges from both partitions.
1221e4b17023SJohn Marino    Duplicate the landing pad and split the edges so that no EH edge
1222e4b17023SJohn Marino    crosses partitions.  */
1223e4b17023SJohn Marino 
1224e4b17023SJohn Marino static void
fix_up_crossing_landing_pad(eh_landing_pad old_lp,basic_block old_bb)1225e4b17023SJohn Marino fix_up_crossing_landing_pad (eh_landing_pad old_lp, basic_block old_bb)
1226e4b17023SJohn Marino {
1227e4b17023SJohn Marino   eh_landing_pad new_lp;
1228e4b17023SJohn Marino   basic_block new_bb, last_bb, post_bb;
1229e4b17023SJohn Marino   rtx new_label, jump, post_label;
1230e4b17023SJohn Marino   unsigned new_partition;
1231e4b17023SJohn Marino   edge_iterator ei;
1232e4b17023SJohn Marino   edge e;
1233e4b17023SJohn Marino 
1234e4b17023SJohn Marino   /* Generate the new landing-pad structure.  */
1235e4b17023SJohn Marino   new_lp = gen_eh_landing_pad (old_lp->region);
1236e4b17023SJohn Marino   new_lp->post_landing_pad = old_lp->post_landing_pad;
1237e4b17023SJohn Marino   new_lp->landing_pad = gen_label_rtx ();
1238e4b17023SJohn Marino   LABEL_PRESERVE_P (new_lp->landing_pad) = 1;
1239e4b17023SJohn Marino 
1240e4b17023SJohn Marino   /* Put appropriate instructions in new bb.  */
1241e4b17023SJohn Marino   new_label = emit_label (new_lp->landing_pad);
1242e4b17023SJohn Marino 
1243e4b17023SJohn Marino   expand_dw2_landing_pad_for_region (old_lp->region);
1244e4b17023SJohn Marino 
1245e4b17023SJohn Marino   post_bb = BLOCK_FOR_INSN (old_lp->landing_pad);
1246e4b17023SJohn Marino   post_bb = single_succ (post_bb);
1247e4b17023SJohn Marino   post_label = block_label (post_bb);
1248e4b17023SJohn Marino   jump = emit_jump_insn (gen_jump (post_label));
1249e4b17023SJohn Marino   JUMP_LABEL (jump) = post_label;
1250e4b17023SJohn Marino 
1251e4b17023SJohn Marino   /* Create new basic block to be dest for lp.  */
1252e4b17023SJohn Marino   last_bb = EXIT_BLOCK_PTR->prev_bb;
1253e4b17023SJohn Marino   new_bb = create_basic_block (new_label, jump, last_bb);
1254e4b17023SJohn Marino   new_bb->aux = last_bb->aux;
1255e4b17023SJohn Marino   last_bb->aux = new_bb;
1256e4b17023SJohn Marino 
1257e4b17023SJohn Marino   emit_barrier_after_bb (new_bb);
1258e4b17023SJohn Marino 
1259e4b17023SJohn Marino   make_edge (new_bb, post_bb, 0);
1260e4b17023SJohn Marino 
1261e4b17023SJohn Marino   /* Make sure new bb is in the other partition.  */
1262e4b17023SJohn Marino   new_partition = BB_PARTITION (old_bb);
1263e4b17023SJohn Marino   new_partition ^= BB_HOT_PARTITION | BB_COLD_PARTITION;
1264e4b17023SJohn Marino   BB_SET_PARTITION (new_bb, new_partition);
1265e4b17023SJohn Marino 
1266e4b17023SJohn Marino   /* Fix up the edges.  */
1267e4b17023SJohn Marino   for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)) != NULL; )
1268e4b17023SJohn Marino     if (BB_PARTITION (e->src) == new_partition)
1269e4b17023SJohn Marino       {
1270e4b17023SJohn Marino 	rtx insn = BB_END (e->src);
1271e4b17023SJohn Marino 	rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1272e4b17023SJohn Marino 
1273e4b17023SJohn Marino 	gcc_assert (note != NULL);
1274e4b17023SJohn Marino 	gcc_checking_assert (INTVAL (XEXP (note, 0)) == old_lp->index);
1275e4b17023SJohn Marino 	XEXP (note, 0) = GEN_INT (new_lp->index);
1276e4b17023SJohn Marino 
1277e4b17023SJohn Marino 	/* Adjust the edge to the new destination.  */
1278e4b17023SJohn Marino 	redirect_edge_succ (e, new_bb);
1279e4b17023SJohn Marino       }
1280e4b17023SJohn Marino     else
1281e4b17023SJohn Marino       ei_next (&ei);
1282e4b17023SJohn Marino }
1283e4b17023SJohn Marino 
1284e4b17023SJohn Marino /* Find the basic blocks that are rarely executed and need to be moved to
1285e4b17023SJohn Marino    a separate section of the .o file (to cut down on paging and improve
1286e4b17023SJohn Marino    cache locality).  Return a vector of all edges that cross.  */
1287e4b17023SJohn Marino 
VEC(edge,heap)1288e4b17023SJohn Marino static VEC(edge, heap) *
1289e4b17023SJohn Marino find_rarely_executed_basic_blocks_and_crossing_edges (void)
1290e4b17023SJohn Marino {
1291e4b17023SJohn Marino   VEC(edge, heap) *crossing_edges = NULL;
1292e4b17023SJohn Marino   basic_block bb;
1293e4b17023SJohn Marino   edge e;
1294e4b17023SJohn Marino   edge_iterator ei;
1295e4b17023SJohn Marino 
1296e4b17023SJohn Marino   /* Mark which partition (hot/cold) each basic block belongs in.  */
1297e4b17023SJohn Marino   FOR_EACH_BB (bb)
1298e4b17023SJohn Marino     {
1299e4b17023SJohn Marino       if (probably_never_executed_bb_p (bb))
1300e4b17023SJohn Marino 	BB_SET_PARTITION (bb, BB_COLD_PARTITION);
1301e4b17023SJohn Marino       else
1302e4b17023SJohn Marino 	BB_SET_PARTITION (bb, BB_HOT_PARTITION);
1303e4b17023SJohn Marino     }
1304e4b17023SJohn Marino 
1305e4b17023SJohn Marino   /* The format of .gcc_except_table does not allow landing pads to
1306e4b17023SJohn Marino      be in a different partition as the throw.  Fix this by either
1307e4b17023SJohn Marino      moving or duplicating the landing pads.  */
1308e4b17023SJohn Marino   if (cfun->eh->lp_array)
1309e4b17023SJohn Marino     {
1310e4b17023SJohn Marino       unsigned i;
1311e4b17023SJohn Marino       eh_landing_pad lp;
1312e4b17023SJohn Marino 
1313e4b17023SJohn Marino       FOR_EACH_VEC_ELT (eh_landing_pad, cfun->eh->lp_array, i, lp)
1314e4b17023SJohn Marino 	{
1315e4b17023SJohn Marino 	  bool all_same, all_diff;
1316e4b17023SJohn Marino 
1317e4b17023SJohn Marino 	  if (lp == NULL
1318e4b17023SJohn Marino 	      || lp->landing_pad == NULL_RTX
1319e4b17023SJohn Marino 	      || !LABEL_P (lp->landing_pad))
1320e4b17023SJohn Marino 	    continue;
1321e4b17023SJohn Marino 
1322e4b17023SJohn Marino 	  all_same = all_diff = true;
1323e4b17023SJohn Marino 	  bb = BLOCK_FOR_INSN (lp->landing_pad);
1324e4b17023SJohn Marino 	  FOR_EACH_EDGE (e, ei, bb->preds)
1325e4b17023SJohn Marino 	    {
1326e4b17023SJohn Marino 	      gcc_assert (e->flags & EDGE_EH);
1327e4b17023SJohn Marino 	      if (BB_PARTITION (bb) == BB_PARTITION (e->src))
1328e4b17023SJohn Marino 		all_diff = false;
1329e4b17023SJohn Marino 	      else
1330e4b17023SJohn Marino 		all_same = false;
1331e4b17023SJohn Marino 	    }
1332e4b17023SJohn Marino 
1333e4b17023SJohn Marino 	  if (all_same)
1334e4b17023SJohn Marino 	    ;
1335e4b17023SJohn Marino 	  else if (all_diff)
1336e4b17023SJohn Marino 	    {
1337e4b17023SJohn Marino 	      int which = BB_PARTITION (bb);
1338e4b17023SJohn Marino 	      which ^= BB_HOT_PARTITION | BB_COLD_PARTITION;
1339e4b17023SJohn Marino 	      BB_SET_PARTITION (bb, which);
1340e4b17023SJohn Marino 	    }
1341e4b17023SJohn Marino 	  else
1342e4b17023SJohn Marino 	    fix_up_crossing_landing_pad (lp, bb);
1343e4b17023SJohn Marino 	}
1344e4b17023SJohn Marino     }
1345e4b17023SJohn Marino 
1346e4b17023SJohn Marino   /* Mark every edge that crosses between sections.  */
1347e4b17023SJohn Marino 
1348e4b17023SJohn Marino   FOR_EACH_BB (bb)
1349e4b17023SJohn Marino     FOR_EACH_EDGE (e, ei, bb->succs)
1350e4b17023SJohn Marino       {
1351e4b17023SJohn Marino 	unsigned int flags = e->flags;
1352e4b17023SJohn Marino 
1353e4b17023SJohn Marino         /* We should never have EDGE_CROSSING set yet.  */
1354e4b17023SJohn Marino 	gcc_checking_assert ((flags & EDGE_CROSSING) == 0);
1355e4b17023SJohn Marino 
1356e4b17023SJohn Marino 	if (e->src != ENTRY_BLOCK_PTR
1357e4b17023SJohn Marino 	    && e->dest != EXIT_BLOCK_PTR
1358e4b17023SJohn Marino 	    && BB_PARTITION (e->src) != BB_PARTITION (e->dest))
1359e4b17023SJohn Marino 	  {
1360e4b17023SJohn Marino 	    VEC_safe_push (edge, heap, crossing_edges, e);
1361e4b17023SJohn Marino 	    flags |= EDGE_CROSSING;
1362e4b17023SJohn Marino 	  }
1363e4b17023SJohn Marino 
1364e4b17023SJohn Marino 	/* Now that we've split eh edges as appropriate, allow landing pads
1365e4b17023SJohn Marino 	   to be merged with the post-landing pads.  */
1366e4b17023SJohn Marino 	flags &= ~EDGE_PRESERVE;
1367e4b17023SJohn Marino 
1368e4b17023SJohn Marino 	e->flags = flags;
1369e4b17023SJohn Marino       }
1370e4b17023SJohn Marino 
1371e4b17023SJohn Marino   return crossing_edges;
1372e4b17023SJohn Marino }
1373e4b17023SJohn Marino 
1374e4b17023SJohn Marino /* If any destination of a crossing edge does not have a label, add label;
1375e4b17023SJohn Marino    Convert any easy fall-through crossing edges to unconditional jumps.  */
1376e4b17023SJohn Marino 
1377e4b17023SJohn Marino static void
add_labels_and_missing_jumps(VEC (edge,heap)* crossing_edges)1378e4b17023SJohn Marino add_labels_and_missing_jumps (VEC(edge, heap) *crossing_edges)
1379e4b17023SJohn Marino {
1380e4b17023SJohn Marino   size_t i;
1381e4b17023SJohn Marino   edge e;
1382e4b17023SJohn Marino 
1383e4b17023SJohn Marino   FOR_EACH_VEC_ELT (edge, crossing_edges, i, e)
1384e4b17023SJohn Marino     {
1385e4b17023SJohn Marino       basic_block src = e->src;
1386e4b17023SJohn Marino       basic_block dest = e->dest;
1387e4b17023SJohn Marino       rtx label, new_jump;
1388e4b17023SJohn Marino 
1389e4b17023SJohn Marino       if (dest == EXIT_BLOCK_PTR)
1390e4b17023SJohn Marino 	continue;
1391e4b17023SJohn Marino 
1392e4b17023SJohn Marino       /* Make sure dest has a label.  */
1393e4b17023SJohn Marino       label = block_label (dest);
1394e4b17023SJohn Marino 
1395e4b17023SJohn Marino       /* Nothing to do for non-fallthru edges.  */
1396e4b17023SJohn Marino       if (src == ENTRY_BLOCK_PTR)
1397e4b17023SJohn Marino 	continue;
1398e4b17023SJohn Marino       if ((e->flags & EDGE_FALLTHRU) == 0)
1399e4b17023SJohn Marino 	continue;
1400e4b17023SJohn Marino 
1401e4b17023SJohn Marino       /* If the block does not end with a control flow insn, then we
1402e4b17023SJohn Marino 	 can trivially add a jump to the end to fixup the crossing.
1403e4b17023SJohn Marino 	 Otherwise the jump will have to go in a new bb, which will
1404e4b17023SJohn Marino 	 be handled by fix_up_fall_thru_edges function.  */
1405e4b17023SJohn Marino       if (control_flow_insn_p (BB_END (src)))
1406e4b17023SJohn Marino 	continue;
1407e4b17023SJohn Marino 
1408e4b17023SJohn Marino       /* Make sure there's only one successor.  */
1409e4b17023SJohn Marino       gcc_assert (single_succ_p (src));
1410e4b17023SJohn Marino 
1411e4b17023SJohn Marino       new_jump = emit_jump_insn_after (gen_jump (label), BB_END (src));
1412e4b17023SJohn Marino       BB_END (src) = new_jump;
1413e4b17023SJohn Marino       JUMP_LABEL (new_jump) = label;
1414e4b17023SJohn Marino       LABEL_NUSES (label) += 1;
1415e4b17023SJohn Marino 
1416e4b17023SJohn Marino       emit_barrier_after_bb (src);
1417e4b17023SJohn Marino 
1418e4b17023SJohn Marino       /* Mark edge as non-fallthru.  */
1419e4b17023SJohn Marino       e->flags &= ~EDGE_FALLTHRU;
1420e4b17023SJohn Marino     }
1421e4b17023SJohn Marino }
1422e4b17023SJohn Marino 
1423e4b17023SJohn Marino /* Find any bb's where the fall-through edge is a crossing edge (note that
1424e4b17023SJohn Marino    these bb's must also contain a conditional jump or end with a call
1425e4b17023SJohn Marino    instruction; we've already dealt with fall-through edges for blocks
1426e4b17023SJohn Marino    that didn't have a conditional jump or didn't end with call instruction
1427e4b17023SJohn Marino    in the call to add_labels_and_missing_jumps).  Convert the fall-through
1428e4b17023SJohn Marino    edge to non-crossing edge by inserting a new bb to fall-through into.
1429e4b17023SJohn Marino    The new bb will contain an unconditional jump (crossing edge) to the
1430e4b17023SJohn Marino    original fall through destination.  */
1431e4b17023SJohn Marino 
1432e4b17023SJohn Marino static void
fix_up_fall_thru_edges(void)1433e4b17023SJohn Marino fix_up_fall_thru_edges (void)
1434e4b17023SJohn Marino {
1435e4b17023SJohn Marino   basic_block cur_bb;
1436e4b17023SJohn Marino   basic_block new_bb;
1437e4b17023SJohn Marino   edge succ1;
1438e4b17023SJohn Marino   edge succ2;
1439e4b17023SJohn Marino   edge fall_thru;
1440e4b17023SJohn Marino   edge cond_jump = NULL;
1441e4b17023SJohn Marino   edge e;
1442e4b17023SJohn Marino   bool cond_jump_crosses;
1443e4b17023SJohn Marino   int invert_worked;
1444e4b17023SJohn Marino   rtx old_jump;
1445e4b17023SJohn Marino   rtx fall_thru_label;
1446e4b17023SJohn Marino 
1447e4b17023SJohn Marino   FOR_EACH_BB (cur_bb)
1448e4b17023SJohn Marino     {
1449e4b17023SJohn Marino       fall_thru = NULL;
1450e4b17023SJohn Marino       if (EDGE_COUNT (cur_bb->succs) > 0)
1451e4b17023SJohn Marino 	succ1 = EDGE_SUCC (cur_bb, 0);
1452e4b17023SJohn Marino       else
1453e4b17023SJohn Marino 	succ1 = NULL;
1454e4b17023SJohn Marino 
1455e4b17023SJohn Marino       if (EDGE_COUNT (cur_bb->succs) > 1)
1456e4b17023SJohn Marino 	succ2 = EDGE_SUCC (cur_bb, 1);
1457e4b17023SJohn Marino       else
1458e4b17023SJohn Marino 	succ2 = NULL;
1459e4b17023SJohn Marino 
1460e4b17023SJohn Marino       /* Find the fall-through edge.  */
1461e4b17023SJohn Marino 
1462e4b17023SJohn Marino       if (succ1
1463e4b17023SJohn Marino 	  && (succ1->flags & EDGE_FALLTHRU))
1464e4b17023SJohn Marino 	{
1465e4b17023SJohn Marino 	  fall_thru = succ1;
1466e4b17023SJohn Marino 	  cond_jump = succ2;
1467e4b17023SJohn Marino 	}
1468e4b17023SJohn Marino       else if (succ2
1469e4b17023SJohn Marino 	       && (succ2->flags & EDGE_FALLTHRU))
1470e4b17023SJohn Marino 	{
1471e4b17023SJohn Marino 	  fall_thru = succ2;
1472e4b17023SJohn Marino 	  cond_jump = succ1;
1473e4b17023SJohn Marino 	}
1474e4b17023SJohn Marino       else if (succ1
1475e4b17023SJohn Marino 	       && (block_ends_with_call_p (cur_bb)
1476e4b17023SJohn Marino 		   || can_throw_internal (BB_END (cur_bb))))
1477e4b17023SJohn Marino 	{
1478e4b17023SJohn Marino 	  edge e;
1479e4b17023SJohn Marino 	  edge_iterator ei;
1480e4b17023SJohn Marino 
1481e4b17023SJohn Marino 	  FOR_EACH_EDGE (e, ei, cur_bb->succs)
1482*95d28233SJohn Marino 	    if (e->flags & EDGE_FALLTHRU)
1483e4b17023SJohn Marino 	      {
1484e4b17023SJohn Marino 		fall_thru = e;
1485e4b17023SJohn Marino 		break;
1486e4b17023SJohn Marino 	      }
1487e4b17023SJohn Marino 	}
1488e4b17023SJohn Marino 
1489e4b17023SJohn Marino       if (fall_thru && (fall_thru->dest != EXIT_BLOCK_PTR))
1490e4b17023SJohn Marino 	{
1491e4b17023SJohn Marino 	  /* Check to see if the fall-thru edge is a crossing edge.  */
1492e4b17023SJohn Marino 
1493e4b17023SJohn Marino 	  if (fall_thru->flags & EDGE_CROSSING)
1494e4b17023SJohn Marino 	    {
1495e4b17023SJohn Marino 	      /* The fall_thru edge crosses; now check the cond jump edge, if
1496e4b17023SJohn Marino 		 it exists.  */
1497e4b17023SJohn Marino 
1498e4b17023SJohn Marino 	      cond_jump_crosses = true;
1499e4b17023SJohn Marino 	      invert_worked  = 0;
1500e4b17023SJohn Marino 	      old_jump = BB_END (cur_bb);
1501e4b17023SJohn Marino 
1502e4b17023SJohn Marino 	      /* Find the jump instruction, if there is one.  */
1503e4b17023SJohn Marino 
1504e4b17023SJohn Marino 	      if (cond_jump)
1505e4b17023SJohn Marino 		{
1506e4b17023SJohn Marino 		  if (!(cond_jump->flags & EDGE_CROSSING))
1507e4b17023SJohn Marino 		    cond_jump_crosses = false;
1508e4b17023SJohn Marino 
1509e4b17023SJohn Marino 		  /* We know the fall-thru edge crosses; if the cond
1510e4b17023SJohn Marino 		     jump edge does NOT cross, and its destination is the
1511e4b17023SJohn Marino 		     next block in the bb order, invert the jump
1512e4b17023SJohn Marino 		     (i.e. fix it so the fall thru does not cross and
1513e4b17023SJohn Marino 		     the cond jump does).  */
1514e4b17023SJohn Marino 
1515e4b17023SJohn Marino 		  if (!cond_jump_crosses
1516e4b17023SJohn Marino 		      && cur_bb->aux == cond_jump->dest)
1517e4b17023SJohn Marino 		    {
1518e4b17023SJohn Marino 		      /* Find label in fall_thru block. We've already added
1519e4b17023SJohn Marino 			 any missing labels, so there must be one.  */
1520e4b17023SJohn Marino 
1521e4b17023SJohn Marino 		      fall_thru_label = block_label (fall_thru->dest);
1522e4b17023SJohn Marino 
1523e4b17023SJohn Marino 		      if (old_jump && JUMP_P (old_jump) && fall_thru_label)
1524e4b17023SJohn Marino 			invert_worked = invert_jump (old_jump,
1525e4b17023SJohn Marino 						     fall_thru_label,0);
1526e4b17023SJohn Marino 		      if (invert_worked)
1527e4b17023SJohn Marino 			{
1528e4b17023SJohn Marino 			  fall_thru->flags &= ~EDGE_FALLTHRU;
1529e4b17023SJohn Marino 			  cond_jump->flags |= EDGE_FALLTHRU;
1530e4b17023SJohn Marino 			  update_br_prob_note (cur_bb);
1531e4b17023SJohn Marino 			  e = fall_thru;
1532e4b17023SJohn Marino 			  fall_thru = cond_jump;
1533e4b17023SJohn Marino 			  cond_jump = e;
1534e4b17023SJohn Marino 			  cond_jump->flags |= EDGE_CROSSING;
1535e4b17023SJohn Marino 			  fall_thru->flags &= ~EDGE_CROSSING;
1536e4b17023SJohn Marino 			}
1537e4b17023SJohn Marino 		    }
1538e4b17023SJohn Marino 		}
1539e4b17023SJohn Marino 
1540e4b17023SJohn Marino 	      if (cond_jump_crosses || !invert_worked)
1541e4b17023SJohn Marino 		{
1542e4b17023SJohn Marino 		  /* This is the case where both edges out of the basic
1543e4b17023SJohn Marino 		     block are crossing edges. Here we will fix up the
1544e4b17023SJohn Marino 		     fall through edge. The jump edge will be taken care
1545e4b17023SJohn Marino 		     of later.  The EDGE_CROSSING flag of fall_thru edge
1546e4b17023SJohn Marino                      is unset before the call to force_nonfallthru
1547e4b17023SJohn Marino                      function because if a new basic-block is created
1548e4b17023SJohn Marino                      this edge remains in the current section boundary
1549e4b17023SJohn Marino                      while the edge between new_bb and the fall_thru->dest
1550e4b17023SJohn Marino                      becomes EDGE_CROSSING.  */
1551e4b17023SJohn Marino 
1552e4b17023SJohn Marino                   fall_thru->flags &= ~EDGE_CROSSING;
1553e4b17023SJohn Marino 		  new_bb = force_nonfallthru (fall_thru);
1554e4b17023SJohn Marino 
1555e4b17023SJohn Marino 		  if (new_bb)
1556e4b17023SJohn Marino 		    {
1557e4b17023SJohn Marino 		      new_bb->aux = cur_bb->aux;
1558e4b17023SJohn Marino 		      cur_bb->aux = new_bb;
1559e4b17023SJohn Marino 
1560e4b17023SJohn Marino 		      /* Make sure new fall-through bb is in same
1561e4b17023SJohn Marino 			 partition as bb it's falling through from.  */
1562e4b17023SJohn Marino 
1563e4b17023SJohn Marino 		      BB_COPY_PARTITION (new_bb, cur_bb);
1564e4b17023SJohn Marino 		      single_succ_edge (new_bb)->flags |= EDGE_CROSSING;
1565e4b17023SJohn Marino 		    }
1566e4b17023SJohn Marino                   else
1567e4b17023SJohn Marino                     {
1568e4b17023SJohn Marino                       /* If a new basic-block was not created; restore
1569e4b17023SJohn Marino                          the EDGE_CROSSING flag.  */
1570e4b17023SJohn Marino                       fall_thru->flags |= EDGE_CROSSING;
1571e4b17023SJohn Marino                     }
1572e4b17023SJohn Marino 
1573e4b17023SJohn Marino 		  /* Add barrier after new jump */
1574e4b17023SJohn Marino 		  emit_barrier_after_bb (new_bb ? new_bb : cur_bb);
1575e4b17023SJohn Marino 		}
1576e4b17023SJohn Marino 	    }
1577e4b17023SJohn Marino 	}
1578e4b17023SJohn Marino     }
1579e4b17023SJohn Marino }
1580e4b17023SJohn Marino 
1581e4b17023SJohn Marino /* This function checks the destination block of a "crossing jump" to
1582e4b17023SJohn Marino    see if it has any crossing predecessors that begin with a code label
1583e4b17023SJohn Marino    and end with an unconditional jump.  If so, it returns that predecessor
1584e4b17023SJohn Marino    block.  (This is to avoid creating lots of new basic blocks that all
1585e4b17023SJohn Marino    contain unconditional jumps to the same destination).  */
1586e4b17023SJohn Marino 
1587e4b17023SJohn Marino static basic_block
find_jump_block(basic_block jump_dest)1588e4b17023SJohn Marino find_jump_block (basic_block jump_dest)
1589e4b17023SJohn Marino {
1590e4b17023SJohn Marino   basic_block source_bb = NULL;
1591e4b17023SJohn Marino   edge e;
1592e4b17023SJohn Marino   rtx insn;
1593e4b17023SJohn Marino   edge_iterator ei;
1594e4b17023SJohn Marino 
1595e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, jump_dest->preds)
1596e4b17023SJohn Marino     if (e->flags & EDGE_CROSSING)
1597e4b17023SJohn Marino       {
1598e4b17023SJohn Marino 	basic_block src = e->src;
1599e4b17023SJohn Marino 
1600e4b17023SJohn Marino 	/* Check each predecessor to see if it has a label, and contains
1601e4b17023SJohn Marino 	   only one executable instruction, which is an unconditional jump.
1602e4b17023SJohn Marino 	   If so, we can use it.  */
1603e4b17023SJohn Marino 
1604e4b17023SJohn Marino 	if (LABEL_P (BB_HEAD (src)))
1605e4b17023SJohn Marino 	  for (insn = BB_HEAD (src);
1606e4b17023SJohn Marino 	       !INSN_P (insn) && insn != NEXT_INSN (BB_END (src));
1607e4b17023SJohn Marino 	       insn = NEXT_INSN (insn))
1608e4b17023SJohn Marino 	    {
1609e4b17023SJohn Marino 	      if (INSN_P (insn)
1610e4b17023SJohn Marino 		  && insn == BB_END (src)
1611e4b17023SJohn Marino 		  && JUMP_P (insn)
1612e4b17023SJohn Marino 		  && !any_condjump_p (insn))
1613e4b17023SJohn Marino 		{
1614e4b17023SJohn Marino 		  source_bb = src;
1615e4b17023SJohn Marino 		  break;
1616e4b17023SJohn Marino 		}
1617e4b17023SJohn Marino 	    }
1618e4b17023SJohn Marino 
1619e4b17023SJohn Marino 	if (source_bb)
1620e4b17023SJohn Marino 	  break;
1621e4b17023SJohn Marino       }
1622e4b17023SJohn Marino 
1623e4b17023SJohn Marino   return source_bb;
1624e4b17023SJohn Marino }
1625e4b17023SJohn Marino 
1626e4b17023SJohn Marino /* Find all BB's with conditional jumps that are crossing edges;
1627e4b17023SJohn Marino    insert a new bb and make the conditional jump branch to the new
1628e4b17023SJohn Marino    bb instead (make the new bb same color so conditional branch won't
1629e4b17023SJohn Marino    be a 'crossing' edge).  Insert an unconditional jump from the
1630e4b17023SJohn Marino    new bb to the original destination of the conditional jump.  */
1631e4b17023SJohn Marino 
1632e4b17023SJohn Marino static void
fix_crossing_conditional_branches(void)1633e4b17023SJohn Marino fix_crossing_conditional_branches (void)
1634e4b17023SJohn Marino {
1635e4b17023SJohn Marino   basic_block cur_bb;
1636e4b17023SJohn Marino   basic_block new_bb;
1637e4b17023SJohn Marino   basic_block dest;
1638e4b17023SJohn Marino   edge succ1;
1639e4b17023SJohn Marino   edge succ2;
1640e4b17023SJohn Marino   edge crossing_edge;
1641e4b17023SJohn Marino   edge new_edge;
1642e4b17023SJohn Marino   rtx old_jump;
1643e4b17023SJohn Marino   rtx set_src;
1644e4b17023SJohn Marino   rtx old_label = NULL_RTX;
1645e4b17023SJohn Marino   rtx new_label;
1646e4b17023SJohn Marino 
1647e4b17023SJohn Marino   FOR_EACH_BB (cur_bb)
1648e4b17023SJohn Marino     {
1649e4b17023SJohn Marino       crossing_edge = NULL;
1650e4b17023SJohn Marino       if (EDGE_COUNT (cur_bb->succs) > 0)
1651e4b17023SJohn Marino 	succ1 = EDGE_SUCC (cur_bb, 0);
1652e4b17023SJohn Marino       else
1653e4b17023SJohn Marino 	succ1 = NULL;
1654e4b17023SJohn Marino 
1655e4b17023SJohn Marino       if (EDGE_COUNT (cur_bb->succs) > 1)
1656e4b17023SJohn Marino 	succ2 = EDGE_SUCC (cur_bb, 1);
1657e4b17023SJohn Marino       else
1658e4b17023SJohn Marino 	succ2 = NULL;
1659e4b17023SJohn Marino 
1660e4b17023SJohn Marino       /* We already took care of fall-through edges, so only one successor
1661e4b17023SJohn Marino 	 can be a crossing edge.  */
1662e4b17023SJohn Marino 
1663e4b17023SJohn Marino       if (succ1 && (succ1->flags & EDGE_CROSSING))
1664e4b17023SJohn Marino 	crossing_edge = succ1;
1665e4b17023SJohn Marino       else if (succ2 && (succ2->flags & EDGE_CROSSING))
1666e4b17023SJohn Marino 	crossing_edge = succ2;
1667e4b17023SJohn Marino 
1668e4b17023SJohn Marino       if (crossing_edge)
1669e4b17023SJohn Marino 	{
1670e4b17023SJohn Marino 	  old_jump = BB_END (cur_bb);
1671e4b17023SJohn Marino 
1672e4b17023SJohn Marino 	  /* Check to make sure the jump instruction is a
1673e4b17023SJohn Marino 	     conditional jump.  */
1674e4b17023SJohn Marino 
1675e4b17023SJohn Marino 	  set_src = NULL_RTX;
1676e4b17023SJohn Marino 
1677e4b17023SJohn Marino 	  if (any_condjump_p (old_jump))
1678e4b17023SJohn Marino 	    {
1679e4b17023SJohn Marino 	      if (GET_CODE (PATTERN (old_jump)) == SET)
1680e4b17023SJohn Marino 		set_src = SET_SRC (PATTERN (old_jump));
1681e4b17023SJohn Marino 	      else if (GET_CODE (PATTERN (old_jump)) == PARALLEL)
1682e4b17023SJohn Marino 		{
1683e4b17023SJohn Marino 		  set_src = XVECEXP (PATTERN (old_jump), 0,0);
1684e4b17023SJohn Marino 		  if (GET_CODE (set_src) == SET)
1685e4b17023SJohn Marino 		    set_src = SET_SRC (set_src);
1686e4b17023SJohn Marino 		  else
1687e4b17023SJohn Marino 		    set_src = NULL_RTX;
1688e4b17023SJohn Marino 		}
1689e4b17023SJohn Marino 	    }
1690e4b17023SJohn Marino 
1691e4b17023SJohn Marino 	  if (set_src && (GET_CODE (set_src) == IF_THEN_ELSE))
1692e4b17023SJohn Marino 	    {
1693e4b17023SJohn Marino 	      if (GET_CODE (XEXP (set_src, 1)) == PC)
1694e4b17023SJohn Marino 		old_label = XEXP (set_src, 2);
1695e4b17023SJohn Marino 	      else if (GET_CODE (XEXP (set_src, 2)) == PC)
1696e4b17023SJohn Marino 		old_label = XEXP (set_src, 1);
1697e4b17023SJohn Marino 
1698e4b17023SJohn Marino 	      /* Check to see if new bb for jumping to that dest has
1699e4b17023SJohn Marino 		 already been created; if so, use it; if not, create
1700e4b17023SJohn Marino 		 a new one.  */
1701e4b17023SJohn Marino 
1702e4b17023SJohn Marino 	      new_bb = find_jump_block (crossing_edge->dest);
1703e4b17023SJohn Marino 
1704e4b17023SJohn Marino 	      if (new_bb)
1705e4b17023SJohn Marino 		new_label = block_label (new_bb);
1706e4b17023SJohn Marino 	      else
1707e4b17023SJohn Marino 		{
1708e4b17023SJohn Marino 		  basic_block last_bb;
1709e4b17023SJohn Marino 		  rtx new_jump;
1710e4b17023SJohn Marino 
1711e4b17023SJohn Marino 		  /* Create new basic block to be dest for
1712e4b17023SJohn Marino 		     conditional jump.  */
1713e4b17023SJohn Marino 
1714e4b17023SJohn Marino 		  /* Put appropriate instructions in new bb.  */
1715e4b17023SJohn Marino 
1716e4b17023SJohn Marino 		  new_label = gen_label_rtx ();
1717e4b17023SJohn Marino 		  emit_label (new_label);
1718e4b17023SJohn Marino 
1719e4b17023SJohn Marino 		  gcc_assert (GET_CODE (old_label) == LABEL_REF);
1720e4b17023SJohn Marino 		  old_label = JUMP_LABEL (old_jump);
1721e4b17023SJohn Marino 		  new_jump = emit_jump_insn (gen_jump (old_label));
1722e4b17023SJohn Marino 		  JUMP_LABEL (new_jump) = old_label;
1723e4b17023SJohn Marino 
1724e4b17023SJohn Marino 		  last_bb = EXIT_BLOCK_PTR->prev_bb;
1725e4b17023SJohn Marino 		  new_bb = create_basic_block (new_label, new_jump, last_bb);
1726e4b17023SJohn Marino 		  new_bb->aux = last_bb->aux;
1727e4b17023SJohn Marino 		  last_bb->aux = new_bb;
1728e4b17023SJohn Marino 
1729e4b17023SJohn Marino 		  emit_barrier_after_bb (new_bb);
1730e4b17023SJohn Marino 
1731e4b17023SJohn Marino 		  /* Make sure new bb is in same partition as source
1732e4b17023SJohn Marino 		     of conditional branch.  */
1733e4b17023SJohn Marino 		  BB_COPY_PARTITION (new_bb, cur_bb);
1734e4b17023SJohn Marino 		}
1735e4b17023SJohn Marino 
1736e4b17023SJohn Marino 	      /* Make old jump branch to new bb.  */
1737e4b17023SJohn Marino 
1738e4b17023SJohn Marino 	      redirect_jump (old_jump, new_label, 0);
1739e4b17023SJohn Marino 
1740e4b17023SJohn Marino 	      /* Remove crossing_edge as predecessor of 'dest'.  */
1741e4b17023SJohn Marino 
1742e4b17023SJohn Marino 	      dest = crossing_edge->dest;
1743e4b17023SJohn Marino 
1744e4b17023SJohn Marino 	      redirect_edge_succ (crossing_edge, new_bb);
1745e4b17023SJohn Marino 
1746e4b17023SJohn Marino 	      /* Make a new edge from new_bb to old dest; new edge
1747e4b17023SJohn Marino 		 will be a successor for new_bb and a predecessor
1748e4b17023SJohn Marino 		 for 'dest'.  */
1749e4b17023SJohn Marino 
1750e4b17023SJohn Marino 	      if (EDGE_COUNT (new_bb->succs) == 0)
1751e4b17023SJohn Marino 		new_edge = make_edge (new_bb, dest, 0);
1752e4b17023SJohn Marino 	      else
1753e4b17023SJohn Marino 		new_edge = EDGE_SUCC (new_bb, 0);
1754e4b17023SJohn Marino 
1755e4b17023SJohn Marino 	      crossing_edge->flags &= ~EDGE_CROSSING;
1756e4b17023SJohn Marino 	      new_edge->flags |= EDGE_CROSSING;
1757e4b17023SJohn Marino 	    }
1758e4b17023SJohn Marino 	}
1759e4b17023SJohn Marino     }
1760e4b17023SJohn Marino }
1761e4b17023SJohn Marino 
1762e4b17023SJohn Marino /* Find any unconditional branches that cross between hot and cold
1763e4b17023SJohn Marino    sections.  Convert them into indirect jumps instead.  */
1764e4b17023SJohn Marino 
1765e4b17023SJohn Marino static void
fix_crossing_unconditional_branches(void)1766e4b17023SJohn Marino fix_crossing_unconditional_branches (void)
1767e4b17023SJohn Marino {
1768e4b17023SJohn Marino   basic_block cur_bb;
1769e4b17023SJohn Marino   rtx last_insn;
1770e4b17023SJohn Marino   rtx label;
1771e4b17023SJohn Marino   rtx label_addr;
1772e4b17023SJohn Marino   rtx indirect_jump_sequence;
1773e4b17023SJohn Marino   rtx jump_insn = NULL_RTX;
1774e4b17023SJohn Marino   rtx new_reg;
1775e4b17023SJohn Marino   rtx cur_insn;
1776e4b17023SJohn Marino   edge succ;
1777e4b17023SJohn Marino 
1778e4b17023SJohn Marino   FOR_EACH_BB (cur_bb)
1779e4b17023SJohn Marino     {
1780e4b17023SJohn Marino       last_insn = BB_END (cur_bb);
1781e4b17023SJohn Marino 
1782e4b17023SJohn Marino       if (EDGE_COUNT (cur_bb->succs) < 1)
1783e4b17023SJohn Marino 	continue;
1784e4b17023SJohn Marino 
1785e4b17023SJohn Marino       succ = EDGE_SUCC (cur_bb, 0);
1786e4b17023SJohn Marino 
1787e4b17023SJohn Marino       /* Check to see if bb ends in a crossing (unconditional) jump.  At
1788e4b17023SJohn Marino 	 this point, no crossing jumps should be conditional.  */
1789e4b17023SJohn Marino 
1790e4b17023SJohn Marino       if (JUMP_P (last_insn)
1791e4b17023SJohn Marino 	  && (succ->flags & EDGE_CROSSING))
1792e4b17023SJohn Marino 	{
1793e4b17023SJohn Marino 	  rtx label2, table;
1794e4b17023SJohn Marino 
1795e4b17023SJohn Marino 	  gcc_assert (!any_condjump_p (last_insn));
1796e4b17023SJohn Marino 
1797e4b17023SJohn Marino 	  /* Make sure the jump is not already an indirect or table jump.  */
1798e4b17023SJohn Marino 
1799e4b17023SJohn Marino 	  if (!computed_jump_p (last_insn)
1800e4b17023SJohn Marino 	      && !tablejump_p (last_insn, &label2, &table))
1801e4b17023SJohn Marino 	    {
1802e4b17023SJohn Marino 	      /* We have found a "crossing" unconditional branch.  Now
1803e4b17023SJohn Marino 		 we must convert it to an indirect jump.  First create
1804e4b17023SJohn Marino 		 reference of label, as target for jump.  */
1805e4b17023SJohn Marino 
1806e4b17023SJohn Marino 	      label = JUMP_LABEL (last_insn);
1807e4b17023SJohn Marino 	      label_addr = gen_rtx_LABEL_REF (Pmode, label);
1808e4b17023SJohn Marino 	      LABEL_NUSES (label) += 1;
1809e4b17023SJohn Marino 
1810e4b17023SJohn Marino 	      /* Get a register to use for the indirect jump.  */
1811e4b17023SJohn Marino 
1812e4b17023SJohn Marino 	      new_reg = gen_reg_rtx (Pmode);
1813e4b17023SJohn Marino 
1814e4b17023SJohn Marino 	      /* Generate indirect the jump sequence.  */
1815e4b17023SJohn Marino 
1816e4b17023SJohn Marino 	      start_sequence ();
1817e4b17023SJohn Marino 	      emit_move_insn (new_reg, label_addr);
1818e4b17023SJohn Marino 	      emit_indirect_jump (new_reg);
1819e4b17023SJohn Marino 	      indirect_jump_sequence = get_insns ();
1820e4b17023SJohn Marino 	      end_sequence ();
1821e4b17023SJohn Marino 
1822e4b17023SJohn Marino 	      /* Make sure every instruction in the new jump sequence has
1823e4b17023SJohn Marino 		 its basic block set to be cur_bb.  */
1824e4b17023SJohn Marino 
1825e4b17023SJohn Marino 	      for (cur_insn = indirect_jump_sequence; cur_insn;
1826e4b17023SJohn Marino 		   cur_insn = NEXT_INSN (cur_insn))
1827e4b17023SJohn Marino 		{
1828e4b17023SJohn Marino 		  if (!BARRIER_P (cur_insn))
1829e4b17023SJohn Marino 		    BLOCK_FOR_INSN (cur_insn) = cur_bb;
1830e4b17023SJohn Marino 		  if (JUMP_P (cur_insn))
1831e4b17023SJohn Marino 		    jump_insn = cur_insn;
1832e4b17023SJohn Marino 		}
1833e4b17023SJohn Marino 
1834e4b17023SJohn Marino 	      /* Insert the new (indirect) jump sequence immediately before
1835e4b17023SJohn Marino 		 the unconditional jump, then delete the unconditional jump.  */
1836e4b17023SJohn Marino 
1837e4b17023SJohn Marino 	      emit_insn_before (indirect_jump_sequence, last_insn);
1838e4b17023SJohn Marino 	      delete_insn (last_insn);
1839e4b17023SJohn Marino 
1840e4b17023SJohn Marino 	      /* Make BB_END for cur_bb be the jump instruction (NOT the
1841e4b17023SJohn Marino 		 barrier instruction at the end of the sequence...).  */
1842e4b17023SJohn Marino 
1843e4b17023SJohn Marino 	      BB_END (cur_bb) = jump_insn;
1844e4b17023SJohn Marino 	    }
1845e4b17023SJohn Marino 	}
1846e4b17023SJohn Marino     }
1847e4b17023SJohn Marino }
1848e4b17023SJohn Marino 
1849e4b17023SJohn Marino /* Add REG_CROSSING_JUMP note to all crossing jump insns.  */
1850e4b17023SJohn Marino 
1851e4b17023SJohn Marino static void
add_reg_crossing_jump_notes(void)1852e4b17023SJohn Marino add_reg_crossing_jump_notes (void)
1853e4b17023SJohn Marino {
1854e4b17023SJohn Marino   basic_block bb;
1855e4b17023SJohn Marino   edge e;
1856e4b17023SJohn Marino   edge_iterator ei;
1857e4b17023SJohn Marino 
1858e4b17023SJohn Marino   FOR_EACH_BB (bb)
1859e4b17023SJohn Marino     FOR_EACH_EDGE (e, ei, bb->succs)
1860e4b17023SJohn Marino       if ((e->flags & EDGE_CROSSING)
1861e4b17023SJohn Marino 	  && JUMP_P (BB_END (e->src)))
1862e4b17023SJohn Marino 	add_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX);
1863e4b17023SJohn Marino }
1864e4b17023SJohn Marino 
1865e4b17023SJohn Marino /* Verify, in the basic block chain, that there is at most one switch
1866e4b17023SJohn Marino    between hot/cold partitions. This is modelled on
1867e4b17023SJohn Marino    rtl_verify_flow_info_1, but it cannot go inside that function
1868e4b17023SJohn Marino    because this condition will not be true until after
1869e4b17023SJohn Marino    reorder_basic_blocks is called.  */
1870e4b17023SJohn Marino 
1871e4b17023SJohn Marino static void
verify_hot_cold_block_grouping(void)1872e4b17023SJohn Marino verify_hot_cold_block_grouping (void)
1873e4b17023SJohn Marino {
1874e4b17023SJohn Marino   basic_block bb;
1875e4b17023SJohn Marino   int err = 0;
1876e4b17023SJohn Marino   bool switched_sections = false;
1877e4b17023SJohn Marino   int current_partition = 0;
1878e4b17023SJohn Marino 
1879e4b17023SJohn Marino   FOR_EACH_BB (bb)
1880e4b17023SJohn Marino     {
1881e4b17023SJohn Marino       if (!current_partition)
1882e4b17023SJohn Marino 	current_partition = BB_PARTITION (bb);
1883e4b17023SJohn Marino       if (BB_PARTITION (bb) != current_partition)
1884e4b17023SJohn Marino 	{
1885e4b17023SJohn Marino 	  if (switched_sections)
1886e4b17023SJohn Marino 	    {
1887e4b17023SJohn Marino 	      error ("multiple hot/cold transitions found (bb %i)",
1888e4b17023SJohn Marino 		     bb->index);
1889e4b17023SJohn Marino 	      err = 1;
1890e4b17023SJohn Marino 	    }
1891e4b17023SJohn Marino 	  else
1892e4b17023SJohn Marino 	    {
1893e4b17023SJohn Marino 	      switched_sections = true;
1894e4b17023SJohn Marino 	      current_partition = BB_PARTITION (bb);
1895e4b17023SJohn Marino 	    }
1896e4b17023SJohn Marino 	}
1897e4b17023SJohn Marino     }
1898e4b17023SJohn Marino 
1899e4b17023SJohn Marino   gcc_assert(!err);
1900e4b17023SJohn Marino }
1901e4b17023SJohn Marino 
1902e4b17023SJohn Marino /* Reorder basic blocks.  The main entry point to this file.  FLAGS is
1903e4b17023SJohn Marino    the set of flags to pass to cfg_layout_initialize().  */
1904e4b17023SJohn Marino 
1905e4b17023SJohn Marino void
reorder_basic_blocks(void)1906e4b17023SJohn Marino reorder_basic_blocks (void)
1907e4b17023SJohn Marino {
1908e4b17023SJohn Marino   int n_traces;
1909e4b17023SJohn Marino   int i;
1910e4b17023SJohn Marino   struct trace *traces;
1911e4b17023SJohn Marino 
1912e4b17023SJohn Marino   gcc_assert (current_ir_type () == IR_RTL_CFGLAYOUT);
1913e4b17023SJohn Marino 
1914e4b17023SJohn Marino   if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
1915e4b17023SJohn Marino     return;
1916e4b17023SJohn Marino 
1917e4b17023SJohn Marino   set_edge_can_fallthru_flag ();
1918e4b17023SJohn Marino   mark_dfs_back_edges ();
1919e4b17023SJohn Marino 
1920e4b17023SJohn Marino   /* We are estimating the length of uncond jump insn only once since the code
1921e4b17023SJohn Marino      for getting the insn length always returns the minimal length now.  */
1922e4b17023SJohn Marino   if (uncond_jump_length == 0)
1923e4b17023SJohn Marino     uncond_jump_length = get_uncond_jump_length ();
1924e4b17023SJohn Marino 
1925e4b17023SJohn Marino   /* We need to know some information for each basic block.  */
1926e4b17023SJohn Marino   array_size = GET_ARRAY_SIZE (last_basic_block);
1927e4b17023SJohn Marino   bbd = XNEWVEC (bbro_basic_block_data, array_size);
1928e4b17023SJohn Marino   for (i = 0; i < array_size; i++)
1929e4b17023SJohn Marino     {
1930e4b17023SJohn Marino       bbd[i].start_of_trace = -1;
1931e4b17023SJohn Marino       bbd[i].in_trace = -1;
1932e4b17023SJohn Marino       bbd[i].end_of_trace = -1;
1933e4b17023SJohn Marino       bbd[i].heap = NULL;
1934e4b17023SJohn Marino       bbd[i].node = NULL;
1935e4b17023SJohn Marino     }
1936e4b17023SJohn Marino 
1937e4b17023SJohn Marino   traces = XNEWVEC (struct trace, n_basic_blocks);
1938e4b17023SJohn Marino   n_traces = 0;
1939e4b17023SJohn Marino   find_traces (&n_traces, traces);
1940e4b17023SJohn Marino   connect_traces (n_traces, traces);
1941e4b17023SJohn Marino   FREE (traces);
1942e4b17023SJohn Marino   FREE (bbd);
1943e4b17023SJohn Marino 
1944e4b17023SJohn Marino   relink_block_chain (/*stay_in_cfglayout_mode=*/true);
1945e4b17023SJohn Marino 
1946e4b17023SJohn Marino   if (dump_file)
1947e4b17023SJohn Marino     dump_flow_info (dump_file, dump_flags);
1948e4b17023SJohn Marino 
1949e4b17023SJohn Marino   if (flag_reorder_blocks_and_partition)
1950e4b17023SJohn Marino     verify_hot_cold_block_grouping ();
1951e4b17023SJohn Marino }
1952e4b17023SJohn Marino 
1953e4b17023SJohn Marino /* Determine which partition the first basic block in the function
1954e4b17023SJohn Marino    belongs to, then find the first basic block in the current function
1955e4b17023SJohn Marino    that belongs to a different section, and insert a
1956e4b17023SJohn Marino    NOTE_INSN_SWITCH_TEXT_SECTIONS note immediately before it in the
1957e4b17023SJohn Marino    instruction stream.  When writing out the assembly code,
1958e4b17023SJohn Marino    encountering this note will make the compiler switch between the
1959e4b17023SJohn Marino    hot and cold text sections.  */
1960e4b17023SJohn Marino 
1961e4b17023SJohn Marino static void
insert_section_boundary_note(void)1962e4b17023SJohn Marino insert_section_boundary_note (void)
1963e4b17023SJohn Marino {
1964e4b17023SJohn Marino   basic_block bb;
1965e4b17023SJohn Marino   rtx new_note;
1966e4b17023SJohn Marino   int first_partition = 0;
1967e4b17023SJohn Marino 
1968e4b17023SJohn Marino   if (!flag_reorder_blocks_and_partition)
1969e4b17023SJohn Marino     return;
1970e4b17023SJohn Marino 
1971e4b17023SJohn Marino   FOR_EACH_BB (bb)
1972e4b17023SJohn Marino     {
1973e4b17023SJohn Marino       if (!first_partition)
1974e4b17023SJohn Marino 	first_partition = BB_PARTITION (bb);
1975e4b17023SJohn Marino       if (BB_PARTITION (bb) != first_partition)
1976e4b17023SJohn Marino 	{
1977e4b17023SJohn Marino 	  new_note = emit_note_before (NOTE_INSN_SWITCH_TEXT_SECTIONS,
1978e4b17023SJohn Marino 				       BB_HEAD (bb));
1979e4b17023SJohn Marino 	  /* ??? This kind of note always lives between basic blocks,
1980e4b17023SJohn Marino 	     but add_insn_before will set BLOCK_FOR_INSN anyway.  */
1981e4b17023SJohn Marino 	  BLOCK_FOR_INSN (new_note) = NULL;
1982e4b17023SJohn Marino 	  break;
1983e4b17023SJohn Marino 	}
1984e4b17023SJohn Marino     }
1985e4b17023SJohn Marino }
1986e4b17023SJohn Marino 
1987e4b17023SJohn Marino /* Duplicate the blocks containing computed gotos.  This basically unfactors
1988e4b17023SJohn Marino    computed gotos that were factored early on in the compilation process to
1989e4b17023SJohn Marino    speed up edge based data flow.  We used to not unfactoring them again,
1990e4b17023SJohn Marino    which can seriously pessimize code with many computed jumps in the source
1991e4b17023SJohn Marino    code, such as interpreters.  See e.g. PR15242.  */
1992e4b17023SJohn Marino 
1993e4b17023SJohn Marino static bool
gate_duplicate_computed_gotos(void)1994e4b17023SJohn Marino gate_duplicate_computed_gotos (void)
1995e4b17023SJohn Marino {
1996e4b17023SJohn Marino   if (targetm.cannot_modify_jumps_p ())
1997e4b17023SJohn Marino     return false;
1998e4b17023SJohn Marino   return (optimize > 0
1999e4b17023SJohn Marino 	  && flag_expensive_optimizations
2000e4b17023SJohn Marino 	  && ! optimize_function_for_size_p (cfun));
2001e4b17023SJohn Marino }
2002e4b17023SJohn Marino 
2003e4b17023SJohn Marino 
2004e4b17023SJohn Marino static unsigned int
duplicate_computed_gotos(void)2005e4b17023SJohn Marino duplicate_computed_gotos (void)
2006e4b17023SJohn Marino {
2007e4b17023SJohn Marino   basic_block bb, new_bb;
2008e4b17023SJohn Marino   bitmap candidates;
2009e4b17023SJohn Marino   int max_size;
2010e4b17023SJohn Marino 
2011e4b17023SJohn Marino   if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
2012e4b17023SJohn Marino     return 0;
2013e4b17023SJohn Marino 
2014e4b17023SJohn Marino   cfg_layout_initialize (0);
2015e4b17023SJohn Marino 
2016e4b17023SJohn Marino   /* We are estimating the length of uncond jump insn only once
2017e4b17023SJohn Marino      since the code for getting the insn length always returns
2018e4b17023SJohn Marino      the minimal length now.  */
2019e4b17023SJohn Marino   if (uncond_jump_length == 0)
2020e4b17023SJohn Marino     uncond_jump_length = get_uncond_jump_length ();
2021e4b17023SJohn Marino 
2022e4b17023SJohn Marino   max_size = uncond_jump_length * PARAM_VALUE (PARAM_MAX_GOTO_DUPLICATION_INSNS);
2023e4b17023SJohn Marino   candidates = BITMAP_ALLOC (NULL);
2024e4b17023SJohn Marino 
2025e4b17023SJohn Marino   /* Look for blocks that end in a computed jump, and see if such blocks
2026e4b17023SJohn Marino      are suitable for unfactoring.  If a block is a candidate for unfactoring,
2027e4b17023SJohn Marino      mark it in the candidates.  */
2028e4b17023SJohn Marino   FOR_EACH_BB (bb)
2029e4b17023SJohn Marino     {
2030e4b17023SJohn Marino       rtx insn;
2031e4b17023SJohn Marino       edge e;
2032e4b17023SJohn Marino       edge_iterator ei;
2033e4b17023SJohn Marino       int size, all_flags;
2034e4b17023SJohn Marino 
2035e4b17023SJohn Marino       /* Build the reorder chain for the original order of blocks.  */
2036e4b17023SJohn Marino       if (bb->next_bb != EXIT_BLOCK_PTR)
2037e4b17023SJohn Marino 	bb->aux = bb->next_bb;
2038e4b17023SJohn Marino 
2039e4b17023SJohn Marino       /* Obviously the block has to end in a computed jump.  */
2040e4b17023SJohn Marino       if (!computed_jump_p (BB_END (bb)))
2041e4b17023SJohn Marino 	continue;
2042e4b17023SJohn Marino 
2043e4b17023SJohn Marino       /* Only consider blocks that can be duplicated.  */
2044e4b17023SJohn Marino       if (find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX)
2045e4b17023SJohn Marino 	  || !can_duplicate_block_p (bb))
2046e4b17023SJohn Marino 	continue;
2047e4b17023SJohn Marino 
2048e4b17023SJohn Marino       /* Make sure that the block is small enough.  */
2049e4b17023SJohn Marino       size = 0;
2050e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
2051e4b17023SJohn Marino 	if (INSN_P (insn))
2052e4b17023SJohn Marino 	  {
2053e4b17023SJohn Marino 	    size += get_attr_min_length (insn);
2054e4b17023SJohn Marino 	    if (size > max_size)
2055e4b17023SJohn Marino 	       break;
2056e4b17023SJohn Marino 	  }
2057e4b17023SJohn Marino       if (size > max_size)
2058e4b17023SJohn Marino 	continue;
2059e4b17023SJohn Marino 
2060e4b17023SJohn Marino       /* Final check: there must not be any incoming abnormal edges.  */
2061e4b17023SJohn Marino       all_flags = 0;
2062e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->preds)
2063e4b17023SJohn Marino 	all_flags |= e->flags;
2064e4b17023SJohn Marino       if (all_flags & EDGE_COMPLEX)
2065e4b17023SJohn Marino 	continue;
2066e4b17023SJohn Marino 
2067e4b17023SJohn Marino       bitmap_set_bit (candidates, bb->index);
2068e4b17023SJohn Marino     }
2069e4b17023SJohn Marino 
2070e4b17023SJohn Marino   /* Nothing to do if there is no computed jump here.  */
2071e4b17023SJohn Marino   if (bitmap_empty_p (candidates))
2072e4b17023SJohn Marino     goto done;
2073e4b17023SJohn Marino 
2074e4b17023SJohn Marino   /* Duplicate computed gotos.  */
2075e4b17023SJohn Marino   FOR_EACH_BB (bb)
2076e4b17023SJohn Marino     {
2077e4b17023SJohn Marino       if (bb->il.rtl->visited)
2078e4b17023SJohn Marino 	continue;
2079e4b17023SJohn Marino 
2080e4b17023SJohn Marino       bb->il.rtl->visited = 1;
2081e4b17023SJohn Marino 
2082e4b17023SJohn Marino       /* BB must have one outgoing edge.  That edge must not lead to
2083e4b17023SJohn Marino 	 the exit block or the next block.
2084e4b17023SJohn Marino 	 The destination must have more than one predecessor.  */
2085e4b17023SJohn Marino       if (!single_succ_p (bb)
2086e4b17023SJohn Marino 	  || single_succ (bb) == EXIT_BLOCK_PTR
2087e4b17023SJohn Marino 	  || single_succ (bb) == bb->next_bb
2088e4b17023SJohn Marino 	  || single_pred_p (single_succ (bb)))
2089e4b17023SJohn Marino 	continue;
2090e4b17023SJohn Marino 
2091e4b17023SJohn Marino       /* The successor block has to be a duplication candidate.  */
2092e4b17023SJohn Marino       if (!bitmap_bit_p (candidates, single_succ (bb)->index))
2093e4b17023SJohn Marino 	continue;
2094e4b17023SJohn Marino 
2095e4b17023SJohn Marino       new_bb = duplicate_block (single_succ (bb), single_succ_edge (bb), bb);
2096e4b17023SJohn Marino       new_bb->aux = bb->aux;
2097e4b17023SJohn Marino       bb->aux = new_bb;
2098e4b17023SJohn Marino       new_bb->il.rtl->visited = 1;
2099e4b17023SJohn Marino     }
2100e4b17023SJohn Marino 
2101e4b17023SJohn Marino done:
2102e4b17023SJohn Marino   cfg_layout_finalize ();
2103e4b17023SJohn Marino 
2104e4b17023SJohn Marino   BITMAP_FREE (candidates);
2105e4b17023SJohn Marino   return 0;
2106e4b17023SJohn Marino }
2107e4b17023SJohn Marino 
2108e4b17023SJohn Marino struct rtl_opt_pass pass_duplicate_computed_gotos =
2109e4b17023SJohn Marino {
2110e4b17023SJohn Marino  {
2111e4b17023SJohn Marino   RTL_PASS,
2112e4b17023SJohn Marino   "compgotos",                          /* name */
2113e4b17023SJohn Marino   gate_duplicate_computed_gotos,        /* gate */
2114e4b17023SJohn Marino   duplicate_computed_gotos,             /* execute */
2115e4b17023SJohn Marino   NULL,                                 /* sub */
2116e4b17023SJohn Marino   NULL,                                 /* next */
2117e4b17023SJohn Marino   0,                                    /* static_pass_number */
2118e4b17023SJohn Marino   TV_REORDER_BLOCKS,                    /* tv_id */
2119e4b17023SJohn Marino   0,                                    /* properties_required */
2120e4b17023SJohn Marino   0,                                    /* properties_provided */
2121e4b17023SJohn Marino   0,                                    /* properties_destroyed */
2122e4b17023SJohn Marino   0,                                    /* todo_flags_start */
2123e4b17023SJohn Marino   TODO_verify_rtl_sharing,/* todo_flags_finish */
2124e4b17023SJohn Marino  }
2125e4b17023SJohn Marino };
2126e4b17023SJohn Marino 
2127e4b17023SJohn Marino 
2128e4b17023SJohn Marino /* This function is the main 'entrance' for the optimization that
2129e4b17023SJohn Marino    partitions hot and cold basic blocks into separate sections of the
2130e4b17023SJohn Marino    .o file (to improve performance and cache locality).  Ideally it
2131e4b17023SJohn Marino    would be called after all optimizations that rearrange the CFG have
2132e4b17023SJohn Marino    been called.  However part of this optimization may introduce new
2133e4b17023SJohn Marino    register usage, so it must be called before register allocation has
2134e4b17023SJohn Marino    occurred.  This means that this optimization is actually called
2135e4b17023SJohn Marino    well before the optimization that reorders basic blocks (see
2136e4b17023SJohn Marino    function above).
2137e4b17023SJohn Marino 
2138e4b17023SJohn Marino    This optimization checks the feedback information to determine
2139e4b17023SJohn Marino    which basic blocks are hot/cold, updates flags on the basic blocks
2140e4b17023SJohn Marino    to indicate which section they belong in.  This information is
2141e4b17023SJohn Marino    later used for writing out sections in the .o file.  Because hot
2142e4b17023SJohn Marino    and cold sections can be arbitrarily large (within the bounds of
2143e4b17023SJohn Marino    memory), far beyond the size of a single function, it is necessary
2144e4b17023SJohn Marino    to fix up all edges that cross section boundaries, to make sure the
2145e4b17023SJohn Marino    instructions used can actually span the required distance.  The
2146e4b17023SJohn Marino    fixes are described below.
2147e4b17023SJohn Marino 
2148e4b17023SJohn Marino    Fall-through edges must be changed into jumps; it is not safe or
2149e4b17023SJohn Marino    legal to fall through across a section boundary.  Whenever a
2150e4b17023SJohn Marino    fall-through edge crossing a section boundary is encountered, a new
2151e4b17023SJohn Marino    basic block is inserted (in the same section as the fall-through
2152e4b17023SJohn Marino    source), and the fall through edge is redirected to the new basic
2153e4b17023SJohn Marino    block.  The new basic block contains an unconditional jump to the
2154e4b17023SJohn Marino    original fall-through target.  (If the unconditional jump is
2155e4b17023SJohn Marino    insufficient to cross section boundaries, that is dealt with a
2156e4b17023SJohn Marino    little later, see below).
2157e4b17023SJohn Marino 
2158e4b17023SJohn Marino    In order to deal with architectures that have short conditional
2159e4b17023SJohn Marino    branches (which cannot span all of memory) we take any conditional
2160e4b17023SJohn Marino    jump that attempts to cross a section boundary and add a level of
2161e4b17023SJohn Marino    indirection: it becomes a conditional jump to a new basic block, in
2162e4b17023SJohn Marino    the same section.  The new basic block contains an unconditional
2163e4b17023SJohn Marino    jump to the original target, in the other section.
2164e4b17023SJohn Marino 
2165e4b17023SJohn Marino    For those architectures whose unconditional branch is also
2166e4b17023SJohn Marino    incapable of reaching all of memory, those unconditional jumps are
2167e4b17023SJohn Marino    converted into indirect jumps, through a register.
2168e4b17023SJohn Marino 
2169e4b17023SJohn Marino    IMPORTANT NOTE: This optimization causes some messy interactions
2170e4b17023SJohn Marino    with the cfg cleanup optimizations; those optimizations want to
2171e4b17023SJohn Marino    merge blocks wherever possible, and to collapse indirect jump
2172e4b17023SJohn Marino    sequences (change "A jumps to B jumps to C" directly into "A jumps
2173e4b17023SJohn Marino    to C").  Those optimizations can undo the jump fixes that
2174e4b17023SJohn Marino    partitioning is required to make (see above), in order to ensure
2175e4b17023SJohn Marino    that jumps attempting to cross section boundaries are really able
2176e4b17023SJohn Marino    to cover whatever distance the jump requires (on many architectures
2177e4b17023SJohn Marino    conditional or unconditional jumps are not able to reach all of
2178e4b17023SJohn Marino    memory).  Therefore tests have to be inserted into each such
2179e4b17023SJohn Marino    optimization to make sure that it does not undo stuff necessary to
2180e4b17023SJohn Marino    cross partition boundaries.  This would be much less of a problem
2181e4b17023SJohn Marino    if we could perform this optimization later in the compilation, but
2182e4b17023SJohn Marino    unfortunately the fact that we may need to create indirect jumps
2183e4b17023SJohn Marino    (through registers) requires that this optimization be performed
2184e4b17023SJohn Marino    before register allocation.
2185e4b17023SJohn Marino 
2186e4b17023SJohn Marino    Hot and cold basic blocks are partitioned and put in separate
2187e4b17023SJohn Marino    sections of the .o file, to reduce paging and improve cache
2188e4b17023SJohn Marino    performance (hopefully).  This can result in bits of code from the
2189e4b17023SJohn Marino    same function being widely separated in the .o file.  However this
2190e4b17023SJohn Marino    is not obvious to the current bb structure.  Therefore we must take
2191e4b17023SJohn Marino    care to ensure that: 1). There are no fall_thru edges that cross
2192e4b17023SJohn Marino    between sections; 2). For those architectures which have "short"
2193e4b17023SJohn Marino    conditional branches, all conditional branches that attempt to
2194e4b17023SJohn Marino    cross between sections are converted to unconditional branches;
2195e4b17023SJohn Marino    and, 3). For those architectures which have "short" unconditional
2196e4b17023SJohn Marino    branches, all unconditional branches that attempt to cross between
2197e4b17023SJohn Marino    sections are converted to indirect jumps.
2198e4b17023SJohn Marino 
2199e4b17023SJohn Marino    The code for fixing up fall_thru edges that cross between hot and
2200e4b17023SJohn Marino    cold basic blocks does so by creating new basic blocks containing
2201e4b17023SJohn Marino    unconditional branches to the appropriate label in the "other"
2202e4b17023SJohn Marino    section.  The new basic block is then put in the same (hot or cold)
2203e4b17023SJohn Marino    section as the original conditional branch, and the fall_thru edge
2204e4b17023SJohn Marino    is modified to fall into the new basic block instead.  By adding
2205e4b17023SJohn Marino    this level of indirection we end up with only unconditional branches
2206e4b17023SJohn Marino    crossing between hot and cold sections.
2207e4b17023SJohn Marino 
2208e4b17023SJohn Marino    Conditional branches are dealt with by adding a level of indirection.
2209e4b17023SJohn Marino    A new basic block is added in the same (hot/cold) section as the
2210e4b17023SJohn Marino    conditional branch, and the conditional branch is retargeted to the
2211e4b17023SJohn Marino    new basic block.  The new basic block contains an unconditional branch
2212e4b17023SJohn Marino    to the original target of the conditional branch (in the other section).
2213e4b17023SJohn Marino 
2214e4b17023SJohn Marino    Unconditional branches are dealt with by converting them into
2215e4b17023SJohn Marino    indirect jumps.  */
2216e4b17023SJohn Marino 
2217e4b17023SJohn Marino static unsigned
partition_hot_cold_basic_blocks(void)2218e4b17023SJohn Marino partition_hot_cold_basic_blocks (void)
2219e4b17023SJohn Marino {
2220e4b17023SJohn Marino   VEC(edge, heap) *crossing_edges;
2221e4b17023SJohn Marino 
2222e4b17023SJohn Marino   if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1)
2223e4b17023SJohn Marino     return 0;
2224e4b17023SJohn Marino 
2225e4b17023SJohn Marino   df_set_flags (DF_DEFER_INSN_RESCAN);
2226e4b17023SJohn Marino 
2227e4b17023SJohn Marino   crossing_edges = find_rarely_executed_basic_blocks_and_crossing_edges ();
2228e4b17023SJohn Marino   if (crossing_edges == NULL)
2229e4b17023SJohn Marino     return 0;
2230e4b17023SJohn Marino 
2231e4b17023SJohn Marino   /* Make sure the source of any crossing edge ends in a jump and the
2232e4b17023SJohn Marino      destination of any crossing edge has a label.  */
2233e4b17023SJohn Marino   add_labels_and_missing_jumps (crossing_edges);
2234e4b17023SJohn Marino 
2235e4b17023SJohn Marino   /* Convert all crossing fall_thru edges to non-crossing fall
2236e4b17023SJohn Marino      thrus to unconditional jumps (that jump to the original fall
2237e4b17023SJohn Marino      thru dest).  */
2238e4b17023SJohn Marino   fix_up_fall_thru_edges ();
2239e4b17023SJohn Marino 
2240e4b17023SJohn Marino   /* If the architecture does not have conditional branches that can
2241e4b17023SJohn Marino      span all of memory, convert crossing conditional branches into
2242e4b17023SJohn Marino      crossing unconditional branches.  */
2243e4b17023SJohn Marino   if (!HAS_LONG_COND_BRANCH)
2244e4b17023SJohn Marino     fix_crossing_conditional_branches ();
2245e4b17023SJohn Marino 
2246e4b17023SJohn Marino   /* If the architecture does not have unconditional branches that
2247e4b17023SJohn Marino      can span all of memory, convert crossing unconditional branches
2248e4b17023SJohn Marino      into indirect jumps.  Since adding an indirect jump also adds
2249e4b17023SJohn Marino      a new register usage, update the register usage information as
2250e4b17023SJohn Marino      well.  */
2251e4b17023SJohn Marino   if (!HAS_LONG_UNCOND_BRANCH)
2252e4b17023SJohn Marino     fix_crossing_unconditional_branches ();
2253e4b17023SJohn Marino 
2254e4b17023SJohn Marino   add_reg_crossing_jump_notes ();
2255e4b17023SJohn Marino 
2256e4b17023SJohn Marino   /* Clear bb->aux fields that the above routines were using.  */
2257e4b17023SJohn Marino   clear_aux_for_blocks ();
2258e4b17023SJohn Marino 
2259e4b17023SJohn Marino   VEC_free (edge, heap, crossing_edges);
2260e4b17023SJohn Marino 
2261e4b17023SJohn Marino   /* ??? FIXME: DF generates the bb info for a block immediately.
2262e4b17023SJohn Marino      And by immediately, I mean *during* creation of the block.
2263e4b17023SJohn Marino 
2264e4b17023SJohn Marino 	#0  df_bb_refs_collect
2265e4b17023SJohn Marino 	#1  in df_bb_refs_record
2266e4b17023SJohn Marino 	#2  in create_basic_block_structure
2267e4b17023SJohn Marino 
2268e4b17023SJohn Marino      Which means that the bb_has_eh_pred test in df_bb_refs_collect
2269e4b17023SJohn Marino      will *always* fail, because no edges can have been added to the
2270e4b17023SJohn Marino      block yet.  Which of course means we don't add the right
2271e4b17023SJohn Marino      artificial refs, which means we fail df_verify (much) later.
2272e4b17023SJohn Marino 
2273e4b17023SJohn Marino      Cleanest solution would seem to make DF_DEFER_INSN_RESCAN imply
2274e4b17023SJohn Marino      that we also shouldn't grab data from the new blocks those new
2275e4b17023SJohn Marino      insns are in either.  In this way one can create the block, link
2276e4b17023SJohn Marino      it up properly, and have everything Just Work later, when deferred
2277e4b17023SJohn Marino      insns are processed.
2278e4b17023SJohn Marino 
2279e4b17023SJohn Marino      In the meantime, we have no other option but to throw away all
2280e4b17023SJohn Marino      of the DF data and recompute it all.  */
2281e4b17023SJohn Marino   if (cfun->eh->lp_array)
2282e4b17023SJohn Marino     {
2283e4b17023SJohn Marino       df_finish_pass (true);
2284e4b17023SJohn Marino       df_scan_alloc (NULL);
2285e4b17023SJohn Marino       df_scan_blocks ();
2286e4b17023SJohn Marino       /* Not all post-landing pads use all of the EH_RETURN_DATA_REGNO
2287e4b17023SJohn Marino 	 data.  We blindly generated all of them when creating the new
2288e4b17023SJohn Marino 	 landing pad.  Delete those assignments we don't use.  */
2289e4b17023SJohn Marino       df_set_flags (DF_LR_RUN_DCE);
2290e4b17023SJohn Marino       df_analyze ();
2291e4b17023SJohn Marino     }
2292e4b17023SJohn Marino 
2293e4b17023SJohn Marino   return TODO_verify_flow | TODO_verify_rtl_sharing;
2294e4b17023SJohn Marino }
2295e4b17023SJohn Marino 
2296e4b17023SJohn Marino static bool
gate_handle_reorder_blocks(void)2297e4b17023SJohn Marino gate_handle_reorder_blocks (void)
2298e4b17023SJohn Marino {
2299e4b17023SJohn Marino   if (targetm.cannot_modify_jumps_p ())
2300e4b17023SJohn Marino     return false;
2301e4b17023SJohn Marino   /* Don't reorder blocks when optimizing for size because extra jump insns may
2302e4b17023SJohn Marino      be created; also barrier may create extra padding.
2303e4b17023SJohn Marino 
2304e4b17023SJohn Marino      More correctly we should have a block reordering mode that tried to
2305e4b17023SJohn Marino      minimize the combined size of all the jumps.  This would more or less
2306e4b17023SJohn Marino      automatically remove extra jumps, but would also try to use more short
2307e4b17023SJohn Marino      jumps instead of long jumps.  */
2308e4b17023SJohn Marino   if (!optimize_function_for_speed_p (cfun))
2309e4b17023SJohn Marino     return false;
2310e4b17023SJohn Marino   return (optimize > 0
2311e4b17023SJohn Marino 	  && (flag_reorder_blocks || flag_reorder_blocks_and_partition));
2312e4b17023SJohn Marino }
2313e4b17023SJohn Marino 
2314e4b17023SJohn Marino 
2315e4b17023SJohn Marino /* Reorder basic blocks.  */
2316e4b17023SJohn Marino static unsigned int
rest_of_handle_reorder_blocks(void)2317e4b17023SJohn Marino rest_of_handle_reorder_blocks (void)
2318e4b17023SJohn Marino {
2319e4b17023SJohn Marino   basic_block bb;
2320e4b17023SJohn Marino 
2321e4b17023SJohn Marino   /* Last attempt to optimize CFG, as scheduling, peepholing and insn
2322e4b17023SJohn Marino      splitting possibly introduced more crossjumping opportunities.  */
2323e4b17023SJohn Marino   cfg_layout_initialize (CLEANUP_EXPENSIVE);
2324e4b17023SJohn Marino 
2325e4b17023SJohn Marino   reorder_basic_blocks ();
2326e4b17023SJohn Marino   cleanup_cfg (CLEANUP_EXPENSIVE);
2327e4b17023SJohn Marino 
2328e4b17023SJohn Marino   FOR_EACH_BB (bb)
2329e4b17023SJohn Marino     if (bb->next_bb != EXIT_BLOCK_PTR)
2330e4b17023SJohn Marino       bb->aux = bb->next_bb;
2331e4b17023SJohn Marino   cfg_layout_finalize ();
2332e4b17023SJohn Marino 
2333e4b17023SJohn Marino   /* Add NOTE_INSN_SWITCH_TEXT_SECTIONS notes.  */
2334e4b17023SJohn Marino   insert_section_boundary_note ();
2335e4b17023SJohn Marino   return 0;
2336e4b17023SJohn Marino }
2337e4b17023SJohn Marino 
2338e4b17023SJohn Marino struct rtl_opt_pass pass_reorder_blocks =
2339e4b17023SJohn Marino {
2340e4b17023SJohn Marino  {
2341e4b17023SJohn Marino   RTL_PASS,
2342e4b17023SJohn Marino   "bbro",                               /* name */
2343e4b17023SJohn Marino   gate_handle_reorder_blocks,           /* gate */
2344e4b17023SJohn Marino   rest_of_handle_reorder_blocks,        /* execute */
2345e4b17023SJohn Marino   NULL,                                 /* sub */
2346e4b17023SJohn Marino   NULL,                                 /* next */
2347e4b17023SJohn Marino   0,                                    /* static_pass_number */
2348e4b17023SJohn Marino   TV_REORDER_BLOCKS,                    /* tv_id */
2349e4b17023SJohn Marino   0,                                    /* properties_required */
2350e4b17023SJohn Marino   0,                                    /* properties_provided */
2351e4b17023SJohn Marino   0,                                    /* properties_destroyed */
2352e4b17023SJohn Marino   0,                                    /* todo_flags_start */
2353e4b17023SJohn Marino   TODO_verify_rtl_sharing,              /* todo_flags_finish */
2354e4b17023SJohn Marino  }
2355e4b17023SJohn Marino };
2356e4b17023SJohn Marino 
2357e4b17023SJohn Marino static bool
gate_handle_partition_blocks(void)2358e4b17023SJohn Marino gate_handle_partition_blocks (void)
2359e4b17023SJohn Marino {
2360e4b17023SJohn Marino   /* The optimization to partition hot/cold basic blocks into separate
2361e4b17023SJohn Marino      sections of the .o file does not work well with linkonce or with
2362e4b17023SJohn Marino      user defined section attributes.  Don't call it if either case
2363e4b17023SJohn Marino      arises.  */
2364e4b17023SJohn Marino   return (flag_reorder_blocks_and_partition
2365e4b17023SJohn Marino           && optimize
2366e4b17023SJohn Marino 	  /* See gate_handle_reorder_blocks.  We should not partition if
2367e4b17023SJohn Marino 	     we are going to omit the reordering.  */
2368e4b17023SJohn Marino 	  && optimize_function_for_speed_p (cfun)
2369e4b17023SJohn Marino 	  && !DECL_ONE_ONLY (current_function_decl)
2370e4b17023SJohn Marino 	  && !user_defined_section_attribute);
2371e4b17023SJohn Marino }
2372e4b17023SJohn Marino 
2373e4b17023SJohn Marino struct rtl_opt_pass pass_partition_blocks =
2374e4b17023SJohn Marino {
2375e4b17023SJohn Marino  {
2376e4b17023SJohn Marino   RTL_PASS,
2377e4b17023SJohn Marino   "bbpart",                             /* name */
2378e4b17023SJohn Marino   gate_handle_partition_blocks,         /* gate */
2379e4b17023SJohn Marino   partition_hot_cold_basic_blocks,      /* execute */
2380e4b17023SJohn Marino   NULL,                                 /* sub */
2381e4b17023SJohn Marino   NULL,                                 /* next */
2382e4b17023SJohn Marino   0,                                    /* static_pass_number */
2383e4b17023SJohn Marino   TV_REORDER_BLOCKS,                    /* tv_id */
2384e4b17023SJohn Marino   PROP_cfglayout,                       /* properties_required */
2385e4b17023SJohn Marino   0,                                    /* properties_provided */
2386e4b17023SJohn Marino   0,                                    /* properties_destroyed */
2387e4b17023SJohn Marino   0,                                    /* todo_flags_start */
2388e4b17023SJohn Marino   0					/* todo_flags_finish */
2389e4b17023SJohn Marino  }
2390e4b17023SJohn Marino };
2391