You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "reload.h"
#include "output.h"
#include "toplev.h"
+#include "tree-pass.h"
+#include "timevar.h"
/* This pass of the compiler performs global register allocation.
It assigns hard register numbers to all the pseudo registers
/* Don't allocate pseudos that cross calls,
if this function receives a nonlocal goto. */
&& (! current_function_has_nonlocal_label
- || REG_N_CALLS_CROSSED (i) == 0))
+ || REG_N_CALLS_CROSSED (i) == 0)
+ /* Don't allocate pseudos that cross calls that may throw. */
+ && REG_N_THROWING_CALLS_CROSSED (i) == 0)
{
if (reg_renumber[i] < 0
&& reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
be explicitly marked in basic_block_live_at_start. */
{
- regset old = b->global_live_at_start;
+ regset old = b->il.rtl->global_live_at_start;
int ax = 0;
reg_set_iterator rsi;
FOR_EACH_BB (bb)
{
- regset r = bb->global_live_at_start;
+ regset r = bb->il.rtl->global_live_at_start;
if (REGNO_REG_SET_P (r, from))
{
CLEAR_REGNO_REG_SET (r, from);
CLEAR_REG_SET (live_relevant_regs);
- EXECUTE_IF_SET_IN_BITMAP (b->global_live_at_start, 0, i, bi)
+ EXECUTE_IF_SET_IN_BITMAP (b->il.rtl->global_live_at_start, 0, i, bi)
{
if (i < FIRST_PSEUDO_REGISTER
? ! TEST_HARD_REG_BIT (eliminable_regset, i)
/* Classes of registers which could be early clobbered in the current
insn. */
-static varray_type earlyclobber_regclass;
+DEF_VEC_I(int);
+DEF_VEC_ALLOC_I(int,heap);
+
+static VEC(int,heap) *earlyclobber_regclass;
/* This function finds and stores register classes that could be early
clobbered in INSN. If any earlyclobber classes are found, the function
extract_insn (insn);
- VARRAY_POP_ALL (earlyclobber_regclass);
+ VEC_truncate (int, earlyclobber_regclass, 0);
for (opno = 0; opno < recog_data.n_operands; opno++)
{
char c;
case ',':
if (amp_p && class != NO_REGS)
{
+ int rc;
+
found = true;
- for (i = VARRAY_ACTIVE_SIZE (earlyclobber_regclass) - 1;
- i >= 0; i--)
- if (VARRAY_INT (earlyclobber_regclass, i) == (int) class)
- break;
- if (i < 0)
- VARRAY_PUSH_INT (earlyclobber_regclass, (int) class);
+ for (i = 0;
+ VEC_iterate (int, earlyclobber_regclass, i, rc);
+ i++)
+ {
+ if (rc == (int) class)
+ goto found_rc;
+ }
+
+ /* We use VEC_quick_push here because
+ earlyclobber_regclass holds no more than
+ N_REG_CLASSES elements. */
+ VEC_quick_push (int, earlyclobber_regclass, (int) class);
+ found_rc:
+ ;
}
amp_p = false;
basic_block bb = data;
struct bb_info *bb_info = BB_INFO (bb);
- if (GET_CODE (*x) == REG && REGNO (*x) >= FIRST_PSEUDO_REGISTER)
+ if (REG_P (*x) && REGNO (*x) >= FIRST_PSEUDO_REGISTER)
{
+ int rc;
+
regno = REGNO (*x);
if (bitmap_bit_p (bb_info->killed, regno)
|| bitmap_bit_p (bb_info->avloc, regno))
return 0;
pref_class = reg_preferred_class (regno);
alt_class = reg_alternate_class (regno);
- for (i = VARRAY_ACTIVE_SIZE (earlyclobber_regclass) - 1; i >= 0; i--)
- if (reg_classes_intersect_p (VARRAY_INT (earlyclobber_regclass, i),
- pref_class)
- || (VARRAY_INT (earlyclobber_regclass, i) != NO_REGS
- && reg_classes_intersect_p (VARRAY_INT (earlyclobber_regclass,
- i),
- alt_class)))
- {
- bitmap_set_bit (bb_info->earlyclobber, regno);
- break;
- }
+ for (i = 0; VEC_iterate (int, earlyclobber_regclass, i, rc); i++)
+ {
+ if (reg_classes_intersect_p (rc, pref_class)
+ || (rc != NO_REGS
+ && reg_classes_intersect_p (rc, alt_class)))
+ {
+ bitmap_set_bit (bb_info->earlyclobber, regno);
+ break;
+ }
+ }
}
return 0;
}
basic_block bb;
rtx insn, bound;
- VARRAY_INT_INIT (earlyclobber_regclass, 20,
- "classes of registers early clobbered in an insn");
+ /* We know that earlyclobber_regclass holds no more than
+ N_REG_CLASSES elements. See check_earlyclobber. */
+ earlyclobber_regclass = VEC_alloc (int, heap, N_REG_CLASSES);
FOR_EACH_BB (bb)
{
bound = NEXT_INSN (BB_END (bb));
note_uses (&PATTERN (insn), mark_reg_use_for_earlyclobber_1, bb);
}
}
+ VEC_free (int, heap, earlyclobber_regclass);
}
/* The function sets up reverse post-order number of each basic
/* Temporary bitmap used for live_pavin, live_pavout calculation. */
static bitmap temp_bitmap;
+DEF_VEC_P(basic_block);
+DEF_VEC_ALLOC_P(basic_block,heap);
+
/* The function calculates partial register availability according to
the following equations:
basic_block bb, succ;
edge e;
int i, nel;
- varray_type bbs, new_bbs, temp;
+ VEC(basic_block,heap) *bbs, *new_bbs, *temp;
basic_block *bb_array;
sbitmap wset;
- VARRAY_BB_INIT (bbs, n_basic_blocks, "basic blocks");
- VARRAY_BB_INIT (new_bbs, n_basic_blocks, "basic blocks for the next iter.");
+ bbs = VEC_alloc (basic_block, heap, n_basic_blocks);
+ new_bbs = VEC_alloc (basic_block, heap, n_basic_blocks);
temp_bitmap = BITMAP_ALLOC (NULL);
FOR_EACH_BB (bb)
{
- VARRAY_PUSH_BB (bbs, bb);
+ VEC_quick_push (basic_block, bbs, bb);
}
wset = sbitmap_alloc (n_basic_blocks + 1);
- while (VARRAY_ACTIVE_SIZE (bbs))
+ while (VEC_length (basic_block, bbs))
{
- bb_array = &VARRAY_BB (bbs, 0);
- nel = VARRAY_ACTIVE_SIZE (bbs);
+ bb_array = VEC_address (basic_block, bbs);
+ nel = VEC_length (basic_block, bbs);
qsort (bb_array, nel, sizeof (basic_block), rpost_cmp);
sbitmap_zero (wset);
for (i = 0; i < nel; i++)
if (pred->index != ENTRY_BLOCK)
bitmap_ior_into (bb_live_pavin, BB_INFO (pred)->live_pavout);
}
- bitmap_and_into (bb_live_pavin, bb->global_live_at_start);
+ bitmap_and_into (bb_live_pavin, bb->il.rtl->global_live_at_start);
bitmap_ior_and_compl (temp_bitmap, bb_info->avloc,
bb_live_pavin, bb_info->killed);
- bitmap_and_into (temp_bitmap, bb->global_live_at_end);
+ bitmap_and_into (temp_bitmap, bb->il.rtl->global_live_at_end);
if (! bitmap_equal_p (temp_bitmap, bb_live_pavout))
{
bitmap_copy (bb_live_pavout, temp_bitmap);
&& !TEST_BIT (wset, succ->index))
{
SET_BIT (wset, succ->index);
- VARRAY_PUSH_BB (new_bbs, succ);
+ VEC_quick_push (basic_block, new_bbs, succ);
}
}
}
temp = bbs;
bbs = new_bbs;
new_bbs = temp;
- VARRAY_POP_ALL (new_bbs);
+ VEC_truncate (basic_block, new_bbs, 0);
}
sbitmap_free (wset);
BITMAP_FREE (temp_bitmap);
+ VEC_free (basic_block, heap, new_bbs);
+ VEC_free (basic_block, heap, bbs);
}
/* The function modifies partial availability information for two
{
bb_info = BB_INFO (bb);
- bitmap_and_into (bb->global_live_at_start, bb_info->live_pavin);
- bitmap_and_into (bb->global_live_at_end, bb_info->live_pavout);
+ bitmap_and_into (bb->il.rtl->global_live_at_start, bb_info->live_pavin);
+ bitmap_and_into (bb->il.rtl->global_live_at_end, bb_info->live_pavout);
}
free_bb_info ();
}
+/* Run old register allocator. Return TRUE if we must exit
+ rest_of_compilation upon return. */
+static void
+rest_of_handle_global_alloc (void)
+{
+ bool failure;
+
+ /* If optimizing, allocate remaining pseudo-regs. Do the reload
+ pass fixing up any insns that are invalid. */
+
+ if (optimize)
+ failure = global_alloc (dump_file);
+ else
+ {
+ build_insn_chain (get_insns ());
+ failure = reload (get_insns (), 0);
+ }
+
+ if (dump_enabled_p (pass_global_alloc.static_pass_number))
+ {
+ timevar_push (TV_DUMP);
+ dump_global_regs (dump_file);
+ timevar_pop (TV_DUMP);
+ }
+
+ gcc_assert (reload_completed || failure);
+ reload_completed = !failure;
+}
+
+struct tree_opt_pass pass_global_alloc =
+{
+ "greg", /* name */
+ NULL, /* gate */
+ rest_of_handle_global_alloc, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_GLOBAL_ALLOC, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func |
+ TODO_ggc_collect, /* todo_flags_finish */
+ 'g' /* letter */
+};
+