tree-optimization/112450 - avoid AVX512 style masking for BImode masks
[official-gcc.git] / gcc / mode-switching.cc
blobc3e4d24de9b89769622b7d66e267bafe1e64091b
1 /* CPU mode switching
2 Copyright (C) 1998-2023 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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"
38 /* We want target macros for the mode switching code to be able to refer
39 to instruction attribute values. */
40 #include "insn-attr.h"
42 #ifdef OPTIMIZE_MODE_SWITCHING
44 /* The algorithm for setting the modes consists of scanning the insn list
45 and finding all the insns which require a specific mode. Each insn gets
46 a unique struct seginfo element. These structures are inserted into a list
47 for each basic block. For each entity, there is an array of bb_info over
48 the flow graph basic blocks (local var 'bb_info'), which contains a list
49 of all insns within that basic block, in the order they are encountered.
51 For each entity, any basic block WITHOUT any insns requiring a specific
52 mode are given a single entry without a mode (each basic block in the
53 flow graph must have at least one entry in the segment table).
55 The LCM algorithm is then run over the flow graph to determine where to
56 place the sets to the highest-priority mode with respect to the first
57 insn in any one block. Any adjustments required to the transparency
58 vectors are made, then the next iteration starts for the next-lower
59 priority mode, till for each entity all modes are exhausted.
61 More details can be found in the code of optimize_mode_switching. */
63 /* This structure contains the information for each insn which requires
64 either single or double mode to be set.
65 MODE is the mode this insn must be executed in.
66 INSN_PTR is the insn to be executed (may be the note that marks the
67 beginning of a basic block).
68 NEXT is the next insn in the same basic block. */
69 struct seginfo
71 int mode;
72 rtx_insn *insn_ptr;
73 struct seginfo *next;
74 HARD_REG_SET regs_live;
77 struct bb_info
79 struct seginfo *seginfo;
80 int computing;
81 int mode_out;
82 int mode_in;
85 /* Clear ode I from entity J in bitmap B. */
86 #define clear_mode_bit(b, j, i) \
87 bitmap_clear_bit (b, (j * max_num_modes) + i)
89 /* Test mode I from entity J in bitmap B. */
90 #define mode_bit_p(b, j, i) \
91 bitmap_bit_p (b, (j * max_num_modes) + i)
93 /* Set mode I from entity J in bitmal B. */
94 #define set_mode_bit(b, j, i) \
95 bitmap_set_bit (b, (j * max_num_modes) + i)
97 /* Emit modes segments from EDGE_LIST associated with entity E.
98 INFO gives mode availability for each mode. */
100 static bool
101 commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info)
103 bool need_commit = false;
105 for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--)
107 edge eg = INDEX_EDGE (edge_list, ed);
108 int mode;
110 if ((mode = (int)(intptr_t)(eg->aux)) != -1)
112 HARD_REG_SET live_at_edge;
113 basic_block src_bb = eg->src;
114 int cur_mode = info[src_bb->index].mode_out;
115 rtx_insn *mode_set;
117 REG_SET_TO_HARD_REG_SET (live_at_edge, df_get_live_out (src_bb));
119 rtl_profile_for_edge (eg);
120 start_sequence ();
122 targetm.mode_switching.emit (e, mode, cur_mode, live_at_edge);
124 mode_set = get_insns ();
125 end_sequence ();
126 default_rtl_profile ();
128 /* Do not bother to insert empty sequence. */
129 if (mode_set == NULL)
130 continue;
132 /* We should not get an abnormal edge here. */
133 gcc_assert (! (eg->flags & EDGE_ABNORMAL));
135 need_commit = true;
136 insert_insn_on_edge (mode_set, eg);
140 return need_commit;
143 /* Allocate a new BBINFO structure, initialized with the MODE, INSN,
144 and REGS_LIVE parameters.
145 INSN may not be a NOTE_INSN_BASIC_BLOCK, unless it is an empty
146 basic block; that allows us later to insert instructions in a FIFO-like
147 manner. */
149 static struct seginfo *
150 new_seginfo (int mode, rtx_insn *insn, const HARD_REG_SET &regs_live)
152 struct seginfo *ptr;
154 gcc_assert (!NOTE_INSN_BASIC_BLOCK_P (insn)
155 || insn == BB_END (NOTE_BASIC_BLOCK (insn)));
156 ptr = XNEW (struct seginfo);
157 ptr->mode = mode;
158 ptr->insn_ptr = insn;
159 ptr->next = NULL;
160 ptr->regs_live = regs_live;
161 return ptr;
164 /* Add a seginfo element to the end of a list.
165 HEAD is a pointer to the list beginning.
166 INFO is the structure to be linked in. */
168 static void
169 add_seginfo (struct bb_info *head, struct seginfo *info)
171 struct seginfo *ptr;
173 if (head->seginfo == NULL)
174 head->seginfo = info;
175 else
177 ptr = head->seginfo;
178 while (ptr->next != NULL)
179 ptr = ptr->next;
180 ptr->next = info;
184 /* Record in LIVE that register REG died. */
186 static void
187 reg_dies (rtx reg, HARD_REG_SET *live)
189 int regno;
191 if (!REG_P (reg))
192 return;
194 regno = REGNO (reg);
195 if (regno < FIRST_PSEUDO_REGISTER)
196 remove_from_hard_reg_set (live, GET_MODE (reg), regno);
199 /* Record in LIVE that register REG became live.
200 This is called via note_stores. */
202 static void
203 reg_becomes_live (rtx reg, const_rtx setter ATTRIBUTE_UNUSED, void *live)
205 int regno;
207 if (GET_CODE (reg) == SUBREG)
208 reg = SUBREG_REG (reg);
210 if (!REG_P (reg))
211 return;
213 regno = REGNO (reg);
214 if (regno < FIRST_PSEUDO_REGISTER)
215 add_to_hard_reg_set ((HARD_REG_SET *) live, GET_MODE (reg), regno);
218 /* Split the fallthrough edge to the exit block, so that we can note
219 that there NORMAL_MODE is required. Return the new block if it's
220 inserted before the exit block. Otherwise return null. */
222 static basic_block
223 create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
225 edge eg;
226 edge_iterator ei;
227 basic_block pre_exit;
229 /* The only non-call predecessor at this stage is a block with a
230 fallthrough edge; there can be at most one, but there could be
231 none at all, e.g. when exit is called. */
232 pre_exit = 0;
233 FOR_EACH_EDGE (eg, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
234 if (eg->flags & EDGE_FALLTHRU)
236 basic_block src_bb = eg->src;
237 rtx_insn *last_insn;
238 rtx ret_reg;
240 gcc_assert (!pre_exit);
241 /* If this function returns a value at the end, we have to
242 insert the final mode switch before the return value copy
243 to its hard register.
245 x86 targets use mode-switching infrastructure to
246 conditionally insert vzeroupper instruction at the exit
247 from the function where there is no need to switch the
248 mode before the return value copy. The vzeroupper insertion
249 pass runs after reload, so use !reload_completed as a stand-in
250 for x86 to skip the search for the return value copy insn.
252 N.b.: the code below assumes that the return copy insn
253 immediately precedes its corresponding use insn. This
254 assumption does not hold after reload, since sched1 pass
255 can schedule the return copy insn away from its
256 corresponding use insn. */
257 if (!reload_completed
258 && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == 1
259 && NONJUMP_INSN_P ((last_insn = BB_END (src_bb)))
260 && GET_CODE (PATTERN (last_insn)) == USE
261 && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG)
263 int ret_start = REGNO (ret_reg);
264 int nregs = REG_NREGS (ret_reg);
265 int ret_end = ret_start + nregs;
266 bool short_block = false;
267 bool multi_reg_return = false;
268 bool forced_late_switch = false;
269 rtx_insn *before_return_copy;
273 rtx_insn *return_copy = PREV_INSN (last_insn);
274 rtx return_copy_pat, copy_reg;
275 int copy_start, copy_num;
276 int j;
278 if (NONDEBUG_INSN_P (return_copy))
280 /* When using SJLJ exceptions, the call to the
281 unregister function is inserted between the
282 clobber of the return value and the copy.
283 We do not want to split the block before this
284 or any other call; if we have not found the
285 copy yet, the copy must have been deleted. */
286 if (CALL_P (return_copy))
288 short_block = true;
289 break;
291 return_copy_pat = PATTERN (return_copy);
292 switch (GET_CODE (return_copy_pat))
294 case USE:
295 /* Skip USEs of multiple return registers.
296 __builtin_apply pattern is also handled here. */
297 if (GET_CODE (XEXP (return_copy_pat, 0)) == REG
298 && (targetm.calls.function_value_regno_p
299 (REGNO (XEXP (return_copy_pat, 0)))))
301 multi_reg_return = true;
302 last_insn = return_copy;
303 continue;
305 break;
307 case ASM_OPERANDS:
308 /* Skip barrier insns. */
309 if (!MEM_VOLATILE_P (return_copy_pat))
310 break;
312 /* Fall through. */
314 case ASM_INPUT:
315 case UNSPEC_VOLATILE:
316 last_insn = return_copy;
317 continue;
319 default:
320 break;
323 /* If the return register is not (in its entirety)
324 likely spilled, the return copy might be
325 partially or completely optimized away. */
326 return_copy_pat = single_set (return_copy);
327 if (!return_copy_pat)
329 return_copy_pat = PATTERN (return_copy);
330 if (GET_CODE (return_copy_pat) != CLOBBER)
331 break;
332 else if (!optimize)
334 /* This might be (clobber (reg [<result>]))
335 when not optimizing. Then check if
336 the previous insn is the clobber for
337 the return register. */
338 copy_reg = SET_DEST (return_copy_pat);
339 if (GET_CODE (copy_reg) == REG
340 && !HARD_REGISTER_NUM_P (REGNO (copy_reg)))
342 if (INSN_P (PREV_INSN (return_copy)))
344 return_copy = PREV_INSN (return_copy);
345 return_copy_pat = PATTERN (return_copy);
346 if (GET_CODE (return_copy_pat) != CLOBBER)
347 break;
352 copy_reg = SET_DEST (return_copy_pat);
353 if (GET_CODE (copy_reg) == REG)
354 copy_start = REGNO (copy_reg);
355 else if (GET_CODE (copy_reg) == SUBREG
356 && GET_CODE (SUBREG_REG (copy_reg)) == REG)
357 copy_start = REGNO (SUBREG_REG (copy_reg));
358 else
360 /* When control reaches end of non-void function,
361 there are no return copy insns at all. This
362 avoids an ice on that invalid function. */
363 if (ret_start + nregs == ret_end)
364 short_block = true;
365 break;
367 if (!targetm.calls.function_value_regno_p (copy_start))
368 copy_num = 0;
369 else
370 copy_num = hard_regno_nregs (copy_start,
371 GET_MODE (copy_reg));
373 /* If the return register is not likely spilled, - as is
374 the case for floating point on SH4 - then it might
375 be set by an arithmetic operation that needs a
376 different mode than the exit block. */
377 for (j = n_entities - 1; j >= 0; j--)
379 int e = entity_map[j];
380 int mode =
381 targetm.mode_switching.needed (e, return_copy);
383 if (mode != num_modes[e]
384 && mode != targetm.mode_switching.exit (e))
385 break;
387 if (j >= 0)
389 /* __builtin_return emits a sequence of loads to all
390 return registers. One of them might require
391 another mode than MODE_EXIT, even if it is
392 unrelated to the return value, so we want to put
393 the final mode switch after it. */
394 if (multi_reg_return
395 && targetm.calls.function_value_regno_p
396 (copy_start))
397 forced_late_switch = true;
399 /* For the SH4, floating point loads depend on fpscr,
400 thus we might need to put the final mode switch
401 after the return value copy. That is still OK,
402 because a floating point return value does not
403 conflict with address reloads. */
404 if (copy_start >= ret_start
405 && copy_start + copy_num <= ret_end
406 && GET_CODE (return_copy_pat) == SET
407 && OBJECT_P (SET_SRC (return_copy_pat)))
408 forced_late_switch = true;
409 break;
411 if (copy_num == 0)
413 last_insn = return_copy;
414 continue;
417 if (copy_start >= ret_start
418 && copy_start + copy_num <= ret_end)
419 nregs -= copy_num;
420 else if (!multi_reg_return
421 || !targetm.calls.function_value_regno_p
422 (copy_start))
423 break;
424 last_insn = return_copy;
426 /* ??? Exception handling can lead to the return value
427 copy being already separated from the return value use,
428 as in unwind-dw2.c .
429 Similarly, conditionally returning without a value,
430 and conditionally using builtin_return can lead to an
431 isolated use. */
432 if (return_copy == BB_HEAD (src_bb))
434 short_block = true;
435 break;
437 last_insn = return_copy;
439 while (nregs);
441 /* If we didn't see a full return value copy, verify that there
442 is a plausible reason for this. If some, but not all of the
443 return register is likely spilled, we can expect that there
444 is a copy for the likely spilled part. */
445 gcc_assert (!nregs
446 || forced_late_switch
447 || short_block
448 || !(targetm.class_likely_spilled_p
449 (REGNO_REG_CLASS (ret_start)))
450 || nregs != REG_NREGS (ret_reg)
451 /* For multi-hard-register floating point
452 values, sometimes the likely-spilled part
453 is ordinarily copied first, then the other
454 part is set with an arithmetic operation.
455 This doesn't actually cause reload
456 failures, so let it pass. */
457 || (GET_MODE_CLASS (GET_MODE (ret_reg)) != MODE_INT
458 && nregs != 1));
460 if (!NOTE_INSN_BASIC_BLOCK_P (last_insn))
462 before_return_copy
463 = emit_note_before (NOTE_INSN_DELETED, last_insn);
464 /* Instructions preceding LAST_INSN in the same block might
465 require a different mode than MODE_EXIT, so if we might
466 have such instructions, keep them in a separate block
467 from pre_exit. */
468 src_bb = split_block (src_bb,
469 PREV_INSN (before_return_copy))->dest;
471 else
472 before_return_copy = last_insn;
473 pre_exit = split_block (src_bb, before_return_copy)->src;
475 else
477 pre_exit = split_edge (eg);
481 return pre_exit;
484 /* Find all insns that need a particular mode setting, and insert the
485 necessary mode switches. Return true if we did work. */
487 static int
488 optimize_mode_switching (void)
490 int e;
491 basic_block bb;
492 bool need_commit = false;
493 static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING;
494 #define N_ENTITIES ARRAY_SIZE (num_modes)
495 int entity_map[N_ENTITIES] = {};
496 struct bb_info *bb_info[N_ENTITIES] = {};
497 int i, j;
498 int n_entities = 0;
499 int max_num_modes = 0;
500 bool emitted ATTRIBUTE_UNUSED = false;
501 basic_block post_entry = 0;
502 basic_block pre_exit = 0;
503 struct edge_list *edge_list = 0;
505 /* These bitmaps are used for the LCM algorithm. */
506 sbitmap *kill, *del, *insert, *antic, *transp, *comp;
507 sbitmap *avin, *avout;
509 for (e = N_ENTITIES - 1; e >= 0; e--)
510 if (OPTIMIZE_MODE_SWITCHING (e))
512 int entry_exit_extra = 0;
514 /* Create the list of segments within each basic block.
515 If NORMAL_MODE is defined, allow for two extra
516 blocks split from the entry and exit block. */
517 if (targetm.mode_switching.entry && targetm.mode_switching.exit)
518 entry_exit_extra = 3;
520 bb_info[n_entities]
521 = XCNEWVEC (struct bb_info,
522 last_basic_block_for_fn (cfun) + entry_exit_extra);
523 entity_map[n_entities++] = e;
524 if (num_modes[e] > max_num_modes)
525 max_num_modes = num_modes[e];
528 if (! n_entities)
529 return 0;
531 /* Make sure if MODE_ENTRY is defined MODE_EXIT is defined. */
532 gcc_assert ((targetm.mode_switching.entry && targetm.mode_switching.exit)
533 || (!targetm.mode_switching.entry
534 && !targetm.mode_switching.exit));
536 if (targetm.mode_switching.entry && targetm.mode_switching.exit)
538 /* Split the edge from the entry block, so that we can note that
539 there NORMAL_MODE is supplied. */
540 post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
541 pre_exit = create_pre_exit (n_entities, entity_map, num_modes);
544 df_analyze ();
546 /* Create the bitmap vectors. */
547 antic = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
548 n_entities * max_num_modes);
549 transp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
550 n_entities * max_num_modes);
551 comp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
552 n_entities * max_num_modes);
553 avin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
554 n_entities * max_num_modes);
555 avout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
556 n_entities * max_num_modes);
557 kill = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
558 n_entities * max_num_modes);
560 bitmap_vector_ones (transp, last_basic_block_for_fn (cfun));
561 bitmap_vector_clear (antic, last_basic_block_for_fn (cfun));
562 bitmap_vector_clear (comp, last_basic_block_for_fn (cfun));
564 for (j = n_entities - 1; j >= 0; j--)
566 int e = entity_map[j];
567 int no_mode = num_modes[e];
568 struct bb_info *info = bb_info[j];
569 rtx_insn *insn;
571 /* Determine what the first use (if any) need for a mode of entity E is.
572 This will be the mode that is anticipatable for this block.
573 Also compute the initial transparency settings. */
574 FOR_EACH_BB_FN (bb, cfun)
576 struct seginfo *ptr;
577 int last_mode = no_mode;
578 bool any_set_required = false;
579 HARD_REG_SET live_now;
581 info[bb->index].mode_out = info[bb->index].mode_in = no_mode;
583 REG_SET_TO_HARD_REG_SET (live_now, df_get_live_in (bb));
585 /* Pretend the mode is clobbered across abnormal edges. */
587 edge_iterator ei;
588 edge eg;
589 FOR_EACH_EDGE (eg, ei, bb->preds)
590 if (eg->flags & EDGE_COMPLEX)
591 break;
592 if (eg)
594 rtx_insn *ins_pos = BB_HEAD (bb);
595 if (LABEL_P (ins_pos))
596 ins_pos = NEXT_INSN (ins_pos);
597 gcc_assert (NOTE_INSN_BASIC_BLOCK_P (ins_pos));
598 if (ins_pos != BB_END (bb))
599 ins_pos = NEXT_INSN (ins_pos);
600 ptr = new_seginfo (no_mode, ins_pos, live_now);
601 add_seginfo (info + bb->index, ptr);
602 for (i = 0; i < no_mode; i++)
603 clear_mode_bit (transp[bb->index], j, i);
607 FOR_BB_INSNS (bb, insn)
609 if (INSN_P (insn))
611 int mode = targetm.mode_switching.needed (e, insn);
612 rtx link;
614 if (mode != no_mode && mode != last_mode)
616 any_set_required = true;
617 last_mode = mode;
618 ptr = new_seginfo (mode, insn, live_now);
619 add_seginfo (info + bb->index, ptr);
620 for (i = 0; i < no_mode; i++)
621 clear_mode_bit (transp[bb->index], j, i);
624 if (targetm.mode_switching.after)
625 last_mode = targetm.mode_switching.after (e, last_mode,
626 insn);
628 /* Update LIVE_NOW. */
629 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
630 if (REG_NOTE_KIND (link) == REG_DEAD)
631 reg_dies (XEXP (link, 0), &live_now);
633 note_stores (insn, reg_becomes_live, &live_now);
634 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
635 if (REG_NOTE_KIND (link) == REG_UNUSED)
636 reg_dies (XEXP (link, 0), &live_now);
640 info[bb->index].computing = last_mode;
641 /* Check for blocks without ANY mode requirements.
642 N.B. because of MODE_AFTER, last_mode might still
643 be different from no_mode, in which case we need to
644 mark the block as nontransparent. */
645 if (!any_set_required)
647 ptr = new_seginfo (no_mode, BB_END (bb), live_now);
648 add_seginfo (info + bb->index, ptr);
649 if (last_mode != no_mode)
650 for (i = 0; i < no_mode; i++)
651 clear_mode_bit (transp[bb->index], j, i);
654 if (targetm.mode_switching.entry && targetm.mode_switching.exit)
656 int mode = targetm.mode_switching.entry (e);
658 info[post_entry->index].mode_out =
659 info[post_entry->index].mode_in = no_mode;
660 if (pre_exit)
662 info[pre_exit->index].mode_out =
663 info[pre_exit->index].mode_in = no_mode;
666 if (mode != no_mode)
668 bb = post_entry;
670 /* By always making this nontransparent, we save
671 an extra check in make_preds_opaque. We also
672 need this to avoid confusing pre_edge_lcm when
673 antic is cleared but transp and comp are set. */
674 for (i = 0; i < no_mode; i++)
675 clear_mode_bit (transp[bb->index], j, i);
677 /* Insert a fake computing definition of MODE into entry
678 blocks which compute no mode. This represents the mode on
679 entry. */
680 info[bb->index].computing = mode;
682 if (pre_exit)
683 info[pre_exit->index].seginfo->mode =
684 targetm.mode_switching.exit (e);
688 /* Set the anticipatable and computing arrays. */
689 for (i = 0; i < no_mode; i++)
691 int m = targetm.mode_switching.priority (entity_map[j], i);
693 FOR_EACH_BB_FN (bb, cfun)
695 if (info[bb->index].seginfo->mode == m)
696 set_mode_bit (antic[bb->index], j, m);
698 if (info[bb->index].computing == m)
699 set_mode_bit (comp[bb->index], j, m);
704 /* Calculate the optimal locations for the
705 placement mode switches to modes with priority I. */
707 FOR_EACH_BB_FN (bb, cfun)
708 bitmap_not (kill[bb->index], transp[bb->index]);
710 edge_list = pre_edge_lcm_avs (n_entities * max_num_modes, transp, comp, antic,
711 kill, avin, avout, &insert, &del);
713 for (j = n_entities - 1; j >= 0; j--)
715 int no_mode = num_modes[entity_map[j]];
717 /* Insert all mode sets that have been inserted by lcm. */
719 for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--)
721 edge eg = INDEX_EDGE (edge_list, ed);
723 eg->aux = (void *)(intptr_t)-1;
725 for (i = 0; i < no_mode; i++)
727 int m = targetm.mode_switching.priority (entity_map[j], i);
728 if (mode_bit_p (insert[ed], j, m))
730 eg->aux = (void *)(intptr_t)m;
731 break;
736 FOR_EACH_BB_FN (bb, cfun)
738 struct bb_info *info = bb_info[j];
739 int last_mode = no_mode;
741 /* intialize mode in availability for bb. */
742 for (i = 0; i < no_mode; i++)
743 if (mode_bit_p (avout[bb->index], j, i))
745 if (last_mode == no_mode)
746 last_mode = i;
747 if (last_mode != i)
749 last_mode = no_mode;
750 break;
753 info[bb->index].mode_out = last_mode;
755 /* intialize mode out availability for bb. */
756 last_mode = no_mode;
757 for (i = 0; i < no_mode; i++)
758 if (mode_bit_p (avin[bb->index], j, i))
760 if (last_mode == no_mode)
761 last_mode = i;
762 if (last_mode != i)
764 last_mode = no_mode;
765 break;
768 info[bb->index].mode_in = last_mode;
770 for (i = 0; i < no_mode; i++)
771 if (mode_bit_p (del[bb->index], j, i))
772 info[bb->index].seginfo->mode = no_mode;
775 /* Now output the remaining mode sets in all the segments. */
777 /* In case there was no mode inserted. the mode information on the edge
778 might not be complete.
779 Update mode info on edges and commit pending mode sets. */
780 need_commit |= commit_mode_sets (edge_list, entity_map[j], bb_info[j]);
782 /* Reset modes for next entity. */
783 clear_aux_for_edges ();
785 FOR_EACH_BB_FN (bb, cfun)
787 struct seginfo *ptr, *next;
788 int cur_mode = bb_info[j][bb->index].mode_in;
790 for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next)
792 next = ptr->next;
793 if (ptr->mode != no_mode)
795 rtx_insn *mode_set;
797 rtl_profile_for_bb (bb);
798 start_sequence ();
800 targetm.mode_switching.emit (entity_map[j], ptr->mode,
801 cur_mode, ptr->regs_live);
802 mode_set = get_insns ();
803 end_sequence ();
805 /* modes kill each other inside a basic block. */
806 cur_mode = ptr->mode;
808 /* Insert MODE_SET only if it is nonempty. */
809 if (mode_set != NULL_RTX)
811 emitted = true;
812 if (NOTE_INSN_BASIC_BLOCK_P (ptr->insn_ptr))
813 /* We need to emit the insns in a FIFO-like manner,
814 i.e. the first to be emitted at our insertion
815 point ends up first in the instruction steam.
816 Because we made sure that NOTE_INSN_BASIC_BLOCK is
817 only used for initially empty basic blocks, we
818 can achieve this by appending at the end of
819 the block. */
820 emit_insn_after
821 (mode_set, BB_END (NOTE_BASIC_BLOCK (ptr->insn_ptr)));
822 else
823 emit_insn_before (mode_set, ptr->insn_ptr);
826 default_rtl_profile ();
829 free (ptr);
833 free (bb_info[j]);
836 free_edge_list (edge_list);
838 /* Finished. Free up all the things we've allocated. */
839 sbitmap_vector_free (del);
840 sbitmap_vector_free (insert);
841 sbitmap_vector_free (kill);
842 sbitmap_vector_free (antic);
843 sbitmap_vector_free (transp);
844 sbitmap_vector_free (comp);
845 sbitmap_vector_free (avin);
846 sbitmap_vector_free (avout);
848 if (need_commit)
849 commit_edge_insertions ();
851 if (targetm.mode_switching.entry && targetm.mode_switching.exit)
853 free_dominance_info (CDI_DOMINATORS);
854 cleanup_cfg (CLEANUP_NO_INSN_DEL);
856 else if (!need_commit && !emitted)
857 return 0;
859 return 1;
862 #endif /* OPTIMIZE_MODE_SWITCHING */
864 namespace {
866 const pass_data pass_data_mode_switching =
868 RTL_PASS, /* type */
869 "mode_sw", /* name */
870 OPTGROUP_NONE, /* optinfo_flags */
871 TV_MODE_SWITCH, /* tv_id */
872 0, /* properties_required */
873 0, /* properties_provided */
874 0, /* properties_destroyed */
875 0, /* todo_flags_start */
876 TODO_df_finish, /* todo_flags_finish */
879 class pass_mode_switching : public rtl_opt_pass
881 public:
882 pass_mode_switching (gcc::context *ctxt)
883 : rtl_opt_pass (pass_data_mode_switching, ctxt)
886 /* opt_pass methods: */
887 /* The epiphany backend creates a second instance of this pass, so we need
888 a clone method. */
889 opt_pass * clone () final override { return new pass_mode_switching (m_ctxt); }
890 bool gate (function *) final override
892 #ifdef OPTIMIZE_MODE_SWITCHING
893 return true;
894 #else
895 return false;
896 #endif
899 unsigned int execute (function *) final override
901 #ifdef OPTIMIZE_MODE_SWITCHING
902 optimize_mode_switching ();
903 #endif /* OPTIMIZE_MODE_SWITCHING */
904 return 0;
907 }; // class pass_mode_switching
909 } // anon namespace
911 rtl_opt_pass *
912 make_pass_mode_switching (gcc::context *ctxt)
914 return new pass_mode_switching (ctxt);