]> gcc.gnu.org Git - gcc.git/blame - gcc/mode-switching.cc
mode-switching: Remove unused bbnum field
[gcc.git] / gcc / mode-switching.cc
CommitLineData
610d2478 1/* CPU mode switching
aeee4812 2 Copyright (C) 1998-2023 Free Software Foundation, Inc.
610d2478
SB
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
9dcd6f09 8Software Foundation; either version 3, or (at your option) any later
610d2478
SB
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
9dcd6f09
NC
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
610d2478
SB
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
c7131fb2 23#include "backend.h"
957060b5 24#include "target.h"
610d2478 25#include "rtl.h"
957060b5 26#include "cfghooks.h"
c7131fb2 27#include "df.h"
4d0cdd0c 28#include "memmodel.h"
957060b5 29#include "tm_p.h"
957060b5
AM
30#include "regs.h"
31#include "emit-rtl.h"
60393bbc
AM
32#include "cfgrtl.h"
33#include "cfganal.h"
34#include "lcm.h"
35#include "cfgcleanup.h"
ef330312 36#include "tree-pass.h"
610d2478
SB
37
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"
41
42#ifdef OPTIMIZE_MODE_SWITCHING
43
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
cee9defb 48 the flow graph basic blocks (local var 'bb_info'), which contains a list
610d2478
SB
49 of all insns within that basic block, in the order they are encountered.
50
51 For each entity, any basic block WITHOUT any insns requiring a specific
cee9defb
EB
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).
610d2478
SB
54
55 The LCM algorithm is then run over the flow graph to determine where to
cee9defb 56 place the sets to the highest-priority mode with respect to the first
610d2478
SB
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.
60
cee9defb 61 More details can be found in the code of optimize_mode_switching. */
610d2478
SB
62\f
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).
610d2478
SB
68 NEXT is the next insn in the same basic block. */
69struct seginfo
70{
71 int mode;
1d455520 72 rtx_insn *insn_ptr;
610d2478
SB
73 struct seginfo *next;
74 HARD_REG_SET regs_live;
75};
76
77struct bb_info
78{
79 struct seginfo *seginfo;
80 int computing;
cbb1e3d9
CB
81 int mode_out;
82 int mode_in;
610d2478
SB
83};
84
cbb1e3d9
CB
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)
88
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)
92
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)
96
97/* Emit modes segments from EDGE_LIST associated with entity E.
98 INFO gives mode availability for each mode. */
99
100static bool
101commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info)
102{
103 bool need_commit = false;
104
105 for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--)
106 {
107 edge eg = INDEX_EDGE (edge_list, ed);
108 int mode;
109
110 if ((mode = (int)(intptr_t)(eg->aux)) != -1)
111 {
112 HARD_REG_SET live_at_edge;
113 basic_block src_bb = eg->src;
114 int cur_mode = info[src_bb->index].mode_out;
f4701c96 115 rtx_insn *mode_set;
cbb1e3d9
CB
116
117 REG_SET_TO_HARD_REG_SET (live_at_edge, df_get_live_out (src_bb));
118
119 rtl_profile_for_edge (eg);
120 start_sequence ();
121
122 targetm.mode_switching.emit (e, mode, cur_mode, live_at_edge);
123
124 mode_set = get_insns ();
125 end_sequence ();
126 default_rtl_profile ();
127
128 /* Do not bother to insert empty sequence. */
f4701c96 129 if (mode_set == NULL)
cbb1e3d9
CB
130 continue;
131
132 /* We should not get an abnormal edge here. */
133 gcc_assert (! (eg->flags & EDGE_ABNORMAL));
134
135 need_commit = true;
136 insert_insn_on_edge (mode_set, eg);
137 }
138 }
139
140 return need_commit;
141}
142
143/* Allocate a new BBINFO structure, initialized with the MODE, INSN,
2d55ed2b 144 and REGS_LIVE parameters.
473fd99a
JR
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. */
610d2478
SB
148
149static struct seginfo *
2d55ed2b 150new_seginfo (int mode, rtx_insn *insn, const HARD_REG_SET &regs_live)
610d2478
SB
151{
152 struct seginfo *ptr;
473fd99a
JR
153
154 gcc_assert (!NOTE_INSN_BASIC_BLOCK_P (insn)
155 || insn == BB_END (NOTE_BASIC_BLOCK (insn)));
5ed6ace5 156 ptr = XNEW (struct seginfo);
610d2478
SB
157 ptr->mode = mode;
158 ptr->insn_ptr = insn;
610d2478 159 ptr->next = NULL;
6576d245 160 ptr->regs_live = regs_live;
610d2478
SB
161 return ptr;
162}
163
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. */
167
168static void
169add_seginfo (struct bb_info *head, struct seginfo *info)
170{
171 struct seginfo *ptr;
172
173 if (head->seginfo == NULL)
174 head->seginfo = info;
175 else
176 {
177 ptr = head->seginfo;
178 while (ptr->next != NULL)
179 ptr = ptr->next;
180 ptr->next = info;
181 }
182}
183
610d2478
SB
184/* Record in LIVE that register REG died. */
185
186static void
408bed3c 187reg_dies (rtx reg, HARD_REG_SET *live)
610d2478 188{
09e18274 189 int regno;
610d2478
SB
190
191 if (!REG_P (reg))
192 return;
193
194 regno = REGNO (reg);
195 if (regno < FIRST_PSEUDO_REGISTER)
09e18274 196 remove_from_hard_reg_set (live, GET_MODE (reg), regno);
610d2478
SB
197}
198
199/* Record in LIVE that register REG became live.
200 This is called via note_stores. */
201
202static void
7bc980e1 203reg_becomes_live (rtx reg, const_rtx setter ATTRIBUTE_UNUSED, void *live)
610d2478 204{
09e18274 205 int regno;
610d2478
SB
206
207 if (GET_CODE (reg) == SUBREG)
208 reg = SUBREG_REG (reg);
209
210 if (!REG_P (reg))
211 return;
212
213 regno = REGNO (reg);
214 if (regno < FIRST_PSEUDO_REGISTER)
09e18274 215 add_to_hard_reg_set ((HARD_REG_SET *) live, GET_MODE (reg), regno);
610d2478
SB
216}
217
610d2478
SB
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. */
221
222static basic_block
223create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
224{
225 edge eg;
226 edge_iterator ei;
227 basic_block pre_exit;
228
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;
fefa31b5 233 FOR_EACH_EDGE (eg, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
610d2478
SB
234 if (eg->flags & EDGE_FALLTHRU)
235 {
236 basic_block src_bb = eg->src;
1d455520
DM
237 rtx_insn *last_insn;
238 rtx ret_reg;
610d2478
SB
239
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
59730cc5
UB
243 to its hard register.
244
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.
251
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
610d2478
SB
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)
262 {
263 int ret_start = REGNO (ret_reg);
dc8afb70 264 int nregs = REG_NREGS (ret_reg);
610d2478 265 int ret_end = ret_start + nregs;
c07757e5
UB
266 bool short_block = false;
267 bool multi_reg_return = false;
268 bool forced_late_switch = false;
1d455520 269 rtx_insn *before_return_copy;
610d2478
SB
270
271 do
272 {
1d455520 273 rtx_insn *return_copy = PREV_INSN (last_insn);
610d2478
SB
274 rtx return_copy_pat, copy_reg;
275 int copy_start, copy_num;
276 int j;
277
141a9e06 278 if (NONDEBUG_INSN_P (return_copy))
610d2478 279 {
2bde7ae9
RS
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))
287 {
c07757e5 288 short_block = true;
2bde7ae9
RS
289 break;
290 }
89ab4659
KK
291 return_copy_pat = PATTERN (return_copy);
292 switch (GET_CODE (return_copy_pat))
07288ab0 293 {
89ab4659 294 case USE:
c07757e5
UB
295 /* Skip USEs of multiple return registers.
296 __builtin_apply pattern is also handled here. */
89ab4659 297 if (GET_CODE (XEXP (return_copy_pat, 0)) == REG
82f81f18 298 && (targetm.calls.function_value_regno_p
89ab4659
KK
299 (REGNO (XEXP (return_copy_pat, 0)))))
300 {
c07757e5 301 multi_reg_return = true;
89ab4659
KK
302 last_insn = return_copy;
303 continue;
304 }
305 break;
306
307 case ASM_OPERANDS:
308 /* Skip barrier insns. */
309 if (!MEM_VOLATILE_P (return_copy_pat))
310 break;
311
312 /* Fall through. */
313
314 case ASM_INPUT:
315 case UNSPEC_VOLATILE:
07288ab0
KK
316 last_insn = return_copy;
317 continue;
89ab4659
KK
318
319 default:
320 break;
07288ab0 321 }
89ab4659 322
610d2478
SB
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)
328 {
329 return_copy_pat = PATTERN (return_copy);
330 if (GET_CODE (return_copy_pat) != CLOBBER)
331 break;
6fb5fa3c
DB
332 else if (!optimize)
333 {
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)))
341 {
342 if (INSN_P (PREV_INSN (return_copy)))
343 {
344 return_copy = PREV_INSN (return_copy);
345 return_copy_pat = PATTERN (return_copy);
346 if (GET_CODE (return_copy_pat) != CLOBBER)
347 break;
348 }
349 }
350 }
610d2478
SB
351 }
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
d78e64db
KK
359 {
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)
c07757e5 364 short_block = true;
d78e64db
KK
365 break;
366 }
ffbbfaba 367 if (!targetm.calls.function_value_regno_p (copy_start))
ce4a9422
JR
368 copy_num = 0;
369 else
ad474626
RS
370 copy_num = hard_regno_nregs (copy_start,
371 GET_MODE (copy_reg));
610d2478
SB
372
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--)
378 {
379 int e = entity_map[j];
06b90602
CB
380 int mode =
381 targetm.mode_switching.needed (e, return_copy);
610d2478 382
06b90602
CB
383 if (mode != num_modes[e]
384 && mode != targetm.mode_switching.exit (e))
610d2478
SB
385 break;
386 }
387 if (j >= 0)
388 {
b8435aa9
UB
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. */
c07757e5 394 if (multi_reg_return
b8435aa9
UB
395 && targetm.calls.function_value_regno_p
396 (copy_start))
c07757e5 397 forced_late_switch = true;
b8435aa9 398
610d2478
SB
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
d5ef0ee3 406 && GET_CODE (return_copy_pat) == SET
610d2478 407 && OBJECT_P (SET_SRC (return_copy_pat)))
c07757e5 408 forced_late_switch = true;
610d2478
SB
409 break;
410 }
ce4a9422
JR
411 if (copy_num == 0)
412 {
413 last_insn = return_copy;
414 continue;
415 }
610d2478
SB
416
417 if (copy_start >= ret_start
418 && copy_start + copy_num <= ret_end)
419 nregs -= copy_num;
c07757e5 420 else if (!multi_reg_return
82f81f18
AS
421 || !targetm.calls.function_value_regno_p
422 (copy_start))
610d2478
SB
423 break;
424 last_insn = return_copy;
425 }
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))
433 {
c07757e5 434 short_block = true;
610d2478
SB
435 break;
436 }
437 last_insn = return_copy;
438 }
439 while (nregs);
b8698a0f 440
610d2478
SB
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
07b8f0a8 448 || !(targetm.class_likely_spilled_p
610d2478 449 (REGNO_REG_CLASS (ret_start)))
462a99aa 450 || nregs != REG_NREGS (ret_reg)
610d2478
SB
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));
b8698a0f 459
bba33211 460 if (!NOTE_INSN_BASIC_BLOCK_P (last_insn))
610d2478
SB
461 {
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. */
bba33211
JR
468 src_bb = split_block (src_bb,
469 PREV_INSN (before_return_copy))->dest;
610d2478
SB
470 }
471 else
472 before_return_copy = last_insn;
473 pre_exit = split_block (src_bb, before_return_copy)->src;
474 }
475 else
476 {
477 pre_exit = split_edge (eg);
610d2478
SB
478 }
479 }
480
481 return pre_exit;
482}
610d2478
SB
483
484/* Find all insns that need a particular mode setting, and insert the
485 necessary mode switches. Return true if we did work. */
486
7399bcb0 487static int
10d22567 488optimize_mode_switching (void)
610d2478 489{
610d2478
SB
490 int e;
491 basic_block bb;
cbb1e3d9 492 bool need_commit = false;
610d2478
SB
493 static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING;
494#define N_ENTITIES ARRAY_SIZE (num_modes)
65c7725e
PL
495 int entity_map[N_ENTITIES] = {};
496 struct bb_info *bb_info[N_ENTITIES] = {};
610d2478 497 int i, j;
cbb1e3d9 498 int n_entities = 0;
610d2478 499 int max_num_modes = 0;
073a8998 500 bool emitted ATTRIBUTE_UNUSED = false;
06b90602
CB
501 basic_block post_entry = 0;
502 basic_block pre_exit = 0;
cbb1e3d9
CB
503 struct edge_list *edge_list = 0;
504
505 /* These bitmaps are used for the LCM algorithm. */
506 sbitmap *kill, *del, *insert, *antic, *transp, *comp;
507 sbitmap *avin, *avout;
610d2478 508
cbb1e3d9 509 for (e = N_ENTITIES - 1; e >= 0; e--)
610d2478
SB
510 if (OPTIMIZE_MODE_SWITCHING (e))
511 {
512 int entry_exit_extra = 0;
513
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. */
06b90602
CB
517 if (targetm.mode_switching.entry && targetm.mode_switching.exit)
518 entry_exit_extra = 3;
519
610d2478 520 bb_info[n_entities]
8b1c6fd7
DM
521 = XCNEWVEC (struct bb_info,
522 last_basic_block_for_fn (cfun) + entry_exit_extra);
610d2478
SB
523 entity_map[n_entities++] = e;
524 if (num_modes[e] > max_num_modes)
525 max_num_modes = num_modes[e];
526 }
527
528 if (! n_entities)
529 return 0;
530
cbb1e3d9 531 /* Make sure if MODE_ENTRY is defined MODE_EXIT is defined. */
06b90602 532 gcc_assert ((targetm.mode_switching.entry && targetm.mode_switching.exit)
cbb1e3d9
CB
533 || (!targetm.mode_switching.entry
534 && !targetm.mode_switching.exit));
06b90602
CB
535
536 if (targetm.mode_switching.entry && targetm.mode_switching.exit)
537 {
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);
542 }
610d2478 543
6fb5fa3c
DB
544 df_analyze ();
545
610d2478 546 /* Create the bitmap vectors. */
cbb1e3d9
CB
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);
610d2478 559
8b1c6fd7 560 bitmap_vector_ones (transp, last_basic_block_for_fn (cfun));
cbb1e3d9
CB
561 bitmap_vector_clear (antic, last_basic_block_for_fn (cfun));
562 bitmap_vector_clear (comp, last_basic_block_for_fn (cfun));
610d2478
SB
563
564 for (j = n_entities - 1; j >= 0; j--)
565 {
566 int e = entity_map[j];
567 int no_mode = num_modes[e];
568 struct bb_info *info = bb_info[j];
1d455520 569 rtx_insn *insn;
610d2478
SB
570
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. */
11cd3bed 574 FOR_EACH_BB_FN (bb, cfun)
610d2478
SB
575 {
576 struct seginfo *ptr;
577 int last_mode = no_mode;
a44250f4 578 bool any_set_required = false;
610d2478
SB
579 HARD_REG_SET live_now;
580
cbb1e3d9
CB
581 info[bb->index].mode_out = info[bb->index].mode_in = no_mode;
582
6fb5fa3c 583 REG_SET_TO_HARD_REG_SET (live_now, df_get_live_in (bb));
24c2fde2
RH
584
585 /* Pretend the mode is clobbered across abnormal edges. */
586 {
587 edge_iterator ei;
cbb1e3d9
CB
588 edge eg;
589 FOR_EACH_EDGE (eg, ei, bb->preds)
590 if (eg->flags & EDGE_COMPLEX)
24c2fde2 591 break;
cbb1e3d9 592 if (eg)
650a59ef 593 {
1d455520 594 rtx_insn *ins_pos = BB_HEAD (bb);
473fd99a
JR
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);
2d55ed2b 600 ptr = new_seginfo (no_mode, ins_pos, live_now);
650a59ef 601 add_seginfo (info + bb->index, ptr);
cbb1e3d9
CB
602 for (i = 0; i < no_mode; i++)
603 clear_mode_bit (transp[bb->index], j, i);
650a59ef 604 }
24c2fde2
RH
605 }
606
0f346928 607 FOR_BB_INSNS (bb, insn)
610d2478
SB
608 {
609 if (INSN_P (insn))
610 {
06b90602 611 int mode = targetm.mode_switching.needed (e, insn);
610d2478
SB
612 rtx link;
613
614 if (mode != no_mode && mode != last_mode)
615 {
a44250f4 616 any_set_required = true;
610d2478 617 last_mode = mode;
2d55ed2b 618 ptr = new_seginfo (mode, insn, live_now);
610d2478 619 add_seginfo (info + bb->index, ptr);
cbb1e3d9
CB
620 for (i = 0; i < no_mode; i++)
621 clear_mode_bit (transp[bb->index], j, i);
610d2478 622 }
06b90602
CB
623
624 if (targetm.mode_switching.after)
cbb1e3d9
CB
625 last_mode = targetm.mode_switching.after (e, last_mode,
626 insn);
06b90602 627
610d2478
SB
628 /* Update LIVE_NOW. */
629 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
630 if (REG_NOTE_KIND (link) == REG_DEAD)
408bed3c 631 reg_dies (XEXP (link, 0), &live_now);
610d2478 632
e8448ba5 633 note_stores (insn, reg_becomes_live, &live_now);
610d2478
SB
634 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
635 if (REG_NOTE_KIND (link) == REG_UNUSED)
408bed3c 636 reg_dies (XEXP (link, 0), &live_now);
610d2478
SB
637 }
638 }
639
640 info[bb->index].computing = last_mode;
a44250f4 641 /* Check for blocks without ANY mode requirements.
611a4849
UB
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. */
a44250f4 645 if (!any_set_required)
610d2478 646 {
2d55ed2b 647 ptr = new_seginfo (no_mode, BB_END (bb), live_now);
610d2478 648 add_seginfo (info + bb->index, ptr);
611a4849 649 if (last_mode != no_mode)
cbb1e3d9
CB
650 for (i = 0; i < no_mode; i++)
651 clear_mode_bit (transp[bb->index], j, i);
610d2478
SB
652 }
653 }
06b90602
CB
654 if (targetm.mode_switching.entry && targetm.mode_switching.exit)
655 {
656 int mode = targetm.mode_switching.entry (e);
610d2478 657
cbb1e3d9
CB
658 info[post_entry->index].mode_out =
659 info[post_entry->index].mode_in = no_mode;
660 if (pre_exit)
661 {
662 info[pre_exit->index].mode_out =
663 info[pre_exit->index].mode_in = no_mode;
664 }
665
06b90602
CB
666 if (mode != no_mode)
667 {
668 bb = post_entry;
669
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. */
cbb1e3d9
CB
674 for (i = 0; i < no_mode; i++)
675 clear_mode_bit (transp[bb->index], j, i);
06b90602
CB
676
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;
681
682 if (pre_exit)
683 info[pre_exit->index].seginfo->mode =
684 targetm.mode_switching.exit (e);
685 }
686 }
610d2478
SB
687
688 /* Set the anticipatable and computing arrays. */
cbb1e3d9 689 for (i = 0; i < no_mode; i++)
610d2478 690 {
cbb1e3d9 691 int m = targetm.mode_switching.priority (entity_map[j], i);
610d2478 692
11cd3bed 693 FOR_EACH_BB_FN (bb, cfun)
610d2478
SB
694 {
695 if (info[bb->index].seginfo->mode == m)
cbb1e3d9 696 set_mode_bit (antic[bb->index], j, m);
610d2478
SB
697
698 if (info[bb->index].computing == m)
cbb1e3d9 699 set_mode_bit (comp[bb->index], j, m);
610d2478
SB
700 }
701 }
cbb1e3d9 702 }
610d2478 703
cbb1e3d9
CB
704 /* Calculate the optimal locations for the
705 placement mode switches to modes with priority I. */
610d2478 706
cbb1e3d9
CB
707 FOR_EACH_BB_FN (bb, cfun)
708 bitmap_not (kill[bb->index], transp[bb->index]);
610d2478 709
cbb1e3d9
CB
710 edge_list = pre_edge_lcm_avs (n_entities * max_num_modes, transp, comp, antic,
711 kill, avin, avout, &insert, &del);
610d2478 712
cbb1e3d9
CB
713 for (j = n_entities - 1; j >= 0; j--)
714 {
715 int no_mode = num_modes[entity_map[j]];
610d2478 716
cbb1e3d9 717 /* Insert all mode sets that have been inserted by lcm. */
610d2478 718
cbb1e3d9
CB
719 for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--)
720 {
721 edge eg = INDEX_EDGE (edge_list, ed);
610d2478 722
cbb1e3d9 723 eg->aux = (void *)(intptr_t)-1;
610d2478 724
cbb1e3d9
CB
725 for (i = 0; i < no_mode; i++)
726 {
727 int m = targetm.mode_switching.priority (entity_map[j], i);
728 if (mode_bit_p (insert[ed], j, m))
729 {
730 eg->aux = (void *)(intptr_t)m;
731 break;
732 }
733 }
734 }
610d2478 735
cbb1e3d9
CB
736 FOR_EACH_BB_FN (bb, cfun)
737 {
738 struct bb_info *info = bb_info[j];
739 int last_mode = no_mode;
650a59ef 740
cbb1e3d9
CB
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))
744 {
745 if (last_mode == no_mode)
746 last_mode = i;
747 if (last_mode != i)
748 {
749 last_mode = no_mode;
750 break;
751 }
752 }
753 info[bb->index].mode_out = last_mode;
610d2478 754
cbb1e3d9
CB
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))
610d2478 759 {
cbb1e3d9
CB
760 if (last_mode == no_mode)
761 last_mode = i;
762 if (last_mode != i)
763 {
764 last_mode = no_mode;
765 break;
766 }
610d2478 767 }
cbb1e3d9
CB
768 info[bb->index].mode_in = last_mode;
769
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;
610d2478
SB
773 }
774
cbb1e3d9 775 /* Now output the remaining mode sets in all the segments. */
610d2478 776
cbb1e3d9
CB
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]);
781
782 /* Reset modes for next entity. */
783 clear_aux_for_edges ();
610d2478 784
cbb1e3d9 785 FOR_EACH_BB_FN (bb, cfun)
610d2478
SB
786 {
787 struct seginfo *ptr, *next;
cbb1e3d9
CB
788 int cur_mode = bb_info[j][bb->index].mode_in;
789
610d2478
SB
790 for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next)
791 {
792 next = ptr->next;
793 if (ptr->mode != no_mode)
794 {
1d455520 795 rtx_insn *mode_set;
610d2478 796
5f28524a 797 rtl_profile_for_bb (bb);
610d2478 798 start_sequence ();
cbb1e3d9
CB
799
800 targetm.mode_switching.emit (entity_map[j], ptr->mode,
801 cur_mode, ptr->regs_live);
610d2478
SB
802 mode_set = get_insns ();
803 end_sequence ();
804
cbb1e3d9
CB
805 /* modes kill each other inside a basic block. */
806 cur_mode = ptr->mode;
807
610d2478
SB
808 /* Insert MODE_SET only if it is nonempty. */
809 if (mode_set != NULL_RTX)
810 {
073a8998 811 emitted = true;
a38e7aa5 812 if (NOTE_INSN_BASIC_BLOCK_P (ptr->insn_ptr))
473fd99a
JR
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
74145685 818 can achieve this by appending at the end of
473fd99a
JR
819 the block. */
820 emit_insn_after
821 (mode_set, BB_END (NOTE_BASIC_BLOCK (ptr->insn_ptr)));
610d2478
SB
822 else
823 emit_insn_before (mode_set, ptr->insn_ptr);
824 }
5f28524a
JH
825
826 default_rtl_profile ();
610d2478
SB
827 }
828
829 free (ptr);
830 }
831 }
832
833 free (bb_info[j]);
834 }
835
cbb1e3d9
CB
836 free_edge_list (edge_list);
837
610d2478 838 /* Finished. Free up all the things we've allocated. */
cbb1e3d9
CB
839 sbitmap_vector_free (del);
840 sbitmap_vector_free (insert);
610d2478
SB
841 sbitmap_vector_free (kill);
842 sbitmap_vector_free (antic);
843 sbitmap_vector_free (transp);
844 sbitmap_vector_free (comp);
cbb1e3d9
CB
845 sbitmap_vector_free (avin);
846 sbitmap_vector_free (avout);
610d2478
SB
847
848 if (need_commit)
849 commit_edge_insertions ();
850
06b90602 851 if (targetm.mode_switching.entry && targetm.mode_switching.exit)
09822562
RB
852 {
853 free_dominance_info (CDI_DOMINATORS);
854 cleanup_cfg (CLEANUP_NO_INSN_DEL);
855 }
06b90602 856 else if (!need_commit && !emitted)
610d2478 857 return 0;
610d2478 858
610d2478
SB
859 return 1;
860}
ef330312 861
610d2478 862#endif /* OPTIMIZE_MODE_SWITCHING */
ef330312 863\f
17795822
TS
864namespace {
865
866const pass_data pass_data_mode_switching =
ef330312 867{
27a4cd48
DM
868 RTL_PASS, /* type */
869 "mode_sw", /* name */
870 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
871 TV_MODE_SWITCH, /* tv_id */
872 0, /* properties_required */
873 0, /* properties_provided */
874 0, /* properties_destroyed */
875 0, /* todo_flags_start */
3bea341f 876 TODO_df_finish, /* todo_flags_finish */
ef330312 877};
27a4cd48 878
17795822 879class pass_mode_switching : public rtl_opt_pass
27a4cd48
DM
880{
881public:
c3284718
RS
882 pass_mode_switching (gcc::context *ctxt)
883 : rtl_opt_pass (pass_data_mode_switching, ctxt)
27a4cd48
DM
884 {}
885
886 /* opt_pass methods: */
05555c4a
DM
887 /* The epiphany backend creates a second instance of this pass, so we need
888 a clone method. */
725793af
DM
889 opt_pass * clone () final override { return new pass_mode_switching (m_ctxt); }
890 bool gate (function *) final override
1a3d085c
TS
891 {
892#ifdef OPTIMIZE_MODE_SWITCHING
893 return true;
894#else
895 return false;
896#endif
897 }
898
725793af 899 unsigned int execute (function *) final override
be55bfe6
TS
900 {
901#ifdef OPTIMIZE_MODE_SWITCHING
902 optimize_mode_switching ();
903#endif /* OPTIMIZE_MODE_SWITCHING */
904 return 0;
905 }
27a4cd48
DM
906
907}; // class pass_mode_switching
908
17795822
TS
909} // anon namespace
910
27a4cd48
DM
911rtl_opt_pass *
912make_pass_mode_switching (gcc::context *ctxt)
913{
914 return new pass_mode_switching (ctxt);
915}
This page took 9.002362 seconds and 5 git commands to generate.