2012-09-04 Janus Weil <janus@gcc.gnu.org>
[official-gcc.git] / gcc / ira-emit.c
blobdbab53741736bdb51f6ffb8089625668d23aa3dd
1 /* Integrated Register Allocator. Changing code and generating moves.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc.
4 Contributed by Vladimir Makarov <vmakarov@redhat.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* When we have more one region, we need to change the original RTL
23 code after coloring. Let us consider two allocnos representing the
24 same pseudo-register outside and inside a region respectively.
25 They can get different hard-registers. The reload pass works on
26 pseudo registers basis and there is no way to say the reload that
27 pseudo could be in different registers and it is even more
28 difficult to say in what places of the code the pseudo should have
29 particular hard-registers. So in this case IRA has to create and
30 use a new pseudo-register inside the region and adds code to move
31 allocno values on the region's borders. This is done by the code
32 in this file.
34 The code makes top-down traversal of the regions and generate new
35 pseudos and the move code on the region borders. In some
36 complicated cases IRA can create a new pseudo used temporarily to
37 move allocno values when a swap of values stored in two
38 hard-registers is needed (e.g. two allocnos representing different
39 pseudos outside region got respectively hard registers 1 and 2 and
40 the corresponding allocnos inside the region got respectively hard
41 registers 2 and 1). At this stage, the new pseudo is marked as
42 spilled.
44 IRA still creates the pseudo-register and the moves on the region
45 borders even when the both corresponding allocnos were assigned to
46 the same hard-register. It is done because, if the reload pass for
47 some reason spills a pseudo-register representing the original
48 pseudo outside or inside the region, the effect will be smaller
49 because another pseudo will still be in the hard-register. In most
50 cases, this is better then spilling the original pseudo in its
51 whole live-range. If reload does not change the allocation for the
52 two pseudo-registers, the trivial move will be removed by
53 post-reload optimizations.
55 IRA does not generate a new pseudo and moves for the allocno values
56 if the both allocnos representing an original pseudo inside and
57 outside region assigned to the same hard register when the register
58 pressure in the region for the corresponding pressure class is less
59 than number of available hard registers for given pressure class.
61 IRA also does some optimizations to remove redundant moves which is
62 transformed into stores by the reload pass on CFG edges
63 representing exits from the region.
65 IRA tries to reduce duplication of code generated on CFG edges
66 which are enters and exits to/from regions by moving some code to
67 the edge sources or destinations when it is possible. */
69 #include "config.h"
70 #include "system.h"
71 #include "coretypes.h"
72 #include "tm.h"
73 #include "regs.h"
74 #include "rtl.h"
75 #include "tm_p.h"
76 #include "target.h"
77 #include "flags.h"
78 #include "obstack.h"
79 #include "bitmap.h"
80 #include "hard-reg-set.h"
81 #include "basic-block.h"
82 #include "expr.h"
83 #include "recog.h"
84 #include "params.h"
85 #include "reload.h"
86 #include "df.h"
87 #include "ira-int.h"
90 /* Data used to emit live range split insns and to flattening IR. */
91 ira_emit_data_t ira_allocno_emit_data;
93 /* Definitions for vectors of pointers. */
94 typedef void *void_p;
95 DEF_VEC_P (void_p);
96 DEF_VEC_ALLOC_P (void_p,heap);
98 /* Pointers to data allocated for allocnos being created during
99 emitting. Usually there are quite few such allocnos because they
100 are created only for resolving loop in register shuffling. */
101 static VEC(void_p, heap) *new_allocno_emit_data_vec;
103 /* Allocate and initiate the emit data. */
104 void
105 ira_initiate_emit_data (void)
107 ira_allocno_t a;
108 ira_allocno_iterator ai;
110 ira_allocno_emit_data
111 = (ira_emit_data_t) ira_allocate (ira_allocnos_num
112 * sizeof (struct ira_emit_data));
113 memset (ira_allocno_emit_data, 0,
114 ira_allocnos_num * sizeof (struct ira_emit_data));
115 FOR_EACH_ALLOCNO (a, ai)
116 ALLOCNO_ADD_DATA (a) = ira_allocno_emit_data + ALLOCNO_NUM (a);
117 new_allocno_emit_data_vec = VEC_alloc (void_p, heap, 50);
121 /* Free the emit data. */
122 void
123 ira_finish_emit_data (void)
125 void_p p;
126 ira_allocno_t a;
127 ira_allocno_iterator ai;
129 ira_free (ira_allocno_emit_data);
130 FOR_EACH_ALLOCNO (a, ai)
131 ALLOCNO_ADD_DATA (a) = NULL;
132 for (;VEC_length (void_p, new_allocno_emit_data_vec) != 0;)
134 p = VEC_pop (void_p, new_allocno_emit_data_vec);
135 ira_free (p);
137 VEC_free (void_p, heap, new_allocno_emit_data_vec);
140 /* Create and return a new allocno with given REGNO and
141 LOOP_TREE_NODE. Allocate emit data for it. */
142 static ira_allocno_t
143 create_new_allocno (int regno, ira_loop_tree_node_t loop_tree_node)
145 ira_allocno_t a;
147 a = ira_create_allocno (regno, false, loop_tree_node);
148 ALLOCNO_ADD_DATA (a) = ira_allocate (sizeof (struct ira_emit_data));
149 memset (ALLOCNO_ADD_DATA (a), 0, sizeof (struct ira_emit_data));
150 VEC_safe_push (void_p, heap, new_allocno_emit_data_vec, ALLOCNO_ADD_DATA (a));
151 return a;
156 /* See comments below. */
157 typedef struct move *move_t;
159 /* The structure represents an allocno move. Both allocnos have the
160 same original regno but different allocation. */
161 struct move
163 /* The allocnos involved in the move. */
164 ira_allocno_t from, to;
165 /* The next move in the move sequence. */
166 move_t next;
167 /* Used for finding dependencies. */
168 bool visited_p;
169 /* The size of the following array. */
170 int deps_num;
171 /* Moves on which given move depends on. Dependency can be cyclic.
172 It means we need a temporary to generates the moves. Sequence
173 A1->A2, B1->B2 where A1 and B2 are assigned to reg R1 and A2 and
174 B1 are assigned to reg R2 is an example of the cyclic
175 dependencies. */
176 move_t *deps;
177 /* First insn generated for the move. */
178 rtx insn;
181 /* Array of moves (indexed by BB index) which should be put at the
182 start/end of the corresponding basic blocks. */
183 static move_t *at_bb_start, *at_bb_end;
185 /* Max regno before renaming some pseudo-registers. For example, the
186 same pseudo-register can be renamed in a loop if its allocation is
187 different outside the loop. */
188 static int max_regno_before_changing;
190 /* Return new move of allocnos TO and FROM. */
191 static move_t
192 create_move (ira_allocno_t to, ira_allocno_t from)
194 move_t move;
196 move = (move_t) ira_allocate (sizeof (struct move));
197 move->deps = NULL;
198 move->deps_num = 0;
199 move->to = to;
200 move->from = from;
201 move->next = NULL;
202 move->insn = NULL_RTX;
203 move->visited_p = false;
204 return move;
207 /* Free memory for MOVE and its dependencies. */
208 static void
209 free_move (move_t move)
211 if (move->deps != NULL)
212 ira_free (move->deps);
213 ira_free (move);
216 /* Free memory for list of the moves given by its HEAD. */
217 static void
218 free_move_list (move_t head)
220 move_t next;
222 for (; head != NULL; head = next)
224 next = head->next;
225 free_move (head);
229 /* Return TRUE if the move list LIST1 and LIST2 are equal (two
230 moves are equal if they involve the same allocnos). */
231 static bool
232 eq_move_lists_p (move_t list1, move_t list2)
234 for (; list1 != NULL && list2 != NULL;
235 list1 = list1->next, list2 = list2->next)
236 if (list1->from != list2->from || list1->to != list2->to)
237 return false;
238 return list1 == list2;
241 /* Print move list LIST into file F. */
242 static void
243 print_move_list (FILE *f, move_t list)
245 for (; list != NULL; list = list->next)
246 fprintf (f, " a%dr%d->a%dr%d",
247 ALLOCNO_NUM (list->from), ALLOCNO_REGNO (list->from),
248 ALLOCNO_NUM (list->to), ALLOCNO_REGNO (list->to));
249 fprintf (f, "\n");
252 extern void ira_debug_move_list (move_t list);
254 /* Print move list LIST into stderr. */
255 void
256 ira_debug_move_list (move_t list)
258 print_move_list (stderr, list);
261 /* This recursive function changes pseudo-registers in *LOC if it is
262 necessary. The function returns TRUE if a change was done. */
263 static bool
264 change_regs (rtx *loc)
266 int i, regno, result = false;
267 const char *fmt;
268 enum rtx_code code;
269 rtx reg;
271 if (*loc == NULL_RTX)
272 return false;
273 code = GET_CODE (*loc);
274 if (code == REG)
276 regno = REGNO (*loc);
277 if (regno < FIRST_PSEUDO_REGISTER)
278 return false;
279 if (regno >= max_regno_before_changing)
280 /* It is a shared register which was changed already. */
281 return false;
282 if (ira_curr_regno_allocno_map[regno] == NULL)
283 return false;
284 reg = allocno_emit_reg (ira_curr_regno_allocno_map[regno]);
285 if (reg == *loc)
286 return false;
287 *loc = reg;
288 return true;
291 fmt = GET_RTX_FORMAT (code);
292 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
294 if (fmt[i] == 'e')
295 result = change_regs (&XEXP (*loc, i)) || result;
296 else if (fmt[i] == 'E')
298 int j;
300 for (j = XVECLEN (*loc, i) - 1; j >= 0; j--)
301 result = change_regs (&XVECEXP (*loc, i, j)) || result;
304 return result;
307 /* Attach MOVE to the edge E. The move is attached to the head of the
308 list if HEAD_P is TRUE. */
309 static void
310 add_to_edge_list (edge e, move_t move, bool head_p)
312 move_t last;
314 if (head_p || e->aux == NULL)
316 move->next = (move_t) e->aux;
317 e->aux = move;
319 else
321 for (last = (move_t) e->aux; last->next != NULL; last = last->next)
323 last->next = move;
324 move->next = NULL;
328 /* Create and return new pseudo-register with the same attributes as
329 ORIGINAL_REG. */
331 ira_create_new_reg (rtx original_reg)
333 rtx new_reg;
335 new_reg = gen_reg_rtx (GET_MODE (original_reg));
336 ORIGINAL_REGNO (new_reg) = ORIGINAL_REGNO (original_reg);
337 REG_USERVAR_P (new_reg) = REG_USERVAR_P (original_reg);
338 REG_POINTER (new_reg) = REG_POINTER (original_reg);
339 REG_ATTRS (new_reg) = REG_ATTRS (original_reg);
340 if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
341 fprintf (ira_dump_file, " Creating newreg=%i from oldreg=%i\n",
342 REGNO (new_reg), REGNO (original_reg));
343 return new_reg;
346 /* Return TRUE if loop given by SUBNODE inside the loop given by
347 NODE. */
348 static bool
349 subloop_tree_node_p (ira_loop_tree_node_t subnode, ira_loop_tree_node_t node)
351 for (; subnode != NULL; subnode = subnode->parent)
352 if (subnode == node)
353 return true;
354 return false;
357 /* Set up member `reg' to REG for allocnos which has the same regno as
358 ALLOCNO and which are inside the loop corresponding to ALLOCNO. */
359 static void
360 set_allocno_reg (ira_allocno_t allocno, rtx reg)
362 int regno;
363 ira_allocno_t a;
364 ira_loop_tree_node_t node;
366 node = ALLOCNO_LOOP_TREE_NODE (allocno);
367 for (a = ira_regno_allocno_map[ALLOCNO_REGNO (allocno)];
368 a != NULL;
369 a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
370 if (subloop_tree_node_p (ALLOCNO_LOOP_TREE_NODE (a), node))
371 ALLOCNO_EMIT_DATA (a)->reg = reg;
372 for (a = ALLOCNO_CAP (allocno); a != NULL; a = ALLOCNO_CAP (a))
373 ALLOCNO_EMIT_DATA (a)->reg = reg;
374 regno = ALLOCNO_REGNO (allocno);
375 for (a = allocno;;)
377 if (a == NULL || (a = ALLOCNO_CAP (a)) == NULL)
379 node = node->parent;
380 if (node == NULL)
381 break;
382 a = node->regno_allocno_map[regno];
384 if (a == NULL)
385 continue;
386 if (ALLOCNO_EMIT_DATA (a)->child_renamed_p)
387 break;
388 ALLOCNO_EMIT_DATA (a)->child_renamed_p = true;
392 /* Return true if there is an entry to given loop not from its parent
393 (or grandparent) block. For example, it is possible for two
394 adjacent loops inside another loop. */
395 static bool
396 entered_from_non_parent_p (ira_loop_tree_node_t loop_node)
398 ira_loop_tree_node_t bb_node, src_loop_node, parent;
399 edge e;
400 edge_iterator ei;
402 for (bb_node = loop_node->children;
403 bb_node != NULL;
404 bb_node = bb_node->next)
405 if (bb_node->bb != NULL)
407 FOR_EACH_EDGE (e, ei, bb_node->bb->preds)
408 if (e->src != ENTRY_BLOCK_PTR
409 && (src_loop_node = IRA_BB_NODE (e->src)->parent) != loop_node)
411 for (parent = src_loop_node->parent;
412 parent != NULL;
413 parent = parent->parent)
414 if (parent == loop_node)
415 break;
416 if (parent != NULL)
417 /* That is an exit from a nested loop -- skip it. */
418 continue;
419 for (parent = loop_node->parent;
420 parent != NULL;
421 parent = parent->parent)
422 if (src_loop_node == parent)
423 break;
424 if (parent == NULL)
425 return true;
428 return false;
431 /* Set up ENTERED_FROM_NON_PARENT_P for each loop region. */
432 static void
433 setup_entered_from_non_parent_p (void)
435 unsigned int i;
436 loop_p loop;
438 ira_assert (current_loops != NULL);
439 FOR_EACH_VEC_ELT (loop_p, ira_loops.larray, i, loop)
440 if (ira_loop_nodes[i].regno_allocno_map != NULL)
441 ira_loop_nodes[i].entered_from_non_parent_p
442 = entered_from_non_parent_p (&ira_loop_nodes[i]);
445 /* Return TRUE if move of SRC_ALLOCNO (assigned to hard register) to
446 DEST_ALLOCNO (assigned to memory) can be removed because it does
447 not change value of the destination. One possible reason for this
448 is the situation when SRC_ALLOCNO is not modified in the
449 corresponding loop. */
450 static bool
451 store_can_be_removed_p (ira_allocno_t src_allocno, ira_allocno_t dest_allocno)
453 int regno, orig_regno;
454 ira_allocno_t a;
455 ira_loop_tree_node_t node;
457 ira_assert (ALLOCNO_CAP_MEMBER (src_allocno) == NULL
458 && ALLOCNO_CAP_MEMBER (dest_allocno) == NULL);
459 orig_regno = ALLOCNO_REGNO (src_allocno);
460 regno = REGNO (allocno_emit_reg (dest_allocno));
461 for (node = ALLOCNO_LOOP_TREE_NODE (src_allocno);
462 node != NULL;
463 node = node->parent)
465 a = node->regno_allocno_map[orig_regno];
466 ira_assert (a != NULL);
467 if (REGNO (allocno_emit_reg (a)) == (unsigned) regno)
468 /* We achieved the destination and everything is ok. */
469 return true;
470 else if (bitmap_bit_p (node->modified_regnos, orig_regno))
471 return false;
472 else if (node->entered_from_non_parent_p)
473 /* If there is a path from a destination loop block to the
474 source loop header containing basic blocks of non-parents
475 (grandparents) of the source loop, we should have checked
476 modifications of the pseudo on this path too to decide
477 about possibility to remove the store. It could be done by
478 solving a data-flow problem. Unfortunately such global
479 solution would complicate IR flattening. Therefore we just
480 prohibit removal of the store in such complicated case. */
481 return false;
483 /* It is actually a loop entry -- do not remove the store. */
484 return false;
487 /* Generate and attach moves to the edge E. This looks at the final
488 regnos of allocnos living on the edge with the same original regno
489 to figure out when moves should be generated. */
490 static void
491 generate_edge_moves (edge e)
493 ira_loop_tree_node_t src_loop_node, dest_loop_node;
494 unsigned int regno;
495 bitmap_iterator bi;
496 ira_allocno_t src_allocno, dest_allocno, *src_map, *dest_map;
497 move_t move;
499 src_loop_node = IRA_BB_NODE (e->src)->parent;
500 dest_loop_node = IRA_BB_NODE (e->dest)->parent;
501 e->aux = NULL;
502 if (src_loop_node == dest_loop_node)
503 return;
504 src_map = src_loop_node->regno_allocno_map;
505 dest_map = dest_loop_node->regno_allocno_map;
506 EXECUTE_IF_SET_IN_REG_SET (DF_LR_IN (e->dest),
507 FIRST_PSEUDO_REGISTER, regno, bi)
508 if (bitmap_bit_p (DF_LR_OUT (e->src), regno))
510 src_allocno = src_map[regno];
511 dest_allocno = dest_map[regno];
512 if (REGNO (allocno_emit_reg (src_allocno))
513 == REGNO (allocno_emit_reg (dest_allocno)))
514 continue;
515 /* Remove unnecessary stores at the region exit. We should do
516 this for readonly memory for sure and this is guaranteed by
517 that we never generate moves on region borders (see
518 checking ira_reg_equiv_invariant_p in function
519 change_loop). */
520 if (ALLOCNO_HARD_REGNO (dest_allocno) < 0
521 && ALLOCNO_HARD_REGNO (src_allocno) >= 0
522 && store_can_be_removed_p (src_allocno, dest_allocno))
524 ALLOCNO_EMIT_DATA (src_allocno)->mem_optimized_dest = dest_allocno;
525 ALLOCNO_EMIT_DATA (dest_allocno)->mem_optimized_dest_p = true;
526 if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
527 fprintf (ira_dump_file, " Remove r%d:a%d->a%d(mem)\n",
528 regno, ALLOCNO_NUM (src_allocno),
529 ALLOCNO_NUM (dest_allocno));
530 continue;
532 move = create_move (dest_allocno, src_allocno);
533 add_to_edge_list (e, move, true);
537 /* Bitmap of allocnos local for the current loop. */
538 static bitmap local_allocno_bitmap;
540 /* This bitmap is used to find that we need to generate and to use a
541 new pseudo-register when processing allocnos with the same original
542 regno. */
543 static bitmap used_regno_bitmap;
545 /* This bitmap contains regnos of allocnos which were renamed locally
546 because the allocnos correspond to disjoint live ranges in loops
547 with a common parent. */
548 static bitmap renamed_regno_bitmap;
550 /* Change (if necessary) pseudo-registers inside loop given by loop
551 tree node NODE. */
552 static void
553 change_loop (ira_loop_tree_node_t node)
555 bitmap_iterator bi;
556 unsigned int i;
557 int regno;
558 bool used_p;
559 ira_allocno_t allocno, parent_allocno, *map;
560 rtx insn, original_reg;
561 enum reg_class aclass, pclass;
562 ira_loop_tree_node_t parent;
564 if (node != ira_loop_tree_root)
566 ira_assert (current_loops != NULL);
568 if (node->bb != NULL)
570 FOR_BB_INSNS (node->bb, insn)
571 if (INSN_P (insn) && change_regs (&insn))
573 df_insn_rescan (insn);
574 df_notes_rescan (insn);
576 return;
579 if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
580 fprintf (ira_dump_file,
581 " Changing RTL for loop %d (header bb%d)\n",
582 node->loop_num, node->loop->header->index);
584 parent = ira_curr_loop_tree_node->parent;
585 map = parent->regno_allocno_map;
586 EXECUTE_IF_SET_IN_REG_SET (ira_curr_loop_tree_node->border_allocnos,
587 0, i, bi)
589 allocno = ira_allocnos[i];
590 regno = ALLOCNO_REGNO (allocno);
591 aclass = ALLOCNO_CLASS (allocno);
592 pclass = ira_pressure_class_translate[aclass];
593 parent_allocno = map[regno];
594 ira_assert (regno < ira_reg_equiv_len);
595 /* We generate the same hard register move because the
596 reload pass can put an allocno into memory in this case
597 we will have live range splitting. If it does not happen
598 such the same hard register moves will be removed. The
599 worst case when the both allocnos are put into memory by
600 the reload is very rare. */
601 if (parent_allocno != NULL
602 && (ALLOCNO_HARD_REGNO (allocno)
603 == ALLOCNO_HARD_REGNO (parent_allocno))
604 && (ALLOCNO_HARD_REGNO (allocno) < 0
605 || (parent->reg_pressure[pclass] + 1
606 <= ira_class_hard_regs_num[pclass])
607 || TEST_HARD_REG_BIT (ira_prohibited_mode_move_regs
608 [ALLOCNO_MODE (allocno)],
609 ALLOCNO_HARD_REGNO (allocno))
610 /* don't create copies because reload can spill an
611 allocno set by copy although the allocno will not
612 get memory slot. */
613 || ira_reg_equiv_invariant_p[regno]
614 || ira_reg_equiv_const[regno] != NULL_RTX))
615 continue;
616 original_reg = allocno_emit_reg (allocno);
617 if (parent_allocno == NULL
618 || (REGNO (allocno_emit_reg (parent_allocno))
619 == REGNO (original_reg)))
621 if (internal_flag_ira_verbose > 3 && ira_dump_file)
622 fprintf (ira_dump_file, " %i vs parent %i:",
623 ALLOCNO_HARD_REGNO (allocno),
624 ALLOCNO_HARD_REGNO (parent_allocno));
625 set_allocno_reg (allocno, ira_create_new_reg (original_reg));
629 /* Rename locals: Local allocnos with same regno in different loops
630 might get the different hard register. So we need to change
631 ALLOCNO_REG. */
632 bitmap_and_compl (local_allocno_bitmap,
633 ira_curr_loop_tree_node->all_allocnos,
634 ira_curr_loop_tree_node->border_allocnos);
635 EXECUTE_IF_SET_IN_REG_SET (local_allocno_bitmap, 0, i, bi)
637 allocno = ira_allocnos[i];
638 regno = ALLOCNO_REGNO (allocno);
639 if (ALLOCNO_CAP_MEMBER (allocno) != NULL)
640 continue;
641 used_p = !bitmap_set_bit (used_regno_bitmap, regno);
642 ALLOCNO_EMIT_DATA (allocno)->somewhere_renamed_p = true;
643 if (! used_p)
644 continue;
645 bitmap_set_bit (renamed_regno_bitmap, regno);
646 set_allocno_reg (allocno, ira_create_new_reg (allocno_emit_reg (allocno)));
650 /* Process to set up flag somewhere_renamed_p. */
651 static void
652 set_allocno_somewhere_renamed_p (void)
654 unsigned int regno;
655 ira_allocno_t allocno;
656 ira_allocno_iterator ai;
658 FOR_EACH_ALLOCNO (allocno, ai)
660 regno = ALLOCNO_REGNO (allocno);
661 if (bitmap_bit_p (renamed_regno_bitmap, regno)
662 && REGNO (allocno_emit_reg (allocno)) == regno)
663 ALLOCNO_EMIT_DATA (allocno)->somewhere_renamed_p = true;
667 /* Return TRUE if move lists on all edges given in vector VEC are
668 equal. */
669 static bool
670 eq_edge_move_lists_p (VEC(edge,gc) *vec)
672 move_t list;
673 int i;
675 list = (move_t) EDGE_I (vec, 0)->aux;
676 for (i = EDGE_COUNT (vec) - 1; i > 0; i--)
677 if (! eq_move_lists_p (list, (move_t) EDGE_I (vec, i)->aux))
678 return false;
679 return true;
682 /* Look at all entry edges (if START_P) or exit edges of basic block
683 BB and put move lists at the BB start or end if it is possible. In
684 other words, this decreases code duplication of allocno moves. */
685 static void
686 unify_moves (basic_block bb, bool start_p)
688 int i;
689 edge e;
690 move_t list;
691 VEC(edge,gc) *vec;
693 vec = (start_p ? bb->preds : bb->succs);
694 if (EDGE_COUNT (vec) == 0 || ! eq_edge_move_lists_p (vec))
695 return;
696 e = EDGE_I (vec, 0);
697 list = (move_t) e->aux;
698 if (! start_p && control_flow_insn_p (BB_END (bb)))
699 return;
700 e->aux = NULL;
701 for (i = EDGE_COUNT (vec) - 1; i > 0; i--)
703 e = EDGE_I (vec, i);
704 free_move_list ((move_t) e->aux);
705 e->aux = NULL;
707 if (start_p)
708 at_bb_start[bb->index] = list;
709 else
710 at_bb_end[bb->index] = list;
713 /* Last move (in move sequence being processed) setting up the
714 corresponding hard register. */
715 static move_t hard_regno_last_set[FIRST_PSEUDO_REGISTER];
717 /* If the element value is equal to CURR_TICK then the corresponding
718 element in `hard_regno_last_set' is defined and correct. */
719 static int hard_regno_last_set_check[FIRST_PSEUDO_REGISTER];
721 /* Last move (in move sequence being processed) setting up the
722 corresponding allocno. */
723 static move_t *allocno_last_set;
725 /* If the element value is equal to CURR_TICK then the corresponding
726 element in . `allocno_last_set' is defined and correct. */
727 static int *allocno_last_set_check;
729 /* Definition of vector of moves. */
730 DEF_VEC_P(move_t);
731 DEF_VEC_ALLOC_P(move_t, heap);
733 /* This vec contains moves sorted topologically (depth-first) on their
734 dependency graph. */
735 static VEC(move_t,heap) *move_vec;
737 /* The variable value is used to check correctness of values of
738 elements of arrays `hard_regno_last_set' and
739 `allocno_last_set_check'. */
740 static int curr_tick;
742 /* This recursive function traverses dependencies of MOVE and produces
743 topological sorting (in depth-first order). */
744 static void
745 traverse_moves (move_t move)
747 int i;
749 if (move->visited_p)
750 return;
751 move->visited_p = true;
752 for (i = move->deps_num - 1; i >= 0; i--)
753 traverse_moves (move->deps[i]);
754 VEC_safe_push (move_t, heap, move_vec, move);
757 /* Remove unnecessary moves in the LIST, makes topological sorting,
758 and removes cycles on hard reg dependencies by introducing new
759 allocnos assigned to memory and additional moves. It returns the
760 result move list. */
761 static move_t
762 modify_move_list (move_t list)
764 int i, n, nregs, hard_regno;
765 ira_allocno_t to, from;
766 move_t move, new_move, set_move, first, last;
768 if (list == NULL)
769 return NULL;
770 /* Creat move deps. */
771 curr_tick++;
772 for (move = list; move != NULL; move = move->next)
774 to = move->to;
775 if ((hard_regno = ALLOCNO_HARD_REGNO (to)) < 0)
776 continue;
777 nregs = hard_regno_nregs[hard_regno][ALLOCNO_MODE (to)];
778 for (i = 0; i < nregs; i++)
780 hard_regno_last_set[hard_regno + i] = move;
781 hard_regno_last_set_check[hard_regno + i] = curr_tick;
784 for (move = list; move != NULL; move = move->next)
786 from = move->from;
787 to = move->to;
788 if ((hard_regno = ALLOCNO_HARD_REGNO (from)) >= 0)
790 nregs = hard_regno_nregs[hard_regno][ALLOCNO_MODE (from)];
791 for (n = i = 0; i < nregs; i++)
792 if (hard_regno_last_set_check[hard_regno + i] == curr_tick
793 && (ALLOCNO_REGNO (hard_regno_last_set[hard_regno + i]->to)
794 != ALLOCNO_REGNO (from)))
795 n++;
796 move->deps = (move_t *) ira_allocate (n * sizeof (move_t));
797 for (n = i = 0; i < nregs; i++)
798 if (hard_regno_last_set_check[hard_regno + i] == curr_tick
799 && (ALLOCNO_REGNO (hard_regno_last_set[hard_regno + i]->to)
800 != ALLOCNO_REGNO (from)))
801 move->deps[n++] = hard_regno_last_set[hard_regno + i];
802 move->deps_num = n;
805 /* Toplogical sorting: */
806 VEC_truncate (move_t, move_vec, 0);
807 for (move = list; move != NULL; move = move->next)
808 traverse_moves (move);
809 last = NULL;
810 for (i = (int) VEC_length (move_t, move_vec) - 1; i >= 0; i--)
812 move = VEC_index (move_t, move_vec, i);
813 move->next = NULL;
814 if (last != NULL)
815 last->next = move;
816 last = move;
818 first = VEC_last (move_t, move_vec);
819 /* Removing cycles: */
820 curr_tick++;
821 VEC_truncate (move_t, move_vec, 0);
822 for (move = first; move != NULL; move = move->next)
824 from = move->from;
825 to = move->to;
826 if ((hard_regno = ALLOCNO_HARD_REGNO (from)) >= 0)
828 nregs = hard_regno_nregs[hard_regno][ALLOCNO_MODE (from)];
829 for (i = 0; i < nregs; i++)
830 if (hard_regno_last_set_check[hard_regno + i] == curr_tick
831 && ALLOCNO_HARD_REGNO
832 (hard_regno_last_set[hard_regno + i]->to) >= 0)
834 int n, j;
835 ira_allocno_t new_allocno;
837 set_move = hard_regno_last_set[hard_regno + i];
838 /* It does not matter what loop_tree_node (of TO or
839 FROM) to use for the new allocno because of
840 subsequent IRA internal representation
841 flattening. */
842 new_allocno
843 = create_new_allocno (ALLOCNO_REGNO (set_move->to),
844 ALLOCNO_LOOP_TREE_NODE (set_move->to));
845 ALLOCNO_MODE (new_allocno) = ALLOCNO_MODE (set_move->to);
846 ira_set_allocno_class (new_allocno,
847 ALLOCNO_CLASS (set_move->to));
848 ira_create_allocno_objects (new_allocno);
849 ALLOCNO_ASSIGNED_P (new_allocno) = true;
850 ALLOCNO_HARD_REGNO (new_allocno) = -1;
851 ALLOCNO_EMIT_DATA (new_allocno)->reg
852 = ira_create_new_reg (allocno_emit_reg (set_move->to));
854 /* Make it possibly conflicting with all earlier
855 created allocnos. Cases where temporary allocnos
856 created to remove the cycles are quite rare. */
857 n = ALLOCNO_NUM_OBJECTS (new_allocno);
858 gcc_assert (n == ALLOCNO_NUM_OBJECTS (set_move->to));
859 for (j = 0; j < n; j++)
861 ira_object_t new_obj = ALLOCNO_OBJECT (new_allocno, j);
863 OBJECT_MIN (new_obj) = 0;
864 OBJECT_MAX (new_obj) = ira_objects_num - 1;
867 new_move = create_move (set_move->to, new_allocno);
868 set_move->to = new_allocno;
869 VEC_safe_push (move_t, heap, move_vec, new_move);
870 ira_move_loops_num++;
871 if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
872 fprintf (ira_dump_file,
873 " Creating temporary allocno a%dr%d\n",
874 ALLOCNO_NUM (new_allocno),
875 REGNO (allocno_emit_reg (new_allocno)));
878 if ((hard_regno = ALLOCNO_HARD_REGNO (to)) < 0)
879 continue;
880 nregs = hard_regno_nregs[hard_regno][ALLOCNO_MODE (to)];
881 for (i = 0; i < nregs; i++)
883 hard_regno_last_set[hard_regno + i] = move;
884 hard_regno_last_set_check[hard_regno + i] = curr_tick;
887 for (i = (int) VEC_length (move_t, move_vec) - 1; i >= 0; i--)
889 move = VEC_index (move_t, move_vec, i);
890 move->next = NULL;
891 last->next = move;
892 last = move;
894 return first;
897 /* Generate RTX move insns from the move list LIST. This updates
898 allocation cost using move execution frequency FREQ. */
899 static rtx
900 emit_move_list (move_t list, int freq)
902 int cost, regno;
903 rtx result, insn, set, to;
904 enum machine_mode mode;
905 enum reg_class aclass;
907 start_sequence ();
908 for (; list != NULL; list = list->next)
910 start_sequence ();
911 emit_move_insn (allocno_emit_reg (list->to),
912 allocno_emit_reg (list->from));
913 list->insn = get_insns ();
914 end_sequence ();
915 for (insn = list->insn; insn != NULL_RTX; insn = NEXT_INSN (insn))
917 /* The reload needs to have set up insn codes. If the
918 reload sets up insn codes by itself, it may fail because
919 insns will have hard registers instead of pseudos and
920 there may be no machine insn with given hard
921 registers. */
922 recog_memoized (insn);
923 /* Add insn to equiv init insn list if it is necessary.
924 Otherwise reload will not remove this insn if it decides
925 to use the equivalence. */
926 if ((set = single_set (insn)) != NULL_RTX)
928 to = SET_DEST (set);
929 if (GET_CODE (to) == SUBREG)
930 to = SUBREG_REG (to);
931 ira_assert (REG_P (to));
932 regno = REGNO (to);
933 if (regno >= ira_reg_equiv_len
934 || (! ira_reg_equiv_invariant_p[regno]
935 && ira_reg_equiv_const[regno] == NULL_RTX))
936 continue; /* regno has no equivalence. */
937 ira_assert ((int) VEC_length (reg_equivs_t, reg_equivs)
938 >= ira_reg_equiv_len);
939 reg_equiv_init (regno)
940 = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init (regno));
943 emit_insn (list->insn);
944 mode = ALLOCNO_MODE (list->to);
945 aclass = ALLOCNO_CLASS (list->to);
946 cost = 0;
947 if (ALLOCNO_HARD_REGNO (list->to) < 0)
949 if (ALLOCNO_HARD_REGNO (list->from) >= 0)
951 cost = ira_memory_move_cost[mode][aclass][0] * freq;
952 ira_store_cost += cost;
955 else if (ALLOCNO_HARD_REGNO (list->from) < 0)
957 if (ALLOCNO_HARD_REGNO (list->to) >= 0)
959 cost = ira_memory_move_cost[mode][aclass][0] * freq;
960 ira_load_cost += cost;
963 else
965 ira_init_register_move_cost_if_necessary (mode);
966 cost = ira_register_move_cost[mode][aclass][aclass] * freq;
967 ira_shuffle_cost += cost;
969 ira_overall_cost += cost;
971 result = get_insns ();
972 end_sequence ();
973 return result;
976 /* Generate RTX move insns from move lists attached to basic blocks
977 and edges. */
978 static void
979 emit_moves (void)
981 basic_block bb;
982 edge_iterator ei;
983 edge e;
984 rtx insns, tmp;
986 FOR_EACH_BB (bb)
988 if (at_bb_start[bb->index] != NULL)
990 at_bb_start[bb->index] = modify_move_list (at_bb_start[bb->index]);
991 insns = emit_move_list (at_bb_start[bb->index],
992 REG_FREQ_FROM_BB (bb));
993 tmp = BB_HEAD (bb);
994 if (LABEL_P (tmp))
995 tmp = NEXT_INSN (tmp);
996 if (NOTE_INSN_BASIC_BLOCK_P (tmp))
997 tmp = NEXT_INSN (tmp);
998 if (tmp == BB_HEAD (bb))
999 emit_insn_before (insns, tmp);
1000 else if (tmp != NULL_RTX)
1001 emit_insn_after (insns, PREV_INSN (tmp));
1002 else
1003 emit_insn_after (insns, get_last_insn ());
1006 if (at_bb_end[bb->index] != NULL)
1008 at_bb_end[bb->index] = modify_move_list (at_bb_end[bb->index]);
1009 insns = emit_move_list (at_bb_end[bb->index], REG_FREQ_FROM_BB (bb));
1010 ira_assert (! control_flow_insn_p (BB_END (bb)));
1011 emit_insn_after (insns, BB_END (bb));
1014 FOR_EACH_EDGE (e, ei, bb->succs)
1016 if (e->aux == NULL)
1017 continue;
1018 ira_assert ((e->flags & EDGE_ABNORMAL) == 0
1019 || ! EDGE_CRITICAL_P (e));
1020 e->aux = modify_move_list ((move_t) e->aux);
1021 insert_insn_on_edge
1022 (emit_move_list ((move_t) e->aux,
1023 REG_FREQ_FROM_EDGE_FREQ (EDGE_FREQUENCY (e))),
1025 if (e->src->next_bb != e->dest)
1026 ira_additional_jumps_num++;
1031 /* Update costs of A and corresponding allocnos on upper levels on the
1032 loop tree from reading (if READ_P) or writing A on an execution
1033 path with FREQ. */
1034 static void
1035 update_costs (ira_allocno_t a, bool read_p, int freq)
1037 ira_loop_tree_node_t parent;
1039 for (;;)
1041 ALLOCNO_NREFS (a)++;
1042 ALLOCNO_FREQ (a) += freq;
1043 ALLOCNO_MEMORY_COST (a)
1044 += (ira_memory_move_cost[ALLOCNO_MODE (a)][ALLOCNO_CLASS (a)]
1045 [read_p ? 1 : 0] * freq);
1046 if (ALLOCNO_CAP (a) != NULL)
1047 a = ALLOCNO_CAP (a);
1048 else if ((parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) == NULL
1049 || (a = parent->regno_allocno_map[ALLOCNO_REGNO (a)]) == NULL)
1050 break;
1054 /* Process moves from LIST with execution FREQ to add ranges, copies,
1055 and modify costs for allocnos involved in the moves. All regnos
1056 living through the list is in LIVE_THROUGH, and the loop tree node
1057 used to find corresponding allocnos is NODE. */
1058 static void
1059 add_range_and_copies_from_move_list (move_t list, ira_loop_tree_node_t node,
1060 bitmap live_through, int freq)
1062 int start, n;
1063 unsigned int regno;
1064 move_t move;
1065 ira_allocno_t a;
1066 ira_copy_t cp;
1067 live_range_t r;
1068 bitmap_iterator bi;
1069 HARD_REG_SET hard_regs_live;
1071 if (list == NULL)
1072 return;
1073 n = 0;
1074 EXECUTE_IF_SET_IN_BITMAP (live_through, FIRST_PSEUDO_REGISTER, regno, bi)
1075 n++;
1076 REG_SET_TO_HARD_REG_SET (hard_regs_live, live_through);
1077 /* This is a trick to guarantee that new ranges is not merged with
1078 the old ones. */
1079 ira_max_point++;
1080 start = ira_max_point;
1081 for (move = list; move != NULL; move = move->next)
1083 ira_allocno_t from = move->from;
1084 ira_allocno_t to = move->to;
1085 int nr, i;
1087 bitmap_clear_bit (live_through, ALLOCNO_REGNO (from));
1088 bitmap_clear_bit (live_through, ALLOCNO_REGNO (to));
1090 nr = ALLOCNO_NUM_OBJECTS (to);
1091 for (i = 0; i < nr; i++)
1093 ira_object_t to_obj = ALLOCNO_OBJECT (to, i);
1094 if (OBJECT_CONFLICT_ARRAY (to_obj) == NULL)
1096 if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
1097 fprintf (ira_dump_file, " Allocate conflicts for a%dr%d\n",
1098 ALLOCNO_NUM (to), REGNO (allocno_emit_reg (to)));
1099 ira_allocate_object_conflicts (to_obj, n);
1102 ior_hard_reg_conflicts (from, &hard_regs_live);
1103 ior_hard_reg_conflicts (to, &hard_regs_live);
1105 update_costs (from, true, freq);
1106 update_costs (to, false, freq);
1107 cp = ira_add_allocno_copy (from, to, freq, false, move->insn, NULL);
1108 if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
1109 fprintf (ira_dump_file, " Adding cp%d:a%dr%d-a%dr%d\n",
1110 cp->num, ALLOCNO_NUM (cp->first),
1111 REGNO (allocno_emit_reg (cp->first)),
1112 ALLOCNO_NUM (cp->second),
1113 REGNO (allocno_emit_reg (cp->second)));
1115 nr = ALLOCNO_NUM_OBJECTS (from);
1116 for (i = 0; i < nr; i++)
1118 ira_object_t from_obj = ALLOCNO_OBJECT (from, i);
1119 r = OBJECT_LIVE_RANGES (from_obj);
1120 if (r == NULL || r->finish >= 0)
1122 ira_add_live_range_to_object (from_obj, start, ira_max_point);
1123 if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
1124 fprintf (ira_dump_file,
1125 " Adding range [%d..%d] to allocno a%dr%d\n",
1126 start, ira_max_point, ALLOCNO_NUM (from),
1127 REGNO (allocno_emit_reg (from)));
1129 else
1131 r->finish = ira_max_point;
1132 if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
1133 fprintf (ira_dump_file,
1134 " Adding range [%d..%d] to allocno a%dr%d\n",
1135 r->start, ira_max_point, ALLOCNO_NUM (from),
1136 REGNO (allocno_emit_reg (from)));
1139 ira_max_point++;
1140 nr = ALLOCNO_NUM_OBJECTS (to);
1141 for (i = 0; i < nr; i++)
1143 ira_object_t to_obj = ALLOCNO_OBJECT (to, i);
1144 ira_add_live_range_to_object (to_obj, ira_max_point, -1);
1146 ira_max_point++;
1148 for (move = list; move != NULL; move = move->next)
1150 int nr, i;
1151 nr = ALLOCNO_NUM_OBJECTS (move->to);
1152 for (i = 0; i < nr; i++)
1154 ira_object_t to_obj = ALLOCNO_OBJECT (move->to, i);
1155 r = OBJECT_LIVE_RANGES (to_obj);
1156 if (r->finish < 0)
1158 r->finish = ira_max_point - 1;
1159 if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
1160 fprintf (ira_dump_file,
1161 " Adding range [%d..%d] to allocno a%dr%d\n",
1162 r->start, r->finish, ALLOCNO_NUM (move->to),
1163 REGNO (allocno_emit_reg (move->to)));
1167 EXECUTE_IF_SET_IN_BITMAP (live_through, FIRST_PSEUDO_REGISTER, regno, bi)
1169 ira_allocno_t to;
1170 int nr, i;
1172 a = node->regno_allocno_map[regno];
1173 if ((to = ALLOCNO_EMIT_DATA (a)->mem_optimized_dest) != NULL)
1174 a = to;
1175 nr = ALLOCNO_NUM_OBJECTS (a);
1176 for (i = 0; i < nr; i++)
1178 ira_object_t obj = ALLOCNO_OBJECT (a, i);
1179 ira_add_live_range_to_object (obj, start, ira_max_point - 1);
1181 if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
1182 fprintf
1183 (ira_dump_file,
1184 " Adding range [%d..%d] to live through %s allocno a%dr%d\n",
1185 start, ira_max_point - 1,
1186 to != NULL ? "upper level" : "",
1187 ALLOCNO_NUM (a), REGNO (allocno_emit_reg (a)));
1191 /* Process all move list to add ranges, conflicts, copies, and modify
1192 costs for allocnos involved in the moves. */
1193 static void
1194 add_ranges_and_copies (void)
1196 basic_block bb;
1197 edge_iterator ei;
1198 edge e;
1199 ira_loop_tree_node_t node;
1200 bitmap live_through;
1202 live_through = ira_allocate_bitmap ();
1203 FOR_EACH_BB (bb)
1205 /* It does not matter what loop_tree_node (of source or
1206 destination block) to use for searching allocnos by their
1207 regnos because of subsequent IR flattening. */
1208 node = IRA_BB_NODE (bb)->parent;
1209 bitmap_copy (live_through, DF_LR_IN (bb));
1210 add_range_and_copies_from_move_list
1211 (at_bb_start[bb->index], node, live_through, REG_FREQ_FROM_BB (bb));
1212 bitmap_copy (live_through, DF_LR_OUT (bb));
1213 add_range_and_copies_from_move_list
1214 (at_bb_end[bb->index], node, live_through, REG_FREQ_FROM_BB (bb));
1215 FOR_EACH_EDGE (e, ei, bb->succs)
1217 bitmap_and (live_through, DF_LR_IN (e->dest), DF_LR_OUT (bb));
1218 add_range_and_copies_from_move_list
1219 ((move_t) e->aux, node, live_through,
1220 REG_FREQ_FROM_EDGE_FREQ (EDGE_FREQUENCY (e)));
1223 ira_free_bitmap (live_through);
1226 /* The entry function changes code and generates shuffling allocnos on
1227 region borders for the regional (LOOPS_P is TRUE in this case)
1228 register allocation. */
1229 void
1230 ira_emit (bool loops_p)
1232 basic_block bb;
1233 rtx insn;
1234 edge_iterator ei;
1235 edge e;
1236 ira_allocno_t a;
1237 ira_allocno_iterator ai;
1239 FOR_EACH_ALLOCNO (a, ai)
1240 ALLOCNO_EMIT_DATA (a)->reg = regno_reg_rtx[ALLOCNO_REGNO (a)];
1241 if (! loops_p)
1242 return;
1243 at_bb_start = (move_t *) ira_allocate (sizeof (move_t) * last_basic_block);
1244 memset (at_bb_start, 0, sizeof (move_t) * last_basic_block);
1245 at_bb_end = (move_t *) ira_allocate (sizeof (move_t) * last_basic_block);
1246 memset (at_bb_end, 0, sizeof (move_t) * last_basic_block);
1247 local_allocno_bitmap = ira_allocate_bitmap ();
1248 used_regno_bitmap = ira_allocate_bitmap ();
1249 renamed_regno_bitmap = ira_allocate_bitmap ();
1250 max_regno_before_changing = max_reg_num ();
1251 ira_traverse_loop_tree (true, ira_loop_tree_root, change_loop, NULL);
1252 set_allocno_somewhere_renamed_p ();
1253 ira_free_bitmap (used_regno_bitmap);
1254 ira_free_bitmap (renamed_regno_bitmap);
1255 ira_free_bitmap (local_allocno_bitmap);
1256 setup_entered_from_non_parent_p ();
1257 FOR_EACH_BB (bb)
1259 at_bb_start[bb->index] = NULL;
1260 at_bb_end[bb->index] = NULL;
1261 FOR_EACH_EDGE (e, ei, bb->succs)
1262 if (e->dest != EXIT_BLOCK_PTR)
1263 generate_edge_moves (e);
1265 allocno_last_set
1266 = (move_t *) ira_allocate (sizeof (move_t) * max_reg_num ());
1267 allocno_last_set_check
1268 = (int *) ira_allocate (sizeof (int) * max_reg_num ());
1269 memset (allocno_last_set_check, 0, sizeof (int) * max_reg_num ());
1270 memset (hard_regno_last_set_check, 0, sizeof (hard_regno_last_set_check));
1271 curr_tick = 0;
1272 FOR_EACH_BB (bb)
1273 unify_moves (bb, true);
1274 FOR_EACH_BB (bb)
1275 unify_moves (bb, false);
1276 move_vec = VEC_alloc (move_t, heap, ira_allocnos_num);
1277 emit_moves ();
1278 add_ranges_and_copies ();
1279 /* Clean up: */
1280 FOR_EACH_BB (bb)
1282 free_move_list (at_bb_start[bb->index]);
1283 free_move_list (at_bb_end[bb->index]);
1284 FOR_EACH_EDGE (e, ei, bb->succs)
1286 free_move_list ((move_t) e->aux);
1287 e->aux = NULL;
1290 VEC_free (move_t, heap, move_vec);
1291 ira_free (allocno_last_set_check);
1292 ira_free (allocno_last_set);
1293 commit_edge_insertions ();
1294 /* Fix insn codes. It is necessary to do it before reload because
1295 reload assumes initial insn codes defined. The insn codes can be
1296 invalidated by CFG infrastructure for example in jump
1297 redirection. */
1298 FOR_EACH_BB (bb)
1299 FOR_BB_INSNS_REVERSE (bb, insn)
1300 if (INSN_P (insn))
1301 recog_memoized (insn);
1302 ira_free (at_bb_end);
1303 ira_free (at_bb_start);