From patchwork Sat Jun 14 19:53:15 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 359788 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id A5C671400E3 for ; Sun, 15 Jun 2014 05:53:36 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; q=dns; s=default; b=wdHE6AH9ozcG+1IhhhjqZnwg16Z19 MteLeCEZVGzcs22d0uaTr1nWiXADJ3yLhAIEaXfxS5t24HK7PL59XgseD6jyodw+ ff/8ZbxuVG1putkgjw3YaqfntUfMvCeZf6TB+E4rAdL02P7Ct5NMNa6gtUlA03US vw0Dw+MF63F/X4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; s=default; bh=EJWi7gNVWRAk2SBQhij7u4iEyWk=; b=LYB Buy8oCBj+FGsJL0jz9Isj4U3CXWbq8+EbRx1mvOSVabz40tpTIb6DClckWBunpfi 3cs031y9/qv6cp0cIyx0urSna4F4qXvwvqhhOMRbXBv2AbTIpdzs58i++eTxOwQj ISu+aliltFl8O6Db+kMQPtfjQD6etVz/pCc9py+4= Received: (qmail 14089 invoked by alias); 14 Jun 2014 19:53:28 -0000 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 Received: (qmail 14075 invoked by uid 89); 14 Jun 2014 19:53:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-wg0-f47.google.com Received: from mail-wg0-f47.google.com (HELO mail-wg0-f47.google.com) (74.125.82.47) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Sat, 14 Jun 2014 19:53:21 +0000 Received: by mail-wg0-f47.google.com with SMTP id k14so4060170wgh.30 for ; Sat, 14 Jun 2014 12:53:17 -0700 (PDT) X-Received: by 10.180.86.4 with SMTP id l4mr14451435wiz.61.1402775597727; Sat, 14 Jun 2014 12:53:17 -0700 (PDT) Received: from localhost ([2.26.169.52]) by mx.google.com with ESMTPSA id ey16sm4410867wid.14.2014.06.14.12.53.15 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 14 Jun 2014 12:53:17 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, rdsandiford@googlemail.com Subject: [PATCH 6/6] Use a linked list for insn defs and uses References: <87a99ftha6.fsf@talisman.default> Date: Sat, 14 Jun 2014 20:53:15 +0100 In-Reply-To: <87a99ftha6.fsf@talisman.default> (Richard Sandiford's message of "Sat, 14 Jun 2014 20:36:33 +0100") Message-ID: <87fvj7s1xw.fsf@talisman.default> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 This is the main change, which is hard to break down much further. Most of this is pretty mechanical. Some of it is reindentation, since it's no longer meaningful (if it was before) to test the defs or artificial_defs against null to see whether a structure had been initialised. Also, df_ref_change_reg_with_loc_1 would choose the wrong reference array for definitions. Richard gcc/ * df.h (df_mw_hardreg, df_base_ref): Add a link pointer. (df_insn_info): Turn defs, uses, eq_uses and mw_hardregs into linked lists. (df_scan_bb_info): Likewise artificial_defs and artificial_uses. (FOR_EACH_INSN_INFO_DEF, FOR_EACH_INSN_INFO_USE) (FOR_EACH_INSN_INFO_EQ_USE, FOR_EACH_INSN_INFO_MW) (FOR_EACH_ARTIFICIAL_USE, FOR_EACH_ARTIFICIAL_DEF) (df_get_artificial_defs, df_get_artificial_uses) (df_single_def, df_single_use): Update accordingly. (df_refs_chain_dump): Take the first element in a linked list as parameter, rather than a pointer to an array of pointers. * df-core.c (df_refs_chain_dump, df_mws_dump): Likewise. * df-problems.c (df_rd_bb_local_compute_process_def): Likewise. (df_chain_create_bb_process_use): Likewise. (df_md_bb_local_compute_process_def): Likewise. * fwprop.c (process_defs, process_uses): Likewise. (register_active_defs, update_uses): Likewise. (forward_propagate_asm): Update for new df_ref linking. * df-scan.c (df_scan_free_ref_vec, df_scan_free_mws_vec): Delete. (df_null_ref_rec, df_null_mw_rec): Likewise. (df_scan_free_internal): Don't free df_ref and df_mw_hardreg lists explicitly. (df_scan_free_bb_info): Remove check for null artificial_defs. (df_install_ref_incremental): Adjust for new df_ref linking. Use a single-element insertion rather than a full sort. (df_ref_chain_delete_du_chain): Take the first element in a linked list as parameter, rather than a pointer to an array of pointers. (df_ref_chain_delete, df_mw_hardreg_chain_delete): Likewise. (df_add_refs_to_table, df_refs_verify, df_mws_verify): Likewise. (df_insn_info_delete): Remove check for null defs and call to df_scan_free_mws_vec. (df_insn_rescan): Initialize df_ref and df_mw_hardreg lists to null rather than df_null_*_rec. (df_insn_rescan_debug_internal): Likewise, and update null checks in the same way. Remove check for null defs. (df_ref_change_reg_with_loc_1): Fix choice of list for defs. Move a single element rather doing a full sort. (df_mw_hardreg_chain_delete_eq_uses): Adjust for new df_mw_hardreg linking. (df_notes_rescan): Likewise. Use a merge rather than a full sort. Initialize df_ref and df_mw_hardreg lists to null rather than df_null_*_rec. (df_ref_compare): Take df_refs as parameter, transferring the old interface to... (df_ref_ptr_compare): ...this new function. (df_sort_and_compress_refs): Update accordingly. (df_mw_compare): Take df_mw_hardregs as parameter, transferring the old interface to... (df_mw_ptr_compare): ...this new function. (df_sort_and_compress_mws): Update accordingly. (df_install_refs, df_install_mws): Return a linked list rather than an array of pointers. (df_refs_add_to_chains): Assert that old lists are empty rather than freeing them. (df_insn_refs_verify): Don't handle null defs speciailly. * web.c (union_match_dups): Update for new df_ref linking. Index: gcc/df.h =================================================================== --- gcc/df.h 2014-06-14 20:16:24.996757215 +0100 +++ gcc/df.h 2014-06-14 20:16:25.448761158 +0100 @@ -339,6 +339,7 @@ struct dataflow REG_UNUSED notes. */ struct df_mw_hardreg { + df_mw_hardreg *next; /* Next entry for this instruction. */ rtx mw_reg; /* The multiword hardreg. */ /* These two bitfields are intentionally oversized, in the hope that accesses to 16-bit fields will usually be quicker. */ @@ -365,6 +366,7 @@ struct df_base_ref int flags : 16; /* Various df_ref_flags. */ unsigned int regno; /* The register number referenced. */ rtx reg; /* The register referenced. */ + union df_ref_d *next_loc; /* Next ref for same insn or bb. */ struct df_link *chain; /* Head of def-use, use-def. */ /* Pointer to the insn info of the containing instruction. FIXME! Currently this is NULL for artificial refs but this will be used @@ -420,11 +422,11 @@ typedef union df_ref_d *df_ref; struct df_insn_info { rtx insn; /* The insn this info comes from. */ - df_ref *defs; /* Head of insn-def chain. */ - df_ref *uses; /* Head of insn-use chain. */ + df_ref defs; /* Head of insn-def chain. */ + df_ref uses; /* Head of insn-use chain. */ /* Head of insn-use chain for uses in REG_EQUAL/EQUIV notes. */ - df_ref *eq_uses; - struct df_mw_hardreg **mw_hardregs; + df_ref eq_uses; + struct df_mw_hardreg *mw_hardregs; /* The logical uid of the insn in the basic block. This is valid after any call to df_analyze but may rot after insns are added, deleted or moved. */ @@ -755,20 +757,16 @@ #define DF_INSN_UID_EQ_USES(INSN) (DF_IN #define DF_INSN_UID_MWS(INSN) (DF_INSN_UID_GET (INSN)->mw_hardregs) #define FOR_EACH_INSN_INFO_DEF(ITER, INSN) \ - for (df_ref *ITER##_ = DF_INSN_INFO_DEFS (INSN); (ITER = *ITER##_); \ - ++ITER##_) + for (ITER = DF_INSN_INFO_DEFS (INSN); ITER; ITER = ITER->base.next_loc) #define FOR_EACH_INSN_INFO_USE(ITER, INSN) \ - for (df_ref *ITER##_ = DF_INSN_INFO_USES (INSN); (ITER = *ITER##_); \ - ++ITER##_) + for (ITER = DF_INSN_INFO_USES (INSN); ITER; ITER = ITER->base.next_loc) #define FOR_EACH_INSN_INFO_EQ_USE(ITER, INSN) \ - for (df_ref *ITER##_ = DF_INSN_INFO_EQ_USES (INSN); (ITER = *ITER##_); \ - ++ITER##_) + for (ITER = DF_INSN_INFO_EQ_USES (INSN); ITER; ITER = ITER->base.next_loc) #define FOR_EACH_INSN_INFO_MW(ITER, INSN) \ - for (df_mw_hardreg **ITER##_ = DF_INSN_INFO_MWS (INSN); (ITER = *ITER##_); \ - ++ITER##_) + for (ITER = DF_INSN_INFO_MWS (INSN); ITER; ITER = ITER->next) #define FOR_EACH_INSN_DEF(ITER, INSN) \ FOR_EACH_INSN_INFO_DEF(ITER, DF_INSN_INFO_GET (INSN)) @@ -780,12 +778,12 @@ #define FOR_EACH_INSN_EQ_USE(ITER, INSN) FOR_EACH_INSN_INFO_EQ_USE(ITER, DF_INSN_INFO_GET (INSN)) #define FOR_EACH_ARTIFICIAL_USE(ITER, BB_INDEX) \ - for (df_ref *ITER##_ = df_get_artificial_uses (BB_INDEX); \ - (ITER = *ITER##_); ++ITER##_) + for (ITER = df_get_artificial_uses (BB_INDEX); ITER; \ + ITER = ITER->base.next_loc) #define FOR_EACH_ARTIFICIAL_DEF(ITER, BB_INDEX) \ - for (df_ref *ITER##_ = df_get_artificial_defs (BB_INDEX); \ - (ITER = *ITER##_); ++ITER##_) + for (ITER = df_get_artificial_defs (BB_INDEX); ITER; \ + ITER = ITER->base.next_loc) /* An obstack for bitmap not related to specific dataflow problems. This obstack should e.g. be used for bitmaps with a short life time @@ -806,13 +804,13 @@ struct df_scan_bb_info Blocks that are the targets of non-local goto's have the hard frame pointer defined at the top of the block. */ - df_ref *artificial_defs; + df_ref artificial_defs; /* Blocks that are targets of exception edges may have some artificial uses. These are logically at the top of the block. Most blocks have artificial uses at the bottom of the block. */ - df_ref *artificial_uses; + df_ref artificial_uses; }; @@ -967,7 +965,7 @@ extern void df_dump_top (basic_block, FI extern void df_dump_bottom (basic_block, FILE *); extern void df_dump_insn_top (const_rtx, FILE *); extern void df_dump_insn_bottom (const_rtx, FILE *); -extern void df_refs_chain_dump (df_ref *, bool, FILE *); +extern void df_refs_chain_dump (df_ref, bool, FILE *); extern void df_regs_chain_dump (df_ref, FILE *); extern void df_insn_debug (rtx, bool, FILE *); extern void df_insn_debug_regno (rtx, FILE *); @@ -1147,7 +1145,7 @@ df_get_live_in (basic_block bb) /* Get basic block info. */ /* Get the artificial defs for a basic block. */ -static inline df_ref * +static inline df_ref df_get_artificial_defs (unsigned int bb_index) { return df_scan_get_bb_info (bb_index)->artificial_defs; @@ -1156,7 +1154,7 @@ df_get_artificial_defs (unsigned int bb_ /* Get the artificial uses for a basic block. */ -static inline df_ref * +static inline df_ref df_get_artificial_uses (unsigned int bb_index) { return df_scan_get_bb_info (bb_index)->artificial_uses; @@ -1168,8 +1166,8 @@ df_get_artificial_uses (unsigned int bb_ static inline df_ref df_single_def (const df_insn_info *info) { - df_ref *defs = DF_INSN_INFO_DEFS (info); - return defs[0] && !defs[1] ? defs[0] : NULL; + df_ref defs = DF_INSN_INFO_DEFS (info); + return defs && !defs->base.next_loc ? defs : NULL; } /* If INSN uses exactly one register, return the associated reference, @@ -1178,8 +1176,8 @@ df_single_def (const df_insn_info *info) static inline df_ref df_single_use (const df_insn_info *info) { - df_ref *uses = DF_INSN_INFO_USES (info); - return uses[0] && !uses[1] ? uses[0] : NULL; + df_ref uses = DF_INSN_INFO_USES (info); + return uses && !uses->base.next_loc ? uses : NULL; } /* web */ Index: gcc/df-core.c =================================================================== --- gcc/df-core.c 2014-06-14 20:08:33.448584144 +0100 +++ gcc/df-core.c 2014-06-14 20:16:25.450761175 +0100 @@ -2319,16 +2319,14 @@ df_ref_dump (df_ref ref, FILE *file) } void -df_refs_chain_dump (df_ref *ref_rec, bool follow_chain, FILE *file) +df_refs_chain_dump (df_ref ref, bool follow_chain, FILE *file) { fprintf (file, "{ "); - while (*ref_rec) + for (; ref; ref = ref->base.next_loc) { - df_ref ref = *ref_rec; df_ref_dump (ref, file); if (follow_chain) df_chain_dump (DF_REF_CHAIN (ref), file); - ref_rec++; } fprintf (file, "}"); } @@ -2350,15 +2348,12 @@ df_regs_chain_dump (df_ref ref, FILE *f static void -df_mws_dump (struct df_mw_hardreg **mws, FILE *file) +df_mws_dump (struct df_mw_hardreg *mws, FILE *file) { - while (*mws) - { - fprintf (file, "mw %c r[%d..%d]\n", - (DF_MWS_REG_DEF_P (*mws)) ? 'd' : 'u', - (*mws)->start_regno, (*mws)->end_regno); - mws++; - } + for (; mws; mws = mws->next) + fprintf (file, "mw %c r[%d..%d]\n", + DF_MWS_REG_DEF_P (mws) ? 'd' : 'u', + mws->start_regno, mws->end_regno); } Index: gcc/df-problems.c =================================================================== --- gcc/df-problems.c 2014-06-14 20:09:37.811177069 +0100 +++ gcc/df-problems.c 2014-06-14 20:16:25.449761166 +0100 @@ -291,12 +291,11 @@ df_rd_simulate_one_insn (basic_block bb static void df_rd_bb_local_compute_process_def (struct df_rd_bb_info *bb_info, - df_ref *def_rec, + df_ref def, int top_flag) { - while (*def_rec) + for (; def; def = def->base.next_loc) { - df_ref def = *def_rec; if (top_flag == (DF_REF_FLAGS (def) & DF_REF_AT_TOP)) { unsigned int regno = DF_REF_REGNO (def); @@ -339,7 +338,6 @@ df_rd_bb_local_compute_process_def (stru } } } - def_rec++; } } @@ -2022,15 +2020,14 @@ df_chain_reset (bitmap blocks_to_clear A static void df_chain_create_bb_process_use (bitmap local_rd, - df_ref *use_rec, + df_ref use, int top_flag) { bitmap_iterator bi; unsigned int def_index; - while (*use_rec) + for (; use; use = use->base.next_loc) { - df_ref use = *use_rec; unsigned int uregno = DF_REF_REGNO (use); if ((!(df->changeable_flags & DF_NO_HARD_REGS)) || (uregno >= FIRST_PSEUDO_REGISTER)) @@ -2059,8 +2056,6 @@ df_chain_create_bb_process_use (bitmap l } } } - - use_rec++; } } @@ -4077,13 +4072,12 @@ df_md_simulate_one_insn (basic_block bb static void df_md_bb_local_compute_process_def (struct df_md_bb_info *bb_info, - df_ref *def_rec, + df_ref def, int top_flag) { - df_ref def; bitmap_clear (&seen_in_insn); - while ((def = *def_rec++) != NULL) + for (; def; def = def->base.next_loc) { unsigned int dregno = DF_REF_REGNO (def); if (((!(df->changeable_flags & DF_NO_HARD_REGS)) Index: gcc/fwprop.c =================================================================== --- gcc/fwprop.c 2014-06-14 20:08:33.442584088 +0100 +++ gcc/fwprop.c 2014-06-14 20:16:25.449761166 +0100 @@ -146,10 +146,9 @@ #define DF_MD_GEN_FLAGS \ (DF_REF_PARTIAL | DF_REF_CONDITIONAL | DF_REF_MAY_CLOBBER) static void -process_defs (df_ref *def_rec, int top_flag) +process_defs (df_ref def, int top_flag) { - df_ref def; - while ((def = *def_rec++) != NULL) + for (; def; def = def->base.next_loc) { df_ref curr_def = reg_defs[DF_REF_REGNO (def)]; unsigned int dregno; @@ -191,10 +190,9 @@ process_defs (df_ref *def_rec, int top_f is an artificial use vector. */ static void -process_uses (df_ref *use_rec, int top_flag) +process_uses (df_ref use, int top_flag) { - df_ref use; - while ((use = *use_rec++) != NULL) + for (; use; use = use->base.next_loc) if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == top_flag) { unsigned int uregno = DF_REF_REGNO (use); @@ -849,11 +847,10 @@ all_uses_available_at (rtx def_insn, rtx too, for checking purposes. */ static void -register_active_defs (df_ref *use_rec) +register_active_defs (df_ref use) { - while (*use_rec) + for (; use; use = use->base.next_loc) { - df_ref use = *use_rec++; df_ref def = get_def_for_use (use); int regno = DF_REF_REGNO (use); @@ -887,11 +884,10 @@ update_df_init (rtx def_insn, rtx insn) in the ACTIVE_DEFS array to match pseudos to their def. */ static inline void -update_uses (df_ref *use_rec) +update_uses (df_ref use) { - while (*use_rec) + for (; use; use = use->base.next_loc) { - df_ref use = *use_rec++; int regno = DF_REF_REGNO (use); /* Set up the use-def chain. */ @@ -1135,7 +1131,7 @@ forward_propagate_asm (df_ref use, rtx d { rtx use_insn = DF_REF_INSN (use), src, use_pat, asm_operands, new_rtx, *loc; int speed_p, i; - df_ref *use_vec; + df_ref uses; gcc_assert ((DF_REF_FLAGS (use) & DF_REF_IN_NOTE) == 0); @@ -1144,8 +1140,8 @@ forward_propagate_asm (df_ref use, rtx d /* In __asm don't replace if src might need more registers than reg, as that could increase register pressure on the __asm. */ - use_vec = DF_INSN_USES (def_insn); - if (use_vec[0] && use_vec[1]) + uses = DF_INSN_USES (def_insn); + if (uses && uses->base.next_loc) return false; update_df_init (def_insn, use_insn); Index: gcc/df-scan.c =================================================================== --- gcc/df-scan.c 2014-06-14 20:16:24.996757215 +0100 +++ gcc/df-scan.c 2014-06-14 20:19:41.889474415 +0100 @@ -62,21 +62,6 @@ #define HAVE_sibcall_epilogue 0 #define EPILOGUE_USES(REGNO) 0 #endif -/* The following two macros free the vecs that hold either the refs or - the mw refs. They are a little tricky because the vec has 0 - elements is special and is not to be freed. */ -#define df_scan_free_ref_vec(V) \ - do { \ - if (V && *V) \ - free (V); \ - } while (0) - -#define df_scan_free_mws_vec(V) \ - do { \ - if (V && *V) \ - free (V); \ - } while (0) - /* The set of hard registers in eliminables[i].from. */ static HARD_REG_SET elim_reg_set; @@ -92,9 +77,6 @@ struct df_collection_rec auto_vec mw_vec; }; -static df_ref df_null_ref_rec[1]; -static struct df_mw_hardreg * df_null_mw_rec[1]; - static void df_ref_record (enum df_ref_class, struct df_collection_rec *, rtx, rtx *, basic_block, struct df_insn_info *, @@ -123,8 +105,8 @@ static void df_record_exit_block_uses (b static void df_get_exit_block_use_set (bitmap); static void df_get_entry_block_def_set (bitmap); 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 *); +static void df_ref_chain_delete_du_chain (df_ref); +static void df_ref_chain_delete (df_ref); static void df_refs_add_to_chains (struct df_collection_rec *, basic_block, rtx, unsigned int); @@ -135,8 +117,10 @@ static void df_exit_block_uses_collect ( static void df_install_ref (df_ref, struct df_reg_info *, struct df_ref_info *, bool); -static int df_ref_compare (const void *, const void *); -static int df_mw_compare (const void *, const void *); +static int df_ref_compare (df_ref, df_ref); +static int df_ref_ptr_compare (const void *, const void *); +static int df_mw_compare (const df_mw_hardreg *, const df_mw_hardreg *); +static int df_mw_ptr_compare (const void *, const void *); static void df_insn_info_delete (unsigned int); @@ -189,36 +173,6 @@ df_scan_free_internal (void) { struct df_scan_problem_data *problem_data = (struct df_scan_problem_data *) df_scan->problem_data; - unsigned int i; - basic_block bb; - - /* The vectors that hold the refs are not pool allocated because - they come in many sizes. This makes them impossible to delete - all at once. */ - for (i = 0; i < DF_INSN_SIZE (); i++) - { - struct df_insn_info *insn_info = DF_INSN_UID_GET (i); - /* Skip the insns that have no insn_info or have been - deleted. */ - if (insn_info) - { - df_scan_free_ref_vec (insn_info->defs); - df_scan_free_ref_vec (insn_info->uses); - df_scan_free_ref_vec (insn_info->eq_uses); - df_scan_free_mws_vec (insn_info->mw_hardregs); - } - } - - FOR_ALL_BB_FN (bb, cfun) - { - unsigned int bb_index = bb->index; - struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb_index); - if (bb_info) - { - df_scan_free_ref_vec (bb_info->artificial_defs); - df_scan_free_ref_vec (bb_info->artificial_uses); - } - } free (df->def_info.refs); free (df->def_info.begin); @@ -275,31 +229,22 @@ df_scan_free_bb_info (basic_block bb, vo { struct df_scan_bb_info *bb_info = (struct df_scan_bb_info *) vbb_info; unsigned int bb_index = bb->index; + rtx insn; - /* See if bb_info is initialized. */ - if (bb_info->artificial_defs) - { - rtx insn; - FOR_BB_INSNS (bb, insn) - { - if (INSN_P (insn)) - df_insn_info_delete (INSN_UID (insn)); - } + FOR_BB_INSNS (bb, insn) + if (INSN_P (insn)) + df_insn_info_delete (INSN_UID (insn)); - if (bb_index < df_scan->block_info_size) - bb_info = df_scan_get_bb_info (bb_index); + if (bb_index < df_scan->block_info_size) + bb_info = df_scan_get_bb_info (bb_index); - /* Get rid of any artificial uses or defs. */ - if (bb_info->artificial_defs) - { - df_ref_chain_delete_du_chain (bb_info->artificial_defs); - df_ref_chain_delete_du_chain (bb_info->artificial_uses); - df_ref_chain_delete (bb_info->artificial_defs); - df_ref_chain_delete (bb_info->artificial_uses); - bb_info->artificial_defs = NULL; - bb_info->artificial_uses = NULL; - } - } + /* Get rid of any artificial uses or defs. */ + df_ref_chain_delete_du_chain (bb_info->artificial_defs); + df_ref_chain_delete_du_chain (bb_info->artificial_uses); + df_ref_chain_delete (bb_info->artificial_defs); + df_ref_chain_delete (bb_info->artificial_uses); + bb_info->artificial_defs = NULL; + bb_info->artificial_uses = NULL; } @@ -695,9 +640,7 @@ df_install_ref_incremental (df_ref ref) { struct df_reg_info **reg_info; struct df_ref_info *ref_info; - df_ref *ref_rec; - df_ref **ref_rec_ptr; - unsigned int count = 0; + df_ref *ref_ptr; bool add_to_table; rtx insn = DF_REF_INSN (ref); @@ -707,14 +650,14 @@ df_install_ref_incremental (df_ref ref) { reg_info = df->def_regs; ref_info = &df->def_info; - ref_rec_ptr = &DF_INSN_DEFS (insn); + ref_ptr = &DF_INSN_DEFS (insn); add_to_table = ref_info->ref_order != DF_REF_ORDER_NO_TABLE; } else if (DF_REF_FLAGS (ref) & DF_REF_IN_NOTE) { reg_info = df->eq_use_regs; ref_info = &df->use_info; - ref_rec_ptr = &DF_INSN_EQ_USES (insn); + ref_ptr = &DF_INSN_EQ_USES (insn); switch (ref_info->ref_order) { case DF_REF_ORDER_UNORDERED_WITH_NOTES: @@ -731,7 +674,7 @@ df_install_ref_incremental (df_ref ref) { reg_info = df->use_regs; ref_info = &df->use_info; - ref_rec_ptr = &DF_INSN_USES (insn); + ref_ptr = &DF_INSN_USES (insn); add_to_table = ref_info->ref_order != DF_REF_ORDER_NO_TABLE; } @@ -754,29 +697,11 @@ df_install_ref_incremental (df_ref ref) break; } - ref_rec = *ref_rec_ptr; - while (*ref_rec) - { - count++; - ref_rec++; - } + while (*ref_ptr && df_ref_compare (*ref_ptr, ref) < 0) + ref_ptr = &(*ref_ptr)->base.next_loc; - ref_rec = *ref_rec_ptr; - if (count) - { - ref_rec = XRESIZEVEC (df_ref, ref_rec, count+2); - *ref_rec_ptr = ref_rec; - ref_rec[count] = ref; - ref_rec[count+1] = NULL; - qsort (ref_rec, count + 1, sizeof (df_ref), df_ref_compare); - } - else - { - df_ref *ref_rec = XNEWVEC (df_ref, 2); - ref_rec[0] = ref; - ref_rec[1] = NULL; - *ref_rec_ptr = ref_rec; - } + ref->base.next_loc = *ref_ptr; + *ref_ptr = ref; #if 0 if (dump_file) @@ -930,55 +855,43 @@ df_insn_create_insn_record (rtx insn) /* Delete all du chain (DF_REF_CHAIN()) of all refs in the ref chain. */ static void -df_ref_chain_delete_du_chain (df_ref *ref_rec) +df_ref_chain_delete_du_chain (df_ref ref) { - while (*ref_rec) - { - df_ref ref = *ref_rec; - /* CHAIN is allocated by DF_CHAIN. So make sure to - pass df_scan instance for the problem. */ - if (DF_REF_CHAIN (ref)) - df_chain_unlink (ref); - ref_rec++; - } + for (; ref; ref = ref->base.next_loc) + /* CHAIN is allocated by DF_CHAIN. So make sure to + pass df_scan instance for the problem. */ + if (DF_REF_CHAIN (ref)) + df_chain_unlink (ref); } /* Delete all refs in the ref chain. */ static void -df_ref_chain_delete (df_ref *ref_rec) +df_ref_chain_delete (df_ref ref) { - df_ref *start = ref_rec; - while (*ref_rec) + df_ref next; + for (; ref; ref = next) { - df_reg_chain_unlink (*ref_rec); - ref_rec++; + next = ref->base.next_loc; + df_reg_chain_unlink (ref); } - - /* If the list is empty, it has a special shared element that is not - to be deleted. */ - if (*start) - free (start); } /* Delete the hardreg chain. */ static void -df_mw_hardreg_chain_delete (struct df_mw_hardreg **hardregs) +df_mw_hardreg_chain_delete (struct df_mw_hardreg *hardregs) { - struct df_scan_problem_data *problem_data; - - if (!hardregs) - return; - - problem_data = (struct df_scan_problem_data *) df_scan->problem_data; + struct df_scan_problem_data *problem_data + = (struct df_scan_problem_data *) df_scan->problem_data; + df_mw_hardreg *next; - while (*hardregs) + for (; hardregs; hardregs = next) { - pool_free (problem_data->mw_reg_pool, *hardregs); - hardregs++; + next = hardregs->next; + pool_free (problem_data->mw_reg_pool, hardregs); } } @@ -1006,22 +919,19 @@ df_insn_info_delete (unsigned int uid) to notes. How clever. So we cannot just check if it is a valid insn before short circuiting this code, we need to see if we actually initialized it. */ - if (insn_info->defs) + df_mw_hardreg_chain_delete (insn_info->mw_hardregs); + + if (df_chain) { - df_mw_hardreg_chain_delete (insn_info->mw_hardregs); + df_ref_chain_delete_du_chain (insn_info->defs); + df_ref_chain_delete_du_chain (insn_info->uses); + df_ref_chain_delete_du_chain (insn_info->eq_uses); + } - if (df_chain) - { - df_ref_chain_delete_du_chain (insn_info->defs); - df_ref_chain_delete_du_chain (insn_info->uses); - df_ref_chain_delete_du_chain (insn_info->eq_uses); - } + df_ref_chain_delete (insn_info->defs); + df_ref_chain_delete (insn_info->uses); + df_ref_chain_delete (insn_info->eq_uses); - df_ref_chain_delete (insn_info->defs); - df_ref_chain_delete (insn_info->uses); - df_ref_chain_delete (insn_info->eq_uses); - df_scan_free_mws_vec (insn_info->mw_hardregs); - } pool_free (problem_data->insn_pool, insn_info); DF_INSN_UID_SET (uid, NULL); } @@ -1149,10 +1059,10 @@ df_insn_rescan (rtx insn) if (!insn_info) { insn_info = df_insn_create_insn_record (insn); - insn_info->defs = df_null_ref_rec; - insn_info->uses = df_null_ref_rec; - insn_info->eq_uses = df_null_ref_rec; - insn_info->mw_hardregs = df_null_mw_rec; + insn_info->defs = 0; + insn_info->uses = 0; + insn_info->eq_uses = 0; + insn_info->mw_hardregs = 0; } if (dump_file) fprintf (dump_file, "deferring rescan insn with uid = %d.\n", uid); @@ -1229,13 +1139,10 @@ df_insn_rescan_debug_internal (rtx insn) bitmap_clear_bit (&df->insns_to_rescan, uid); bitmap_clear_bit (&df->insns_to_notes_rescan, uid); - if (!insn_info->defs) - return false; - - if (insn_info->defs == df_null_ref_rec - && insn_info->uses == df_null_ref_rec - && insn_info->eq_uses == df_null_ref_rec - && insn_info->mw_hardregs == df_null_mw_rec) + if (insn_info->defs == 0 + && insn_info->uses == 0 + && insn_info->eq_uses == 0 + && insn_info->mw_hardregs == 0) return false; df_mw_hardreg_chain_delete (insn_info->mw_hardregs); @@ -1250,12 +1157,11 @@ df_insn_rescan_debug_internal (rtx insn) df_ref_chain_delete (insn_info->defs); df_ref_chain_delete (insn_info->uses); df_ref_chain_delete (insn_info->eq_uses); - df_scan_free_mws_vec (insn_info->mw_hardregs); - insn_info->defs = df_null_ref_rec; - insn_info->uses = df_null_ref_rec; - insn_info->eq_uses = df_null_ref_rec; - insn_info->mw_hardregs = df_null_mw_rec; + insn_info->defs = 0; + insn_info->uses = 0; + insn_info->eq_uses = 0; + insn_info->mw_hardregs = 0; return true; } @@ -1682,19 +1588,15 @@ df_reorganize_refs_by_reg (struct df_ref static unsigned int df_add_refs_to_table (unsigned int offset, struct df_ref_info *ref_info, - df_ref *ref_vec) + df_ref ref) { - while (*ref_vec) - { - df_ref ref = *ref_vec; - if ((!(df->changeable_flags & DF_NO_HARD_REGS)) - || (DF_REF_REGNO (ref) >= FIRST_PSEUDO_REGISTER)) - { - ref_info->refs[offset] = ref; - DF_REF_ID (*ref_vec) = offset++; - } - ref_vec++; - } + for (; ref; ref = ref->base.next_loc) + if (!(df->changeable_flags & DF_NO_HARD_REGS) + || (DF_REF_REGNO (ref) >= FIRST_PSEUDO_REGISTER)) + { + ref_info->refs[offset] = ref; + DF_REF_ID (ref) = offset++; + } return offset; } @@ -1921,9 +1823,8 @@ df_ref_change_reg_with_loc_1 (struct df_ { df_ref next_ref = DF_REF_NEXT_REG (the_ref); df_ref prev_ref = DF_REF_PREV_REG (the_ref); - df_ref *ref_vec, *ref_vec_t; + df_ref *ref_ptr; struct df_insn_info *insn_info = DF_REF_INSN_INFO (the_ref); - unsigned int count = 0; DF_REF_REGNO (the_ref) = new_regno; DF_REF_REG (the_ref) = regno_reg_rtx[new_regno]; @@ -1950,23 +1851,42 @@ df_ref_change_reg_with_loc_1 (struct df_ /* Need to sort the record again that the ref was in because the regno is a sorting key. First, find the right record. */ - if (DF_REF_FLAGS (the_ref) & DF_REF_IN_NOTE) - ref_vec = insn_info->eq_uses; + if (DF_REF_REG_DEF_P (the_ref)) + ref_ptr = &insn_info->defs; + else if (DF_REF_FLAGS (the_ref) & DF_REF_IN_NOTE) + ref_ptr = &insn_info->eq_uses; else - ref_vec = insn_info->uses; + ref_ptr = &insn_info->uses; if (dump_file) fprintf (dump_file, "changing reg in insn %d\n", DF_REF_INSN_UID (the_ref)); - ref_vec_t = ref_vec; - - /* Find the length. */ - while (*ref_vec_t) + /* Stop if we find the current reference or where the reference + needs to be. */ + while (*ref_ptr != the_ref && df_ref_compare (*ref_ptr, the_ref) < 0) + ref_ptr = &(*ref_ptr)->base.next_loc; + if (*ref_ptr != the_ref) { - count++; - ref_vec_t++; + /* The reference needs to be promoted up the list. */ + df_ref next = the_ref->base.next_loc; + the_ref->base.next_loc = *ref_ptr; + *ref_ptr = the_ref; + do + ref_ptr = &(*ref_ptr)->base.next_loc; + while (*ref_ptr != the_ref); + *ref_ptr = next; + } + else if (the_ref->base.next_loc + && df_ref_compare (the_ref, the_ref->base.next_loc) > 0) + { + /* The reference needs to be demoted down the list. */ + *ref_ptr = the_ref->base.next_loc; + do + ref_ptr = &(*ref_ptr)->base.next_loc; + while (*ref_ptr && df_ref_compare (the_ref, *ref_ptr) > 0); + the_ref->base.next_loc = *ref_ptr; + *ref_ptr = the_ref; } - qsort (ref_vec, count, sizeof (df_ref ), df_ref_compare); the_ref = next_ref; } @@ -2000,51 +1920,24 @@ df_ref_change_reg_with_loc (int old_regn /* Delete the mw_hardregs that point into the eq_notes. */ -static unsigned int +static void df_mw_hardreg_chain_delete_eq_uses (struct df_insn_info *insn_info) { - struct df_mw_hardreg **mw_vec = insn_info->mw_hardregs; - unsigned int deleted = 0; - unsigned int count = 0; + struct df_mw_hardreg **mw_ptr = &insn_info->mw_hardregs; struct df_scan_problem_data *problem_data = (struct df_scan_problem_data *) df_scan->problem_data; - if (!*mw_vec) - return 0; - - while (*mw_vec) + while (*mw_ptr) { - if ((*mw_vec)->flags & DF_REF_IN_NOTE) + df_mw_hardreg *mw = *mw_ptr; + if (mw->flags & DF_REF_IN_NOTE) { - struct df_mw_hardreg **temp_vec = mw_vec; - - pool_free (problem_data->mw_reg_pool, *mw_vec); - temp_vec = mw_vec; - /* Shove the remaining ones down one to fill the gap. While - this looks n**2, it is highly unusual to have any mw regs - in eq_notes and the chances of more than one are almost - non existent. */ - while (*temp_vec) - { - *temp_vec = *(temp_vec + 1); - temp_vec++; - } - deleted++; + *mw_ptr = mw->next; + pool_free (problem_data->mw_reg_pool, mw); } else - { - mw_vec++; - count++; - } - } - - if (count == 0) - { - df_scan_free_mws_vec (insn_info->mw_hardregs); - insn_info->mw_hardregs = df_null_mw_rec; - return 0; + mw_ptr = &mw->next; } - return deleted; } @@ -2078,10 +1971,10 @@ df_notes_rescan (rtx insn) if (!insn_info) { insn_info = df_insn_create_insn_record (insn); - insn_info->defs = df_null_ref_rec; - insn_info->uses = df_null_ref_rec; - insn_info->eq_uses = df_null_ref_rec; - insn_info->mw_hardregs = df_null_mw_rec; + insn_info->defs = 0; + insn_info->uses = 0; + insn_info->eq_uses = 0; + insn_info->mw_hardregs = 0; } bitmap_clear_bit (&df->insns_to_delete, uid); @@ -2100,10 +1993,9 @@ df_notes_rescan (rtx insn) basic_block bb = BLOCK_FOR_INSN (insn); rtx note; struct df_collection_rec collection_rec; - unsigned int num_deleted; - unsigned int mw_len; + unsigned int i; - num_deleted = df_mw_hardreg_chain_delete_eq_uses (insn_info); + df_mw_hardreg_chain_delete_eq_uses (insn_info); df_ref_chain_delete (insn_info->eq_uses); insn_info->eq_uses = NULL; @@ -2125,45 +2017,14 @@ df_notes_rescan (rtx insn) /* Find some place to put any new mw_hardregs. */ df_canonize_collection_rec (&collection_rec); - mw_len = collection_rec.mw_vec.length (); - if (mw_len) + struct df_mw_hardreg **mw_ptr = &insn_info->mw_hardregs, *mw; + FOR_EACH_VEC_ELT (collection_rec.mw_vec, i, mw) { - unsigned int count = 0; - struct df_mw_hardreg **mw_rec = insn_info->mw_hardregs; - while (*mw_rec) - { - count++; - mw_rec++; - } - - if (count) - { - /* Append to the end of the existing record after - expanding it if necessary. */ - if (mw_len > num_deleted) - { - insn_info->mw_hardregs = - XRESIZEVEC (struct df_mw_hardreg *, - insn_info->mw_hardregs, - count + 1 + mw_len); - } - memcpy (&insn_info->mw_hardregs[count], - collection_rec.mw_vec.address (), - mw_len * sizeof (struct df_mw_hardreg *)); - insn_info->mw_hardregs[count + mw_len] = NULL; - qsort (insn_info->mw_hardregs, count + mw_len, - sizeof (struct df_mw_hardreg *), df_mw_compare); - } - else - { - /* No vector there. */ - insn_info->mw_hardregs - = XNEWVEC (struct df_mw_hardreg*, 1 + mw_len); - memcpy (insn_info->mw_hardregs, - collection_rec.mw_vec.address (), - mw_len * sizeof (struct df_mw_hardreg *)); - insn_info->mw_hardregs[mw_len] = NULL; - } + while (*mw_ptr && df_mw_compare (*mw_ptr, mw) < 0) + mw_ptr = &(*mw_ptr)->next; + mw->next = *mw_ptr; + *mw_ptr = mw; + mw_ptr = &mw->next; } df_refs_add_to_chains (&collection_rec, bb, insn, copy_eq_uses); } @@ -2222,14 +2083,8 @@ df_ref_equal_p (df_ref ref1, df_ref ref2 have the same bb. So these fields are not checked. */ static int -df_ref_compare (const void *r1, const void *r2) +df_ref_compare (df_ref ref1, df_ref ref2) { - const df_ref ref1 = *(const df_ref *)r1; - const df_ref ref2 = *(const df_ref *)r2; - - if (ref1 == ref2) - return 0; - if (DF_REF_CLASS (ref1) != DF_REF_CLASS (ref2)) return (int)DF_REF_CLASS (ref1) - (int)DF_REF_CLASS (ref2); @@ -2264,6 +2119,14 @@ df_ref_compare (const void *r1, const vo return (int)DF_REF_ORDER (ref1) - (int)DF_REF_ORDER (ref2); } +/* Like df_ref_compare, but compare two df_ref* pointers R1 and R2. */ + +static int +df_ref_ptr_compare (const void *r1, const void *r2) +{ + return df_ref_compare (*(const df_ref *) r1, *(const df_ref *) r2); +} + static void df_swap_refs (vec *ref_vec, int i, int j) { @@ -2290,7 +2153,7 @@ df_sort_and_compress_refs (vec 0) + if (df_ref_compare (r0, r1) > 0) df_swap_refs (ref_vec, 0, 1); } else @@ -2299,7 +2162,7 @@ df_sort_and_compress_refs (vec= 0) + if (df_ref_compare (r0, r1) >= 0) break; } /* If the array is already strictly ordered, @@ -2311,7 +2174,7 @@ df_sort_and_compress_refs (vecqsort (df_ref_compare); + ref_vec->qsort (df_ref_ptr_compare); } for (i=0; itype != mw2->type) return mw1->type - mw2->type; @@ -2380,6 +2237,14 @@ df_mw_compare (const void *m1, const voi return 0; } +/* Like df_mw_compare, but compare two df_mw_hardreg** pointers R1 and R2. */ + +static int +df_mw_ptr_compare (const void *m1, const void *m2) +{ + return df_mw_compare (*(const df_mw_hardreg *const *) m1, + *(const df_mw_hardreg *const *) m2); +} /* Sort and compress a set of refs. */ @@ -2399,7 +2264,7 @@ df_sort_and_compress_mws (vec 0) + if (df_mw_compare (m0, m1) > 0) { struct df_mw_hardreg *tmp = (*mw_vec)[0]; (*mw_vec)[0] = (*mw_vec)[1]; @@ -2407,7 +2272,7 @@ df_sort_and_compress_mws (vecqsort (df_mw_compare); + mw_vec->qsort (df_mw_ptr_compare); for (i=0; i *old_vec, struct df_reg_info **reg_info, @@ -2503,7 +2368,6 @@ df_install_refs (basic_block bb, unsigned int count = old_vec->length (); if (count) { - df_ref *new_vec = XNEWVEC (df_ref, count + 1); bool add_to_table; df_ref this_ref; unsigned int ix; @@ -2533,37 +2397,35 @@ df_install_refs (basic_block bb, FOR_EACH_VEC_ELT (*old_vec, ix, this_ref) { - new_vec[ix] = this_ref; + this_ref->base.next_loc = (ix + 1 < old_vec->length () + ? (*old_vec)[ix + 1] + : NULL); df_install_ref (this_ref, reg_info[DF_REF_REGNO (this_ref)], ref_info, add_to_table); } - - new_vec[count] = NULL; - return new_vec; + return (*old_vec)[0]; } else - return df_null_ref_rec; + return 0; } /* This function takes the mws installs the entire group into the insn. */ -static struct df_mw_hardreg ** +static struct df_mw_hardreg * df_install_mws (const vec *old_vec) { unsigned int count = old_vec->length (); if (count) { - struct df_mw_hardreg **new_vec - = XNEWVEC (struct df_mw_hardreg*, count + 1); - memcpy (new_vec, old_vec->address (), - sizeof (struct df_mw_hardreg*) * count); - new_vec[count] = NULL; - return new_vec; + for (unsigned int i = 0; i < count - 1; i++) + (*old_vec)[i]->next = (*old_vec)[i + 1]; + (*old_vec)[count - 1]->next = 0; + return (*old_vec)[0]; } else - return df_null_mw_rec; + return 0; } @@ -2582,7 +2444,7 @@ df_refs_add_to_chains (struct df_collect chain specially. */ if (flags & copy_defs) { - df_scan_free_ref_vec (insn_rec->defs); + gcc_checking_assert (!insn_rec->defs); insn_rec->defs = df_install_refs (bb, &collection_rec->def_vec, df->def_regs, @@ -2590,7 +2452,7 @@ df_refs_add_to_chains (struct df_collect } if (flags & copy_uses) { - df_scan_free_ref_vec (insn_rec->uses); + gcc_checking_assert (!insn_rec->uses); insn_rec->uses = df_install_refs (bb, &collection_rec->use_vec, df->use_regs, @@ -2598,7 +2460,7 @@ df_refs_add_to_chains (struct df_collect } if (flags & copy_eq_uses) { - df_scan_free_ref_vec (insn_rec->eq_uses); + gcc_checking_assert (!insn_rec->eq_uses); insn_rec->eq_uses = df_install_refs (bb, &collection_rec->eq_use_vec, df->eq_use_regs, @@ -2606,7 +2468,7 @@ df_refs_add_to_chains (struct df_collect } if (flags & copy_mw) { - df_scan_free_mws_vec (insn_rec->mw_hardregs); + gcc_checking_assert (!insn_rec->mw_hardregs); insn_rec->mw_hardregs = df_install_mws (&collection_rec->mw_vec); } @@ -2615,12 +2477,12 @@ df_refs_add_to_chains (struct df_collect { struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb->index); - df_scan_free_ref_vec (bb_info->artificial_defs); + gcc_checking_assert (!bb_info->artificial_defs); bb_info->artificial_defs = df_install_refs (bb, &collection_rec->def_vec, df->def_regs, &df->def_info, false); - df_scan_free_ref_vec (bb_info->artificial_uses); + gcc_checking_assert (!bb_info->artificial_uses); bb_info->artificial_uses = df_install_refs (bb, &collection_rec->use_vec, df->use_regs, @@ -4194,7 +4056,7 @@ df_reg_chain_verify_unmarked (df_ref ref /* Verify that NEW_REC and OLD_REC have exactly the same members. */ static bool -df_refs_verify (const vec *new_rec, df_ref *old_rec, +df_refs_verify (const vec *new_rec, df_ref old_rec, bool abort_if_fail) { unsigned int ix; @@ -4202,7 +4064,7 @@ df_refs_verify (const vecbase.next_loc; } if (abort_if_fail) - gcc_assert (*old_rec == NULL); + gcc_assert (old_rec == NULL); else - return *old_rec == NULL; + return old_rec == NULL; return false; } @@ -4233,7 +4095,7 @@ df_refs_verify (const vec *new_rec, - struct df_mw_hardreg **old_rec, + struct df_mw_hardreg *old_rec, bool abort_if_fail) { unsigned int ix; @@ -4241,20 +4103,20 @@ df_mws_verify (const vecnext; } if (abort_if_fail) - gcc_assert (*old_rec == NULL); + gcc_assert (old_rec == NULL); else - return *old_rec == NULL; + return old_rec == NULL; return false; } @@ -4282,15 +4144,6 @@ df_insn_refs_verify (struct df_collectio df_insn_refs_collect (collection_rec, bb, insn_info); - if (!DF_INSN_UID_DEFS (uid)) - { - /* The insn_rec was created but it was never filled out. */ - if (abort_if_fail) - gcc_assert (0); - else - return false; - } - /* Unfortunately we cannot opt out early if one of these is not right because the marks will not get cleared. */ ret1 = df_refs_verify (&collection_rec->def_vec, DF_INSN_UID_DEFS (uid), Index: gcc/web.c =================================================================== --- gcc/web.c 2014-06-14 20:08:33.448584144 +0100 +++ gcc/web.c 2014-06-14 20:16:25.450761175 +0100 @@ -93,8 +93,8 @@ union_match_dups (rtx insn, struct web_e bool (*fun) (struct web_entry *, struct web_entry *)) { struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn); - df_ref *use_link = DF_INSN_INFO_USES (insn_info); - df_ref *def_link = DF_INSN_INFO_DEFS (insn_info); + df_ref use_link = DF_INSN_INFO_USES (insn_info); + df_ref def_link = DF_INSN_INFO_DEFS (insn_info); struct web_entry *dup_entry; int i; @@ -104,18 +104,19 @@ union_match_dups (rtx insn, struct web_e { int op = recog_data.dup_num[i]; enum op_type type = recog_data.operand_type[op]; - df_ref *ref, *dupref; + df_ref ref, dupref; struct web_entry *entry; - for (dup_entry = use_entry, dupref = use_link; *dupref; dupref++) - if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i]) + dup_entry = use_entry; + for (dupref = use_link; dupref; dupref = dupref->base.next_loc) + if (DF_REF_LOC (dupref) == recog_data.dup_loc[i]) break; - if (*dupref == NULL && type == OP_INOUT) + if (dupref == NULL && type == OP_INOUT) { - - for (dup_entry = def_entry, dupref = def_link; *dupref; dupref++) - if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i]) + dup_entry = def_entry; + for (dupref = def_link; dupref; dupref = dupref->base.next_loc) + if (DF_REF_LOC (dupref) == recog_data.dup_loc[i]) break; } /* ??? *DUPREF can still be zero, because when an operand matches @@ -125,35 +126,36 @@ union_match_dups (rtx insn, struct web_e even though it is there. Example: i686-pc-linux-gnu gcc.c-torture/compile/950607-1.c -O3 -fomit-frame-pointer -funroll-loops */ - if (*dupref == NULL - || DF_REF_REGNO (*dupref) < FIRST_PSEUDO_REGISTER) + if (dupref == NULL + || DF_REF_REGNO (dupref) < FIRST_PSEUDO_REGISTER) continue; ref = type == OP_IN ? use_link : def_link; entry = type == OP_IN ? use_entry : def_entry; - for (; *ref; ref++) + for (; ref; ref = ref->base.next_loc) { - rtx *l = DF_REF_LOC (*ref); + rtx *l = DF_REF_LOC (ref); if (l == recog_data.operand_loc[op]) break; - if (l && DF_REF_REAL_LOC (*ref) == recog_data.operand_loc[op]) + if (l && DF_REF_REAL_LOC (ref) == recog_data.operand_loc[op]) break; } - if (!*ref && type == OP_INOUT) + if (!ref && type == OP_INOUT) { - for (ref = use_link, entry = use_entry; *ref; ref++) + entry = use_entry; + for (ref = use_link; ref; ref = ref->base.next_loc) { - rtx *l = DF_REF_LOC (*ref); + rtx *l = DF_REF_LOC (ref); if (l == recog_data.operand_loc[op]) break; - if (l && DF_REF_REAL_LOC (*ref) == recog_data.operand_loc[op]) + if (l && DF_REF_REAL_LOC (ref) == recog_data.operand_loc[op]) break; } } - gcc_assert (*ref); - (*fun) (dup_entry + DF_REF_ID (*dupref), entry + DF_REF_ID (*ref)); + gcc_assert (ref); + (*fun) (dup_entry + DF_REF_ID (dupref), entry + DF_REF_ID (ref)); } }