Line data Source code
1 : /* CPU mode switching
2 : Copyright (C) 1998-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : #include "config.h"
21 : #include "system.h"
22 : #include "coretypes.h"
23 : #include "backend.h"
24 : #include "target.h"
25 : #include "rtl.h"
26 : #include "cfghooks.h"
27 : #include "df.h"
28 : #include "memmodel.h"
29 : #include "tm_p.h"
30 : #include "regs.h"
31 : #include "emit-rtl.h"
32 : #include "cfgrtl.h"
33 : #include "cfganal.h"
34 : #include "lcm.h"
35 : #include "cfgcleanup.h"
36 : #include "tree-pass.h"
37 : #include "cfgbuild.h"
38 :
39 : /* We want target macros for the mode switching code to be able to refer
40 : to instruction attribute values. */
41 : #include "insn-attr.h"
42 :
43 : #ifdef OPTIMIZE_MODE_SWITCHING
44 :
45 : /* The algorithm for setting the modes consists of scanning the insn list
46 : and finding all the insns which require a specific mode. Each insn gets
47 : a unique struct seginfo element. These structures are inserted into a list
48 : for each basic block. For each entity, there is an array of bb_info over
49 : the flow graph basic blocks (local var 'bb_info'), which contains a list
50 : of all insns within that basic block, in the order they are encountered.
51 :
52 : For each entity, any basic block WITHOUT any insns requiring a specific
53 : mode are given a single entry without a mode (each basic block in the
54 : flow graph must have at least one entry in the segment table).
55 :
56 : The LCM algorithm is then run over the flow graph to determine where to
57 : place the sets to the highest-priority mode with respect to the first
58 : insn in any one block. Any adjustments required to the transparency
59 : vectors are made, then the next iteration starts for the next-lower
60 : priority mode, till for each entity all modes are exhausted.
61 :
62 : More details can be found in the code of optimize_mode_switching. */
63 :
64 : /* This structure contains the information for each insn which requires
65 : either single or double mode to be set.
66 : MODE is the mode this insn must be executed in.
67 : INSN_PTR is the insn to be executed (may be the note that marks the
68 : beginning of a basic block).
69 : NEXT is the next insn in the same basic block. */
70 : struct seginfo
71 : {
72 : int prev_mode;
73 : int mode;
74 : rtx_insn *insn_ptr;
75 : struct seginfo *next;
76 : HARD_REG_SET regs_live;
77 : };
78 :
79 : struct bb_info
80 : {
81 : struct seginfo *seginfo;
82 : int computing;
83 : int mode_out;
84 : int mode_in;
85 : int single_succ;
86 : };
87 :
88 : /* Clear ode I from entity J in bitmap B. */
89 : #define clear_mode_bit(b, j, i) \
90 : bitmap_clear_bit (b, (j * max_num_modes) + i)
91 :
92 : /* Test mode I from entity J in bitmap B. */
93 : #define mode_bit_p(b, j, i) \
94 : bitmap_bit_p (b, (j * max_num_modes) + i)
95 :
96 : /* Set mode I from entity J in bitmal B. */
97 : #define set_mode_bit(b, j, i) \
98 : bitmap_set_bit (b, (j * max_num_modes) + i)
99 :
100 : /* Emit modes segments from EDGE_LIST associated with entity E.
101 : INFO gives mode availability for each mode. */
102 :
103 : static bool
104 75712 : commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info)
105 : {
106 75712 : bool need_commit = false;
107 :
108 897209 : for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--)
109 : {
110 821497 : edge eg = INDEX_EDGE (edge_list, ed);
111 :
112 821497 : if (eg->aux)
113 : {
114 11606 : int mode = (int) (intptr_t) eg->aux - 1;
115 11606 : HARD_REG_SET live_at_edge;
116 11606 : basic_block src_bb = eg->src;
117 11606 : int cur_mode = info[src_bb->index].mode_out;
118 11606 : rtx_insn *mode_set;
119 :
120 23212 : REG_SET_TO_HARD_REG_SET (live_at_edge, df_get_live_out (src_bb));
121 :
122 11606 : rtl_profile_for_edge (eg);
123 11606 : start_sequence ();
124 :
125 11606 : targetm.mode_switching.emit (e, mode, cur_mode, live_at_edge);
126 :
127 11606 : mode_set = end_sequence ();
128 11606 : default_rtl_profile ();
129 :
130 : /* Do not bother to insert empty sequence. */
131 11606 : if (mode_set == NULL)
132 3394 : continue;
133 :
134 : /* We should not get an abnormal edge here. */
135 8212 : gcc_assert (! (eg->flags & EDGE_ABNORMAL));
136 :
137 8212 : need_commit = true;
138 8212 : insert_insn_on_edge (mode_set, eg);
139 : }
140 : }
141 :
142 75712 : return need_commit;
143 : }
144 :
145 : /* Allocate a new BBINFO structure, initialized with the PREV_MODE, MODE,
146 : INSN, and REGS_LIVE parameters.
147 : INSN may not be a NOTE_INSN_BASIC_BLOCK, unless it is an empty
148 : basic block; that allows us later to insert instructions in a FIFO-like
149 : manner. */
150 :
151 : static struct seginfo *
152 563819 : new_seginfo (int prev_mode, int mode, rtx_insn *insn,
153 : const HARD_REG_SET ®s_live)
154 : {
155 563819 : struct seginfo *ptr;
156 :
157 563819 : gcc_assert (!NOTE_INSN_BASIC_BLOCK_P (insn)
158 : || insn == BB_END (NOTE_BASIC_BLOCK (insn)));
159 563819 : ptr = XNEW (struct seginfo);
160 563819 : ptr->prev_mode = prev_mode;
161 563819 : ptr->mode = mode;
162 563819 : ptr->insn_ptr = insn;
163 563819 : ptr->next = NULL;
164 563819 : ptr->regs_live = regs_live;
165 563819 : return ptr;
166 : }
167 :
168 : /* Add a seginfo element to the end of a list.
169 : TAIL is a pointer to the list's null terminator.
170 : INFO is the structure to be linked in. */
171 :
172 : static void
173 563819 : add_seginfo (struct seginfo ***tail_ptr, struct seginfo *info)
174 : {
175 563819 : **tail_ptr = info;
176 563819 : *tail_ptr = &info->next;
177 0 : }
178 :
179 : /* Record in LIVE that register REG died. */
180 :
181 : static void
182 1605815 : reg_dies (rtx reg, HARD_REG_SET *live)
183 : {
184 1605815 : int regno;
185 :
186 1605815 : if (!REG_P (reg))
187 : return;
188 :
189 1605815 : regno = REGNO (reg);
190 1605815 : if (regno < FIRST_PSEUDO_REGISTER)
191 1435728 : remove_from_hard_reg_set (live, GET_MODE (reg), regno);
192 : }
193 :
194 : /* Record in LIVE that register REG became live.
195 : This is called via note_stores. */
196 :
197 : static void
198 2798965 : reg_becomes_live (rtx reg, const_rtx setter ATTRIBUTE_UNUSED, void *live)
199 : {
200 2798965 : int regno;
201 :
202 2798965 : if (GET_CODE (reg) == SUBREG)
203 27 : reg = SUBREG_REG (reg);
204 :
205 2798965 : if (!REG_P (reg))
206 : return;
207 :
208 2164004 : regno = REGNO (reg);
209 2164004 : if (regno < FIRST_PSEUDO_REGISTER)
210 1978983 : add_to_hard_reg_set ((HARD_REG_SET *) live, GET_MODE (reg), regno);
211 : }
212 :
213 : /* Split the fallthrough edge to the exit block, so that we can note
214 : that there NORMAL_MODE is required. Return the new block if it's
215 : inserted before the exit block. Otherwise return null. */
216 :
217 : static basic_block
218 75696 : create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
219 : {
220 75696 : edge eg;
221 75696 : edge_iterator ei;
222 75696 : basic_block pre_exit;
223 :
224 : /* The only non-call predecessor at this stage is a block with a
225 : fallthrough edge; there can be at most one, but there could be
226 : none at all, e.g. when exit is called. */
227 75696 : pre_exit = 0;
228 151345 : FOR_EACH_EDGE (eg, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
229 75649 : if (eg->flags & EDGE_FALLTHRU)
230 : {
231 74308 : basic_block src_bb = eg->src;
232 74308 : rtx_insn *last_insn;
233 74308 : rtx ret_reg;
234 :
235 74308 : gcc_assert (!pre_exit);
236 : /* If this function returns a value at the end, we have to
237 : insert the final mode switch before the return value copy
238 : to its hard register.
239 :
240 : x86 targets use mode-switching infrastructure to
241 : conditionally insert vzeroupper instruction at the exit
242 : from the function where there is no need to switch the
243 : mode before the return value copy. The vzeroupper insertion
244 : pass runs after reload, so use !reload_completed as a stand-in
245 : for x86 to skip the search for the return value copy insn.
246 :
247 : N.b.: the code below assumes that the return copy insn
248 : immediately precedes its corresponding use insn. This
249 : assumption does not hold after reload, since sched1 pass
250 : can schedule the return copy insn away from its
251 : corresponding use insn. */
252 74308 : if (!reload_completed
253 1108 : && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == 1
254 1095 : && NONJUMP_INSN_P ((last_insn = BB_END (src_bb)))
255 943 : && GET_CODE (PATTERN (last_insn)) == USE
256 75135 : && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG)
257 : {
258 827 : auto_bitmap live;
259 827 : df_simulate_initialize_backwards (src_bb, live);
260 :
261 827 : int ret_start = REGNO (ret_reg);
262 827 : int nregs = REG_NREGS (ret_reg);
263 827 : int ret_end = ret_start + nregs;
264 827 : bool short_block = false;
265 827 : bool multi_reg_return = false;
266 827 : bool forced_late_switch = false;
267 827 : rtx_insn *before_return_copy;
268 :
269 827 : df_simulate_one_insn_backwards (src_bb, last_insn, live);
270 :
271 922 : do
272 : {
273 922 : rtx_insn *return_copy = PREV_INSN (last_insn);
274 922 : rtx return_copy_pat, copy_reg;
275 922 : int copy_start, copy_num;
276 922 : int j;
277 :
278 922 : df_simulate_one_insn_backwards (src_bb, return_copy, live);
279 :
280 922 : if (NONDEBUG_INSN_P (return_copy))
281 : {
282 : /* When using SJLJ exceptions, the call to the
283 : unregister function is inserted between the
284 : clobber of the return value and the copy.
285 : We do not want to split the block before this
286 : or any other call; if we have not found the
287 : copy yet, the copy must have been deleted. */
288 922 : if (CALL_P (return_copy))
289 : {
290 : short_block = true;
291 0 : break;
292 : }
293 922 : return_copy_pat = PATTERN (return_copy);
294 922 : switch (GET_CODE (return_copy_pat))
295 : {
296 0 : case USE:
297 : /* Skip USEs of multiple return registers.
298 : __builtin_apply pattern is also handled here. */
299 0 : if (GET_CODE (XEXP (return_copy_pat, 0)) == REG
300 0 : && (targetm.calls.function_value_regno_p
301 0 : (REGNO (XEXP (return_copy_pat, 0)))))
302 : {
303 0 : multi_reg_return = true;
304 0 : last_insn = return_copy;
305 95 : continue;
306 : }
307 : break;
308 :
309 0 : case ASM_OPERANDS:
310 : /* Skip barrier insns. */
311 0 : if (!MEM_VOLATILE_P (return_copy_pat))
312 : break;
313 :
314 : /* Fall through. */
315 :
316 95 : case ASM_INPUT:
317 95 : case UNSPEC_VOLATILE:
318 95 : last_insn = return_copy;
319 95 : continue;
320 :
321 : default:
322 : break;
323 95 : }
324 :
325 : /* If the return register is not (in its entirety)
326 : likely spilled, the return copy might be
327 : partially or completely optimized away. */
328 827 : return_copy_pat = single_set (return_copy);
329 827 : if (!return_copy_pat)
330 : {
331 0 : return_copy_pat = PATTERN (return_copy);
332 0 : if (GET_CODE (return_copy_pat) != CLOBBER)
333 : break;
334 0 : else if (!optimize)
335 : {
336 : /* This might be (clobber (reg [<result>]))
337 : when not optimizing. Then check if
338 : the previous insn is the clobber for
339 : the return register. */
340 0 : copy_reg = SET_DEST (return_copy_pat);
341 0 : if (GET_CODE (copy_reg) == REG
342 0 : && !HARD_REGISTER_NUM_P (REGNO (copy_reg)))
343 : {
344 0 : if (INSN_P (PREV_INSN (return_copy)))
345 : {
346 0 : return_copy = PREV_INSN (return_copy);
347 0 : return_copy_pat = PATTERN (return_copy);
348 0 : if (GET_CODE (return_copy_pat) != CLOBBER)
349 : break;
350 : }
351 : }
352 : }
353 : }
354 827 : copy_reg = SET_DEST (return_copy_pat);
355 827 : if (GET_CODE (copy_reg) == REG)
356 827 : copy_start = REGNO (copy_reg);
357 0 : else if (GET_CODE (copy_reg) == SUBREG
358 0 : && GET_CODE (SUBREG_REG (copy_reg)) == REG)
359 0 : copy_start = REGNO (SUBREG_REG (copy_reg));
360 : else
361 : {
362 : /* When control reaches end of non-void function,
363 : there are no return copy insns at all. This
364 : avoids an ice on that invalid function. */
365 0 : if (ret_start + nregs == ret_end)
366 0 : short_block = true;
367 : break;
368 : }
369 827 : if (!targetm.calls.function_value_regno_p (copy_start))
370 : copy_num = 0;
371 : else
372 827 : copy_num = hard_regno_nregs (copy_start,
373 827 : GET_MODE (copy_reg));
374 :
375 : /* If the return register is not likely spilled, - as is
376 : the case for floating point on SH4 - then it might
377 : be set by an arithmetic operation that needs a
378 : different mode than the exit block. */
379 827 : HARD_REG_SET hard_regs_live;
380 1654 : REG_SET_TO_HARD_REG_SET (hard_regs_live, live);
381 1668 : for (j = n_entities - 1; j >= 0; j--)
382 : {
383 841 : int e = entity_map[j];
384 841 : int mode =
385 841 : targetm.mode_switching.needed (e, return_copy,
386 : hard_regs_live);
387 :
388 841 : if (mode != num_modes[e]
389 841 : && mode != targetm.mode_switching.exit (e))
390 : break;
391 : }
392 827 : if (j >= 0)
393 : {
394 : /* __builtin_return emits a sequence of loads to all
395 : return registers. One of them might require
396 : another mode than MODE_EXIT, even if it is
397 : unrelated to the return value, so we want to put
398 : the final mode switch after it. */
399 0 : if (multi_reg_return
400 0 : && targetm.calls.function_value_regno_p
401 0 : (copy_start))
402 : forced_late_switch = true;
403 :
404 : /* For the SH4, floating point loads depend on fpscr,
405 : thus we might need to put the final mode switch
406 : after the return value copy. That is still OK,
407 : because a floating point return value does not
408 : conflict with address reloads. */
409 0 : if (copy_start >= ret_start
410 0 : && copy_start + copy_num <= ret_end
411 0 : && GET_CODE (return_copy_pat) == SET
412 0 : && OBJECT_P (SET_SRC (return_copy_pat)))
413 0 : forced_late_switch = true;
414 : break;
415 : }
416 827 : if (copy_num == 0)
417 : {
418 0 : last_insn = return_copy;
419 0 : continue;
420 : }
421 :
422 827 : if (copy_start >= ret_start
423 827 : && copy_start + copy_num <= ret_end)
424 827 : nregs -= copy_num;
425 0 : else if (!multi_reg_return
426 0 : || !targetm.calls.function_value_regno_p
427 0 : (copy_start))
428 : break;
429 827 : last_insn = return_copy;
430 : }
431 : /* ??? Exception handling can lead to the return value
432 : copy being already separated from the return value use,
433 : as in unwind-dw2.c .
434 : Similarly, conditionally returning without a value,
435 : and conditionally using builtin_return can lead to an
436 : isolated use. */
437 827 : if (return_copy == BB_HEAD (src_bb))
438 : {
439 : short_block = true;
440 : break;
441 : }
442 : last_insn = return_copy;
443 : }
444 922 : while (nregs);
445 :
446 : /* If we didn't see a full return value copy, verify that there
447 : is a plausible reason for this. If some, but not all of the
448 : return register is likely spilled, we can expect that there
449 : is a copy for the likely spilled part. */
450 827 : gcc_assert (!nregs
451 : || forced_late_switch
452 : || short_block
453 : || !(targetm.class_likely_spilled_p
454 : (REGNO_REG_CLASS (ret_start)))
455 : || nregs != REG_NREGS (ret_reg)
456 : /* For multi-hard-register floating point
457 : values, sometimes the likely-spilled part
458 : is ordinarily copied first, then the other
459 : part is set with an arithmetic operation.
460 : This doesn't actually cause reload
461 : failures, so let it pass. */
462 : || (GET_MODE_CLASS (GET_MODE (ret_reg)) != MODE_INT
463 : && nregs != 1));
464 :
465 827 : if (!NOTE_INSN_BASIC_BLOCK_P (last_insn))
466 : {
467 827 : before_return_copy
468 827 : = emit_note_before (NOTE_INSN_DELETED, last_insn);
469 : /* Instructions preceding LAST_INSN in the same block might
470 : require a different mode than MODE_EXIT, so if we might
471 : have such instructions, keep them in a separate block
472 : from pre_exit. */
473 1654 : src_bb = split_block (src_bb,
474 827 : PREV_INSN (before_return_copy))->dest;
475 : }
476 : else
477 : before_return_copy = last_insn;
478 827 : pre_exit = split_block (src_bb, before_return_copy)->src;
479 827 : }
480 : else
481 : {
482 73481 : pre_exit = split_edge (eg);
483 : }
484 : }
485 :
486 75696 : return pre_exit;
487 : }
488 :
489 : /* Return the confluence of modes MODE1 and MODE2 for entity ENTITY,
490 : using NO_MODE to represent an unknown mode if nothing more precise
491 : is available. */
492 :
493 : int
494 0 : mode_confluence (int entity, int mode1, int mode2, int no_mode)
495 : {
496 0 : if (mode1 == mode2)
497 : return mode1;
498 :
499 0 : if (mode1 != no_mode
500 0 : && mode2 != no_mode
501 0 : && targetm.mode_switching.confluence)
502 0 : return targetm.mode_switching.confluence (entity, mode1, mode2);
503 :
504 : return no_mode;
505 : }
506 :
507 : /* Information for the dataflow problems below. */
508 : struct
509 : {
510 : /* Information about each basic block, indexed by block id. */
511 : struct bb_info *bb_info;
512 :
513 : /* A bitmap of blocks for which the current entity is transparent. */
514 : sbitmap transp;
515 :
516 : /* The entity that we're processing. */
517 : int entity;
518 :
519 : /* The number of modes defined for the entity, and thus the identifier
520 : of the "don't know" mode. */
521 : int no_mode;
522 : } confluence_info;
523 :
524 : /* Propagate information about any mode change on edge E to the
525 : destination block's mode_in. Return true if something changed.
526 :
527 : The mode_in and mode_out fields use no_mode + 1 to mean "not yet set". */
528 :
529 : static bool
530 0 : forward_confluence_n (edge e)
531 : {
532 : /* The entry and exit blocks have no useful mode information. */
533 0 : if (e->src->index == ENTRY_BLOCK || e->dest->index == EXIT_BLOCK)
534 : return false;
535 :
536 : /* We don't control mode changes across abnormal edges. */
537 0 : if (e->flags & EDGE_ABNORMAL)
538 : return false;
539 :
540 : /* E->aux is nonzero if we have computed the LCM problem and scheduled
541 : E to change the mode to E->aux - 1. Otherwise model the change
542 : from the source to the destination. */
543 0 : struct bb_info *bb_info = confluence_info.bb_info;
544 0 : int no_mode = confluence_info.no_mode;
545 0 : int src_mode = bb_info[e->src->index].mode_out;
546 0 : if (e->aux)
547 0 : src_mode = (int) (intptr_t) e->aux - 1;
548 0 : if (src_mode == no_mode + 1)
549 : return false;
550 :
551 0 : int dest_mode = bb_info[e->dest->index].mode_in;
552 0 : if (dest_mode == no_mode + 1)
553 : {
554 0 : bb_info[e->dest->index].mode_in = src_mode;
555 0 : return true;
556 : }
557 :
558 0 : int entity = confluence_info.entity;
559 0 : int new_mode = mode_confluence (entity, src_mode, dest_mode, no_mode);
560 0 : if (dest_mode == new_mode)
561 : return false;
562 :
563 0 : bb_info[e->dest->index].mode_in = new_mode;
564 0 : return true;
565 : }
566 :
567 : /* Update block BB_INDEX's mode_out based on its mode_in. Return true if
568 : something changed. */
569 :
570 : static bool
571 0 : forward_transfer (int bb_index)
572 : {
573 : /* The entry and exit blocks have no useful mode information. */
574 0 : if (bb_index == ENTRY_BLOCK || bb_index == EXIT_BLOCK)
575 : return false;
576 :
577 : /* Only propagate through a block if the entity is transparent. */
578 0 : struct bb_info *bb_info = confluence_info.bb_info;
579 0 : if (bb_info[bb_index].computing != confluence_info.no_mode
580 0 : || bb_info[bb_index].mode_out == bb_info[bb_index].mode_in)
581 : return false;
582 :
583 0 : bb_info[bb_index].mode_out = bb_info[bb_index].mode_in;
584 0 : return true;
585 : }
586 :
587 : /* A backwards confluence function. Update the bb_info single_succ
588 : field for E's source block, based on changes to E's destination block.
589 : At the end of the dataflow problem, single_succ is the single mode
590 : that all successors require (directly or indirectly), or no_mode
591 : if there are conflicting requirements.
592 :
593 : Initially, a value of no_mode + 1 means "don't know". */
594 :
595 : static bool
596 0 : single_succ_confluence_n (edge e)
597 : {
598 : /* The entry block has no associated mode information. */
599 0 : if (e->src->index == ENTRY_BLOCK)
600 : return false;
601 :
602 : /* We don't control mode changes across abnormal edges. */
603 0 : if (e->flags & EDGE_ABNORMAL)
604 : return false;
605 :
606 : /* Do nothing if we've already found a conflict. */
607 0 : struct bb_info *bb_info = confluence_info.bb_info;
608 0 : int no_mode = confluence_info.no_mode;
609 0 : int src_mode = bb_info[e->src->index].single_succ;
610 0 : if (src_mode == no_mode)
611 : return false;
612 :
613 : /* Work out what mode the destination block (or its successors) require. */
614 0 : int dest_mode;
615 0 : if (e->dest->index == EXIT_BLOCK)
616 : dest_mode = no_mode;
617 0 : else if (bitmap_bit_p (confluence_info.transp, e->dest->index))
618 0 : dest_mode = bb_info[e->dest->index].single_succ;
619 : else
620 0 : dest_mode = bb_info[e->dest->index].seginfo->mode;
621 :
622 : /* Do nothing if the destination block has no new information. */
623 0 : if (dest_mode == no_mode + 1 || dest_mode == src_mode)
624 : return false;
625 :
626 : /* Detect conflicting modes. */
627 0 : if (src_mode != no_mode + 1)
628 0 : dest_mode = no_mode;
629 :
630 0 : bb_info[e->src->index].single_succ = dest_mode;
631 0 : return true;
632 : }
633 :
634 : /* A backward transfer function for computing the bb_info single_succ
635 : fields, as described above single_succ_confluence. */
636 :
637 : static bool
638 0 : single_succ_transfer (int bb_index)
639 : {
640 : /* We don't have any field to transfer to. Assume that, after the
641 : first iteration, we are only called if single_succ has changed.
642 : We should then process incoming edges if the entity is transparent. */
643 0 : return bitmap_bit_p (confluence_info.transp, bb_index);
644 : }
645 :
646 : /* Check whether the target wants to back-propagate a mode change across
647 : edge E, and update the source block's computed mode if so. Return true
648 : if something changed. */
649 :
650 : static bool
651 0 : backprop_confluence_n (edge e)
652 : {
653 : /* The entry and exit blocks have no useful mode information. */
654 0 : if (e->src->index == ENTRY_BLOCK || e->dest->index == EXIT_BLOCK)
655 : return false;
656 :
657 : /* We don't control mode changes across abnormal edges. */
658 0 : if (e->flags & EDGE_ABNORMAL)
659 : return false;
660 :
661 : /* We can only require a new mode in the source block if the entity
662 : was originally transparent there. */
663 0 : if (!bitmap_bit_p (confluence_info.transp, e->src->index))
664 : return false;
665 :
666 : /* Exit now if there is no required mode, or if all paths into the
667 : source block leave the entity in the required mode. */
668 0 : struct bb_info *bb_info = confluence_info.bb_info;
669 0 : int no_mode = confluence_info.no_mode;
670 0 : int src_mode = bb_info[e->src->index].mode_out;
671 0 : int dest_mode = bb_info[e->dest->index].mode_in;
672 0 : if (dest_mode == no_mode || src_mode == dest_mode)
673 : return false;
674 :
675 : /* See what the target thinks about this transition. */
676 0 : int entity = confluence_info.entity;
677 0 : int new_mode = targetm.mode_switching.backprop (entity, src_mode,
678 : dest_mode);
679 0 : if (new_mode == no_mode)
680 : return false;
681 :
682 : /* The target doesn't like the current transition, but would be happy
683 : with a transition from NEW_MODE.
684 :
685 : If we force the source block to use NEW_MODE, we might introduce a
686 : double transition on at least one path through the function (one to
687 : NEW_MODE and then one to DEST_MODE). Therefore, if all destination
688 : blocks require the same mode, it is usually better to bring that
689 : mode requirement forward.
690 :
691 : If that isn't possible, merge the preference for this edge with
692 : the preferences for other edges. no_mode + 1 indicates that there
693 : was no previous preference. */
694 0 : int old_mode = bb_info[e->src->index].computing;
695 0 : if (bb_info[e->src->index].single_succ != no_mode)
696 : new_mode = bb_info[e->src->index].single_succ;
697 0 : else if (old_mode != no_mode + 1)
698 0 : new_mode = mode_confluence (entity, old_mode, new_mode, no_mode);
699 :
700 0 : if (old_mode == new_mode)
701 : return false;
702 :
703 0 : bb_info[e->src->index].computing = new_mode;
704 0 : return true;
705 : }
706 :
707 : /* If the current entity was originally transparent in block BB_INDEX,
708 : update the incoming mode to match the outgoing mode. Register a mode
709 : change if the entity is no longer transparent.
710 :
711 : Also, as an on-the-fly optimization, check whether the entity was
712 : originally transparent in BB_INDEX and if all successor blocks require
713 : the same mode. If so, anticipate the mode change in BB_INDEX if
714 : doing it on the incoming edges would require no more mode changes than
715 : doing it on the outgoing edges. The aim is to reduce the total number
716 : of mode changes emitted for the function (and thus reduce code size and
717 : cfg complexity) without increasing the number of mode changes on any
718 : given path through the function. A typical case where it helps is:
719 :
720 : T
721 : / \
722 : T M
723 : \ /
724 : M
725 :
726 : where the entity is transparent in the T blocks and is required to have
727 : mode M in the M blocks. If there are no redundancies leading up to this,
728 : there will be two mutually-exclusive changes to mode M, one on each of
729 : the T->M edges. The optimization instead converts it to:
730 :
731 : T T M
732 : / \ / \ / \
733 : T M -> M M -> M M
734 : \ / \ / \ /
735 : M M M
736 :
737 : which creates a single transition to M for both paths through the diamond.
738 :
739 : Return true if something changed. */
740 :
741 : static bool
742 0 : backprop_transfer (int bb_index)
743 : {
744 : /* The entry and exit blocks have no useful mode information. */
745 0 : if (bb_index == ENTRY_BLOCK || bb_index == EXIT_BLOCK)
746 : return false;
747 :
748 : /* We can only require a new mode if the entity was previously
749 : transparent. */
750 0 : if (!bitmap_bit_p (confluence_info.transp, bb_index))
751 : return false;
752 :
753 0 : struct bb_info *bb_info = confluence_info.bb_info;
754 0 : basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
755 0 : int no_mode = confluence_info.no_mode;
756 0 : int mode_in = bb_info[bb_index].mode_in;
757 0 : int mode_out = bb_info[bb_index].computing;
758 0 : if (mode_out == no_mode + 1)
759 : {
760 : /* The entity is still transparent for this block. See whether
761 : all successor blocks need the same mode, either directly or
762 : indirectly. */
763 0 : mode_out = bb_info[bb_index].single_succ;
764 0 : if (mode_out == no_mode)
765 : return false;
766 :
767 : /* Get a minimum bound on the number of transitions that would be
768 : removed if BB itself required MODE_OUT. */
769 0 : unsigned int moved = 0;
770 0 : for (edge e : bb->succs)
771 0 : if (e->dest->index != EXIT_BLOCK
772 0 : && mode_out == bb_info[e->dest->index].seginfo->mode)
773 0 : moved += 1;
774 :
775 : /* See whether making the mode change on all incoming edges would
776 : be no worse than making it on MOVED outgoing edges. */
777 0 : if (moved < EDGE_COUNT (bb->preds))
778 : return false;
779 :
780 0 : bb_info[bb_index].mode_out = mode_out;
781 0 : bb_info[bb_index].computing = mode_out;
782 : }
783 0 : else if (mode_out == mode_in)
784 : return false;
785 :
786 0 : bb_info[bb_index].mode_in = mode_out;
787 0 : bb_info[bb_index].seginfo->mode = mode_out;
788 0 : return true;
789 : }
790 :
791 : /* Find all insns that need a particular mode setting, and insert the
792 : necessary mode switches. Return true if we did work. */
793 :
794 : static int
795 1545804 : optimize_mode_switching (void)
796 : {
797 1545804 : int e;
798 1545804 : basic_block bb;
799 1545804 : bool need_commit = false;
800 1545804 : static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING;
801 : #define N_ENTITIES ARRAY_SIZE (num_modes)
802 1545804 : int entity_map[N_ENTITIES] = {};
803 1545804 : struct bb_info *bb_info[N_ENTITIES] = {};
804 1545804 : int i, j;
805 1545804 : int n_entities = 0;
806 1545804 : int max_num_modes = 0;
807 1545804 : bool emitted ATTRIBUTE_UNUSED = false;
808 1545804 : basic_block post_entry = 0;
809 1545804 : basic_block pre_exit = 0;
810 1545804 : struct edge_list *edge_list = 0;
811 :
812 : /* These bitmaps are used for the LCM algorithm. */
813 1545804 : sbitmap *kill, *del, *insert, *antic, *transp, *comp;
814 1545804 : sbitmap *avin, *avout;
815 :
816 10820628 : for (e = N_ENTITIES - 1; e >= 0; e--)
817 9274824 : if (OPTIMIZE_MODE_SWITCHING (e))
818 : {
819 75712 : int entry_exit_extra = 0;
820 :
821 : /* Create the list of segments within each basic block.
822 : If NORMAL_MODE is defined, allow for two extra
823 : blocks split from the entry and exit block. */
824 75712 : if (targetm.mode_switching.entry && targetm.mode_switching.exit)
825 75712 : entry_exit_extra = 3;
826 :
827 75712 : bb_info[n_entities]
828 75712 : = XCNEWVEC (struct bb_info,
829 : last_basic_block_for_fn (cfun) + entry_exit_extra);
830 75712 : entity_map[n_entities++] = e;
831 75712 : if (num_modes[e] > max_num_modes)
832 75696 : max_num_modes = num_modes[e];
833 : }
834 :
835 1545804 : if (! n_entities)
836 : return 0;
837 :
838 : /* Make sure if MODE_ENTRY is defined MODE_EXIT is defined. */
839 75696 : gcc_assert ((targetm.mode_switching.entry && targetm.mode_switching.exit)
840 : || (!targetm.mode_switching.entry
841 : && !targetm.mode_switching.exit));
842 :
843 75696 : if (targetm.mode_switching.entry && targetm.mode_switching.exit)
844 : {
845 : /* Split the edge from the entry block, so that we can note that
846 : there NORMAL_MODE is supplied. */
847 75696 : post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
848 75696 : pre_exit = create_pre_exit (n_entities, entity_map, num_modes);
849 : }
850 :
851 75696 : df_note_add_problem ();
852 75696 : df_analyze ();
853 :
854 : /* Create the bitmap vectors. */
855 151392 : antic = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
856 75696 : n_entities * max_num_modes);
857 151392 : transp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
858 75696 : n_entities * max_num_modes);
859 151392 : comp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
860 75696 : n_entities * max_num_modes);
861 151392 : avin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
862 75696 : n_entities * max_num_modes);
863 151392 : avout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
864 75696 : n_entities * max_num_modes);
865 151392 : kill = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
866 75696 : n_entities * max_num_modes);
867 :
868 75696 : bitmap_vector_ones (transp, last_basic_block_for_fn (cfun));
869 75696 : bitmap_vector_clear (antic, last_basic_block_for_fn (cfun));
870 75696 : bitmap_vector_clear (comp, last_basic_block_for_fn (cfun));
871 :
872 75696 : auto_sbitmap transp_all (last_basic_block_for_fn (cfun));
873 :
874 75696 : auto_bitmap blocks;
875 :
876 : /* Forward-propagate mode information through blocks where the entity
877 : is transparent, so that mode_in describes the mode on entry to each
878 : block and mode_out describes the mode on exit from each block. */
879 75696 : auto forwprop_mode_info = [&](struct bb_info *info,
880 : int entity, int no_mode)
881 : {
882 : /* Use no_mode + 1 to mean "not yet set". */
883 0 : FOR_EACH_BB_FN (bb, cfun)
884 : {
885 0 : if (bb_has_abnormal_pred (bb))
886 0 : info[bb->index].mode_in = info[bb->index].seginfo->mode;
887 : else
888 0 : info[bb->index].mode_in = no_mode + 1;
889 0 : if (info[bb->index].computing != no_mode)
890 0 : info[bb->index].mode_out = info[bb->index].computing;
891 : else
892 0 : info[bb->index].mode_out = no_mode + 1;
893 : }
894 :
895 0 : confluence_info.bb_info = info;
896 0 : confluence_info.transp = nullptr;
897 0 : confluence_info.entity = entity;
898 0 : confluence_info.no_mode = no_mode;
899 :
900 0 : bitmap_set_range (blocks, 0, last_basic_block_for_fn (cfun));
901 0 : df_simple_dataflow (DF_FORWARD, NULL, NULL, forward_confluence_n,
902 : forward_transfer, blocks,
903 : df_get_postorder (DF_FORWARD),
904 : df_get_n_blocks (DF_FORWARD));
905 :
906 75696 : };
907 :
908 75696 : if (targetm.mode_switching.backprop)
909 0 : clear_aux_for_edges ();
910 :
911 151408 : for (j = n_entities - 1; j >= 0; j--)
912 : {
913 75712 : int e = entity_map[j];
914 75712 : int no_mode = num_modes[e];
915 75712 : struct bb_info *info = bb_info[j];
916 75712 : rtx_insn *insn;
917 :
918 75712 : bitmap_ones (transp_all);
919 :
920 : /* Determine what the first use (if any) need for a mode of entity E is.
921 : This will be the mode that is anticipatable for this block.
922 : Also compute the initial transparency settings. */
923 628782 : FOR_EACH_BB_FN (bb, cfun)
924 : {
925 553070 : struct seginfo **tail_ptr = &info[bb->index].seginfo;
926 553070 : struct seginfo *ptr;
927 553070 : int last_mode = no_mode;
928 553070 : bool any_set_required = false;
929 553070 : HARD_REG_SET live_now;
930 :
931 553070 : info[bb->index].mode_out = info[bb->index].mode_in = no_mode;
932 :
933 1106140 : REG_SET_TO_HARD_REG_SET (live_now, df_get_live_in (bb));
934 :
935 : /* Pretend the mode is clobbered across abnormal edges. */
936 553070 : {
937 553070 : edge_iterator ei;
938 553070 : edge eg;
939 1297829 : FOR_EACH_EDGE (eg, ei, bb->preds)
940 744911 : if (eg->flags & EDGE_COMPLEX)
941 : break;
942 553070 : if (eg)
943 : {
944 152 : rtx_insn *ins_pos = BB_HEAD (bb);
945 152 : if (LABEL_P (ins_pos))
946 152 : ins_pos = NEXT_INSN (ins_pos);
947 152 : gcc_assert (NOTE_INSN_BASIC_BLOCK_P (ins_pos));
948 152 : if (ins_pos != BB_END (bb))
949 151 : ins_pos = NEXT_INSN (ins_pos);
950 152 : if (bb_has_eh_pred (bb)
951 152 : && targetm.mode_switching.eh_handler)
952 0 : last_mode = targetm.mode_switching.eh_handler (e);
953 152 : ptr = new_seginfo (no_mode, last_mode, ins_pos, live_now);
954 152 : add_seginfo (&tail_ptr, ptr);
955 152 : bitmap_clear_bit (transp_all, bb->index);
956 : }
957 : }
958 :
959 5295905 : FOR_BB_INSNS (bb, insn)
960 : {
961 4742835 : if (NONDEBUG_INSN_P (insn))
962 : {
963 2508636 : int mode = targetm.mode_switching.needed (e, insn, live_now);
964 2508636 : rtx link;
965 :
966 2508636 : if (mode != no_mode && mode != last_mode)
967 : {
968 104341 : ptr = new_seginfo (last_mode, mode, insn, live_now);
969 104341 : add_seginfo (&tail_ptr, ptr);
970 104341 : bitmap_clear_bit (transp_all, bb->index);
971 104341 : any_set_required = true;
972 104341 : last_mode = mode;
973 : }
974 :
975 : /* Update LIVE_NOW. */
976 4712497 : for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
977 2203861 : if (REG_NOTE_KIND (link) == REG_DEAD)
978 1223099 : reg_dies (XEXP (link, 0), &live_now);
979 :
980 2508636 : note_stores (insn, reg_becomes_live, &live_now);
981 4712497 : for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
982 2203861 : if (REG_NOTE_KIND (link) == REG_UNUSED)
983 382716 : reg_dies (XEXP (link, 0), &live_now);
984 :
985 2508636 : if (targetm.mode_switching.after)
986 2508636 : last_mode = targetm.mode_switching.after (e, last_mode,
987 : insn, live_now);
988 : }
989 : }
990 :
991 553070 : info[bb->index].computing = last_mode;
992 : /* Check for blocks without ANY mode requirements.
993 : N.B. because of MODE_AFTER, last_mode might still
994 : be different from no_mode, in which case we need to
995 : mark the block as nontransparent. */
996 553070 : if (!any_set_required)
997 : {
998 459326 : ptr = new_seginfo (last_mode, no_mode, BB_END (bb), live_now);
999 459326 : add_seginfo (&tail_ptr, ptr);
1000 459326 : if (last_mode != no_mode)
1001 11 : bitmap_clear_bit (transp_all, bb->index);
1002 : }
1003 : }
1004 75712 : if (targetm.mode_switching.entry && targetm.mode_switching.exit)
1005 : {
1006 75712 : info[post_entry->index].mode_out =
1007 75712 : info[post_entry->index].mode_in = no_mode;
1008 :
1009 75712 : int mode = targetm.mode_switching.entry (e);
1010 75712 : if (mode != no_mode)
1011 : {
1012 : /* Insert a fake computing definition of MODE into entry
1013 : blocks which compute no mode. This represents the mode on
1014 : entry. */
1015 74443 : info[post_entry->index].computing = mode;
1016 74443 : bitmap_clear_bit (transp_all, post_entry->index);
1017 : }
1018 :
1019 75712 : if (pre_exit)
1020 : {
1021 74324 : info[pre_exit->index].mode_out =
1022 74324 : info[pre_exit->index].mode_in = no_mode;
1023 :
1024 74324 : int mode = targetm.mode_switching.exit (e);
1025 74324 : if (mode != no_mode)
1026 : {
1027 73200 : info[pre_exit->index].seginfo->mode = mode;
1028 73200 : bitmap_clear_bit (transp_all, pre_exit->index);
1029 : }
1030 : }
1031 : }
1032 :
1033 : /* If the target requests it, back-propagate selected mode requirements
1034 : through transparent blocks. */
1035 75712 : if (targetm.mode_switching.backprop)
1036 : {
1037 : /* First work out the mode on entry to and exit from each block. */
1038 0 : forwprop_mode_info (info, e, no_mode);
1039 :
1040 : /* Compute the single_succ fields, as described above
1041 : single_succ_confluence. */
1042 0 : FOR_EACH_BB_FN (bb, cfun)
1043 0 : info[bb->index].single_succ = no_mode + 1;
1044 :
1045 0 : confluence_info.transp = transp_all;
1046 0 : bitmap_set_range (blocks, 0, last_basic_block_for_fn (cfun));
1047 0 : df_simple_dataflow (DF_BACKWARD, NULL, NULL,
1048 : single_succ_confluence_n,
1049 : single_succ_transfer, blocks,
1050 : df_get_postorder (DF_BACKWARD),
1051 : df_get_n_blocks (DF_BACKWARD));
1052 :
1053 0 : FOR_EACH_BB_FN (bb, cfun)
1054 : {
1055 : /* Repurpose mode_in as the first mode required by the block,
1056 : or the output mode if none. */
1057 0 : if (info[bb->index].seginfo->mode != no_mode)
1058 0 : info[bb->index].mode_in = info[bb->index].seginfo->mode;
1059 :
1060 : /* In transparent blocks, use computing == no_mode + 1
1061 : to indicate that no propagation has taken place. */
1062 0 : if (info[bb->index].computing == no_mode)
1063 0 : info[bb->index].computing = no_mode + 1;
1064 : }
1065 :
1066 0 : bitmap_set_range (blocks, 0, last_basic_block_for_fn (cfun));
1067 0 : df_simple_dataflow (DF_BACKWARD, NULL, NULL, backprop_confluence_n,
1068 : backprop_transfer, blocks,
1069 : df_get_postorder (DF_BACKWARD),
1070 : df_get_n_blocks (DF_BACKWARD));
1071 :
1072 : /* Any block that now computes a mode is no longer transparent. */
1073 0 : FOR_EACH_BB_FN (bb, cfun)
1074 0 : if (info[bb->index].computing == no_mode + 1)
1075 0 : info[bb->index].computing = no_mode;
1076 0 : else if (info[bb->index].computing != no_mode)
1077 0 : bitmap_clear_bit (transp_all, bb->index);
1078 : }
1079 :
1080 : /* Set the anticipatable and computing arrays. */
1081 230463 : for (i = 0; i < no_mode; i++)
1082 : {
1083 154751 : int m = targetm.mode_switching.priority (entity_map[j], i);
1084 :
1085 1495274 : FOR_EACH_BB_FN (bb, cfun)
1086 : {
1087 1340523 : if (!bitmap_bit_p (transp_all, bb->index))
1088 535682 : clear_mode_bit (transp[bb->index], j, m);
1089 :
1090 1340523 : if (info[bb->index].seginfo->mode == m)
1091 166892 : set_mode_bit (antic[bb->index], j, m);
1092 :
1093 1340523 : if (info[bb->index].computing == m)
1094 165636 : set_mode_bit (comp[bb->index], j, m);
1095 : }
1096 : }
1097 : }
1098 :
1099 : /* Calculate the optimal locations for the
1100 : placement mode switches to modes with priority I. */
1101 :
1102 628386 : FOR_EACH_BB_FN (bb, cfun)
1103 552690 : bitmap_not (kill[bb->index], transp[bb->index]);
1104 :
1105 75696 : edge_list = pre_edge_lcm_avs (n_entities * max_num_modes, transp, comp, antic,
1106 : kill, avin, avout, &insert, &del);
1107 :
1108 75696 : auto_sbitmap jumping_blocks (last_basic_block_for_fn (cfun));
1109 75696 : bitmap_clear (jumping_blocks);
1110 151408 : for (j = n_entities - 1; j >= 0; j--)
1111 : {
1112 75712 : int no_mode = num_modes[entity_map[j]];
1113 75712 : struct bb_info *info = bb_info[j];
1114 :
1115 : /* Insert all mode sets that have been inserted by lcm. */
1116 :
1117 897209 : for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--)
1118 : {
1119 821497 : edge eg = INDEX_EDGE (edge_list, ed);
1120 :
1121 821497 : eg->aux = (void *) (intptr_t) 0;
1122 :
1123 2832221 : for (i = 0; i < no_mode; i++)
1124 : {
1125 2022330 : int m = targetm.mode_switching.priority (entity_map[j], i);
1126 2022330 : if (mode_bit_p (insert[ed], j, m))
1127 : {
1128 11606 : eg->aux = (void *) (intptr_t) (m + 1);
1129 11606 : break;
1130 : }
1131 : }
1132 : }
1133 :
1134 : /* mode_in and mode_out can be calculated directly from avin and
1135 : avout if all the modes are mutually exclusive. Use the target-
1136 : provided confluence function otherwise. */
1137 75712 : if (targetm.mode_switching.confluence)
1138 0 : forwprop_mode_info (info, entity_map[j], no_mode);
1139 :
1140 628782 : FOR_EACH_BB_FN (bb, cfun)
1141 : {
1142 1659210 : auto modes_confluence = [&](sbitmap *av)
1143 : {
1144 2277671 : for (int i = 0; i < no_mode; ++i)
1145 2057294 : if (mode_bit_p (av[bb->index], j, i))
1146 : {
1147 1509515 : for (int i2 = i + 1; i2 < no_mode; ++i2)
1148 623752 : if (mode_bit_p (av[bb->index], j, i2))
1149 : return no_mode;
1150 : return i;
1151 : }
1152 : return no_mode;
1153 553070 : };
1154 :
1155 : /* intialize mode in/out availability for bb. */
1156 553070 : if (!targetm.mode_switching.confluence)
1157 : {
1158 553070 : info[bb->index].mode_out = modes_confluence (avout);
1159 553070 : info[bb->index].mode_in = modes_confluence (avin);
1160 : }
1161 :
1162 1893593 : for (i = 0; i < no_mode; i++)
1163 1340523 : if (mode_bit_p (del[bb->index], j, i))
1164 136586 : info[bb->index].seginfo->mode = no_mode;
1165 :
1166 : /* See whether the target can perform the first transition.
1167 : If not, push it onto the incoming edges. The earlier backprop
1168 : pass should ensure that the resulting transitions are valid. */
1169 553070 : if (targetm.mode_switching.backprop)
1170 : {
1171 0 : int from_mode = info[bb->index].mode_in;
1172 0 : int to_mode = info[bb->index].seginfo->mode;
1173 0 : if (targetm.mode_switching.backprop (entity_map[j], from_mode,
1174 0 : to_mode) != no_mode)
1175 : {
1176 0 : for (edge e : bb->preds)
1177 0 : e->aux = (void *) (intptr_t) (to_mode + 1);
1178 0 : info[bb->index].mode_in = to_mode;
1179 : }
1180 : }
1181 : }
1182 :
1183 : /* Now output the remaining mode sets in all the segments. */
1184 :
1185 : /* In case there was no mode inserted. the mode information on the edge
1186 : might not be complete.
1187 : Update mode info on edges and commit pending mode sets. */
1188 75712 : need_commit |= commit_mode_sets (edge_list, entity_map[j], bb_info[j]);
1189 :
1190 : /* Reset modes for next entity. */
1191 75712 : clear_aux_for_edges ();
1192 :
1193 628782 : FOR_EACH_BB_FN (bb, cfun)
1194 : {
1195 553070 : struct seginfo *ptr, *next;
1196 553070 : struct seginfo *first = bb_info[j][bb->index].seginfo;
1197 :
1198 1116889 : for (ptr = first; ptr; ptr = next)
1199 : {
1200 563819 : next = ptr->next;
1201 563819 : if (ptr->mode != no_mode)
1202 : {
1203 40955 : rtx_insn *mode_set;
1204 :
1205 40955 : rtl_profile_for_bb (bb);
1206 40955 : start_sequence ();
1207 :
1208 40955 : int cur_mode = (ptr == first && ptr->prev_mode == no_mode
1209 71260 : ? bb_info[j][bb->index].mode_in
1210 : : ptr->prev_mode);
1211 :
1212 40955 : targetm.mode_switching.emit (entity_map[j], ptr->mode,
1213 : cur_mode, ptr->regs_live);
1214 40955 : mode_set = end_sequence ();
1215 :
1216 : /* Insert MODE_SET only if it is nonempty. */
1217 40955 : if (mode_set != NULL_RTX)
1218 : {
1219 40273 : for (auto insn = mode_set; insn; insn = NEXT_INSN (insn))
1220 22374 : if (JUMP_P (insn))
1221 : {
1222 0 : rebuild_jump_labels_chain (mode_set);
1223 0 : bitmap_set_bit (jumping_blocks, bb->index);
1224 0 : break;
1225 : }
1226 17899 : emitted = true;
1227 17899 : if (NOTE_INSN_BASIC_BLOCK_P (ptr->insn_ptr))
1228 : /* We need to emit the insns in a FIFO-like manner,
1229 : i.e. the first to be emitted at our insertion
1230 : point ends up first in the instruction steam.
1231 : Because we made sure that NOTE_INSN_BASIC_BLOCK is
1232 : only used for initially empty basic blocks, we
1233 : can achieve this by appending at the end of
1234 : the block. */
1235 6696 : emit_insn_after
1236 6696 : (mode_set, BB_END (NOTE_BASIC_BLOCK (ptr->insn_ptr)));
1237 : else
1238 11203 : emit_insn_before (mode_set, ptr->insn_ptr);
1239 : }
1240 :
1241 40955 : default_rtl_profile ();
1242 : }
1243 :
1244 563819 : free (ptr);
1245 : }
1246 : }
1247 :
1248 75712 : free (bb_info[j]);
1249 : }
1250 :
1251 75696 : free_edge_list (edge_list);
1252 :
1253 : /* Finished. Free up all the things we've allocated. */
1254 75696 : sbitmap_vector_free (del);
1255 75696 : sbitmap_vector_free (insert);
1256 75696 : sbitmap_vector_free (kill);
1257 75696 : sbitmap_vector_free (antic);
1258 75696 : sbitmap_vector_free (transp);
1259 75696 : sbitmap_vector_free (comp);
1260 75696 : sbitmap_vector_free (avin);
1261 75696 : sbitmap_vector_free (avout);
1262 :
1263 75696 : gcc_assert (SBITMAP_SIZE ((sbitmap) jumping_blocks)
1264 : == (unsigned int) last_basic_block_for_fn (cfun));
1265 75696 : if (!bitmap_empty_p (jumping_blocks))
1266 0 : find_many_sub_basic_blocks (jumping_blocks);
1267 :
1268 75696 : if (need_commit)
1269 2111 : commit_edge_insertions ();
1270 :
1271 75696 : if (targetm.mode_switching.entry && targetm.mode_switching.exit)
1272 : {
1273 75696 : free_dominance_info (CDI_DOMINATORS);
1274 75696 : cleanup_cfg (CLEANUP_NO_INSN_DEL);
1275 : }
1276 0 : else if (!need_commit && !emitted)
1277 : return 0;
1278 :
1279 : return 1;
1280 75696 : }
1281 :
1282 : #endif /* OPTIMIZE_MODE_SWITCHING */
1283 :
1284 : namespace {
1285 :
1286 : const pass_data pass_data_mode_switching =
1287 : {
1288 : RTL_PASS, /* type */
1289 : "mode_sw", /* name */
1290 : OPTGROUP_NONE, /* optinfo_flags */
1291 : TV_MODE_SWITCH, /* tv_id */
1292 : 0, /* properties_required */
1293 : 0, /* properties_provided */
1294 : 0, /* properties_destroyed */
1295 : 0, /* todo_flags_start */
1296 : TODO_df_finish, /* todo_flags_finish */
1297 : };
1298 :
1299 : class pass_mode_switching : public rtl_opt_pass
1300 : {
1301 : public:
1302 285722 : pass_mode_switching (gcc::context *ctxt)
1303 571444 : : rtl_opt_pass (pass_data_mode_switching, ctxt)
1304 : {}
1305 :
1306 : /* opt_pass methods: */
1307 : /* The epiphany backend creates a second instance of this pass, so we need
1308 : a clone method. */
1309 0 : opt_pass * clone () final override { return new pass_mode_switching (m_ctxt); }
1310 1471370 : bool gate (function *) final override
1311 : {
1312 : #ifdef OPTIMIZE_MODE_SWITCHING
1313 1471370 : return true;
1314 : #else
1315 : return false;
1316 : #endif
1317 : }
1318 :
1319 1545804 : unsigned int execute (function *) final override
1320 : {
1321 : #ifdef OPTIMIZE_MODE_SWITCHING
1322 1545804 : optimize_mode_switching ();
1323 : #endif /* OPTIMIZE_MODE_SWITCHING */
1324 1545804 : return 0;
1325 : }
1326 :
1327 : }; // class pass_mode_switching
1328 :
1329 : } // anon namespace
1330 :
1331 : rtl_opt_pass *
1332 285722 : make_pass_mode_switching (gcc::context *ctxt)
1333 : {
1334 285722 : return new pass_mode_switching (ctxt);
1335 : }
|