Mercurial > hg > CbC > CbC_gcc
annotate gcc/mode-switching.c @ 56:3c8a44c06a95
Added tag gcc-4.4.5 for changeset 77e2b8dfacca
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:41:23 +0900 |
parents | 77e2b8dfacca |
children | b7f97abdc517 |
rev | line source |
---|---|
0 | 1 /* CPU mode switching |
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, | |
3 2009 Free Software Foundation, Inc. | |
4 | |
5 This file is part of GCC. | |
6 | |
7 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 | |
9 Software Foundation; either version 3, or (at your option) any later | |
10 version. | |
11 | |
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GCC; see the file COPYING3. If not see | |
19 <http://www.gnu.org/licenses/>. */ | |
20 | |
21 #include "config.h" | |
22 #include "system.h" | |
23 #include "coretypes.h" | |
24 #include "tm.h" | |
25 #include "rtl.h" | |
26 #include "regs.h" | |
27 #include "hard-reg-set.h" | |
28 #include "flags.h" | |
29 #include "real.h" | |
30 #include "insn-config.h" | |
31 #include "recog.h" | |
32 #include "basic-block.h" | |
33 #include "output.h" | |
34 #include "tm_p.h" | |
35 #include "function.h" | |
36 #include "tree-pass.h" | |
37 #include "timevar.h" | |
38 #include "df.h" | |
39 | |
40 /* We want target macros for the mode switching code to be able to refer | |
41 to instruction attribute values. */ | |
42 #include "insn-attr.h" | |
43 | |
44 #ifdef OPTIMIZE_MODE_SWITCHING | |
45 | |
46 /* The algorithm for setting the modes consists of scanning the insn list | |
47 and finding all the insns which require a specific mode. Each insn gets | |
48 a unique struct seginfo element. These structures are inserted into a list | |
49 for each basic block. For each entity, there is an array of bb_info over | |
50 the flow graph basic blocks (local var 'bb_info'), and contains a list | |
51 of all insns within that basic block, in the order they are encountered. | |
52 | |
53 For each entity, any basic block WITHOUT any insns requiring a specific | |
54 mode are given a single entry, without a mode. (Each basic block | |
55 in the flow graph must have at least one entry in the segment table.) | |
56 | |
57 The LCM algorithm is then run over the flow graph to determine where to | |
58 place the sets to the highest-priority value in respect of first the first | |
59 insn in any one block. Any adjustments required to the transparency | |
60 vectors are made, then the next iteration starts for the next-lower | |
61 priority mode, till for each entity all modes are exhausted. | |
62 | |
63 More details are located in the code for optimize_mode_switching(). */ | |
64 | |
65 /* This structure contains the information for each insn which requires | |
66 either single or double mode to be set. | |
67 MODE is the mode this insn must be executed in. | |
68 INSN_PTR is the insn to be executed (may be the note that marks the | |
69 beginning of a basic block). | |
70 BBNUM is the flow graph basic block this insn occurs in. | |
71 NEXT is the next insn in the same basic block. */ | |
72 struct seginfo | |
73 { | |
74 int mode; | |
75 rtx insn_ptr; | |
76 int bbnum; | |
77 struct seginfo *next; | |
78 HARD_REG_SET regs_live; | |
79 }; | |
80 | |
81 struct bb_info | |
82 { | |
83 struct seginfo *seginfo; | |
84 int computing; | |
85 }; | |
86 | |
87 /* These bitmaps are used for the LCM algorithm. */ | |
88 | |
89 static sbitmap *antic; | |
90 static sbitmap *transp; | |
91 static sbitmap *comp; | |
92 | |
93 static struct seginfo * new_seginfo (int, rtx, int, HARD_REG_SET); | |
94 static void add_seginfo (struct bb_info *, struct seginfo *); | |
95 static void reg_dies (rtx, HARD_REG_SET *); | |
96 static void reg_becomes_live (rtx, const_rtx, void *); | |
97 static void make_preds_opaque (basic_block, int); | |
98 | |
99 | |
100 /* This function will allocate a new BBINFO structure, initialized | |
101 with the MODE, INSN, and basic block BB parameters. */ | |
102 | |
103 static struct seginfo * | |
104 new_seginfo (int mode, rtx insn, int bb, HARD_REG_SET regs_live) | |
105 { | |
106 struct seginfo *ptr; | |
107 ptr = XNEW (struct seginfo); | |
108 ptr->mode = mode; | |
109 ptr->insn_ptr = insn; | |
110 ptr->bbnum = bb; | |
111 ptr->next = NULL; | |
112 COPY_HARD_REG_SET (ptr->regs_live, regs_live); | |
113 return ptr; | |
114 } | |
115 | |
116 /* Add a seginfo element to the end of a list. | |
117 HEAD is a pointer to the list beginning. | |
118 INFO is the structure to be linked in. */ | |
119 | |
120 static void | |
121 add_seginfo (struct bb_info *head, struct seginfo *info) | |
122 { | |
123 struct seginfo *ptr; | |
124 | |
125 if (head->seginfo == NULL) | |
126 head->seginfo = info; | |
127 else | |
128 { | |
129 ptr = head->seginfo; | |
130 while (ptr->next != NULL) | |
131 ptr = ptr->next; | |
132 ptr->next = info; | |
133 } | |
134 } | |
135 | |
136 /* Make all predecessors of basic block B opaque, recursively, till we hit | |
137 some that are already non-transparent, or an edge where aux is set; that | |
138 denotes that a mode set is to be done on that edge. | |
139 J is the bit number in the bitmaps that corresponds to the entity that | |
140 we are currently handling mode-switching for. */ | |
141 | |
142 static void | |
143 make_preds_opaque (basic_block b, int j) | |
144 { | |
145 edge e; | |
146 edge_iterator ei; | |
147 | |
148 FOR_EACH_EDGE (e, ei, b->preds) | |
149 { | |
150 basic_block pb = e->src; | |
151 | |
152 if (e->aux || ! TEST_BIT (transp[pb->index], j)) | |
153 continue; | |
154 | |
155 RESET_BIT (transp[pb->index], j); | |
156 make_preds_opaque (pb, j); | |
157 } | |
158 } | |
159 | |
160 /* Record in LIVE that register REG died. */ | |
161 | |
162 static void | |
163 reg_dies (rtx reg, HARD_REG_SET *live) | |
164 { | |
165 int regno; | |
166 | |
167 if (!REG_P (reg)) | |
168 return; | |
169 | |
170 regno = REGNO (reg); | |
171 if (regno < FIRST_PSEUDO_REGISTER) | |
172 remove_from_hard_reg_set (live, GET_MODE (reg), regno); | |
173 } | |
174 | |
175 /* Record in LIVE that register REG became live. | |
176 This is called via note_stores. */ | |
177 | |
178 static void | |
179 reg_becomes_live (rtx reg, const_rtx setter ATTRIBUTE_UNUSED, void *live) | |
180 { | |
181 int regno; | |
182 | |
183 if (GET_CODE (reg) == SUBREG) | |
184 reg = SUBREG_REG (reg); | |
185 | |
186 if (!REG_P (reg)) | |
187 return; | |
188 | |
189 regno = REGNO (reg); | |
190 if (regno < FIRST_PSEUDO_REGISTER) | |
191 add_to_hard_reg_set ((HARD_REG_SET *) live, GET_MODE (reg), regno); | |
192 } | |
193 | |
194 /* Make sure if MODE_ENTRY is defined the MODE_EXIT is defined | |
195 and vice versa. */ | |
196 #if defined (MODE_ENTRY) != defined (MODE_EXIT) | |
197 #error "Both MODE_ENTRY and MODE_EXIT must be defined" | |
198 #endif | |
199 | |
200 #if defined (MODE_ENTRY) && defined (MODE_EXIT) | |
201 /* Split the fallthrough edge to the exit block, so that we can note | |
202 that there NORMAL_MODE is required. Return the new block if it's | |
203 inserted before the exit block. Otherwise return null. */ | |
204 | |
205 static basic_block | |
206 create_pre_exit (int n_entities, int *entity_map, const int *num_modes) | |
207 { | |
208 edge eg; | |
209 edge_iterator ei; | |
210 basic_block pre_exit; | |
211 | |
212 /* The only non-call predecessor at this stage is a block with a | |
213 fallthrough edge; there can be at most one, but there could be | |
214 none at all, e.g. when exit is called. */ | |
215 pre_exit = 0; | |
216 FOR_EACH_EDGE (eg, ei, EXIT_BLOCK_PTR->preds) | |
217 if (eg->flags & EDGE_FALLTHRU) | |
218 { | |
219 basic_block src_bb = eg->src; | |
220 rtx last_insn, ret_reg; | |
221 | |
222 gcc_assert (!pre_exit); | |
223 /* If this function returns a value at the end, we have to | |
224 insert the final mode switch before the return value copy | |
225 to its hard register. */ | |
226 if (EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 1 | |
227 && NONJUMP_INSN_P ((last_insn = BB_END (src_bb))) | |
228 && GET_CODE (PATTERN (last_insn)) == USE | |
229 && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG) | |
230 { | |
231 int ret_start = REGNO (ret_reg); | |
232 int nregs = hard_regno_nregs[ret_start][GET_MODE (ret_reg)]; | |
233 int ret_end = ret_start + nregs; | |
234 int short_block = 0; | |
235 int maybe_builtin_apply = 0; | |
236 int forced_late_switch = 0; | |
237 rtx before_return_copy; | |
238 | |
239 do | |
240 { | |
241 rtx return_copy = PREV_INSN (last_insn); | |
242 rtx return_copy_pat, copy_reg; | |
243 int copy_start, copy_num; | |
244 int j; | |
245 | |
246 if (INSN_P (return_copy)) | |
247 { | |
248 /* When using SJLJ exceptions, the call to the | |
249 unregister function is inserted between the | |
250 clobber of the return value and the copy. | |
251 We do not want to split the block before this | |
252 or any other call; if we have not found the | |
253 copy yet, the copy must have been deleted. */ | |
254 if (CALL_P (return_copy)) | |
255 { | |
256 short_block = 1; | |
257 break; | |
258 } | |
259 return_copy_pat = PATTERN (return_copy); | |
260 switch (GET_CODE (return_copy_pat)) | |
261 { | |
262 case USE: | |
263 /* Skip __builtin_apply pattern. */ | |
264 if (GET_CODE (XEXP (return_copy_pat, 0)) == REG | |
265 && (FUNCTION_VALUE_REGNO_P | |
266 (REGNO (XEXP (return_copy_pat, 0))))) | |
267 { | |
268 maybe_builtin_apply = 1; | |
269 last_insn = return_copy; | |
270 continue; | |
271 } | |
272 break; | |
273 | |
274 case ASM_OPERANDS: | |
275 /* Skip barrier insns. */ | |
276 if (!MEM_VOLATILE_P (return_copy_pat)) | |
277 break; | |
278 | |
279 /* Fall through. */ | |
280 | |
281 case ASM_INPUT: | |
282 case UNSPEC_VOLATILE: | |
283 last_insn = return_copy; | |
284 continue; | |
285 | |
286 default: | |
287 break; | |
288 } | |
289 | |
290 /* If the return register is not (in its entirety) | |
291 likely spilled, the return copy might be | |
292 partially or completely optimized away. */ | |
293 return_copy_pat = single_set (return_copy); | |
294 if (!return_copy_pat) | |
295 { | |
296 return_copy_pat = PATTERN (return_copy); | |
297 if (GET_CODE (return_copy_pat) != CLOBBER) | |
298 break; | |
299 else if (!optimize) | |
300 { | |
301 /* This might be (clobber (reg [<result>])) | |
302 when not optimizing. Then check if | |
303 the previous insn is the clobber for | |
304 the return register. */ | |
305 copy_reg = SET_DEST (return_copy_pat); | |
306 if (GET_CODE (copy_reg) == REG | |
307 && !HARD_REGISTER_NUM_P (REGNO (copy_reg))) | |
308 { | |
309 if (INSN_P (PREV_INSN (return_copy))) | |
310 { | |
311 return_copy = PREV_INSN (return_copy); | |
312 return_copy_pat = PATTERN (return_copy); | |
313 if (GET_CODE (return_copy_pat) != CLOBBER) | |
314 break; | |
315 } | |
316 } | |
317 } | |
318 } | |
319 copy_reg = SET_DEST (return_copy_pat); | |
320 if (GET_CODE (copy_reg) == REG) | |
321 copy_start = REGNO (copy_reg); | |
322 else if (GET_CODE (copy_reg) == SUBREG | |
323 && GET_CODE (SUBREG_REG (copy_reg)) == REG) | |
324 copy_start = REGNO (SUBREG_REG (copy_reg)); | |
325 else | |
326 break; | |
327 if (copy_start >= FIRST_PSEUDO_REGISTER) | |
328 break; | |
329 copy_num | |
330 = hard_regno_nregs[copy_start][GET_MODE (copy_reg)]; | |
331 | |
332 /* If the return register is not likely spilled, - as is | |
333 the case for floating point on SH4 - then it might | |
334 be set by an arithmetic operation that needs a | |
335 different mode than the exit block. */ | |
336 for (j = n_entities - 1; j >= 0; j--) | |
337 { | |
338 int e = entity_map[j]; | |
339 int mode = MODE_NEEDED (e, return_copy); | |
340 | |
341 if (mode != num_modes[e] && mode != MODE_EXIT (e)) | |
342 break; | |
343 } | |
344 if (j >= 0) | |
345 { | |
346 /* For the SH4, floating point loads depend on fpscr, | |
347 thus we might need to put the final mode switch | |
348 after the return value copy. That is still OK, | |
349 because a floating point return value does not | |
350 conflict with address reloads. */ | |
351 if (copy_start >= ret_start | |
352 && copy_start + copy_num <= ret_end | |
353 && OBJECT_P (SET_SRC (return_copy_pat))) | |
354 forced_late_switch = 1; | |
355 break; | |
356 } | |
357 | |
358 if (copy_start >= ret_start | |
359 && copy_start + copy_num <= ret_end) | |
360 nregs -= copy_num; | |
361 else if (!maybe_builtin_apply | |
362 || !FUNCTION_VALUE_REGNO_P (copy_start)) | |
363 break; | |
364 last_insn = return_copy; | |
365 } | |
366 /* ??? Exception handling can lead to the return value | |
367 copy being already separated from the return value use, | |
368 as in unwind-dw2.c . | |
369 Similarly, conditionally returning without a value, | |
370 and conditionally using builtin_return can lead to an | |
371 isolated use. */ | |
372 if (return_copy == BB_HEAD (src_bb)) | |
373 { | |
374 short_block = 1; | |
375 break; | |
376 } | |
377 last_insn = return_copy; | |
378 } | |
379 while (nregs); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
380 |
0 | 381 /* If we didn't see a full return value copy, verify that there |
382 is a plausible reason for this. If some, but not all of the | |
383 return register is likely spilled, we can expect that there | |
384 is a copy for the likely spilled part. */ | |
385 gcc_assert (!nregs | |
386 || forced_late_switch | |
387 || short_block | |
388 || !(CLASS_LIKELY_SPILLED_P | |
389 (REGNO_REG_CLASS (ret_start))) | |
390 || (nregs | |
391 != hard_regno_nregs[ret_start][GET_MODE (ret_reg)]) | |
392 /* For multi-hard-register floating point | |
393 values, sometimes the likely-spilled part | |
394 is ordinarily copied first, then the other | |
395 part is set with an arithmetic operation. | |
396 This doesn't actually cause reload | |
397 failures, so let it pass. */ | |
398 || (GET_MODE_CLASS (GET_MODE (ret_reg)) != MODE_INT | |
399 && nregs != 1)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
400 |
0 | 401 if (INSN_P (last_insn)) |
402 { | |
403 before_return_copy | |
404 = emit_note_before (NOTE_INSN_DELETED, last_insn); | |
405 /* Instructions preceding LAST_INSN in the same block might | |
406 require a different mode than MODE_EXIT, so if we might | |
407 have such instructions, keep them in a separate block | |
408 from pre_exit. */ | |
409 if (last_insn != BB_HEAD (src_bb)) | |
410 src_bb = split_block (src_bb, | |
411 PREV_INSN (before_return_copy))->dest; | |
412 } | |
413 else | |
414 before_return_copy = last_insn; | |
415 pre_exit = split_block (src_bb, before_return_copy)->src; | |
416 } | |
417 else | |
418 { | |
419 pre_exit = split_edge (eg); | |
420 } | |
421 } | |
422 | |
423 return pre_exit; | |
424 } | |
425 #endif | |
426 | |
427 /* Find all insns that need a particular mode setting, and insert the | |
428 necessary mode switches. Return true if we did work. */ | |
429 | |
430 static int | |
431 optimize_mode_switching (void) | |
432 { | |
433 rtx insn; | |
434 int e; | |
435 basic_block bb; | |
436 int need_commit = 0; | |
437 sbitmap *kill; | |
438 struct edge_list *edge_list; | |
439 static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING; | |
440 #define N_ENTITIES ARRAY_SIZE (num_modes) | |
441 int entity_map[N_ENTITIES]; | |
442 struct bb_info *bb_info[N_ENTITIES]; | |
443 int i, j; | |
444 int n_entities; | |
445 int max_num_modes = 0; | |
446 bool emited = false; | |
447 basic_block post_entry ATTRIBUTE_UNUSED, pre_exit ATTRIBUTE_UNUSED; | |
448 | |
449 for (e = N_ENTITIES - 1, n_entities = 0; e >= 0; e--) | |
450 if (OPTIMIZE_MODE_SWITCHING (e)) | |
451 { | |
452 int entry_exit_extra = 0; | |
453 | |
454 /* Create the list of segments within each basic block. | |
455 If NORMAL_MODE is defined, allow for two extra | |
456 blocks split from the entry and exit block. */ | |
457 #if defined (MODE_ENTRY) && defined (MODE_EXIT) | |
458 entry_exit_extra = 3; | |
459 #endif | |
460 bb_info[n_entities] | |
461 = XCNEWVEC (struct bb_info, last_basic_block + entry_exit_extra); | |
462 entity_map[n_entities++] = e; | |
463 if (num_modes[e] > max_num_modes) | |
464 max_num_modes = num_modes[e]; | |
465 } | |
466 | |
467 if (! n_entities) | |
468 return 0; | |
469 | |
470 #if defined (MODE_ENTRY) && defined (MODE_EXIT) | |
471 /* Split the edge from the entry block, so that we can note that | |
472 there NORMAL_MODE is supplied. */ | |
473 post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR)); | |
474 pre_exit = create_pre_exit (n_entities, entity_map, num_modes); | |
475 #endif | |
476 | |
477 df_analyze (); | |
478 | |
479 /* Create the bitmap vectors. */ | |
480 | |
481 antic = sbitmap_vector_alloc (last_basic_block, n_entities); | |
482 transp = sbitmap_vector_alloc (last_basic_block, n_entities); | |
483 comp = sbitmap_vector_alloc (last_basic_block, n_entities); | |
484 | |
485 sbitmap_vector_ones (transp, last_basic_block); | |
486 | |
487 for (j = n_entities - 1; j >= 0; j--) | |
488 { | |
489 int e = entity_map[j]; | |
490 int no_mode = num_modes[e]; | |
491 struct bb_info *info = bb_info[j]; | |
492 | |
493 /* Determine what the first use (if any) need for a mode of entity E is. | |
494 This will be the mode that is anticipatable for this block. | |
495 Also compute the initial transparency settings. */ | |
496 FOR_EACH_BB (bb) | |
497 { | |
498 struct seginfo *ptr; | |
499 int last_mode = no_mode; | |
500 HARD_REG_SET live_now; | |
501 | |
502 REG_SET_TO_HARD_REG_SET (live_now, df_get_live_in (bb)); | |
503 | |
504 /* Pretend the mode is clobbered across abnormal edges. */ | |
505 { | |
506 edge_iterator ei; | |
507 edge e; | |
508 FOR_EACH_EDGE (e, ei, bb->preds) | |
509 if (e->flags & EDGE_COMPLEX) | |
510 break; | |
511 if (e) | |
512 { | |
513 ptr = new_seginfo (no_mode, BB_HEAD (bb), bb->index, live_now); | |
514 add_seginfo (info + bb->index, ptr); | |
515 RESET_BIT (transp[bb->index], j); | |
516 } | |
517 } | |
518 | |
519 for (insn = BB_HEAD (bb); | |
520 insn != NULL && insn != NEXT_INSN (BB_END (bb)); | |
521 insn = NEXT_INSN (insn)) | |
522 { | |
523 if (INSN_P (insn)) | |
524 { | |
525 int mode = MODE_NEEDED (e, insn); | |
526 rtx link; | |
527 | |
528 if (mode != no_mode && mode != last_mode) | |
529 { | |
530 last_mode = mode; | |
531 ptr = new_seginfo (mode, insn, bb->index, live_now); | |
532 add_seginfo (info + bb->index, ptr); | |
533 RESET_BIT (transp[bb->index], j); | |
534 } | |
535 #ifdef MODE_AFTER | |
536 last_mode = MODE_AFTER (last_mode, insn); | |
537 #endif | |
538 /* Update LIVE_NOW. */ | |
539 for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) | |
540 if (REG_NOTE_KIND (link) == REG_DEAD) | |
541 reg_dies (XEXP (link, 0), &live_now); | |
542 | |
543 note_stores (PATTERN (insn), reg_becomes_live, &live_now); | |
544 for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) | |
545 if (REG_NOTE_KIND (link) == REG_UNUSED) | |
546 reg_dies (XEXP (link, 0), &live_now); | |
547 } | |
548 } | |
549 | |
550 info[bb->index].computing = last_mode; | |
551 /* Check for blocks without ANY mode requirements. */ | |
552 if (last_mode == no_mode) | |
553 { | |
554 ptr = new_seginfo (no_mode, BB_END (bb), bb->index, live_now); | |
555 add_seginfo (info + bb->index, ptr); | |
556 } | |
557 } | |
558 #if defined (MODE_ENTRY) && defined (MODE_EXIT) | |
559 { | |
560 int mode = MODE_ENTRY (e); | |
561 | |
562 if (mode != no_mode) | |
563 { | |
564 bb = post_entry; | |
565 | |
566 /* By always making this nontransparent, we save | |
567 an extra check in make_preds_opaque. We also | |
568 need this to avoid confusing pre_edge_lcm when | |
569 antic is cleared but transp and comp are set. */ | |
570 RESET_BIT (transp[bb->index], j); | |
571 | |
572 /* Insert a fake computing definition of MODE into entry | |
573 blocks which compute no mode. This represents the mode on | |
574 entry. */ | |
575 info[bb->index].computing = mode; | |
576 | |
577 if (pre_exit) | |
578 info[pre_exit->index].seginfo->mode = MODE_EXIT (e); | |
579 } | |
580 } | |
581 #endif /* NORMAL_MODE */ | |
582 } | |
583 | |
584 kill = sbitmap_vector_alloc (last_basic_block, n_entities); | |
585 for (i = 0; i < max_num_modes; i++) | |
586 { | |
587 int current_mode[N_ENTITIES]; | |
588 sbitmap *del; | |
589 sbitmap *insert; | |
590 | |
591 /* Set the anticipatable and computing arrays. */ | |
592 sbitmap_vector_zero (antic, last_basic_block); | |
593 sbitmap_vector_zero (comp, last_basic_block); | |
594 for (j = n_entities - 1; j >= 0; j--) | |
595 { | |
596 int m = current_mode[j] = MODE_PRIORITY_TO_MODE (entity_map[j], i); | |
597 struct bb_info *info = bb_info[j]; | |
598 | |
599 FOR_EACH_BB (bb) | |
600 { | |
601 if (info[bb->index].seginfo->mode == m) | |
602 SET_BIT (antic[bb->index], j); | |
603 | |
604 if (info[bb->index].computing == m) | |
605 SET_BIT (comp[bb->index], j); | |
606 } | |
607 } | |
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 } | |
679 | |
680 /* Now output the remaining mode sets in all the segments. */ | |
681 for (j = n_entities - 1; j >= 0; j--) | |
682 { | |
683 int no_mode = num_modes[entity_map[j]]; | |
684 | |
685 FOR_EACH_BB_REVERSE (bb) | |
686 { | |
687 struct seginfo *ptr, *next; | |
688 for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next) | |
689 { | |
690 next = ptr->next; | |
691 if (ptr->mode != no_mode) | |
692 { | |
693 rtx mode_set; | |
694 | |
695 start_sequence (); | |
696 EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live); | |
697 mode_set = get_insns (); | |
698 end_sequence (); | |
699 | |
700 /* Insert MODE_SET only if it is nonempty. */ | |
701 if (mode_set != NULL_RTX) | |
702 { | |
703 emited = true; | |
704 if (NOTE_INSN_BASIC_BLOCK_P (ptr->insn_ptr)) | |
705 emit_insn_after (mode_set, ptr->insn_ptr); | |
706 else | |
707 emit_insn_before (mode_set, ptr->insn_ptr); | |
708 } | |
709 } | |
710 | |
711 free (ptr); | |
712 } | |
713 } | |
714 | |
715 free (bb_info[j]); | |
716 } | |
717 | |
718 /* Finished. Free up all the things we've allocated. */ | |
719 sbitmap_vector_free (kill); | |
720 sbitmap_vector_free (antic); | |
721 sbitmap_vector_free (transp); | |
722 sbitmap_vector_free (comp); | |
723 | |
724 if (need_commit) | |
725 commit_edge_insertions (); | |
726 | |
727 #if defined (MODE_ENTRY) && defined (MODE_EXIT) | |
728 cleanup_cfg (CLEANUP_NO_INSN_DEL); | |
729 #else | |
730 if (!need_commit && !emited) | |
731 return 0; | |
732 #endif | |
733 | |
734 return 1; | |
735 } | |
736 | |
737 #endif /* OPTIMIZE_MODE_SWITCHING */ | |
738 | |
739 static bool | |
740 gate_mode_switching (void) | |
741 { | |
742 #ifdef OPTIMIZE_MODE_SWITCHING | |
743 return true; | |
744 #else | |
745 return false; | |
746 #endif | |
747 } | |
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 }; |