Mercurial > hg > CbC > GCC_original
comparison gcc/mode-switching.c @ 16:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
15:561a7518be6b | 16:04ced10e8804 |
---|---|
1 /* CPU mode switching | 1 /* CPU mode switching |
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, | 2 Copyright (C) 1998-2017 Free Software Foundation, Inc. |
3 2009, 2010 Free Software Foundation, Inc. | |
4 | 3 |
5 This file is part of GCC. | 4 This file is part of GCC. |
6 | 5 |
7 GCC is free software; you can redistribute it and/or modify it under | 6 GCC is free software; you can redistribute it and/or modify it under |
8 the terms of the GNU General Public License as published by the Free | 7 the terms of the GNU General Public License as published by the Free |
19 <http://www.gnu.org/licenses/>. */ | 18 <http://www.gnu.org/licenses/>. */ |
20 | 19 |
21 #include "config.h" | 20 #include "config.h" |
22 #include "system.h" | 21 #include "system.h" |
23 #include "coretypes.h" | 22 #include "coretypes.h" |
24 #include "tm.h" | 23 #include "backend.h" |
25 #include "target.h" | 24 #include "target.h" |
26 #include "rtl.h" | 25 #include "rtl.h" |
26 #include "cfghooks.h" | |
27 #include "df.h" | |
28 #include "memmodel.h" | |
29 #include "tm_p.h" | |
27 #include "regs.h" | 30 #include "regs.h" |
28 #include "hard-reg-set.h" | 31 #include "emit-rtl.h" |
29 #include "flags.h" | 32 #include "cfgrtl.h" |
30 #include "insn-config.h" | 33 #include "cfganal.h" |
31 #include "recog.h" | 34 #include "lcm.h" |
32 #include "basic-block.h" | 35 #include "cfgcleanup.h" |
33 #include "output.h" | |
34 #include "tm_p.h" | |
35 #include "function.h" | |
36 #include "tree-pass.h" | 36 #include "tree-pass.h" |
37 #include "timevar.h" | |
38 #include "df.h" | |
39 #include "emit-rtl.h" | |
40 | 37 |
41 /* We want target macros for the mode switching code to be able to refer | 38 /* We want target macros for the mode switching code to be able to refer |
42 to instruction attribute values. */ | 39 to instruction attribute values. */ |
43 #include "insn-attr.h" | 40 #include "insn-attr.h" |
44 | 41 |
46 | 43 |
47 /* The algorithm for setting the modes consists of scanning the insn list | 44 /* The algorithm for setting the modes consists of scanning the insn list |
48 and finding all the insns which require a specific mode. Each insn gets | 45 and finding all the insns which require a specific mode. Each insn gets |
49 a unique struct seginfo element. These structures are inserted into a list | 46 a unique struct seginfo element. These structures are inserted into a list |
50 for each basic block. For each entity, there is an array of bb_info over | 47 for each basic block. For each entity, there is an array of bb_info over |
51 the flow graph basic blocks (local var 'bb_info'), and contains a list | 48 the flow graph basic blocks (local var 'bb_info'), which contains a list |
52 of all insns within that basic block, in the order they are encountered. | 49 of all insns within that basic block, in the order they are encountered. |
53 | 50 |
54 For each entity, any basic block WITHOUT any insns requiring a specific | 51 For each entity, any basic block WITHOUT any insns requiring a specific |
55 mode are given a single entry, without a mode. (Each basic block | 52 mode are given a single entry without a mode (each basic block in the |
56 in the flow graph must have at least one entry in the segment table.) | 53 flow graph must have at least one entry in the segment table). |
57 | 54 |
58 The LCM algorithm is then run over the flow graph to determine where to | 55 The LCM algorithm is then run over the flow graph to determine where to |
59 place the sets to the highest-priority value in respect of first the first | 56 place the sets to the highest-priority mode with respect to the first |
60 insn in any one block. Any adjustments required to the transparency | 57 insn in any one block. Any adjustments required to the transparency |
61 vectors are made, then the next iteration starts for the next-lower | 58 vectors are made, then the next iteration starts for the next-lower |
62 priority mode, till for each entity all modes are exhausted. | 59 priority mode, till for each entity all modes are exhausted. |
63 | 60 |
64 More details are located in the code for optimize_mode_switching(). */ | 61 More details can be found in the code of optimize_mode_switching. */ |
65 | 62 |
66 /* This structure contains the information for each insn which requires | 63 /* This structure contains the information for each insn which requires |
67 either single or double mode to be set. | 64 either single or double mode to be set. |
68 MODE is the mode this insn must be executed in. | 65 MODE is the mode this insn must be executed in. |
69 INSN_PTR is the insn to be executed (may be the note that marks the | 66 INSN_PTR is the insn to be executed (may be the note that marks the |
71 BBNUM is the flow graph basic block this insn occurs in. | 68 BBNUM is the flow graph basic block this insn occurs in. |
72 NEXT is the next insn in the same basic block. */ | 69 NEXT is the next insn in the same basic block. */ |
73 struct seginfo | 70 struct seginfo |
74 { | 71 { |
75 int mode; | 72 int mode; |
76 rtx insn_ptr; | 73 rtx_insn *insn_ptr; |
77 int bbnum; | 74 int bbnum; |
78 struct seginfo *next; | 75 struct seginfo *next; |
79 HARD_REG_SET regs_live; | 76 HARD_REG_SET regs_live; |
80 }; | 77 }; |
81 | 78 |
82 struct bb_info | 79 struct bb_info |
83 { | 80 { |
84 struct seginfo *seginfo; | 81 struct seginfo *seginfo; |
85 int computing; | 82 int computing; |
83 int mode_out; | |
84 int mode_in; | |
86 }; | 85 }; |
87 | 86 |
88 /* These bitmaps are used for the LCM algorithm. */ | 87 static struct seginfo * new_seginfo (int, rtx_insn *, int, HARD_REG_SET); |
89 | |
90 static sbitmap *antic; | |
91 static sbitmap *transp; | |
92 static sbitmap *comp; | |
93 | |
94 static struct seginfo * new_seginfo (int, rtx, int, HARD_REG_SET); | |
95 static void add_seginfo (struct bb_info *, struct seginfo *); | 88 static void add_seginfo (struct bb_info *, struct seginfo *); |
96 static void reg_dies (rtx, HARD_REG_SET *); | 89 static void reg_dies (rtx, HARD_REG_SET *); |
97 static void reg_becomes_live (rtx, const_rtx, void *); | 90 static void reg_becomes_live (rtx, const_rtx, void *); |
98 static void make_preds_opaque (basic_block, int); | 91 |
99 | 92 /* Clear ode I from entity J in bitmap B. */ |
100 | 93 #define clear_mode_bit(b, j, i) \ |
101 /* This function will allocate a new BBINFO structure, initialized | 94 bitmap_clear_bit (b, (j * max_num_modes) + i) |
102 with the MODE, INSN, and basic block BB parameters. */ | 95 |
96 /* Test mode I from entity J in bitmap B. */ | |
97 #define mode_bit_p(b, j, i) \ | |
98 bitmap_bit_p (b, (j * max_num_modes) + i) | |
99 | |
100 /* Set mode I from entity J in bitmal B. */ | |
101 #define set_mode_bit(b, j, i) \ | |
102 bitmap_set_bit (b, (j * max_num_modes) + i) | |
103 | |
104 /* Emit modes segments from EDGE_LIST associated with entity E. | |
105 INFO gives mode availability for each mode. */ | |
106 | |
107 static bool | |
108 commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info) | |
109 { | |
110 bool need_commit = false; | |
111 | |
112 for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--) | |
113 { | |
114 edge eg = INDEX_EDGE (edge_list, ed); | |
115 int mode; | |
116 | |
117 if ((mode = (int)(intptr_t)(eg->aux)) != -1) | |
118 { | |
119 HARD_REG_SET live_at_edge; | |
120 basic_block src_bb = eg->src; | |
121 int cur_mode = info[src_bb->index].mode_out; | |
122 rtx_insn *mode_set; | |
123 | |
124 REG_SET_TO_HARD_REG_SET (live_at_edge, df_get_live_out (src_bb)); | |
125 | |
126 rtl_profile_for_edge (eg); | |
127 start_sequence (); | |
128 | |
129 targetm.mode_switching.emit (e, mode, cur_mode, live_at_edge); | |
130 | |
131 mode_set = get_insns (); | |
132 end_sequence (); | |
133 default_rtl_profile (); | |
134 | |
135 /* Do not bother to insert empty sequence. */ | |
136 if (mode_set == NULL) | |
137 continue; | |
138 | |
139 /* We should not get an abnormal edge here. */ | |
140 gcc_assert (! (eg->flags & EDGE_ABNORMAL)); | |
141 | |
142 need_commit = true; | |
143 insert_insn_on_edge (mode_set, eg); | |
144 } | |
145 } | |
146 | |
147 return need_commit; | |
148 } | |
149 | |
150 /* Allocate a new BBINFO structure, initialized with the MODE, INSN, | |
151 and basic block BB parameters. | |
152 INSN may not be a NOTE_INSN_BASIC_BLOCK, unless it is an empty | |
153 basic block; that allows us later to insert instructions in a FIFO-like | |
154 manner. */ | |
103 | 155 |
104 static struct seginfo * | 156 static struct seginfo * |
105 new_seginfo (int mode, rtx insn, int bb, HARD_REG_SET regs_live) | 157 new_seginfo (int mode, rtx_insn *insn, int bb, HARD_REG_SET regs_live) |
106 { | 158 { |
107 struct seginfo *ptr; | 159 struct seginfo *ptr; |
160 | |
161 gcc_assert (!NOTE_INSN_BASIC_BLOCK_P (insn) | |
162 || insn == BB_END (NOTE_BASIC_BLOCK (insn))); | |
108 ptr = XNEW (struct seginfo); | 163 ptr = XNEW (struct seginfo); |
109 ptr->mode = mode; | 164 ptr->mode = mode; |
110 ptr->insn_ptr = insn; | 165 ptr->insn_ptr = insn; |
111 ptr->bbnum = bb; | 166 ptr->bbnum = bb; |
112 ptr->next = NULL; | 167 ptr->next = NULL; |
132 ptr = ptr->next; | 187 ptr = ptr->next; |
133 ptr->next = info; | 188 ptr->next = info; |
134 } | 189 } |
135 } | 190 } |
136 | 191 |
137 /* Make all predecessors of basic block B opaque, recursively, till we hit | |
138 some that are already non-transparent, or an edge where aux is set; that | |
139 denotes that a mode set is to be done on that edge. | |
140 J is the bit number in the bitmaps that corresponds to the entity that | |
141 we are currently handling mode-switching for. */ | |
142 | |
143 static void | |
144 make_preds_opaque (basic_block b, int j) | |
145 { | |
146 edge e; | |
147 edge_iterator ei; | |
148 | |
149 FOR_EACH_EDGE (e, ei, b->preds) | |
150 { | |
151 basic_block pb = e->src; | |
152 | |
153 if (e->aux || ! TEST_BIT (transp[pb->index], j)) | |
154 continue; | |
155 | |
156 RESET_BIT (transp[pb->index], j); | |
157 make_preds_opaque (pb, j); | |
158 } | |
159 } | |
160 | |
161 /* Record in LIVE that register REG died. */ | 192 /* Record in LIVE that register REG died. */ |
162 | 193 |
163 static void | 194 static void |
164 reg_dies (rtx reg, HARD_REG_SET *live) | 195 reg_dies (rtx reg, HARD_REG_SET *live) |
165 { | 196 { |
190 regno = REGNO (reg); | 221 regno = REGNO (reg); |
191 if (regno < FIRST_PSEUDO_REGISTER) | 222 if (regno < FIRST_PSEUDO_REGISTER) |
192 add_to_hard_reg_set ((HARD_REG_SET *) live, GET_MODE (reg), regno); | 223 add_to_hard_reg_set ((HARD_REG_SET *) live, GET_MODE (reg), regno); |
193 } | 224 } |
194 | 225 |
195 /* Make sure if MODE_ENTRY is defined the MODE_EXIT is defined | |
196 and vice versa. */ | |
197 #if defined (MODE_ENTRY) != defined (MODE_EXIT) | |
198 #error "Both MODE_ENTRY and MODE_EXIT must be defined" | |
199 #endif | |
200 | |
201 #if defined (MODE_ENTRY) && defined (MODE_EXIT) | |
202 /* Split the fallthrough edge to the exit block, so that we can note | 226 /* Split the fallthrough edge to the exit block, so that we can note |
203 that there NORMAL_MODE is required. Return the new block if it's | 227 that there NORMAL_MODE is required. Return the new block if it's |
204 inserted before the exit block. Otherwise return null. */ | 228 inserted before the exit block. Otherwise return null. */ |
205 | 229 |
206 static basic_block | 230 static basic_block |
212 | 236 |
213 /* The only non-call predecessor at this stage is a block with a | 237 /* The only non-call predecessor at this stage is a block with a |
214 fallthrough edge; there can be at most one, but there could be | 238 fallthrough edge; there can be at most one, but there could be |
215 none at all, e.g. when exit is called. */ | 239 none at all, e.g. when exit is called. */ |
216 pre_exit = 0; | 240 pre_exit = 0; |
217 FOR_EACH_EDGE (eg, ei, EXIT_BLOCK_PTR->preds) | 241 FOR_EACH_EDGE (eg, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) |
218 if (eg->flags & EDGE_FALLTHRU) | 242 if (eg->flags & EDGE_FALLTHRU) |
219 { | 243 { |
220 basic_block src_bb = eg->src; | 244 basic_block src_bb = eg->src; |
221 rtx last_insn, ret_reg; | 245 rtx_insn *last_insn; |
246 rtx ret_reg; | |
222 | 247 |
223 gcc_assert (!pre_exit); | 248 gcc_assert (!pre_exit); |
224 /* If this function returns a value at the end, we have to | 249 /* If this function returns a value at the end, we have to |
225 insert the final mode switch before the return value copy | 250 insert the final mode switch before the return value copy |
226 to its hard register. */ | 251 to its hard register. */ |
227 if (EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 1 | 252 if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == 1 |
228 && NONJUMP_INSN_P ((last_insn = BB_END (src_bb))) | 253 && NONJUMP_INSN_P ((last_insn = BB_END (src_bb))) |
229 && GET_CODE (PATTERN (last_insn)) == USE | 254 && GET_CODE (PATTERN (last_insn)) == USE |
230 && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG) | 255 && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG) |
231 { | 256 { |
232 int ret_start = REGNO (ret_reg); | 257 int ret_start = REGNO (ret_reg); |
233 int nregs = hard_regno_nregs[ret_start][GET_MODE (ret_reg)]; | 258 int nregs = REG_NREGS (ret_reg); |
234 int ret_end = ret_start + nregs; | 259 int ret_end = ret_start + nregs; |
235 int short_block = 0; | 260 bool short_block = false; |
236 int maybe_builtin_apply = 0; | 261 bool multi_reg_return = false; |
237 int forced_late_switch = 0; | 262 bool forced_late_switch = false; |
238 rtx before_return_copy; | 263 rtx_insn *before_return_copy; |
239 | 264 |
240 do | 265 do |
241 { | 266 { |
242 rtx return_copy = PREV_INSN (last_insn); | 267 rtx_insn *return_copy = PREV_INSN (last_insn); |
243 rtx return_copy_pat, copy_reg; | 268 rtx return_copy_pat, copy_reg; |
244 int copy_start, copy_num; | 269 int copy_start, copy_num; |
245 int j; | 270 int j; |
246 | 271 |
247 if (INSN_P (return_copy)) | 272 if (NONDEBUG_INSN_P (return_copy)) |
248 { | 273 { |
249 /* When using SJLJ exceptions, the call to the | 274 /* When using SJLJ exceptions, the call to the |
250 unregister function is inserted between the | 275 unregister function is inserted between the |
251 clobber of the return value and the copy. | 276 clobber of the return value and the copy. |
252 We do not want to split the block before this | 277 We do not want to split the block before this |
253 or any other call; if we have not found the | 278 or any other call; if we have not found the |
254 copy yet, the copy must have been deleted. */ | 279 copy yet, the copy must have been deleted. */ |
255 if (CALL_P (return_copy)) | 280 if (CALL_P (return_copy)) |
256 { | 281 { |
257 short_block = 1; | 282 short_block = true; |
258 break; | 283 break; |
259 } | 284 } |
260 return_copy_pat = PATTERN (return_copy); | 285 return_copy_pat = PATTERN (return_copy); |
261 switch (GET_CODE (return_copy_pat)) | 286 switch (GET_CODE (return_copy_pat)) |
262 { | 287 { |
263 case USE: | 288 case USE: |
264 /* Skip __builtin_apply pattern. */ | 289 /* Skip USEs of multiple return registers. |
290 __builtin_apply pattern is also handled here. */ | |
265 if (GET_CODE (XEXP (return_copy_pat, 0)) == REG | 291 if (GET_CODE (XEXP (return_copy_pat, 0)) == REG |
266 && (targetm.calls.function_value_regno_p | 292 && (targetm.calls.function_value_regno_p |
267 (REGNO (XEXP (return_copy_pat, 0))))) | 293 (REGNO (XEXP (return_copy_pat, 0))))) |
268 { | 294 { |
269 maybe_builtin_apply = 1; | 295 multi_reg_return = true; |
270 last_insn = return_copy; | 296 last_insn = return_copy; |
271 continue; | 297 continue; |
272 } | 298 } |
273 break; | 299 break; |
274 | 300 |
322 copy_start = REGNO (copy_reg); | 348 copy_start = REGNO (copy_reg); |
323 else if (GET_CODE (copy_reg) == SUBREG | 349 else if (GET_CODE (copy_reg) == SUBREG |
324 && GET_CODE (SUBREG_REG (copy_reg)) == REG) | 350 && GET_CODE (SUBREG_REG (copy_reg)) == REG) |
325 copy_start = REGNO (SUBREG_REG (copy_reg)); | 351 copy_start = REGNO (SUBREG_REG (copy_reg)); |
326 else | 352 else |
327 break; | 353 { |
328 if (copy_start >= FIRST_PSEUDO_REGISTER) | 354 /* When control reaches end of non-void function, |
329 break; | 355 there are no return copy insns at all. This |
330 copy_num | 356 avoids an ice on that invalid function. */ |
331 = hard_regno_nregs[copy_start][GET_MODE (copy_reg)]; | 357 if (ret_start + nregs == ret_end) |
358 short_block = true; | |
359 break; | |
360 } | |
361 if (!targetm.calls.function_value_regno_p (copy_start)) | |
362 copy_num = 0; | |
363 else | |
364 copy_num = hard_regno_nregs (copy_start, | |
365 GET_MODE (copy_reg)); | |
332 | 366 |
333 /* If the return register is not likely spilled, - as is | 367 /* If the return register is not likely spilled, - as is |
334 the case for floating point on SH4 - then it might | 368 the case for floating point on SH4 - then it might |
335 be set by an arithmetic operation that needs a | 369 be set by an arithmetic operation that needs a |
336 different mode than the exit block. */ | 370 different mode than the exit block. */ |
337 for (j = n_entities - 1; j >= 0; j--) | 371 for (j = n_entities - 1; j >= 0; j--) |
338 { | 372 { |
339 int e = entity_map[j]; | 373 int e = entity_map[j]; |
340 int mode = MODE_NEEDED (e, return_copy); | 374 int mode = |
341 | 375 targetm.mode_switching.needed (e, return_copy); |
342 if (mode != num_modes[e] && mode != MODE_EXIT (e)) | 376 |
377 if (mode != num_modes[e] | |
378 && mode != targetm.mode_switching.exit (e)) | |
343 break; | 379 break; |
344 } | 380 } |
345 if (j >= 0) | 381 if (j >= 0) |
346 { | 382 { |
383 /* __builtin_return emits a sequence of loads to all | |
384 return registers. One of them might require | |
385 another mode than MODE_EXIT, even if it is | |
386 unrelated to the return value, so we want to put | |
387 the final mode switch after it. */ | |
388 if (multi_reg_return | |
389 && targetm.calls.function_value_regno_p | |
390 (copy_start)) | |
391 forced_late_switch = true; | |
392 | |
347 /* For the SH4, floating point loads depend on fpscr, | 393 /* For the SH4, floating point loads depend on fpscr, |
348 thus we might need to put the final mode switch | 394 thus we might need to put the final mode switch |
349 after the return value copy. That is still OK, | 395 after the return value copy. That is still OK, |
350 because a floating point return value does not | 396 because a floating point return value does not |
351 conflict with address reloads. */ | 397 conflict with address reloads. */ |
352 if (copy_start >= ret_start | 398 if (copy_start >= ret_start |
353 && copy_start + copy_num <= ret_end | 399 && copy_start + copy_num <= ret_end |
354 && OBJECT_P (SET_SRC (return_copy_pat))) | 400 && OBJECT_P (SET_SRC (return_copy_pat))) |
355 forced_late_switch = 1; | 401 forced_late_switch = true; |
356 break; | 402 break; |
403 } | |
404 if (copy_num == 0) | |
405 { | |
406 last_insn = return_copy; | |
407 continue; | |
357 } | 408 } |
358 | 409 |
359 if (copy_start >= ret_start | 410 if (copy_start >= ret_start |
360 && copy_start + copy_num <= ret_end) | 411 && copy_start + copy_num <= ret_end) |
361 nregs -= copy_num; | 412 nregs -= copy_num; |
362 else if (!maybe_builtin_apply | 413 else if (!multi_reg_return |
363 || !targetm.calls.function_value_regno_p | 414 || !targetm.calls.function_value_regno_p |
364 (copy_start)) | 415 (copy_start)) |
365 break; | 416 break; |
366 last_insn = return_copy; | 417 last_insn = return_copy; |
367 } | 418 } |
371 Similarly, conditionally returning without a value, | 422 Similarly, conditionally returning without a value, |
372 and conditionally using builtin_return can lead to an | 423 and conditionally using builtin_return can lead to an |
373 isolated use. */ | 424 isolated use. */ |
374 if (return_copy == BB_HEAD (src_bb)) | 425 if (return_copy == BB_HEAD (src_bb)) |
375 { | 426 { |
376 short_block = 1; | 427 short_block = true; |
377 break; | 428 break; |
378 } | 429 } |
379 last_insn = return_copy; | 430 last_insn = return_copy; |
380 } | 431 } |
381 while (nregs); | 432 while (nregs); |
387 gcc_assert (!nregs | 438 gcc_assert (!nregs |
388 || forced_late_switch | 439 || forced_late_switch |
389 || short_block | 440 || short_block |
390 || !(targetm.class_likely_spilled_p | 441 || !(targetm.class_likely_spilled_p |
391 (REGNO_REG_CLASS (ret_start))) | 442 (REGNO_REG_CLASS (ret_start))) |
392 || (nregs | 443 || nregs != REG_NREGS (ret_reg) |
393 != hard_regno_nregs[ret_start][GET_MODE (ret_reg)]) | |
394 /* For multi-hard-register floating point | 444 /* For multi-hard-register floating point |
395 values, sometimes the likely-spilled part | 445 values, sometimes the likely-spilled part |
396 is ordinarily copied first, then the other | 446 is ordinarily copied first, then the other |
397 part is set with an arithmetic operation. | 447 part is set with an arithmetic operation. |
398 This doesn't actually cause reload | 448 This doesn't actually cause reload |
399 failures, so let it pass. */ | 449 failures, so let it pass. */ |
400 || (GET_MODE_CLASS (GET_MODE (ret_reg)) != MODE_INT | 450 || (GET_MODE_CLASS (GET_MODE (ret_reg)) != MODE_INT |
401 && nregs != 1)); | 451 && nregs != 1)); |
402 | 452 |
403 if (INSN_P (last_insn)) | 453 if (!NOTE_INSN_BASIC_BLOCK_P (last_insn)) |
404 { | 454 { |
405 before_return_copy | 455 before_return_copy |
406 = emit_note_before (NOTE_INSN_DELETED, last_insn); | 456 = emit_note_before (NOTE_INSN_DELETED, last_insn); |
407 /* Instructions preceding LAST_INSN in the same block might | 457 /* Instructions preceding LAST_INSN in the same block might |
408 require a different mode than MODE_EXIT, so if we might | 458 require a different mode than MODE_EXIT, so if we might |
409 have such instructions, keep them in a separate block | 459 have such instructions, keep them in a separate block |
410 from pre_exit. */ | 460 from pre_exit. */ |
411 if (last_insn != BB_HEAD (src_bb)) | 461 src_bb = split_block (src_bb, |
412 src_bb = split_block (src_bb, | 462 PREV_INSN (before_return_copy))->dest; |
413 PREV_INSN (before_return_copy))->dest; | |
414 } | 463 } |
415 else | 464 else |
416 before_return_copy = last_insn; | 465 before_return_copy = last_insn; |
417 pre_exit = split_block (src_bb, before_return_copy)->src; | 466 pre_exit = split_block (src_bb, before_return_copy)->src; |
418 } | 467 } |
422 } | 471 } |
423 } | 472 } |
424 | 473 |
425 return pre_exit; | 474 return pre_exit; |
426 } | 475 } |
427 #endif | |
428 | 476 |
429 /* Find all insns that need a particular mode setting, and insert the | 477 /* Find all insns that need a particular mode setting, and insert the |
430 necessary mode switches. Return true if we did work. */ | 478 necessary mode switches. Return true if we did work. */ |
431 | 479 |
432 static int | 480 static int |
433 optimize_mode_switching (void) | 481 optimize_mode_switching (void) |
434 { | 482 { |
435 rtx insn; | |
436 int e; | 483 int e; |
437 basic_block bb; | 484 basic_block bb; |
438 int need_commit = 0; | 485 bool need_commit = false; |
439 sbitmap *kill; | |
440 struct edge_list *edge_list; | |
441 static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING; | 486 static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING; |
442 #define N_ENTITIES ARRAY_SIZE (num_modes) | 487 #define N_ENTITIES ARRAY_SIZE (num_modes) |
443 int entity_map[N_ENTITIES]; | 488 int entity_map[N_ENTITIES]; |
444 struct bb_info *bb_info[N_ENTITIES]; | 489 struct bb_info *bb_info[N_ENTITIES]; |
445 int i, j; | 490 int i, j; |
446 int n_entities; | 491 int n_entities = 0; |
447 int max_num_modes = 0; | 492 int max_num_modes = 0; |
448 bool emited ATTRIBUTE_UNUSED = false; | 493 bool emitted ATTRIBUTE_UNUSED = false; |
449 basic_block post_entry ATTRIBUTE_UNUSED, pre_exit ATTRIBUTE_UNUSED; | 494 basic_block post_entry = 0; |
450 | 495 basic_block pre_exit = 0; |
451 for (e = N_ENTITIES - 1, n_entities = 0; e >= 0; e--) | 496 struct edge_list *edge_list = 0; |
497 | |
498 /* These bitmaps are used for the LCM algorithm. */ | |
499 sbitmap *kill, *del, *insert, *antic, *transp, *comp; | |
500 sbitmap *avin, *avout; | |
501 | |
502 for (e = N_ENTITIES - 1; e >= 0; e--) | |
452 if (OPTIMIZE_MODE_SWITCHING (e)) | 503 if (OPTIMIZE_MODE_SWITCHING (e)) |
453 { | 504 { |
454 int entry_exit_extra = 0; | 505 int entry_exit_extra = 0; |
455 | 506 |
456 /* Create the list of segments within each basic block. | 507 /* Create the list of segments within each basic block. |
457 If NORMAL_MODE is defined, allow for two extra | 508 If NORMAL_MODE is defined, allow for two extra |
458 blocks split from the entry and exit block. */ | 509 blocks split from the entry and exit block. */ |
459 #if defined (MODE_ENTRY) && defined (MODE_EXIT) | 510 if (targetm.mode_switching.entry && targetm.mode_switching.exit) |
460 entry_exit_extra = 3; | 511 entry_exit_extra = 3; |
461 #endif | 512 |
462 bb_info[n_entities] | 513 bb_info[n_entities] |
463 = XCNEWVEC (struct bb_info, last_basic_block + entry_exit_extra); | 514 = XCNEWVEC (struct bb_info, |
515 last_basic_block_for_fn (cfun) + entry_exit_extra); | |
464 entity_map[n_entities++] = e; | 516 entity_map[n_entities++] = e; |
465 if (num_modes[e] > max_num_modes) | 517 if (num_modes[e] > max_num_modes) |
466 max_num_modes = num_modes[e]; | 518 max_num_modes = num_modes[e]; |
467 } | 519 } |
468 | 520 |
469 if (! n_entities) | 521 if (! n_entities) |
470 return 0; | 522 return 0; |
471 | 523 |
472 #if defined (MODE_ENTRY) && defined (MODE_EXIT) | 524 /* Make sure if MODE_ENTRY is defined MODE_EXIT is defined. */ |
473 /* Split the edge from the entry block, so that we can note that | 525 gcc_assert ((targetm.mode_switching.entry && targetm.mode_switching.exit) |
474 there NORMAL_MODE is supplied. */ | 526 || (!targetm.mode_switching.entry |
475 post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR)); | 527 && !targetm.mode_switching.exit)); |
476 pre_exit = create_pre_exit (n_entities, entity_map, num_modes); | 528 |
477 #endif | 529 if (targetm.mode_switching.entry && targetm.mode_switching.exit) |
530 { | |
531 /* Split the edge from the entry block, so that we can note that | |
532 there NORMAL_MODE is supplied. */ | |
533 post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))); | |
534 pre_exit = create_pre_exit (n_entities, entity_map, num_modes); | |
535 } | |
478 | 536 |
479 df_analyze (); | 537 df_analyze (); |
480 | 538 |
481 /* Create the bitmap vectors. */ | 539 /* Create the bitmap vectors. */ |
482 | 540 antic = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), |
483 antic = sbitmap_vector_alloc (last_basic_block, n_entities); | 541 n_entities * max_num_modes); |
484 transp = sbitmap_vector_alloc (last_basic_block, n_entities); | 542 transp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), |
485 comp = sbitmap_vector_alloc (last_basic_block, n_entities); | 543 n_entities * max_num_modes); |
486 | 544 comp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), |
487 sbitmap_vector_ones (transp, last_basic_block); | 545 n_entities * max_num_modes); |
546 avin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), | |
547 n_entities * max_num_modes); | |
548 avout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), | |
549 n_entities * max_num_modes); | |
550 kill = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), | |
551 n_entities * max_num_modes); | |
552 | |
553 bitmap_vector_ones (transp, last_basic_block_for_fn (cfun)); | |
554 bitmap_vector_clear (antic, last_basic_block_for_fn (cfun)); | |
555 bitmap_vector_clear (comp, last_basic_block_for_fn (cfun)); | |
488 | 556 |
489 for (j = n_entities - 1; j >= 0; j--) | 557 for (j = n_entities - 1; j >= 0; j--) |
490 { | 558 { |
491 int e = entity_map[j]; | 559 int e = entity_map[j]; |
492 int no_mode = num_modes[e]; | 560 int no_mode = num_modes[e]; |
493 struct bb_info *info = bb_info[j]; | 561 struct bb_info *info = bb_info[j]; |
562 rtx_insn *insn; | |
494 | 563 |
495 /* Determine what the first use (if any) need for a mode of entity E is. | 564 /* Determine what the first use (if any) need for a mode of entity E is. |
496 This will be the mode that is anticipatable for this block. | 565 This will be the mode that is anticipatable for this block. |
497 Also compute the initial transparency settings. */ | 566 Also compute the initial transparency settings. */ |
498 FOR_EACH_BB (bb) | 567 FOR_EACH_BB_FN (bb, cfun) |
499 { | 568 { |
500 struct seginfo *ptr; | 569 struct seginfo *ptr; |
501 int last_mode = no_mode; | 570 int last_mode = no_mode; |
571 bool any_set_required = false; | |
502 HARD_REG_SET live_now; | 572 HARD_REG_SET live_now; |
573 | |
574 info[bb->index].mode_out = info[bb->index].mode_in = no_mode; | |
503 | 575 |
504 REG_SET_TO_HARD_REG_SET (live_now, df_get_live_in (bb)); | 576 REG_SET_TO_HARD_REG_SET (live_now, df_get_live_in (bb)); |
505 | 577 |
506 /* Pretend the mode is clobbered across abnormal edges. */ | 578 /* Pretend the mode is clobbered across abnormal edges. */ |
507 { | 579 { |
508 edge_iterator ei; | 580 edge_iterator ei; |
509 edge e; | 581 edge eg; |
510 FOR_EACH_EDGE (e, ei, bb->preds) | 582 FOR_EACH_EDGE (eg, ei, bb->preds) |
511 if (e->flags & EDGE_COMPLEX) | 583 if (eg->flags & EDGE_COMPLEX) |
512 break; | 584 break; |
513 if (e) | 585 if (eg) |
514 { | 586 { |
515 ptr = new_seginfo (no_mode, BB_HEAD (bb), bb->index, live_now); | 587 rtx_insn *ins_pos = BB_HEAD (bb); |
588 if (LABEL_P (ins_pos)) | |
589 ins_pos = NEXT_INSN (ins_pos); | |
590 gcc_assert (NOTE_INSN_BASIC_BLOCK_P (ins_pos)); | |
591 if (ins_pos != BB_END (bb)) | |
592 ins_pos = NEXT_INSN (ins_pos); | |
593 ptr = new_seginfo (no_mode, ins_pos, bb->index, live_now); | |
516 add_seginfo (info + bb->index, ptr); | 594 add_seginfo (info + bb->index, ptr); |
517 RESET_BIT (transp[bb->index], j); | 595 for (i = 0; i < no_mode; i++) |
596 clear_mode_bit (transp[bb->index], j, i); | |
518 } | 597 } |
519 } | 598 } |
520 | 599 |
521 FOR_BB_INSNS (bb, insn) | 600 FOR_BB_INSNS (bb, insn) |
522 { | 601 { |
523 if (INSN_P (insn)) | 602 if (INSN_P (insn)) |
524 { | 603 { |
525 int mode = MODE_NEEDED (e, insn); | 604 int mode = targetm.mode_switching.needed (e, insn); |
526 rtx link; | 605 rtx link; |
527 | 606 |
528 if (mode != no_mode && mode != last_mode) | 607 if (mode != no_mode && mode != last_mode) |
529 { | 608 { |
609 any_set_required = true; | |
530 last_mode = mode; | 610 last_mode = mode; |
531 ptr = new_seginfo (mode, insn, bb->index, live_now); | 611 ptr = new_seginfo (mode, insn, bb->index, live_now); |
532 add_seginfo (info + bb->index, ptr); | 612 add_seginfo (info + bb->index, ptr); |
533 RESET_BIT (transp[bb->index], j); | 613 for (i = 0; i < no_mode; i++) |
614 clear_mode_bit (transp[bb->index], j, i); | |
534 } | 615 } |
535 #ifdef MODE_AFTER | 616 |
536 last_mode = MODE_AFTER (last_mode, insn); | 617 if (targetm.mode_switching.after) |
537 #endif | 618 last_mode = targetm.mode_switching.after (e, last_mode, |
619 insn); | |
620 | |
538 /* Update LIVE_NOW. */ | 621 /* Update LIVE_NOW. */ |
539 for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) | 622 for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) |
540 if (REG_NOTE_KIND (link) == REG_DEAD) | 623 if (REG_NOTE_KIND (link) == REG_DEAD) |
541 reg_dies (XEXP (link, 0), &live_now); | 624 reg_dies (XEXP (link, 0), &live_now); |
542 | 625 |
546 reg_dies (XEXP (link, 0), &live_now); | 629 reg_dies (XEXP (link, 0), &live_now); |
547 } | 630 } |
548 } | 631 } |
549 | 632 |
550 info[bb->index].computing = last_mode; | 633 info[bb->index].computing = last_mode; |
551 /* Check for blocks without ANY mode requirements. */ | 634 /* Check for blocks without ANY mode requirements. |
552 if (last_mode == no_mode) | 635 N.B. because of MODE_AFTER, last_mode might still |
636 be different from no_mode, in which case we need to | |
637 mark the block as nontransparent. */ | |
638 if (!any_set_required) | |
553 { | 639 { |
554 ptr = new_seginfo (no_mode, BB_END (bb), bb->index, live_now); | 640 ptr = new_seginfo (no_mode, BB_END (bb), bb->index, live_now); |
555 add_seginfo (info + bb->index, ptr); | 641 add_seginfo (info + bb->index, ptr); |
642 if (last_mode != no_mode) | |
643 for (i = 0; i < no_mode; i++) | |
644 clear_mode_bit (transp[bb->index], j, i); | |
556 } | 645 } |
557 } | 646 } |
558 #if defined (MODE_ENTRY) && defined (MODE_EXIT) | 647 if (targetm.mode_switching.entry && targetm.mode_switching.exit) |
559 { | 648 { |
560 int mode = MODE_ENTRY (e); | 649 int mode = targetm.mode_switching.entry (e); |
561 | 650 |
562 if (mode != no_mode) | 651 info[post_entry->index].mode_out = |
563 { | 652 info[post_entry->index].mode_in = no_mode; |
564 bb = post_entry; | 653 if (pre_exit) |
565 | 654 { |
566 /* By always making this nontransparent, we save | 655 info[pre_exit->index].mode_out = |
567 an extra check in make_preds_opaque. We also | 656 info[pre_exit->index].mode_in = no_mode; |
568 need this to avoid confusing pre_edge_lcm when | 657 } |
569 antic is cleared but transp and comp are set. */ | 658 |
570 RESET_BIT (transp[bb->index], j); | 659 if (mode != no_mode) |
571 | 660 { |
572 /* Insert a fake computing definition of MODE into entry | 661 bb = post_entry; |
573 blocks which compute no mode. This represents the mode on | 662 |
574 entry. */ | 663 /* By always making this nontransparent, we save |
575 info[bb->index].computing = mode; | 664 an extra check in make_preds_opaque. We also |
576 | 665 need this to avoid confusing pre_edge_lcm when |
577 if (pre_exit) | 666 antic is cleared but transp and comp are set. */ |
578 info[pre_exit->index].seginfo->mode = MODE_EXIT (e); | 667 for (i = 0; i < no_mode; i++) |
579 } | 668 clear_mode_bit (transp[bb->index], j, i); |
580 } | 669 |
581 #endif /* NORMAL_MODE */ | 670 /* Insert a fake computing definition of MODE into entry |
582 } | 671 blocks which compute no mode. This represents the mode on |
583 | 672 entry. */ |
584 kill = sbitmap_vector_alloc (last_basic_block, n_entities); | 673 info[bb->index].computing = mode; |
585 for (i = 0; i < max_num_modes; i++) | 674 |
586 { | 675 if (pre_exit) |
587 int current_mode[N_ENTITIES]; | 676 info[pre_exit->index].seginfo->mode = |
588 sbitmap *del; | 677 targetm.mode_switching.exit (e); |
589 sbitmap *insert; | 678 } |
679 } | |
590 | 680 |
591 /* Set the anticipatable and computing arrays. */ | 681 /* Set the anticipatable and computing arrays. */ |
592 sbitmap_vector_zero (antic, last_basic_block); | 682 for (i = 0; i < no_mode; i++) |
593 sbitmap_vector_zero (comp, last_basic_block); | |
594 for (j = n_entities - 1; j >= 0; j--) | |
595 { | 683 { |
596 int m = current_mode[j] = MODE_PRIORITY_TO_MODE (entity_map[j], i); | 684 int m = targetm.mode_switching.priority (entity_map[j], i); |
597 struct bb_info *info = bb_info[j]; | 685 |
598 | 686 FOR_EACH_BB_FN (bb, cfun) |
599 FOR_EACH_BB (bb) | |
600 { | 687 { |
601 if (info[bb->index].seginfo->mode == m) | 688 if (info[bb->index].seginfo->mode == m) |
602 SET_BIT (antic[bb->index], j); | 689 set_mode_bit (antic[bb->index], j, m); |
603 | 690 |
604 if (info[bb->index].computing == m) | 691 if (info[bb->index].computing == m) |
605 SET_BIT (comp[bb->index], j); | 692 set_mode_bit (comp[bb->index], j, m); |
606 } | 693 } |
607 } | 694 } |
608 | |
609 /* Calculate the optimal locations for the | |
610 placement mode switches to modes with priority I. */ | |
611 | |
612 FOR_EACH_BB (bb) | |
613 sbitmap_not (kill[bb->index], transp[bb->index]); | |
614 edge_list = pre_edge_lcm (n_entities, transp, comp, antic, | |
615 kill, &insert, &del); | |
616 | |
617 for (j = n_entities - 1; j >= 0; j--) | |
618 { | |
619 /* Insert all mode sets that have been inserted by lcm. */ | |
620 int no_mode = num_modes[entity_map[j]]; | |
621 | |
622 /* Wherever we have moved a mode setting upwards in the flow graph, | |
623 the blocks between the new setting site and the now redundant | |
624 computation ceases to be transparent for any lower-priority | |
625 mode of the same entity. First set the aux field of each | |
626 insertion site edge non-transparent, then propagate the new | |
627 non-transparency from the redundant computation upwards till | |
628 we hit an insertion site or an already non-transparent block. */ | |
629 for (e = NUM_EDGES (edge_list) - 1; e >= 0; e--) | |
630 { | |
631 edge eg = INDEX_EDGE (edge_list, e); | |
632 int mode; | |
633 basic_block src_bb; | |
634 HARD_REG_SET live_at_edge; | |
635 rtx mode_set; | |
636 | |
637 eg->aux = 0; | |
638 | |
639 if (! TEST_BIT (insert[e], j)) | |
640 continue; | |
641 | |
642 eg->aux = (void *)1; | |
643 | |
644 mode = current_mode[j]; | |
645 src_bb = eg->src; | |
646 | |
647 REG_SET_TO_HARD_REG_SET (live_at_edge, df_get_live_out (src_bb)); | |
648 | |
649 start_sequence (); | |
650 EMIT_MODE_SET (entity_map[j], mode, live_at_edge); | |
651 mode_set = get_insns (); | |
652 end_sequence (); | |
653 | |
654 /* Do not bother to insert empty sequence. */ | |
655 if (mode_set == NULL_RTX) | |
656 continue; | |
657 | |
658 /* We should not get an abnormal edge here. */ | |
659 gcc_assert (! (eg->flags & EDGE_ABNORMAL)); | |
660 | |
661 need_commit = 1; | |
662 insert_insn_on_edge (mode_set, eg); | |
663 } | |
664 | |
665 FOR_EACH_BB_REVERSE (bb) | |
666 if (TEST_BIT (del[bb->index], j)) | |
667 { | |
668 make_preds_opaque (bb, j); | |
669 /* Cancel the 'deleted' mode set. */ | |
670 bb_info[j][bb->index].seginfo->mode = no_mode; | |
671 } | |
672 } | |
673 | |
674 sbitmap_vector_free (del); | |
675 sbitmap_vector_free (insert); | |
676 clear_aux_for_edges (); | |
677 free_edge_list (edge_list); | |
678 } | 695 } |
679 | 696 |
680 /* Now output the remaining mode sets in all the segments. */ | 697 /* Calculate the optimal locations for the |
698 placement mode switches to modes with priority I. */ | |
699 | |
700 FOR_EACH_BB_FN (bb, cfun) | |
701 bitmap_not (kill[bb->index], transp[bb->index]); | |
702 | |
703 edge_list = pre_edge_lcm_avs (n_entities * max_num_modes, transp, comp, antic, | |
704 kill, avin, avout, &insert, &del); | |
705 | |
681 for (j = n_entities - 1; j >= 0; j--) | 706 for (j = n_entities - 1; j >= 0; j--) |
682 { | 707 { |
683 int no_mode = num_modes[entity_map[j]]; | 708 int no_mode = num_modes[entity_map[j]]; |
684 | 709 |
685 FOR_EACH_BB_REVERSE (bb) | 710 /* Insert all mode sets that have been inserted by lcm. */ |
711 | |
712 for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--) | |
713 { | |
714 edge eg = INDEX_EDGE (edge_list, ed); | |
715 | |
716 eg->aux = (void *)(intptr_t)-1; | |
717 | |
718 for (i = 0; i < no_mode; i++) | |
719 { | |
720 int m = targetm.mode_switching.priority (entity_map[j], i); | |
721 if (mode_bit_p (insert[ed], j, m)) | |
722 { | |
723 eg->aux = (void *)(intptr_t)m; | |
724 break; | |
725 } | |
726 } | |
727 } | |
728 | |
729 FOR_EACH_BB_FN (bb, cfun) | |
730 { | |
731 struct bb_info *info = bb_info[j]; | |
732 int last_mode = no_mode; | |
733 | |
734 /* intialize mode in availability for bb. */ | |
735 for (i = 0; i < no_mode; i++) | |
736 if (mode_bit_p (avout[bb->index], j, i)) | |
737 { | |
738 if (last_mode == no_mode) | |
739 last_mode = i; | |
740 if (last_mode != i) | |
741 { | |
742 last_mode = no_mode; | |
743 break; | |
744 } | |
745 } | |
746 info[bb->index].mode_out = last_mode; | |
747 | |
748 /* intialize mode out availability for bb. */ | |
749 last_mode = no_mode; | |
750 for (i = 0; i < no_mode; i++) | |
751 if (mode_bit_p (avin[bb->index], j, i)) | |
752 { | |
753 if (last_mode == no_mode) | |
754 last_mode = i; | |
755 if (last_mode != i) | |
756 { | |
757 last_mode = no_mode; | |
758 break; | |
759 } | |
760 } | |
761 info[bb->index].mode_in = last_mode; | |
762 | |
763 for (i = 0; i < no_mode; i++) | |
764 if (mode_bit_p (del[bb->index], j, i)) | |
765 info[bb->index].seginfo->mode = no_mode; | |
766 } | |
767 | |
768 /* Now output the remaining mode sets in all the segments. */ | |
769 | |
770 /* In case there was no mode inserted. the mode information on the edge | |
771 might not be complete. | |
772 Update mode info on edges and commit pending mode sets. */ | |
773 need_commit |= commit_mode_sets (edge_list, entity_map[j], bb_info[j]); | |
774 | |
775 /* Reset modes for next entity. */ | |
776 clear_aux_for_edges (); | |
777 | |
778 FOR_EACH_BB_FN (bb, cfun) | |
686 { | 779 { |
687 struct seginfo *ptr, *next; | 780 struct seginfo *ptr, *next; |
781 int cur_mode = bb_info[j][bb->index].mode_in; | |
782 | |
688 for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next) | 783 for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next) |
689 { | 784 { |
690 next = ptr->next; | 785 next = ptr->next; |
691 if (ptr->mode != no_mode) | 786 if (ptr->mode != no_mode) |
692 { | 787 { |
693 rtx mode_set; | 788 rtx_insn *mode_set; |
694 | 789 |
790 rtl_profile_for_bb (bb); | |
695 start_sequence (); | 791 start_sequence (); |
696 EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live); | 792 |
793 targetm.mode_switching.emit (entity_map[j], ptr->mode, | |
794 cur_mode, ptr->regs_live); | |
697 mode_set = get_insns (); | 795 mode_set = get_insns (); |
698 end_sequence (); | 796 end_sequence (); |
797 | |
798 /* modes kill each other inside a basic block. */ | |
799 cur_mode = ptr->mode; | |
699 | 800 |
700 /* Insert MODE_SET only if it is nonempty. */ | 801 /* Insert MODE_SET only if it is nonempty. */ |
701 if (mode_set != NULL_RTX) | 802 if (mode_set != NULL_RTX) |
702 { | 803 { |
703 emited = true; | 804 emitted = true; |
704 if (NOTE_INSN_BASIC_BLOCK_P (ptr->insn_ptr)) | 805 if (NOTE_INSN_BASIC_BLOCK_P (ptr->insn_ptr)) |
705 emit_insn_after (mode_set, ptr->insn_ptr); | 806 /* We need to emit the insns in a FIFO-like manner, |
807 i.e. the first to be emitted at our insertion | |
808 point ends up first in the instruction steam. | |
809 Because we made sure that NOTE_INSN_BASIC_BLOCK is | |
810 only used for initially empty basic blocks, we | |
811 can achieve this by appending at the end of | |
812 the block. */ | |
813 emit_insn_after | |
814 (mode_set, BB_END (NOTE_BASIC_BLOCK (ptr->insn_ptr))); | |
706 else | 815 else |
707 emit_insn_before (mode_set, ptr->insn_ptr); | 816 emit_insn_before (mode_set, ptr->insn_ptr); |
708 } | 817 } |
818 | |
819 default_rtl_profile (); | |
709 } | 820 } |
710 | 821 |
711 free (ptr); | 822 free (ptr); |
712 } | 823 } |
713 } | 824 } |
714 | 825 |
715 free (bb_info[j]); | 826 free (bb_info[j]); |
716 } | 827 } |
717 | 828 |
829 free_edge_list (edge_list); | |
830 | |
718 /* Finished. Free up all the things we've allocated. */ | 831 /* Finished. Free up all the things we've allocated. */ |
832 sbitmap_vector_free (del); | |
833 sbitmap_vector_free (insert); | |
719 sbitmap_vector_free (kill); | 834 sbitmap_vector_free (kill); |
720 sbitmap_vector_free (antic); | 835 sbitmap_vector_free (antic); |
721 sbitmap_vector_free (transp); | 836 sbitmap_vector_free (transp); |
722 sbitmap_vector_free (comp); | 837 sbitmap_vector_free (comp); |
838 sbitmap_vector_free (avin); | |
839 sbitmap_vector_free (avout); | |
723 | 840 |
724 if (need_commit) | 841 if (need_commit) |
725 commit_edge_insertions (); | 842 commit_edge_insertions (); |
726 | 843 |
727 #if defined (MODE_ENTRY) && defined (MODE_EXIT) | 844 if (targetm.mode_switching.entry && targetm.mode_switching.exit) |
728 cleanup_cfg (CLEANUP_NO_INSN_DEL); | 845 cleanup_cfg (CLEANUP_NO_INSN_DEL); |
729 #else | 846 else if (!need_commit && !emitted) |
730 if (!need_commit && !emited) | |
731 return 0; | 847 return 0; |
732 #endif | |
733 | 848 |
734 return 1; | 849 return 1; |
735 } | 850 } |
736 | 851 |
737 #endif /* OPTIMIZE_MODE_SWITCHING */ | 852 #endif /* OPTIMIZE_MODE_SWITCHING */ |
738 | 853 |
739 static bool | 854 namespace { |
740 gate_mode_switching (void) | 855 |
741 { | 856 const pass_data pass_data_mode_switching = |
857 { | |
858 RTL_PASS, /* type */ | |
859 "mode_sw", /* name */ | |
860 OPTGROUP_NONE, /* optinfo_flags */ | |
861 TV_MODE_SWITCH, /* tv_id */ | |
862 0, /* properties_required */ | |
863 0, /* properties_provided */ | |
864 0, /* properties_destroyed */ | |
865 0, /* todo_flags_start */ | |
866 TODO_df_finish, /* todo_flags_finish */ | |
867 }; | |
868 | |
869 class pass_mode_switching : public rtl_opt_pass | |
870 { | |
871 public: | |
872 pass_mode_switching (gcc::context *ctxt) | |
873 : rtl_opt_pass (pass_data_mode_switching, ctxt) | |
874 {} | |
875 | |
876 /* opt_pass methods: */ | |
877 /* The epiphany backend creates a second instance of this pass, so we need | |
878 a clone method. */ | |
879 opt_pass * clone () { return new pass_mode_switching (m_ctxt); } | |
880 virtual bool gate (function *) | |
881 { | |
742 #ifdef OPTIMIZE_MODE_SWITCHING | 882 #ifdef OPTIMIZE_MODE_SWITCHING |
743 return true; | 883 return true; |
744 #else | 884 #else |
745 return false; | 885 return false; |
746 #endif | 886 #endif |
887 } | |
888 | |
889 virtual unsigned int execute (function *) | |
890 { | |
891 #ifdef OPTIMIZE_MODE_SWITCHING | |
892 optimize_mode_switching (); | |
893 #endif /* OPTIMIZE_MODE_SWITCHING */ | |
894 return 0; | |
895 } | |
896 | |
897 }; // class pass_mode_switching | |
898 | |
899 } // anon namespace | |
900 | |
901 rtl_opt_pass * | |
902 make_pass_mode_switching (gcc::context *ctxt) | |
903 { | |
904 return new pass_mode_switching (ctxt); | |
747 } | 905 } |
748 | |
749 static unsigned int | |
750 rest_of_handle_mode_switching (void) | |
751 { | |
752 #ifdef OPTIMIZE_MODE_SWITCHING | |
753 optimize_mode_switching (); | |
754 #endif /* OPTIMIZE_MODE_SWITCHING */ | |
755 return 0; | |
756 } | |
757 | |
758 | |
759 struct rtl_opt_pass pass_mode_switching = | |
760 { | |
761 { | |
762 RTL_PASS, | |
763 "mode_sw", /* name */ | |
764 gate_mode_switching, /* gate */ | |
765 rest_of_handle_mode_switching, /* execute */ | |
766 NULL, /* sub */ | |
767 NULL, /* next */ | |
768 0, /* static_pass_number */ | |
769 TV_MODE_SWITCH, /* tv_id */ | |
770 0, /* properties_required */ | |
771 0, /* properties_provided */ | |
772 0, /* properties_destroyed */ | |
773 0, /* todo_flags_start */ | |
774 TODO_df_finish | TODO_verify_rtl_sharing | | |
775 TODO_dump_func /* todo_flags_finish */ | |
776 } | |
777 }; |