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