From patchwork Sun Nov 6 02:19:00 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitrios Apostolou X-Patchwork-Id: 123909 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 4EBC9B6F72 for ; Sun, 6 Nov 2011 13:19:39 +1100 (EST) Received: (qmail 32698 invoked by alias); 6 Nov 2011 02:19:37 -0000 Received: (qmail 32680 invoked by uid 22791); 6 Nov 2011 02:19:30 -0000 X-SWARE-Spam-Status: No, hits=-1.3 required=5.0 tests=AWL, BAYES_50, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mailout-de.gmx.net (HELO mailout-de.gmx.net) (213.165.64.23) by sourceware.org (qpsmtpd/0.43rc1) with SMTP; Sun, 06 Nov 2011 02:19:07 +0000 Received: (qmail invoked by alias); 06 Nov 2011 02:19:04 -0000 Received: from teras.ics.forth.gr (EHLO [139.91.70.93]) [139.91.70.93] by mail.gmx.net (mp055) with SMTP; 06 Nov 2011 03:19:04 +0100 Date: Sun, 6 Nov 2011 04:19:00 +0200 (EET) From: Dimitrios Apostolou To: Jeff Law cc: gcc-patches@gcc.gnu.org, Steven Bosscher , Paolo Bonzini , Jakub Jelinek Subject: Re: repost: [DF] Use HARD_REG_SETs instead of bitmaps In-Reply-To: <4E528F62.5030901@redhat.com> Message-ID: References: <4E528F62.5030901@redhat.com> User-Agent: Alpine 2.02 (LNX 1266 2009-07-14) MIME-Version: 1.0 Content-ID: X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello, better late than never, an update to my patch that converts most bitmaps in DF to HARD_REG_SETs and also refactors hard-reg-set.h. On Mon, 22 Aug 2011, Jeff Law wrote: > On 08/22/11 11:16, Dimitrios Apostolou wrote: >> >> Any updates will come as a followup to this thread. I still have to >> do some testing on other platforms. Do we have access to any PA and >> MIPS machinery? I also wanted to test on architecture with lots of >> hard registers and small long size, but my 32-bit sparcstation >> crashed badly, any ideas which arch to try next? > I thought there was a PA available in the testfarm. I appreciate the advice Jeff, indeed I've tried running my patch on gcc61 (PA-RISC), and I'm also running tests on MIPS machines. Everyone: I attach the latest version of this patch, updated to latest trunk and with an obscure bug I had introduced, fixed, together with some updates in reorg.c which depended on HARD_REG_SET implementation if DELAY_SLOTS was set. Previously it was tested succesfully on i386, x86_64. Now I tested it on on i386 and sparc-linux-gnu, no regressions. I'll report back when testing on PA-RISC, MIPS is finished. Changelog and comments from the previous email apply here too: http://gcc.gnu.org/ml/gcc-patches/2011-08/msg01796.html Additional Changelog: * reorg.c (resource_conflicts_p): Removed code dependant on HARD_REG_SET implementation, replaced with hard_reg_set_intersect_p(). Jakub, Paolo: You had voiced concerns about the struct-ification of HARD_REG_SET but I don't think we ended up anywhere? Any updates? I understand major hassle is when the register file is big, too much data is being copied on a function call, when it has a HARD_REG_SET as a pass by value parameter. So I did some testing on SPARC, which has the biggest register file I know of, and there is a small performance regression indeed. On the other hand I really like the code reduction in hard-reg-set.h. So how should I proceed? FWIW I'm already testing passing the parameter by reference in the hottest functions. Last but not least, what about the other aspects of this patch? Thanks, Dimitris === modified file 'gcc/config/i386/i386.c' --- gcc/config/i386/i386.c 2011-10-21 19:32:20 +0000 +++ gcc/config/i386/i386.c 2011-10-23 21:13:15 +0000 @@ -11206,12 +11206,12 @@ ix86_expand_split_stack_prologue (void) is initializing a scratch register. */ static void -ix86_live_on_entry (bitmap regs) +ix86_live_on_entry (HARD_REG_SET *regs) { if (cfun->machine->split_stack_varargs_pointer != NULL_RTX) { gcc_assert (flag_split_stack); - bitmap_set_bit (regs, split_stack_prologue_scratch_regno ()); + SET_HARD_REG_BIT (*regs, split_stack_prologue_scratch_regno ()); } } === modified file 'gcc/config/mips/mips.c' --- gcc/config/mips/mips.c 2011-10-02 17:46:11 +0000 +++ gcc/config/mips/mips.c 2011-10-23 21:13:15 +0000 @@ -9419,22 +9419,22 @@ mips_initial_elimination_offset (int fro /* Implement TARGET_EXTRA_LIVE_ON_ENTRY. */ static void -mips_extra_live_on_entry (bitmap regs) +mips_extra_live_on_entry (HARD_REG_SET *regs) { if (TARGET_USE_GOT) { /* PIC_FUNCTION_ADDR_REGNUM is live if we need it to set up the global pointer. */ if (!TARGET_ABSOLUTE_ABICALLS) - bitmap_set_bit (regs, PIC_FUNCTION_ADDR_REGNUM); + SET_HARD_REG_BIT (*regs, PIC_FUNCTION_ADDR_REGNUM); /* The prologue may set MIPS16_PIC_TEMP_REGNUM to the value of the global pointer. */ if (TARGET_MIPS16) - bitmap_set_bit (regs, MIPS16_PIC_TEMP_REGNUM); + SET_HARD_REG_BIT (*regs, MIPS16_PIC_TEMP_REGNUM); /* See the comment above load_call for details. */ - bitmap_set_bit (regs, GOT_VERSION_REGNUM); + SET_HARD_REG_BIT (*regs, GOT_VERSION_REGNUM); } } === modified file 'gcc/config/pa/pa.c' --- gcc/config/pa/pa.c 2011-10-12 13:08:11 +0000 +++ gcc/config/pa/pa.c 2011-10-23 21:13:15 +0000 @@ -171,7 +171,7 @@ static struct machine_function * pa_init static reg_class_t pa_secondary_reload (bool, rtx, reg_class_t, enum machine_mode, secondary_reload_info *); -static void pa_extra_live_on_entry (bitmap); +static void pa_extra_live_on_entry (HARD_REG_SET *); static enum machine_mode pa_promote_function_mode (const_tree, enum machine_mode, int *, const_tree, int); @@ -5936,10 +5936,10 @@ pa_secondary_reload (bool in_p, rtx x, r so we need to mark it here. */ static void -pa_extra_live_on_entry (bitmap regs) +pa_extra_live_on_entry (HARD_REG_SET *regs) { if (TARGET_64BIT) - bitmap_set_bit (regs, ARG_POINTER_REGNUM); + SET_HARD_REG_BIT (*regs, ARG_POINTER_REGNUM); } /* Implement EH_RETURN_HANDLER_RTX. The MEM needs to be volatile === modified file 'gcc/dce.c' --- gcc/dce.c 2011-07-19 17:43:15 +0000 +++ gcc/dce.c 2011-10-23 21:13:15 +0000 @@ -867,7 +867,7 @@ word_dce_process_block (basic_block bb, artificial uses. */ static bool -dce_process_block (basic_block bb, bool redo_out, bitmap au) +dce_process_block (basic_block bb, bool redo_out, HARD_REG_SET au) { bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); rtx insn; @@ -906,7 +906,8 @@ dce_process_block (basic_block bb, bool if (!needed) for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec)) - || bitmap_bit_p (au, DF_REF_REGNO (*def_rec))) + || ( DF_REF_REGNO (*def_rec) < FIRST_PSEUDO_REGISTER + && TEST_HARD_REG_BIT (au, DF_REF_REGNO (*def_rec)))) { needed = true; mark_insn (insn, true); @@ -952,13 +953,16 @@ fast_dce (bool word_level) bool global_changed = true; /* These regs are considered always live so if they end up dying - because of some def, we need to bring the back again. Calling + because of some def, we need to bring them back again. Calling df_simulate_fixup_sets has the disadvantage of calling bb_has_eh_pred once per insn, so we cache the information here. */ - bitmap au = &df->regular_block_artificial_uses; - bitmap au_eh = &df->eh_block_artificial_uses; + HARD_REG_SET au; + HARD_REG_SET au_eh; int i; + + COPY_HARD_REG_SET (au, df->regular_block_artificial_uses); + COPY_HARD_REG_SET (au_eh, df->eh_block_artificial_uses); prescan_insns_for_dce (true); === modified file 'gcc/df-core.c' --- gcc/df-core.c 2011-04-20 18:19:03 +0000 +++ gcc/df-core.c 2011-10-23 21:13:15 +0000 @@ -1885,6 +1885,17 @@ df_print_regset (FILE *file, bitmap r) fprintf (file, "\n"); } +void +df_print_hard_reg_set (FILE *f, HARD_REG_SET r) +{ + unsigned int i; + hard_reg_set_iterator iter; + + EXECUTE_IF_SET_IN_HARD_REG_SET (r, 0, i, iter) + fprintf (f, " %d [%s]", i, reg_names[i]); + fprintf (f, "\n"); +} + /* Write information about registers and basic blocks into FILE. The bitmap is in the form used by df_byte_lr. This is part of making a === modified file 'gcc/df-problems.c' --- gcc/df-problems.c 2011-08-26 14:21:19 +0000 +++ gcc/df-problems.c 2011-10-23 21:13:15 +0000 @@ -432,6 +432,7 @@ df_rd_local_compute (bitmap all_blocks) { unsigned int bb_index; bitmap_iterator bi; + hard_reg_set_iterator iter; unsigned int regno; struct df_rd_problem_data *problem_data = (struct df_rd_problem_data *) df_rd->problem_data; @@ -449,7 +450,7 @@ df_rd_local_compute (bitmap all_blocks) } /* Set up the knockout bit vectors to be applied across EH_EDGES. */ - EXECUTE_IF_SET_IN_BITMAP (regs_invalidated_by_call_regset, 0, regno, bi) + EXECUTE_IF_SET_IN_HARD_REG_SET (regs_invalidated_by_call, 0, regno, iter) { if (DF_DEFS_COUNT (regno) > DF_SPARSE_THRESHOLD) bitmap_set_bit (sparse_invalidated, regno); @@ -887,6 +888,31 @@ df_lr_bb_local_compute (unsigned int bb_ df_recompute_luids (bb); } +/* TODO optimise per-word */ +static void +bitmap_copy_from_hard_reg_set(bitmap to, HARD_REG_SET from) +{ + unsigned int i; + hard_reg_set_iterator iter; + + bitmap_clear (to); + EXECUTE_IF_SET_IN_HARD_REG_SET (from, 0, i, iter) + bitmap_set_bit (to, i); +} + +/* TODO optimise per-word */ +static bool +bitmap_ior_from_hard_reg_set(bitmap to, HARD_REG_SET from) +{ + bool ret= false; + hard_reg_set_iterator iter; + unsigned int i; + + EXECUTE_IF_SET_IN_HARD_REG_SET (from, 0, i, iter) + ret |= bitmap_set_bit (to, i); + + return ret; +} /* Compute local live register info for each basic block within BLOCKS. */ @@ -896,10 +922,10 @@ df_lr_local_compute (bitmap all_blocks A unsigned int bb_index; bitmap_iterator bi; - bitmap_clear (&df->hardware_regs_used); + CLEAR_HARD_REG_SET (df->hardware_regs_used); /* The all-important stack pointer must always be live. */ - bitmap_set_bit (&df->hardware_regs_used, STACK_POINTER_REGNUM); + SET_HARD_REG_BIT (df->hardware_regs_used, STACK_POINTER_REGNUM); /* Before reload, there are a few registers that must be forced live everywhere -- which might not already be the case for @@ -909,20 +935,20 @@ df_lr_local_compute (bitmap all_blocks A unsigned int pic_offset_table_regnum = PIC_OFFSET_TABLE_REGNUM; /* Any reference to any pseudo before reload is a potential reference of the frame pointer. */ - bitmap_set_bit (&df->hardware_regs_used, FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (df->hardware_regs_used, FRAME_POINTER_REGNUM); #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM /* Pseudos with argument area equivalences may require reloading via the argument pointer. */ if (fixed_regs[ARG_POINTER_REGNUM]) - bitmap_set_bit (&df->hardware_regs_used, ARG_POINTER_REGNUM); + SET_HARD_REG_BIT (df->hardware_regs_used, ARG_POINTER_REGNUM); #endif /* Any constant, or pseudo with constant equivalences, may require reloading from memory using the pic register. */ if (pic_offset_table_regnum != INVALID_REGNUM && fixed_regs[pic_offset_table_regnum]) - bitmap_set_bit (&df->hardware_regs_used, pic_offset_table_regnum); + SET_HARD_REG_BIT (df->hardware_regs_used, pic_offset_table_regnum); } EXECUTE_IF_SET_IN_BITMAP (df_lr->out_of_date_transfer_functions, 0, bb_index, bi) @@ -932,7 +958,7 @@ df_lr_local_compute (bitmap all_blocks A /* The exit block is special for this problem and its bits are computed from thin air. */ struct df_lr_bb_info *bb_info = df_lr_get_bb_info (EXIT_BLOCK); - bitmap_copy (&bb_info->use, df->exit_block_uses); + bitmap_copy_from_hard_reg_set (&bb_info->use, df->exit_block_uses); } else df_lr_bb_local_compute (bb_index); @@ -967,9 +993,32 @@ df_lr_confluence_0 (basic_block bb) { bitmap op1 = &df_lr_get_bb_info (bb->index)->out; if (bb != EXIT_BLOCK_PTR) - bitmap_copy (op1, &df->hardware_regs_used); + bitmap_copy_from_hard_reg_set (op1, df->hardware_regs_used); } +/* to |= from1 & ~from2 + from2 is of type HARD_REG_SET */ + +static bool +bitmap_ior_and_compl_from_hard_reg_set (bitmap to, const_bitmap from1, + HARD_REG_SET from2) +{ + bool ret; + unsigned int i; + bitmap_head from1_tmp; + hard_reg_set_iterator iter; + + bitmap_initialize (&from1_tmp, &bitmap_default_obstack); + bitmap_copy (&from1_tmp, from1); + + /* TODO optimise per-word */ + EXECUTE_IF_SET_IN_HARD_REG_SET (from2, 0, i, iter) + bitmap_clear_bit (&from1_tmp, i); + ret = bitmap_ior_into (to, &from1_tmp); + + bitmap_clear (&from1_tmp); + return ret; +} /* Confluence function that ignores fake edges. */ @@ -984,11 +1033,12 @@ df_lr_confluence_n (edge e) /* ??? Abnormal call edges ignored for the moment, as this gets confused by sibling call edges, which crashes reg-stack. */ if (e->flags & EDGE_EH) - changed = bitmap_ior_and_compl_into (op1, op2, regs_invalidated_by_call_regset); + changed = bitmap_ior_and_compl_from_hard_reg_set (op1, op2, + regs_invalidated_by_call); else changed = bitmap_ior_into (op1, op2); - changed |= bitmap_ior_into (op1, &df->hardware_regs_used); + changed |= bitmap_ior_from_hard_reg_set (op1, df->hardware_regs_used); return changed; } @@ -2507,19 +2557,10 @@ df_word_lr_local_compute (bitmap all_blo unsigned int bb_index; bitmap_iterator bi; - EXECUTE_IF_SET_IN_BITMAP (df_word_lr->out_of_date_transfer_functions, 0, bb_index, bi) - { - if (bb_index == EXIT_BLOCK) - { - unsigned regno; - bitmap_iterator bi; - EXECUTE_IF_SET_IN_BITMAP (df->exit_block_uses, FIRST_PSEUDO_REGISTER, - regno, bi) - gcc_unreachable (); - } - else - df_word_lr_bb_local_compute (bb_index); - } + EXECUTE_IF_SET_IN_BITMAP (df_word_lr->out_of_date_transfer_functions, + 0, bb_index, bi) + if (bb_index != EXIT_BLOCK) + df_word_lr_bb_local_compute (bb_index); bitmap_clear (df_word_lr->out_of_date_transfer_functions); } @@ -3650,9 +3691,9 @@ df_simulate_fixup_sets (basic_block bb, /* These regs are considered always live so if they end up dying because of some def, we need to bring the back again. */ if (bb_has_eh_pred (bb)) - bitmap_ior_into (live, &df->eh_block_artificial_uses); + bitmap_ior_from_hard_reg_set (live, df->eh_block_artificial_uses); else - bitmap_ior_into (live, &df->regular_block_artificial_uses); + bitmap_ior_from_hard_reg_set (live, df->regular_block_artificial_uses); } @@ -4471,8 +4512,8 @@ df_md_confluence_n (edge e) return false; if (e->flags & EDGE_EH) - return bitmap_ior_and_compl_into (op1, op2, - regs_invalidated_by_call_regset); + return bitmap_ior_and_compl_from_hard_reg_set (op1, op2, + regs_invalidated_by_call); else return bitmap_ior_into (op1, op2); } === modified file 'gcc/df-scan.c' --- gcc/df-scan.c 2011-08-27 17:38:58 +0000 +++ gcc/df-scan.c 2011-10-23 21:13:15 +0000 @@ -131,13 +131,13 @@ static void df_insn_refs_collect (struct basic_block, struct df_insn_info *); static void df_canonize_collection_rec (struct df_collection_rec *); -static void df_get_regular_block_artificial_uses (bitmap); -static void df_get_eh_block_artificial_uses (bitmap); +static void df_get_regular_block_artificial_uses (HARD_REG_SET *); +static void df_get_eh_block_artificial_uses (HARD_REG_SET *); -static void df_record_entry_block_defs (bitmap); -static void df_record_exit_block_uses (bitmap); -static void df_get_exit_block_use_set (bitmap); -static void df_get_entry_block_def_set (bitmap); +static void df_record_entry_block_defs (HARD_REG_SET); +static void df_record_exit_block_uses (HARD_REG_SET); +static void df_get_exit_block_use_set (HARD_REG_SET *); +static void df_get_entry_block_def_set (HARD_REG_SET *); static void df_grow_ref_info (struct df_ref_info *, unsigned int); static void df_ref_chain_delete_du_chain (df_ref *); static void df_ref_chain_delete (df_ref *); @@ -146,8 +146,8 @@ static void df_refs_add_to_chains (struc basic_block, rtx); static bool df_insn_refs_verify (struct df_collection_rec *, basic_block, rtx, bool); -static void df_entry_block_defs_collect (struct df_collection_rec *, bitmap); -static void df_exit_block_uses_collect (struct df_collection_rec *, bitmap); +static void df_entry_block_defs_collect (struct df_collection_rec *, HARD_REG_SET); +static void df_exit_block_uses_collect (struct df_collection_rec *, HARD_REG_SET); static void df_install_ref (df_ref, struct df_reg_info *, struct df_ref_info *, bool); @@ -162,7 +162,7 @@ static int df_mw_compare (const void *, regs. Final uses it to generate the code in the function prologue and epilogue to save and restore registers as needed. */ -static bool regs_ever_live[FIRST_PSEUDO_REGISTER]; +static HARD_REG_SET regs_ever_live; /*---------------------------------------------------------------------------- SCANNING DATAFLOW PROBLEM @@ -253,11 +253,9 @@ df_scan_free_internal (void) df_scan->block_info = NULL; df_scan->block_info_size = 0; - bitmap_clear (&df->hardware_regs_used); - bitmap_clear (&df->regular_block_artificial_uses); - bitmap_clear (&df->eh_block_artificial_uses); - BITMAP_FREE (df->entry_block_defs); - BITMAP_FREE (df->exit_block_uses); + CLEAR_HARD_REG_SET (df->hardware_regs_used); + CLEAR_HARD_REG_SET (df->regular_block_artificial_uses); + CLEAR_HARD_REG_SET (df->eh_block_artificial_uses); bitmap_clear (&df->insns_to_delete); bitmap_clear (&df->insns_to_rescan); bitmap_clear (&df->insns_to_notes_rescan); @@ -366,11 +364,11 @@ df_scan_alloc (bitmap all_blocks ATTRIBU bb_info->artificial_uses = NULL; } - bitmap_initialize (&df->hardware_regs_used, &problem_data->reg_bitmaps); - bitmap_initialize (&df->regular_block_artificial_uses, &problem_data->reg_bitmaps); - bitmap_initialize (&df->eh_block_artificial_uses, &problem_data->reg_bitmaps); - df->entry_block_defs = BITMAP_ALLOC (&problem_data->reg_bitmaps); - df->exit_block_uses = BITMAP_ALLOC (&problem_data->reg_bitmaps); + CLEAR_HARD_REG_SET (df->hardware_regs_used); + CLEAR_HARD_REG_SET (df->regular_block_artificial_uses); + CLEAR_HARD_REG_SET (df->eh_block_artificial_uses); + CLEAR_HARD_REG_SET (df->entry_block_defs); + CLEAR_HARD_REG_SET (df->exit_block_uses); bitmap_initialize (&df->insns_to_delete, &problem_data->insn_bitmaps); bitmap_initialize (&df->insns_to_rescan, &problem_data->insn_bitmaps); bitmap_initialize (&df->insns_to_notes_rescan, &problem_data->insn_bitmaps); @@ -409,21 +407,28 @@ df_scan_start_dump (FILE *file ATTRIBUTE rtx insn; fprintf (file, ";; invalidated by call \t"); - df_print_regset (file, regs_invalidated_by_call_regset); + df_print_hard_reg_set (file, regs_invalidated_by_call); + fprintf (file, ";; hardware regs used \t"); - df_print_regset (file, &df->hardware_regs_used); + df_print_hard_reg_set (file, df->hardware_regs_used); + fprintf (file, ";; regular block artificial uses \t"); - df_print_regset (file, &df->regular_block_artificial_uses); + df_print_hard_reg_set (file, df->regular_block_artificial_uses); + fprintf (file, ";; eh block artificial uses \t"); - df_print_regset (file, &df->eh_block_artificial_uses); + df_print_hard_reg_set (file, df->eh_block_artificial_uses); + fprintf (file, ";; entry block defs \t"); - df_print_regset (file, df->entry_block_defs); + df_print_hard_reg_set (file, df->entry_block_defs); + fprintf (file, ";; exit block uses \t"); - df_print_regset (file, df->exit_block_uses); + df_print_hard_reg_set (file, df->exit_block_uses); + fprintf (file, ";; regs ever live \t"); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (df_regs_ever_live_p (i)) fprintf (file, " %d[%s]", i, reg_names[i]); + fprintf (file, "\n;; ref usage \t"); for (i = 0; i < (int)df->regs_inited; i++) @@ -662,13 +667,13 @@ df_scan_blocks (void) df_get_regular_block_artificial_uses (&df->regular_block_artificial_uses); df_get_eh_block_artificial_uses (&df->eh_block_artificial_uses); - bitmap_ior_into (&df->eh_block_artificial_uses, - &df->regular_block_artificial_uses); + IOR_HARD_REG_SET (df->eh_block_artificial_uses, + df->regular_block_artificial_uses); /* ENTRY and EXIT blocks have special defs/uses. */ - df_get_entry_block_def_set (df->entry_block_defs); + df_get_entry_block_def_set (&df->entry_block_defs); df_record_entry_block_defs (df->entry_block_defs); - df_get_exit_block_use_set (df->exit_block_uses); + df_get_exit_block_use_set (&df->exit_block_uses); df_record_exit_block_uses (df->exit_block_uses); df_set_bb_dirty (BASIC_BLOCK (ENTRY_BLOCK)); df_set_bb_dirty (BASIC_BLOCK (EXIT_BLOCK)); @@ -3318,20 +3323,20 @@ df_get_call_refs (struct df_collection_r int flags) { rtx note; - bitmap_iterator bi; + hard_reg_set_iterator iter; unsigned int ui; bool is_sibling_call; unsigned int i; df_ref def; - bitmap_head defs_generated; + HARD_REG_SET defs_generated; - bitmap_initialize (&defs_generated, &df_bitmap_obstack); + CLEAR_HARD_REG_SET(defs_generated); /* Do not generate clobbers for registers that are the result of the call. This causes ordering problems in the chain building code depending on which def is seen first. */ FOR_EACH_VEC_ELT (df_ref, collection_rec->def_vec, i, def) - bitmap_set_bit (&defs_generated, DF_REF_REGNO (def)); + SET_HARD_REG_BIT (defs_generated, DF_REF_REGNO (def)); /* Record the registers used to pass arguments, and explicitly noted as clobbered. */ @@ -3346,7 +3351,7 @@ df_get_call_refs (struct df_collection_r if (REG_P (XEXP (XEXP (note, 0), 0))) { unsigned int regno = REGNO (XEXP (XEXP (note, 0), 0)); - if (!bitmap_bit_p (&defs_generated, regno)) + if (!TEST_HARD_REG_BIT (defs_generated, regno)) df_defs_record (collection_rec, XEXP (note, 0), bb, insn_info, flags); } @@ -3376,12 +3381,12 @@ df_get_call_refs (struct df_collection_r } is_sibling_call = SIBLING_CALL_P (insn_info->insn); - EXECUTE_IF_SET_IN_BITMAP (regs_invalidated_by_call_regset, 0, ui, bi) + EXECUTE_IF_SET_IN_HARD_REG_SET (regs_invalidated_by_call, 0, ui, iter) { if (!global_regs[ui] - && (!bitmap_bit_p (&defs_generated, ui)) + && (!TEST_HARD_REG_BIT (defs_generated, ui)) && (!is_sibling_call - || !bitmap_bit_p (df->exit_block_uses, ui) + || !TEST_HARD_REG_BIT (df->exit_block_uses, ui) || refers_to_regno_p (ui, ui+1, crtl->return_rtx, NULL))) df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[ui], @@ -3389,7 +3394,6 @@ df_get_call_refs (struct df_collection_r DF_REF_MAY_CLOBBER | flags); } - bitmap_clear (&defs_generated); return; } @@ -3535,13 +3539,13 @@ df_bb_refs_collect (struct df_collection /* Add the artificial uses. */ if (bb->index >= NUM_FIXED_BLOCKS) { - bitmap_iterator bi; + hard_reg_set_iterator iter; unsigned int regno; - bitmap au = bb_has_eh_pred (bb) - ? &df->eh_block_artificial_uses - : &df->regular_block_artificial_uses; + HARD_REG_SET *au= bb_has_eh_pred (bb) + ? &(df->eh_block_artificial_uses) + : &(df->regular_block_artificial_uses); - EXECUTE_IF_SET_IN_BITMAP (au, 0, regno, bi) + EXECUTE_IF_SET_IN_HARD_REG_SET (*au, 0, regno, iter) { df_ref_record (DF_REF_ARTIFICIAL, collection_rec, regno_reg_rtx[regno], NULL, bb, NULL, DF_REF_REG_USE, 0); @@ -3608,18 +3612,18 @@ df_bb_refs_record (int bb_index, bool sc block. */ static void -df_get_regular_block_artificial_uses (bitmap regular_block_artificial_uses) +df_get_regular_block_artificial_uses (HARD_REG_SET *regular_block_artificial_uses) { #ifdef EH_USES unsigned int i; #endif - bitmap_clear (regular_block_artificial_uses); + CLEAR_HARD_REG_SET (*regular_block_artificial_uses); if (reload_completed) { if (frame_pointer_needed) - bitmap_set_bit (regular_block_artificial_uses, HARD_FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (*regular_block_artificial_uses, HARD_FRAME_POINTER_REGNUM); } else /* Before reload, there are a few registers that must be forced @@ -3630,27 +3634,27 @@ df_get_regular_block_artificial_uses (bi /* Any reference to any pseudo before reload is a potential reference of the frame pointer. */ - bitmap_set_bit (regular_block_artificial_uses, FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (*regular_block_artificial_uses, FRAME_POINTER_REGNUM); #if !HARD_FRAME_POINTER_IS_FRAME_POINTER - bitmap_set_bit (regular_block_artificial_uses, HARD_FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (*regular_block_artificial_uses, HARD_FRAME_POINTER_REGNUM); #endif #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM /* Pseudos with argument area equivalences may require reloading via the argument pointer. */ if (fixed_regs[ARG_POINTER_REGNUM]) - bitmap_set_bit (regular_block_artificial_uses, ARG_POINTER_REGNUM); + SET_HARD_REG_BIT (*regular_block_artificial_uses, ARG_POINTER_REGNUM); #endif /* Any constant, or pseudo with constant equivalences, may require reloading from memory using the pic register. */ if (picreg != INVALID_REGNUM && fixed_regs[picreg]) - bitmap_set_bit (regular_block_artificial_uses, picreg); + SET_HARD_REG_BIT (*regular_block_artificial_uses, picreg); } /* The all-important stack pointer must always be live. */ - bitmap_set_bit (regular_block_artificial_uses, STACK_POINTER_REGNUM); + SET_HARD_REG_BIT (*regular_block_artificial_uses, STACK_POINTER_REGNUM); #ifdef EH_USES /* EH_USES registers are used: @@ -3663,7 +3667,7 @@ df_get_regular_block_artificial_uses (bi (noreturn call or infinite loop). */ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (EH_USES (i)) - bitmap_set_bit (regular_block_artificial_uses, i); + SET_HARD_REG_BIT (*regular_block_artificial_uses, i); #endif } @@ -3671,9 +3675,9 @@ df_get_regular_block_artificial_uses (bi /* Get the artificial use set for an eh block. */ static void -df_get_eh_block_artificial_uses (bitmap eh_block_artificial_uses) +df_get_eh_block_artificial_uses (HARD_REG_SET *eh_block_artificial_uses) { - bitmap_clear (eh_block_artificial_uses); + CLEAR_HARD_REG_SET (*eh_block_artificial_uses); /* The following code (down thru the arg_pointer setting APPEARS to be necessary because there is nothing that actually @@ -3683,14 +3687,14 @@ df_get_eh_block_artificial_uses (bitmap { if (frame_pointer_needed) { - bitmap_set_bit (eh_block_artificial_uses, FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (*eh_block_artificial_uses, FRAME_POINTER_REGNUM); #if !HARD_FRAME_POINTER_IS_FRAME_POINTER - bitmap_set_bit (eh_block_artificial_uses, HARD_FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (*eh_block_artificial_uses, HARD_FRAME_POINTER_REGNUM); #endif } #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM if (fixed_regs[ARG_POINTER_REGNUM]) - bitmap_set_bit (eh_block_artificial_uses, ARG_POINTER_REGNUM); + SET_HARD_REG_BIT (*eh_block_artificial_uses, ARG_POINTER_REGNUM); #endif } } @@ -3708,7 +3712,7 @@ df_get_eh_block_artificial_uses (bitmap static void df_mark_reg (rtx reg, void *vset) { - bitmap set = (bitmap) vset; + HARD_REG_SET *set = (HARD_REG_SET *) vset; int regno = REGNO (reg); gcc_assert (GET_MODE (reg) != BLKmode); @@ -3716,29 +3720,34 @@ df_mark_reg (rtx reg, void *vset) if (regno < FIRST_PSEUDO_REGISTER) { int n = hard_regno_nregs[regno][GET_MODE (reg)]; - bitmap_set_range (set, regno, n); + int i; + for (i=regno; ientry_block_defs) - { - if (!bitmap_equal_p (df->entry_block_defs, &refs)) - { - struct df_scan_bb_info *bb_info = df_scan_get_bb_info (ENTRY_BLOCK); - df_ref_chain_delete_du_chain (bb_info->artificial_defs); - df_ref_chain_delete (bb_info->artificial_defs); - bb_info->artificial_defs = NULL; - changed = true; - } - } - else + if (!hard_reg_set_equal_p (df->entry_block_defs, refs)) { - struct df_scan_problem_data *problem_data - = (struct df_scan_problem_data *) df_scan->problem_data; - gcc_unreachable (); - df->entry_block_defs = BITMAP_ALLOC (&problem_data->reg_bitmaps); - changed = true; - } + struct df_scan_bb_info *bb_info = df_scan_get_bb_info (ENTRY_BLOCK); + df_ref_chain_delete_du_chain (bb_info->artificial_defs); + df_ref_chain_delete (bb_info->artificial_defs); + bb_info->artificial_defs = NULL; - if (changed) - { - df_record_entry_block_defs (&refs); - bitmap_copy (df->entry_block_defs, &refs); + df_record_entry_block_defs (refs); + COPY_HARD_REG_SET (df->entry_block_defs, refs); df_set_bb_dirty (BASIC_BLOCK (ENTRY_BLOCK)); } - bitmap_clear (&refs); } /* Set the bit for regs that are considered being used at the exit. */ static void -df_get_exit_block_use_set (bitmap exit_block_uses) +df_get_exit_block_use_set (HARD_REG_SET *exit_block_uses) { unsigned int i; unsigned int picreg = PIC_OFFSET_TABLE_REGNUM; - bitmap_clear (exit_block_uses); + CLEAR_HARD_REG_SET (*exit_block_uses); /* Stack pointer is always live at the exit. */ - bitmap_set_bit (exit_block_uses, STACK_POINTER_REGNUM); + SET_HARD_REG_BIT (*exit_block_uses, STACK_POINTER_REGNUM); /* Mark the frame pointer if needed at the end of the function. If we end up eliminating it, it will be removed from the live @@ -3903,11 +3896,11 @@ df_get_exit_block_use_set (bitmap exit_b if ((!reload_completed) || frame_pointer_needed) { - bitmap_set_bit (exit_block_uses, FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (*exit_block_uses, FRAME_POINTER_REGNUM); #if !HARD_FRAME_POINTER_IS_FRAME_POINTER /* If they are different, also mark the hard frame pointer as live. */ if (!LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM)) - bitmap_set_bit (exit_block_uses, HARD_FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (*exit_block_uses, HARD_FRAME_POINTER_REGNUM); #endif } @@ -3917,14 +3910,14 @@ df_get_exit_block_use_set (bitmap exit_b if (!PIC_OFFSET_TABLE_REG_CALL_CLOBBERED && picreg != INVALID_REGNUM && fixed_regs[picreg]) - bitmap_set_bit (exit_block_uses, picreg); + SET_HARD_REG_BIT (*exit_block_uses, picreg); /* Mark all global registers, and all registers used by the epilogue as being live at the end of the function since they may be referenced by our caller. */ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (global_regs[i] || EPILOGUE_USES (i)) - bitmap_set_bit (exit_block_uses, i); + SET_HARD_REG_BIT (*exit_block_uses, i); if (HAVE_epilogue && epilogue_completed) { @@ -3932,7 +3925,7 @@ df_get_exit_block_use_set (bitmap exit_b for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (df_regs_ever_live_p (i) && !LOCAL_REGNO (i) && !TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) - bitmap_set_bit (exit_block_uses, i); + SET_HARD_REG_BIT (*exit_block_uses, i); } #ifdef EH_RETURN_DATA_REGNO @@ -3943,7 +3936,7 @@ df_get_exit_block_use_set (bitmap exit_b unsigned regno = EH_RETURN_DATA_REGNO (i); if (regno == INVALID_REGNUM) break; - bitmap_set_bit (exit_block_uses, regno); + SET_HARD_REG_BIT (*exit_block_uses, regno); } #endif @@ -3976,12 +3969,12 @@ df_get_exit_block_use_set (bitmap exit_b It uses df->exit_block_uses to determine register to include. */ static void -df_exit_block_uses_collect (struct df_collection_rec *collection_rec, bitmap exit_block_uses) +df_exit_block_uses_collect (struct df_collection_rec *collection_rec, HARD_REG_SET exit_block_uses) { unsigned int i; - bitmap_iterator bi; + hard_reg_set_iterator iter; - EXECUTE_IF_SET_IN_BITMAP (exit_block_uses, 0, i, bi) + EXECUTE_IF_SET_IN_HARD_REG_SET (exit_block_uses, 0, i, iter) df_ref_record (DF_REF_ARTIFICIAL, collection_rec, regno_reg_rtx[i], NULL, EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 0); @@ -3989,7 +3982,7 @@ df_exit_block_uses_collect (struct df_co /* It is deliberate that this is not put in the exit block uses but I do not know why. */ if (reload_completed - && !bitmap_bit_p (exit_block_uses, ARG_POINTER_REGNUM) + && !TEST_HARD_REG_BIT (exit_block_uses, ARG_POINTER_REGNUM) && bb_has_eh_pred (EXIT_BLOCK_PTR) && fixed_regs[ARG_POINTER_REGNUM]) df_ref_record (DF_REF_ARTIFICIAL, collection_rec, regno_reg_rtx[ARG_POINTER_REGNUM], NULL, @@ -4004,16 +3997,17 @@ df_exit_block_uses_collect (struct df_co It uses df->exit_block_uses to determine which bit to include. */ static void -df_record_exit_block_uses (bitmap exit_block_uses) +df_record_exit_block_uses (HARD_REG_SET exit_block_uses) { struct df_collection_rec collection_rec; + memset (&collection_rec, 0, sizeof (struct df_collection_rec)); collection_rec.use_vec = VEC_alloc (df_ref, stack, FIRST_PSEUDO_REGISTER); df_exit_block_uses_collect (&collection_rec, exit_block_uses); - /* Process bb_refs chain */ df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (EXIT_BLOCK), NULL); + VEC_free (df_ref, stack, collection_rec.use_vec); } @@ -4023,38 +4017,20 @@ df_record_exit_block_uses (bitmap exit_b void df_update_exit_block_uses (void) { - bitmap_head refs; - bool changed = false; + HARD_REG_SET refs; - bitmap_initialize (&refs, &df_bitmap_obstack); df_get_exit_block_use_set (&refs); - if (df->exit_block_uses) - { - if (!bitmap_equal_p (df->exit_block_uses, &refs)) - { - struct df_scan_bb_info *bb_info = df_scan_get_bb_info (EXIT_BLOCK); - df_ref_chain_delete_du_chain (bb_info->artificial_uses); - df_ref_chain_delete (bb_info->artificial_uses); - bb_info->artificial_uses = NULL; - changed = true; - } - } - else + if (!hard_reg_set_equal_p (df->exit_block_uses, refs)) { - struct df_scan_problem_data *problem_data - = (struct df_scan_problem_data *) df_scan->problem_data; - gcc_unreachable (); - df->exit_block_uses = BITMAP_ALLOC (&problem_data->reg_bitmaps); - changed = true; - } + struct df_scan_bb_info *bb_info = df_scan_get_bb_info (EXIT_BLOCK); + df_ref_chain_delete_du_chain (bb_info->artificial_uses); + df_ref_chain_delete (bb_info->artificial_uses); + bb_info->artificial_uses = NULL; - if (changed) - { - df_record_exit_block_uses (&refs); - bitmap_copy (df->exit_block_uses,& refs); + df_record_exit_block_uses (refs); + COPY_HARD_REG_SET (df->exit_block_uses, refs); df_set_bb_dirty (BASIC_BLOCK (EXIT_BLOCK)); } - bitmap_clear (&refs); } static bool initialized = false; @@ -4143,7 +4119,7 @@ df_hard_reg_used_count (unsigned int reg bool df_regs_ever_live_p (unsigned int regno) { - return regs_ever_live[regno]; + return TEST_HARD_REG_BIT (regs_ever_live, regno); } @@ -4153,10 +4129,14 @@ df_regs_ever_live_p (unsigned int regno) void df_set_regs_ever_live (unsigned int regno, bool value) { - if (regs_ever_live[regno] == value) + if (df_regs_ever_live_p (regno) == value) return; - regs_ever_live[regno] = value; + if (value) + SET_HARD_REG_BIT (regs_ever_live, regno); + else + CLEAR_HARD_REG_BIT (regs_ever_live, regno); + if (df) df->redo_entry_and_exit = true; } @@ -4172,12 +4152,12 @@ df_compute_regs_ever_live (bool reset) bool changed = df->redo_entry_and_exit; if (reset) - memset (regs_ever_live, 0, sizeof (regs_ever_live)); + CLEAR_HARD_REG_SET (regs_ever_live); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if ((!regs_ever_live[i]) && df_hard_reg_used_p (i)) + if ((!df_regs_ever_live_p (i)) && df_hard_reg_used_p (i)) { - regs_ever_live[i] = true; + df_set_regs_ever_live (i, true); changed = true; } if (changed) @@ -4410,26 +4390,23 @@ df_bb_verify (basic_block bb) static bool df_entry_block_bitmap_verify (bool abort_if_fail) { - bitmap_head entry_block_defs; + HARD_REG_SET entry_block_defs; bool is_eq; - bitmap_initialize (&entry_block_defs, &df_bitmap_obstack); df_get_entry_block_def_set (&entry_block_defs); - is_eq = bitmap_equal_p (&entry_block_defs, df->entry_block_defs); + is_eq = hard_reg_set_equal_p (entry_block_defs, df->entry_block_defs); if (!is_eq && abort_if_fail) { print_current_pass (stderr); fprintf (stderr, "entry_block_defs = "); - df_print_regset (stderr, &entry_block_defs); + df_print_hard_reg_set (stderr, entry_block_defs); fprintf (stderr, "df->entry_block_defs = "); - df_print_regset (stderr, df->entry_block_defs); + df_print_hard_reg_set (stderr, df->entry_block_defs); gcc_assert (0); } - bitmap_clear (&entry_block_defs); - return is_eq; } @@ -4440,26 +4417,23 @@ df_entry_block_bitmap_verify (bool abort static bool df_exit_block_bitmap_verify (bool abort_if_fail) { - bitmap_head exit_block_uses; + HARD_REG_SET exit_block_uses; bool is_eq; - bitmap_initialize (&exit_block_uses, &df_bitmap_obstack); df_get_exit_block_use_set (&exit_block_uses); - is_eq = bitmap_equal_p (&exit_block_uses, df->exit_block_uses); + is_eq = hard_reg_set_equal_p (exit_block_uses, df->exit_block_uses); if (!is_eq && abort_if_fail) { print_current_pass (stderr); fprintf (stderr, "exit_block_uses = "); - df_print_regset (stderr, &exit_block_uses); + df_print_hard_reg_set (stderr, exit_block_uses); fprintf (stderr, "df->exit_block_uses = "); - df_print_regset (stderr, df->exit_block_uses); + df_print_hard_reg_set (stderr, df->exit_block_uses); gcc_assert (0); } - bitmap_clear (&exit_block_uses); - return is_eq; } @@ -4472,8 +4446,8 @@ df_scan_verify (void) { unsigned int i; basic_block bb; - bitmap_head regular_block_artificial_uses; - bitmap_head eh_block_artificial_uses; + HARD_REG_SET regular_block_artificial_uses; + HARD_REG_SET eh_block_artificial_uses; if (!df) return; @@ -4494,23 +4468,18 @@ df_scan_verify (void) /* (2) There are various bitmaps whose value may change over the course of the compilation. This step recomputes them to make sure that they have not slipped out of date. */ - bitmap_initialize (®ular_block_artificial_uses, &df_bitmap_obstack); - bitmap_initialize (&eh_block_artificial_uses, &df_bitmap_obstack); df_get_regular_block_artificial_uses (®ular_block_artificial_uses); df_get_eh_block_artificial_uses (&eh_block_artificial_uses); - bitmap_ior_into (&eh_block_artificial_uses, - ®ular_block_artificial_uses); + IOR_HARD_REG_SET (eh_block_artificial_uses, + regular_block_artificial_uses); /* Check artificial_uses bitmaps didn't change. */ - gcc_assert (bitmap_equal_p (®ular_block_artificial_uses, - &df->regular_block_artificial_uses)); - gcc_assert (bitmap_equal_p (&eh_block_artificial_uses, - &df->eh_block_artificial_uses)); - - bitmap_clear (®ular_block_artificial_uses); - bitmap_clear (&eh_block_artificial_uses); + gcc_assert (hard_reg_set_equal_p (regular_block_artificial_uses, + df->regular_block_artificial_uses)); + gcc_assert (hard_reg_set_equal_p (eh_block_artificial_uses, + df->eh_block_artificial_uses)); /* Verify entry block and exit block. These only verify the bitmaps, the refs are verified in df_bb_verify. */ === modified file 'gcc/df.h' --- gcc/df.h 2010-12-14 00:23:40 +0000 +++ gcc/df.h 2011-10-23 21:13:15 +0000 @@ -69,7 +69,7 @@ enum df_flow_dir /* Descriminator for the various df_ref types. */ enum df_ref_class {DF_REF_BASE, DF_REF_ARTIFICIAL, DF_REF_REGULAR}; -/* The first of these us a set of a registers. The remaining three +/* The first of these uses a set of a registers. The remaining three are all uses of a register (the mem_load and mem_store relate to how the register as an addressing operand). */ enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, @@ -545,16 +545,17 @@ struct df_d int num_problems_defined; - bitmap_head hardware_regs_used; /* The set of hardware registers used. */ + HARD_REG_SET hardware_regs_used; /* The set of hardware registers used. */ /* The set of hard regs that are in the artificial uses at the end of a regular basic block. */ - bitmap_head regular_block_artificial_uses; + HARD_REG_SET regular_block_artificial_uses; /* The set of hard regs that are in the artificial uses at the end of a basic block that has an EH pred. */ - bitmap_head eh_block_artificial_uses; + HARD_REG_SET eh_block_artificial_uses; /* The set of hardware registers live on entry to the function. */ - bitmap entry_block_defs; - bitmap exit_block_uses; /* The set of hardware registers used in exit block. */ + HARD_REG_SET entry_block_defs; + /* The set of hardware registers used in exit block. */ + HARD_REG_SET exit_block_uses; /* Insns to delete, rescan or reprocess the notes at next df_rescan_all or df_process_deferred_rescans. */ @@ -911,6 +912,7 @@ extern bool df_reg_defined (rtx, rtx); extern df_ref df_find_use (rtx, rtx); extern bool df_reg_used (rtx, rtx); extern void df_worklist_dataflow (struct dataflow *,bitmap, int *, int); +extern void df_print_hard_reg_set (FILE *f, HARD_REG_SET r); extern void df_print_regset (FILE *file, bitmap r); extern void df_print_word_regset (FILE *file, bitmap r); extern void df_dump (FILE *); === modified file 'gcc/doc/tm.texi' --- gcc/doc/tm.texi 2011-10-20 20:10:05 +0000 +++ gcc/doc/tm.texi 2011-10-23 21:13:15 +0000 @@ -4946,7 +4946,7 @@ as the @code{sibcall} md pattern can not may vary greatly between different architectures. @end deftypefn -@deftypefn {Target Hook} void TARGET_EXTRA_LIVE_ON_ENTRY (bitmap @var{regs}) +@deftypefn {Target Hook} void TARGET_EXTRA_LIVE_ON_ENTRY (HARD_REG_SET *@var{regs}) Add any hard registers to @var{regs} that are live on entry to the function. This hook only needs to be defined to provide registers that cannot be found by examination of FUNCTION_ARG_REGNO_P, the callee saved === modified file 'gcc/hard-reg-set.h' --- gcc/hard-reg-set.h 2011-01-03 20:52:22 +0000 +++ gcc/hard-reg-set.h 2011-10-23 21:13:15 +0000 @@ -24,35 +24,31 @@ along with GCC; see the file COPYING3. /* Define the type of a set of hard registers. */ /* HARD_REG_ELT_TYPE is a typedef of the unsigned integral type which - will be used for hard reg sets, either alone or in an array. - - If HARD_REG_SET is a macro, its definition is HARD_REG_ELT_TYPE, - and it has enough bits to represent all the target machine's hard - registers. Otherwise, it is a typedef for a suitably sized array - of HARD_REG_ELT_TYPEs. HARD_REG_SET_LONGS is defined as how many. + will be used for hard reg sets. An HARD_REG_ELT_TYPE, or an + array of them is wrapped in a struct. Note that lots of code assumes that the first part of a regset is the same format as a HARD_REG_SET. To help make sure this is true, we only try the widest fast integer mode (HOST_WIDEST_FAST_INT) - instead of all the smaller types. This approach loses only if - there are very few registers and then only in the few cases where - we have an array of HARD_REG_SETs, so it needn't be as complex as - it used to be. */ - -typedef unsigned HOST_WIDEST_FAST_INT HARD_REG_ELT_TYPE; - -#if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDEST_FAST_INT - -#define HARD_REG_SET HARD_REG_ELT_TYPE + instead of all the smaller types. */ +#ifdef ENABLE_RTL_CHECKING +#define gcc_rtl_assert(EXPR) gcc_assert (EXPR) #else +#define gcc_rtl_assert(EXPR) ((void)(0 && (EXPR))) +#endif + +typedef unsigned HOST_WIDEST_FAST_INT HARD_REG_ELT_TYPE; #define HARD_REG_SET_LONGS \ ((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_WIDEST_FAST_INT - 1) \ / HOST_BITS_PER_WIDEST_FAST_INT) -typedef HARD_REG_ELT_TYPE HARD_REG_SET[HARD_REG_SET_LONGS]; -#endif +#define HARD_REG_SET struct hard_reg_set + +struct hard_reg_set { + HARD_REG_ELT_TYPE elems[HARD_REG_SET_LONGS]; +}; /* HARD_CONST is used to cast a constant to the appropriate type for use with a HARD_REG_SET. */ @@ -89,343 +85,108 @@ typedef HARD_REG_ELT_TYPE HARD_REG_SET[H hard_reg_set_intersect_p (X, Y), which returns true if X and Y intersect. hard_reg_set_empty_p (X), which returns true if X is empty. */ -#define UHOST_BITS_PER_WIDE_INT ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT) -#ifdef HARD_REG_SET +#define HARD_REG_ELT_BITS ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT) #define SET_HARD_REG_BIT(SET, BIT) \ - ((SET) |= HARD_CONST (1) << (BIT)) + hard_reg_set_set_bit (&(SET), (BIT)) #define CLEAR_HARD_REG_BIT(SET, BIT) \ - ((SET) &= ~(HARD_CONST (1) << (BIT))) + hard_reg_set_clear_bit(&(SET), (BIT)) #define TEST_HARD_REG_BIT(SET, BIT) \ - (!!((SET) & (HARD_CONST (1) << (BIT)))) - -#define CLEAR_HARD_REG_SET(TO) ((TO) = HARD_CONST (0)) -#define SET_HARD_REG_SET(TO) ((TO) = ~ HARD_CONST (0)) - -#define COPY_HARD_REG_SET(TO, FROM) ((TO) = (FROM)) -#define COMPL_HARD_REG_SET(TO, FROM) ((TO) = ~(FROM)) - -#define IOR_HARD_REG_SET(TO, FROM) ((TO) |= (FROM)) -#define IOR_COMPL_HARD_REG_SET(TO, FROM) ((TO) |= ~ (FROM)) -#define AND_HARD_REG_SET(TO, FROM) ((TO) &= (FROM)) -#define AND_COMPL_HARD_REG_SET(TO, FROM) ((TO) &= ~ (FROM)) - -static inline bool -hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return (x & ~y) == HARD_CONST (0); -} + hard_reg_set_bit_p((SET), (BIT)) -static inline bool -hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return x == y; -} - -static inline bool -hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return (x & y) != HARD_CONST (0); -} - -static inline bool -hard_reg_set_empty_p (const HARD_REG_SET x) +static inline void +hard_reg_set_set_bit (HARD_REG_SET *s, unsigned int bit) { - return x == HARD_CONST (0); -} - +#if HARD_REG_SET_LONGS > 1 + int word = bit / HARD_REG_ELT_BITS; + int bitpos = bit % HARD_REG_ELT_BITS; #else - -#define SET_HARD_REG_BIT(SET, BIT) \ - ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ - |= HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT)) - -#define CLEAR_HARD_REG_BIT(SET, BIT) \ - ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ - &= ~(HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT))) - -#define TEST_HARD_REG_BIT(SET, BIT) \ - (!!((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ - & (HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT)))) - -#if FIRST_PSEUDO_REGISTER <= 2*HOST_BITS_PER_WIDEST_FAST_INT -#define CLEAR_HARD_REG_SET(TO) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - scan_tp_[0] = 0; \ - scan_tp_[1] = 0; } while (0) - -#define SET_HARD_REG_SET(TO) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - scan_tp_[0] = -1; \ - scan_tp_[1] = -1; } while (0) - -#define COPY_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] = scan_fp_[0]; \ - scan_tp_[1] = scan_fp_[1]; } while (0) - -#define COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] = ~ scan_fp_[0]; \ - scan_tp_[1] = ~ scan_fp_[1]; } while (0) - -#define AND_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] &= scan_fp_[0]; \ - scan_tp_[1] &= scan_fp_[1]; } while (0) - -#define AND_COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] &= ~ scan_fp_[0]; \ - scan_tp_[1] &= ~ scan_fp_[1]; } while (0) - -#define IOR_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] |= scan_fp_[0]; \ - scan_tp_[1] |= scan_fp_[1]; } while (0) - -#define IOR_COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] |= ~ scan_fp_[0]; \ - scan_tp_[1] |= ~ scan_fp_[1]; } while (0) - -static inline bool -hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return (x[0] & ~y[0]) == 0 && (x[1] & ~y[1]) == 0; -} - -static inline bool -hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return x[0] == y[0] && x[1] == y[1]; -} - -static inline bool -hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return (x[0] & y[0]) != 0 || (x[1] & y[1]) != 0; + int word = 0; + int bitpos = bit; +#endif + gcc_rtl_assert (bit < FIRST_PSEUDO_REGISTER); + (s->elems)[word] |= HARD_CONST (1) << bitpos; } -static inline bool -hard_reg_set_empty_p (const HARD_REG_SET x) +static inline void +hard_reg_set_clear_bit (HARD_REG_SET *s, unsigned int bit) { - return x[0] == 0 && x[1] == 0; -} - +#if HARD_REG_SET_LONGS > 1 + int word = bit / HARD_REG_ELT_BITS; + int bitpos = bit % HARD_REG_ELT_BITS; #else -#if FIRST_PSEUDO_REGISTER <= 3*HOST_BITS_PER_WIDEST_FAST_INT -#define CLEAR_HARD_REG_SET(TO) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - scan_tp_[0] = 0; \ - scan_tp_[1] = 0; \ - scan_tp_[2] = 0; } while (0) - -#define SET_HARD_REG_SET(TO) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - scan_tp_[0] = -1; \ - scan_tp_[1] = -1; \ - scan_tp_[2] = -1; } while (0) - -#define COPY_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] = scan_fp_[0]; \ - scan_tp_[1] = scan_fp_[1]; \ - scan_tp_[2] = scan_fp_[2]; } while (0) - -#define COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] = ~ scan_fp_[0]; \ - scan_tp_[1] = ~ scan_fp_[1]; \ - scan_tp_[2] = ~ scan_fp_[2]; } while (0) - -#define AND_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] &= scan_fp_[0]; \ - scan_tp_[1] &= scan_fp_[1]; \ - scan_tp_[2] &= scan_fp_[2]; } while (0) - -#define AND_COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] &= ~ scan_fp_[0]; \ - scan_tp_[1] &= ~ scan_fp_[1]; \ - scan_tp_[2] &= ~ scan_fp_[2]; } while (0) - -#define IOR_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] |= scan_fp_[0]; \ - scan_tp_[1] |= scan_fp_[1]; \ - scan_tp_[2] |= scan_fp_[2]; } while (0) - -#define IOR_COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] |= ~ scan_fp_[0]; \ - scan_tp_[1] |= ~ scan_fp_[1]; \ - scan_tp_[2] |= ~ scan_fp_[2]; } while (0) - -static inline bool -hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return ((x[0] & ~y[0]) == 0 - && (x[1] & ~y[1]) == 0 - && (x[2] & ~y[2]) == 0); -} - -static inline bool -hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return x[0] == y[0] && x[1] == y[1] && x[2] == y[2]; -} - -static inline bool -hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return ((x[0] & y[0]) != 0 - || (x[1] & y[1]) != 0 - || (x[2] & y[2]) != 0); + int word = 0; + int bitpos = bit; +#endif + gcc_rtl_assert (bit < FIRST_PSEUDO_REGISTER); + (s->elems)[word] &= ~(HARD_CONST (1) << bitpos); } static inline bool -hard_reg_set_empty_p (const HARD_REG_SET x) +hard_reg_set_bit_p (const HARD_REG_SET s, unsigned int bit) { - return x[0] == 0 && x[1] == 0 && x[2] == 0; -} - +#if HARD_REG_SET_LONGS > 1 + int word = bit / HARD_REG_ELT_BITS; + int bitpos = bit % HARD_REG_ELT_BITS; #else -#if FIRST_PSEUDO_REGISTER <= 4*HOST_BITS_PER_WIDEST_FAST_INT -#define CLEAR_HARD_REG_SET(TO) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - scan_tp_[0] = 0; \ - scan_tp_[1] = 0; \ - scan_tp_[2] = 0; \ - scan_tp_[3] = 0; } while (0) - -#define SET_HARD_REG_SET(TO) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - scan_tp_[0] = -1; \ - scan_tp_[1] = -1; \ - scan_tp_[2] = -1; \ - scan_tp_[3] = -1; } while (0) - -#define COPY_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] = scan_fp_[0]; \ - scan_tp_[1] = scan_fp_[1]; \ - scan_tp_[2] = scan_fp_[2]; \ - scan_tp_[3] = scan_fp_[3]; } while (0) - -#define COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] = ~ scan_fp_[0]; \ - scan_tp_[1] = ~ scan_fp_[1]; \ - scan_tp_[2] = ~ scan_fp_[2]; \ - scan_tp_[3] = ~ scan_fp_[3]; } while (0) - -#define AND_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] &= scan_fp_[0]; \ - scan_tp_[1] &= scan_fp_[1]; \ - scan_tp_[2] &= scan_fp_[2]; \ - scan_tp_[3] &= scan_fp_[3]; } while (0) - -#define AND_COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] &= ~ scan_fp_[0]; \ - scan_tp_[1] &= ~ scan_fp_[1]; \ - scan_tp_[2] &= ~ scan_fp_[2]; \ - scan_tp_[3] &= ~ scan_fp_[3]; } while (0) - -#define IOR_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] |= scan_fp_[0]; \ - scan_tp_[1] |= scan_fp_[1]; \ - scan_tp_[2] |= scan_fp_[2]; \ - scan_tp_[3] |= scan_fp_[3]; } while (0) - -#define IOR_COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ - scan_tp_[0] |= ~ scan_fp_[0]; \ - scan_tp_[1] |= ~ scan_fp_[1]; \ - scan_tp_[2] |= ~ scan_fp_[2]; \ - scan_tp_[3] |= ~ scan_fp_[3]; } while (0) - -static inline bool -hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return ((x[0] & ~y[0]) == 0 - && (x[1] & ~y[1]) == 0 - && (x[2] & ~y[2]) == 0 - && (x[3] & ~y[3]) == 0); -} - -static inline bool -hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3]; -} - -static inline bool -hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) -{ - return ((x[0] & y[0]) != 0 - || (x[1] & y[1]) != 0 - || (x[2] & y[2]) != 0 - || (x[3] & y[3]) != 0); -} - -static inline bool -hard_reg_set_empty_p (const HARD_REG_SET x) -{ - return x[0] == 0 && x[1] == 0 && x[2] == 0 && x[3] == 0; + int word = 0; + int bitpos = bit; +#endif + gcc_rtl_assert (bit < FIRST_PSEUDO_REGISTER); + return ((s.elems[word] >> bitpos) & HARD_CONST (1)); } -#else /* FIRST_PSEUDO_REGISTER > 4*HOST_BITS_PER_WIDEST_FAST_INT */ - #define CLEAR_HARD_REG_SET(TO) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ +do { HARD_REG_ELT_TYPE *scan_tp_ = (TO).elems; \ int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *scan_tp_++ = 0; } while (0) #define SET_HARD_REG_SET(TO) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ +do { HARD_REG_ELT_TYPE *scan_tp_ = (TO).elems; \ int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *scan_tp_++ = -1; } while (0) #define COPY_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ +do { HARD_REG_ELT_TYPE *scan_tp_ = (TO).elems; \ + HARD_REG_ELT_TYPE *scan_fp_ = (FROM).elems; \ int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *scan_tp_++ = *scan_fp_++; } while (0) #define COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ +do { HARD_REG_ELT_TYPE *scan_tp_ = (TO).elems; \ + HARD_REG_ELT_TYPE *scan_fp_ = (FROM).elems; \ int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *scan_tp_++ = ~ *scan_fp_++; } while (0) #define AND_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ +do { HARD_REG_ELT_TYPE *scan_tp_ = (TO).elems; \ + HARD_REG_ELT_TYPE *scan_fp_ = (FROM).elems; \ int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *scan_tp_++ &= *scan_fp_++; } while (0) #define AND_COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ +do { HARD_REG_ELT_TYPE *scan_tp_ = (TO).elems; \ + HARD_REG_ELT_TYPE *scan_fp_ = (FROM).elems; \ int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *scan_tp_++ &= ~ *scan_fp_++; } while (0) #define IOR_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ +do { HARD_REG_ELT_TYPE *scan_tp_ = (TO).elems; \ + HARD_REG_ELT_TYPE *scan_fp_ = (FROM).elems; \ int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *scan_tp_++ |= *scan_fp_++; } while (0) #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ -do { HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \ +do { HARD_REG_ELT_TYPE *scan_tp_ = (TO).elems; \ + HARD_REG_ELT_TYPE *scan_fp_ = (FROM).elems; \ int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *scan_tp_++ |= ~ *scan_fp_++; } while (0) @@ -436,7 +197,7 @@ hard_reg_set_subset_p (const HARD_REG_SE int i; for (i = 0; i < HARD_REG_SET_LONGS; i++) - if ((x[i] & ~y[i]) != 0) + if ((x.elems[i] & ~y.elems[i]) != 0) return false; return true; } @@ -447,7 +208,7 @@ hard_reg_set_equal_p (const HARD_REG_SET int i; for (i = 0; i < HARD_REG_SET_LONGS; i++) - if (x[i] != y[i]) + if (x.elems[i] != y.elems[i]) return false; return true; } @@ -458,7 +219,7 @@ hard_reg_set_intersect_p (const HARD_REG int i; for (i = 0; i < HARD_REG_SET_LONGS; i++) - if ((x[i] & y[i]) != 0) + if ((x.elems[i] & y.elems[i]) != 0) return true; return false; } @@ -469,26 +230,19 @@ hard_reg_set_empty_p (const HARD_REG_SET int i; for (i = 0; i < HARD_REG_SET_LONGS; i++) - if (x[i] != 0) + if (x.elems[i] != 0) return false; return true; } -#endif -#endif -#endif -#endif /* Iterator for hard register sets. */ typedef struct { - /* Pointer to the current element. */ + /* Pointer to the array of elements. */ HARD_REG_ELT_TYPE *pelt; - /* The length of the set. */ - unsigned short length; - /* Word within the current element. */ unsigned short word_no; @@ -498,42 +252,32 @@ typedef struct HARD_REG_ELT_TYPE bits; } hard_reg_set_iterator; -#define HARD_REG_ELT_BITS UHOST_BITS_PER_WIDE_INT - /* The implementation of the iterator functions is fully analogous to the bitmap iterators. */ static inline void -hard_reg_set_iter_init (hard_reg_set_iterator *iter, HARD_REG_SET set, +hard_reg_set_iter_init (hard_reg_set_iterator *iter, HARD_REG_SET *set, unsigned min, unsigned *regno) { -#ifdef HARD_REG_SET_LONGS - iter->pelt = set; - iter->length = HARD_REG_SET_LONGS; -#else - iter->pelt = &set; - iter->length = 1; -#endif + gcc_rtl_assert (min < FIRST_PSEUDO_REGISTER); iter->word_no = min / HARD_REG_ELT_BITS; - if (iter->word_no < iter->length) - { - iter->bits = iter->pelt[iter->word_no]; - iter->bits >>= min % HARD_REG_ELT_BITS; + gcc_rtl_assert (iter->word_no < HARD_REG_SET_LONGS); + iter->pelt = &(set->elems[0]); + + iter->bits = iter->pelt[iter->word_no]; + iter->bits >>= min % HARD_REG_ELT_BITS; + + /* This is required for correct search of the next bit. */ + min += !iter->bits; - /* This is required for correct search of the next bit. */ - min += !iter->bits; - } *regno = min; } static inline bool hard_reg_set_iter_set (hard_reg_set_iterator *iter, unsigned *regno) { - while (1) + /* Return false when we're advanced past the end of the set. */ + while (iter->word_no < HARD_REG_SET_LONGS) { - /* Return false when we're advanced past the end of the set. */ - if (iter->word_no >= iter->length) - return false; - if (iter->bits) { /* Find the correct bit and return it. */ @@ -550,7 +294,7 @@ hard_reg_set_iter_set (hard_reg_set_iter *regno -= *regno % HARD_REG_ELT_BITS; /* Find the next non-zero word. */ - while (++iter->word_no < iter->length) + while (++iter->word_no < HARD_REG_SET_LONGS) { iter->bits = iter->pelt[iter->word_no]; if (iter->bits) @@ -558,6 +302,7 @@ hard_reg_set_iter_set (hard_reg_set_iter *regno += HARD_REG_ELT_BITS; } } + return false; } static inline void @@ -568,7 +313,7 @@ hard_reg_set_iter_next (hard_reg_set_ite } #define EXECUTE_IF_SET_IN_HARD_REG_SET(SET, MIN, REGNUM, ITER) \ - for (hard_reg_set_iter_init (&(ITER), (SET), (MIN), &(REGNUM)); \ + for (hard_reg_set_iter_init (&(ITER), &(SET), (MIN), &(REGNUM)); \ hard_reg_set_iter_set (&(ITER), &(REGNUM)); \ hard_reg_set_iter_next (&(ITER), &(REGNUM))) === modified file 'gcc/reginfo.c' --- gcc/reginfo.c 2011-07-19 22:34:31 +0000 +++ gcc/reginfo.c 2011-10-23 21:13:15 +0000 @@ -90,14 +90,6 @@ char global_regs[FIRST_PSEUDO_REGISTER]; /* Declaration for the global register. */ static tree GTY(()) global_regs_decl[FIRST_PSEUDO_REGISTER]; -/* Same information as REGS_INVALIDATED_BY_CALL but in regset form to be used - in dataflow more conveniently. */ -regset regs_invalidated_by_call_regset; - -/* The bitmap_obstack is used to hold some static variables that - should not be reset after each function is compiled. */ -static bitmap_obstack persistent_obstack; - /* Used to initialize reg_alloc_order. */ #ifdef REG_ALLOC_ORDER static int initial_reg_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER; @@ -444,13 +436,6 @@ init_reg_sets_1 (void) CLEAR_HARD_REG_SET (call_used_reg_set); CLEAR_HARD_REG_SET (call_fixed_reg_set); CLEAR_HARD_REG_SET (regs_invalidated_by_call); - if (!regs_invalidated_by_call_regset) - { - bitmap_obstack_initialize (&persistent_obstack); - regs_invalidated_by_call_regset = ALLOC_REG_SET (&persistent_obstack); - } - else - CLEAR_REG_SET (regs_invalidated_by_call_regset); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { @@ -480,10 +465,7 @@ init_reg_sets_1 (void) if (i == STACK_POINTER_REGNUM) ; else if (global_regs[i]) - { SET_HARD_REG_BIT (regs_invalidated_by_call, i); - SET_REGNO_REG_SET (regs_invalidated_by_call_regset, i); - } else if (i == FRAME_POINTER_REGNUM) ; #if !HARD_FRAME_POINTER_IS_FRAME_POINTER @@ -498,10 +480,7 @@ init_reg_sets_1 (void) && i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i]) ; else if (CALL_REALLY_USED_REGNO_P (i)) - { SET_HARD_REG_BIT (regs_invalidated_by_call, i); - SET_REGNO_REG_SET (regs_invalidated_by_call_regset, i); - } } COPY_HARD_REG_SET(call_fixed_reg_set, fixed_reg_set); @@ -862,10 +841,7 @@ globalize_reg (tree decl, int i) appropriate regs_invalidated_by_call bit, even if it's already set in fixed_regs. */ if (i != STACK_POINTER_REGNUM) - { SET_HARD_REG_BIT (regs_invalidated_by_call, i); - SET_REGNO_REG_SET (regs_invalidated_by_call_regset, i); - } /* If already fixed, nothing else to do. */ if (fixed_regs[i]) === modified file 'gcc/regset.h' --- gcc/regset.h 2010-05-22 21:24:53 +0000 +++ gcc/regset.h 2011-10-23 21:13:15 +0000 @@ -110,11 +110,6 @@ typedef bitmap_iterator reg_set_iterator #define EXECUTE_IF_AND_IN_REG_SET(REGSET1, REGSET2, MIN, REGNUM, RSI) \ EXECUTE_IF_AND_IN_BITMAP (REGSET1, REGSET2, MIN, REGNUM, RSI) \ -/* Same information as REGS_INVALIDATED_BY_CALL but in regset form to be used - in dataflow more conveniently. */ - -extern regset regs_invalidated_by_call_regset; - /* An obstack for regsets. */ extern bitmap_obstack reg_obstack; === modified file 'gcc/reorg.c' --- gcc/reorg.c 2011-10-15 10:32:33 +0000 +++ gcc/reorg.c 2011-10-23 21:28:05 +0000 @@ -293,18 +293,7 @@ resource_conflicts_p (struct resources * || res1->volatil || res2->volatil) return 1; -#ifdef HARD_REG_SET - return (res1->regs & res2->regs) != HARD_CONST (0); -#else - { - int i; - - for (i = 0; i < HARD_REG_SET_LONGS; i++) - if ((res1->regs[i] & res2->regs[i]) != 0) - return 1; - return 0; - } -#endif + return hard_reg_set_intersect_p(res1->regs, res2->regs); } /* Return TRUE if any resource marked in RES, a `struct resources', is === modified file 'gcc/target.def' --- gcc/target.def 2011-10-20 20:10:05 +0000 +++ gcc/target.def 2011-10-23 21:13:15 +0000 @@ -2598,8 +2598,8 @@ HOOK_VECTOR_END (target_option) DEFHOOK (extra_live_on_entry, "", - void, (bitmap regs), - hook_void_bitmap) + void, (HARD_REG_SET *regs), + hook_void_hard_reg_set) /* Determine the type of unwind info to emit for debugging. */ DEFHOOK === modified file 'gcc/target.h' --- gcc/target.h 2011-06-16 13:45:47 +0000 +++ gcc/target.h 2011-10-23 21:13:15 +0000 @@ -52,6 +52,11 @@ #include "insn-modes.h" +/* We can't include target-dependant hard-reg-set.h thus the opaque struct */ +struct hard_reg_set; + +#define HARD_REG_SET struct hard_reg_set + #ifdef ENABLE_CHECKING typedef struct { void *magic; void *p; } cumulative_args_t; === modified file 'gcc/targhooks.c' --- gcc/targhooks.c 2011-10-06 19:25:53 +0000 +++ gcc/targhooks.c 2011-10-23 21:13:15 +0000 @@ -607,7 +607,7 @@ default_function_arg_round_boundary (enu } void -hook_void_bitmap (bitmap regs ATTRIBUTE_UNUSED) +hook_void_hard_reg_set (HARD_REG_SET *regs ATTRIBUTE_UNUSED) { } === modified file 'gcc/targhooks.h' --- gcc/targhooks.h 2011-10-06 19:25:53 +0000 +++ gcc/targhooks.h 2011-10-23 21:13:15 +0000 @@ -128,7 +128,7 @@ extern reg_class_t default_secondary_rel enum machine_mode, secondary_reload_info *); extern void default_target_option_override (void); -extern void hook_void_bitmap (bitmap); +extern void hook_void_hard_reg_set (HARD_REG_SET *); extern int default_reloc_rw_mask (void); extern tree default_mangle_decl_assembler_name (tree, tree); extern tree default_emutls_var_fields (tree, tree *);