From patchwork Wed Oct 17 19:53:32 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [lra] patch implementing proposals from the Richard Sandiford's review of lra.c Date: Wed, 17 Oct 2012 09:53:32 -0000 From: Vladimir Makarov X-Patchwork-Id: 192131 Message-Id: <507F0CBC.5060805@redhat.com> To: GCC Patches The following patch implements most proposals of Richard's review of lra.c and lra-int.h. The patch was successfully bootstrapped and tested on x86/x86-64. Committed as rev. 192544. 2012-10-17 Vladimir Makarov * Makefile.in (LRA_INT_H): Add $(BITMAP_H) $(RECOG_H) $(INSN_ATTR_H) insn-codes.h. * lra-int.h: Include recog.h and insn-codes.h. (struct lra_insn_reg, struct lra_static_insn_data): Improve comments. (lra_expand_reg_info, lra_secondary_memory): Remove. (lra_save_restore, lra_hard_reg_set_intersection_p): Ditto. (lra_add_hard_reg_set): Ditto. (lra_get_hard_regno_and_offset): Set up offset to zero. (struct target_lra_int): New. (default_target_lra_int, this_target_lra_int, op_alt_data): Ditto. * target-globals.h (this_target_lra_int): New external. (target_globals): New member lra_int. (restore_target_globals): Restore this_target_lra_int. * target-globals.c: Include lra-int.h. (default_target_globals): Add &default_target_lra_int. * doc/md.texi: Add new interpretation of hint * for LRA. * lra-assigns.c (find_hard_regno_for, spill_for): Use add_to_hard_reg_set instead of lra_add_hard_reg_set. Use overlaps_hard_reg_set_p instead of lra_hard_reg_set_intersection_p. (setup_live_pseudos_and_spill_after_risky): Ditto. (setup_try_hard_regno_pseudos): Use overlaps_hard_reg_set_p instead of lra_hard_reg_set_intersection_p. * lra-constraints.c (uses_hard_regs_p, contains_reg_p): Ditto. (need_for_call_save_p): Ditto. (process_alt_operands, inherit_in_ebb): Use add_to_hard_reg_set instead of lra_add_hard_reg_set. * lra-eliminations.c (spill_pseudos): Use overlaps_hard_reg_set_p instead of lra_hard_reg_set_intersection_p. * lra-spills.c (assign_spill_hard_regs): Use add_to_hard_reg_set instead of lra_add_hard_reg_set. Use overlaps_hard_reg_set_p instead of lra_hard_reg_set_intersection_p. * lra.c (lra_create_new_reg_with_unique_value): Improve comments. (lra_emit_add): Ditto. (this_target_lra_int, default_target_lra_int): New. (op_alt_data): Move to struct target_lra_int. (collect_non_operand_hard_regs): Simplify code. (lra_set_insn_recog_data): Use recog_memoized. (lra_update_insn_recog_data): Fix typo in a comment. (initialize_lra_reg_info_element): New. (init_reg_info, expand_reg_info): Use initialize_lra_reg_info_element. (add_regs_to_insn_regno_info): Simplify the code. (check_rtl): Use AUTOINC. (has_nonexceptional_receiver): Simplify code. (update_reg_notes): Rename to update_inc_notes. Ignore REG_DEAD and REG_UNUSED. (lra_init): Improve comment. Index: Makefile.in =================================================================== --- Makefile.in (revision 192534) +++ Makefile.in (working copy) @@ -939,7 +939,7 @@ TREE_DATA_REF_H = tree-data-ref.h $(OMEG TREE_INLINE_H = tree-inline.h vecir.h REAL_H = real.h $(MACHMODE_H) IRA_INT_H = ira.h ira-int.h $(CFGLOOP_H) alloc-pool.h -LRA_INT_H = lra.h lra-int.h +LRA_INT_H = lra.h $(BITMAP_H) $(RECOG_H) $(INSN_ATTR_H) insn-codes.h lra-int.h DBGCNT_H = dbgcnt.h dbgcnt.def EBITMAP_H = ebitmap.h sbitmap.h LTO_STREAMER_H = lto-streamer.h $(LINKER_PLUGIN_API_H) $(TARGET_H) \ Index: doc/md.texi =================================================================== --- doc/md.texi (revision 192534) +++ doc/md.texi (working copy) @@ -1,5 +1,5 @@ @c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001, -@c 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 +@c 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 @c Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -1606,7 +1606,9 @@ register preferences. @item * Says that the following character should be ignored when choosing register preferences. @samp{*} has no effect on the meaning of the -constraint as a constraint, and no effect on reloading. +constraint as a constraint, and no effect on reloading. For LRA +@samp{*} additionally disparages slightly the alternative if the +following character matches the operand. @ifset INTERNALS Here is an example: the 68000 has an instruction to sign-extend a Index: lra-assigns.c =================================================================== --- lra-assigns.c (revision 192534) +++ lra-assigns.c (working copy) @@ -523,9 +523,9 @@ find_hard_regno_for (int regno, int *cos } else { - lra_add_hard_reg_set (live_pseudos_reg_renumber[conflict_regno], - lra_reg_info[conflict_regno].biggest_mode, - &conflict_set); + add_to_hard_reg_set (&conflict_set, + lra_reg_info[conflict_regno].biggest_mode, + live_pseudos_reg_renumber[conflict_regno]); if (hard_reg_set_subset_p (reg_class_contents[rclass], conflict_set)) return -1; @@ -564,9 +564,8 @@ find_hard_regno_for (int regno, int *cos hard_regno = try_only_hard_regno; else hard_regno = ira_class_hard_regs[rclass][i]; - if (! lra_hard_reg_set_intersection_p (hard_regno, - PSEUDO_REGNO_MODE (regno), - conflict_set) + if (! overlaps_hard_reg_set_p (conflict_set, + PSEUDO_REGNO_MODE (regno), hard_regno) /* We can not use prohibited_class_mode_regs because it is not defined for all classes. */ && HARD_REGNO_MODE_OK (hard_regno, PSEUDO_REGNO_MODE (regno)) @@ -741,8 +740,8 @@ setup_try_hard_regno_pseudos (int p, enu { mode = PSEUDO_REGNO_MODE (spill_regno); hard_regno = live_pseudos_reg_renumber[spill_regno]; - if (lra_hard_reg_set_intersection_p (hard_regno, mode, - reg_class_contents[rclass])) + if (overlaps_hard_reg_set_p (reg_class_contents[rclass], + mode, hard_regno)) { for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--) { @@ -862,8 +861,8 @@ spill_for (int regno, bitmap spilled_pse if (lra_dump_file != NULL) fprintf (lra_dump_file, " spill %d(freq=%d)", spill_regno, lra_reg_info[spill_regno].freq); - lra_add_hard_reg_set (reg_renumber[spill_regno], mode2, - &spilled_hard_regs); + add_to_hard_reg_set (&spilled_hard_regs, + mode2, reg_renumber[spill_regno]); for (r = lra_reg_info[spill_regno].live_ranges; r != NULL; r = r->next) @@ -903,9 +902,9 @@ spill_for (int regno, bitmap spilled_pse if ((reload_hard_regno = find_hard_regno_for (reload_regno, &reload_cost, -1)) >= 0 - && (lra_hard_reg_set_intersection_p - (reload_hard_regno, PSEUDO_REGNO_MODE (reload_regno), - spilled_hard_regs))) + && (overlaps_hard_reg_set_p + (spilled_hard_regs, + PSEUDO_REGNO_MODE (reload_regno), reload_hard_regno))) { if (lra_dump_file != NULL) fprintf (lra_dump_file, " assign %d(cost=%d)", @@ -1058,10 +1057,10 @@ setup_live_pseudos_and_spill_after_risky /* If it is multi-register pseudos they should start on the same hard register. */ || hard_regno != reg_renumber[conflict_regno]) - lra_add_hard_reg_set (reg_renumber[conflict_regno], - lra_reg_info[conflict_regno].biggest_mode, - &conflict_set); - if (! lra_hard_reg_set_intersection_p (hard_regno, mode, conflict_set)) + add_to_hard_reg_set (&conflict_set, + lra_reg_info[conflict_regno].biggest_mode, + reg_renumber[conflict_regno]); + if (! overlaps_hard_reg_set_p (conflict_set, mode, hard_regno)) { update_lives (regno, false); continue; @@ -1357,9 +1356,8 @@ lra_assign (void) for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0 && lra_reg_info[i].call_p - && lra_hard_reg_set_intersection_p (reg_renumber[i], - PSEUDO_REGNO_MODE (i), - call_used_reg_set)) + && overlaps_hard_reg_set_p (call_used_reg_set, + PSEUDO_REGNO_MODE (i), reg_renumber[i])) gcc_unreachable (); #endif /* Setup insns to process on the next constraint pass. */ Index: lra-constraints.c =================================================================== --- lra-constraints.c (revision 192534) +++ lra-constraints.c (working copy) @@ -1465,7 +1465,7 @@ uses_hard_regs_p (rtx x, HARD_REG_SET se /* The real hard regno of the operand after the allocation. */ x_hard_regno = get_final_hard_regno (x_hard_regno, offset); return (x_hard_regno >= 0 - && lra_hard_reg_set_intersection_p (x_hard_regno, mode, set)); + && overlaps_hard_reg_set_p (set, mode, x_hard_regno)); } if (MEM_P (x)) { @@ -2223,7 +2223,7 @@ process_alt_operands (int only_alternati continue; clobbered_hard_regno = hard_regno[i]; CLEAR_HARD_REG_SET (temp_set); - lra_add_hard_reg_set (clobbered_hard_regno, biggest_mode[i], &temp_set); + add_to_hard_reg_set (&temp_set, biggest_mode[i], clobbered_hard_regno); for (j = 0; j < n_operands; j++) if (j == i /* We don't want process insides of match_operator and @@ -3330,8 +3330,7 @@ contains_reg_p (rtx x, bool hard_reg_p, if (regno < 0) return false; COMPL_HARD_REG_SET (alloc_regs, lra_no_alloc_regs); - return lra_hard_reg_set_intersection_p (regno, GET_MODE (x), - alloc_regs); + return overlaps_hard_reg_set_p (alloc_regs, GET_MODE (x), regno); } else { @@ -3972,9 +3971,9 @@ need_for_call_save_p (int regno) { lra_assert (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0); return (usage_insns[regno].calls_num < calls_num - && (lra_hard_reg_set_intersection_p - (reg_renumber[regno], PSEUDO_REGNO_MODE (regno), - call_used_reg_set))); + && (overlaps_hard_reg_set_p + (call_used_reg_set, + PSEUDO_REGNO_MODE (regno), reg_renumber[regno]))); } /* Global registers occuring in the current EBB. */ @@ -4504,9 +4503,9 @@ inherit_in_ebb (rtx head, rtx tail) if (j < FIRST_PSEUDO_REGISTER) SET_HARD_REG_BIT (live_hard_regs, j); else - lra_add_hard_reg_set (reg_renumber[j], - PSEUDO_REGNO_MODE (j), - &live_hard_regs); + add_to_hard_reg_set (&live_hard_regs, + PSEUDO_REGNO_MODE (j), + reg_renumber[j]); setup_next_usage_insn (j, last_insn, reloads_num, after_p); } } @@ -4605,10 +4604,10 @@ inherit_in_ebb (rtx head, rtx tail) change_p = true; CLEAR_HARD_REG_SET (s); if (dst_regno < FIRST_PSEUDO_REGISTER) - lra_add_hard_reg_set (dst_regno, reg->biggest_mode, &s); + add_to_hard_reg_set (&s, reg->biggest_mode, dst_regno); else - lra_add_hard_reg_set (reg_renumber[dst_regno], - PSEUDO_REGNO_MODE (dst_regno), &s); + add_to_hard_reg_set (&s, PSEUDO_REGNO_MODE (dst_regno), + reg_renumber[dst_regno]); AND_COMPL_HARD_REG_SET (live_hard_regs, s); } /* We should invalidate potential inheritance for the @@ -4704,12 +4703,12 @@ inherit_in_ebb (rtx head, rtx tail) if (NONDEBUG_INSN_P (curr_insn)) { if (src_regno < FIRST_PSEUDO_REGISTER) - lra_add_hard_reg_set (src_regno, reg->biggest_mode, - &live_hard_regs); + add_to_hard_reg_set (&live_hard_regs, + reg->biggest_mode, src_regno); else - lra_add_hard_reg_set (reg_renumber[src_regno], - PSEUDO_REGNO_MODE (src_regno), - &live_hard_regs); + add_to_hard_reg_set (&live_hard_regs, + PSEUDO_REGNO_MODE (src_regno), + reg_renumber[src_regno]); } add_next_usage_insn (src_regno, use_insn, reloads_num); } Index: lra-eliminations.c =================================================================== --- lra-eliminations.c (revision 192534) +++ lra-eliminations.c (working copy) @@ -1016,8 +1016,8 @@ spill_pseudos (HARD_REG_SET set) bitmap_initialize (&to_process, ®_obstack); for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++) if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0 - && lra_hard_reg_set_intersection_p (reg_renumber[i], - PSEUDO_REGNO_MODE (i), set)) + && overlaps_hard_reg_set_p (set, + PSEUDO_REGNO_MODE (i), reg_renumber[i])) { if (lra_dump_file != NULL) fprintf (lra_dump_file, " Spilling r%d(%d)\n", Index: lra-int.h =================================================================== --- lra-int.h (revision 192534) +++ lra-int.h (working copy) @@ -21,7 +21,9 @@ along with GCC; see the file COPYING3. I #include "lra.h" #include "bitmap.h" +#include "recog.h" #include "insn-attr.h" +#include "insn-codes.h" #ifdef ENABLE_CHECKING #define lra_assert(c) gcc_assert (c) @@ -161,12 +163,12 @@ struct lra_operand_data unsigned int is_address : 1; }; -/* Info about register in an insn. */ +/* Info about register occurrence in an insn. */ struct lra_insn_reg { /* The biggest mode through which the insn refers to the register - (remember the register can be accessed through a subreg in the - insn). */ + occurrence (remember the register can be accessed through a + subreg in the insn). */ ENUM_BITFIELD(machine_mode) biggest_mode : 16; /* The type of the corresponding operand which is the register. */ ENUM_BITFIELD (op_type) type : 8; @@ -183,10 +185,11 @@ struct lra_insn_reg }; /* Static part (common info for insns with the same ICODE) of LRA - internal insn info. It exists in at most one exemplar for each - non-negative ICODE. Warning: if the structure definition is - changed, the initializer for debug_insn_static_data in lra.c should - be changed too. */ + internal insn info. It exists in at most one exemplar for each + non-negative ICODE. There is only one exception. Each asm insn has + own structure. Warning: if the structure definition is changed, + the initializer for debug_insn_static_data in lra.c should be + changed too. */ struct lra_static_insn_data { /* Static info about each insn operand. */ @@ -215,9 +218,12 @@ struct lra_static_insn_data representation). */ struct lra_insn_recog_data { - int icode; /* The insn code. */ - rtx insn; /* The insn itself. */ - /* Common data for insns with the same ICODE. */ + /* The insn code. */ + int icode; + /* The insn itself. */ + rtx insn; + /* Common data for insns with the same ICODE. Asm insns (their + ICODE is negative) do not share such structures. */ struct lra_static_insn_data *insn_static_data; /* Two arrays of size correspondingly equal to the operand and the duplication numbers: */ @@ -235,7 +241,8 @@ struct lra_insn_recog_data should try to use any alternative, or the insn is a debug insn. */ int used_insn_alternative; - struct lra_insn_reg *regs; /* Always NULL for a debug insn. */ + /* The following member value is always NULL for a debug insn. */ + struct lra_insn_reg *regs; }; typedef struct lra_insn_recog_data *lra_insn_recog_data_t; @@ -280,7 +287,6 @@ extern void lra_invalidate_insn_regno_in extern void lra_update_insn_regno_info (rtx); extern struct lra_insn_reg *lra_get_insn_regs (int); -extern void lra_expand_reg_info (void); extern void lra_free_copies (void); extern void lra_create_copy (int, int, int); extern lra_copy_t lra_get_copy (int); @@ -297,8 +303,6 @@ extern int lra_constraint_new_insn_uid_s extern bitmap_head lra_special_reload_pseudos; -extern rtx lra_secondary_memory[NUM_MACHINE_MODES]; - extern int lra_constraint_offset (int, enum machine_mode); extern int lra_constraint_iter; @@ -346,10 +350,6 @@ extern bool lra_assign (void); extern int lra_coalesce_iter; extern bool lra_coalesce (void); -/* lra-saves.c: */ - -extern bool lra_save_restore (void); - /* lra-spills.c: */ extern bool lra_need_for_spills_p (void); @@ -368,22 +368,6 @@ extern void lra_eliminate_reg_if_possibl -/* The function returns TRUE if at least one hard register from ones - starting with HARD_REGNO and containing value of MODE are in set - HARD_REGSET. */ -static inline bool -lra_hard_reg_set_intersection_p (int hard_regno, enum machine_mode mode, - HARD_REG_SET hard_regset) -{ - int i; - - lra_assert (hard_regno >= 0); - for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--) - if (TEST_HARD_REG_BIT (hard_regset, hard_regno + i)) - return true; - return false; -} - /* Return hard regno and offset of (sub-)register X through arguments HARD_REGNO and OFFSET. If it is not (sub-)register or the hard register is unknown, then return -1 and 0 correspondingly. */ @@ -392,7 +376,8 @@ lra_get_hard_regno_and_offset (rtx x, in { rtx reg; - *hard_regno = *offset = -1; + *hard_regno = -1; + *offset = 0; reg = x; if (GET_CODE (x) == SUBREG) reg = SUBREG_REG (x); @@ -402,23 +387,11 @@ lra_get_hard_regno_and_offset (rtx x, in *hard_regno = lra_get_regno_hard_regno (*hard_regno); if (*hard_regno < 0) return; - *offset = 0; if (GET_CODE (x) == SUBREG) *offset += subreg_regno_offset (*hard_regno, GET_MODE (reg), SUBREG_BYTE (x), GET_MODE (x)); } -/* Add hard registers starting with HARD_REGNO and holding value of - MODE to the set S. */ -static inline void -lra_add_hard_reg_set (int hard_regno, enum machine_mode mode, HARD_REG_SET *s) -{ - int i; - - for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--) - SET_HARD_REG_BIT (*s, hard_regno + i); -} - /* Update insn operands which are duplication of NOP operand. The insn is represented by its LRA internal representation ID. */ static inline void @@ -470,3 +443,22 @@ lra_get_insn_recog_data (rtx insn) } return lra_set_insn_recog_data (insn); } + + + +struct target_lra_int +{ + /* Map INSN_UID -> the operand alternative data (NULL if unknown). + We assume that this data is valid until register info is changed + because classes in the data can be changed. */ + struct operand_alternative *x_op_alt_data[LAST_INSN_CODE]; +}; + +extern struct target_lra_int default_target_lra_int; +#if SWITCHABLE_TARGET +extern struct target_lra_int *this_target_lra_int; +#else +#define this_target_lra_int (&default_target_lra_int) +#endif + +#define op_alt_data (this_target_lra_int->x_op_alt_data) Index: lra-spills.c =================================================================== --- lra-spills.c (revision 192534) +++ lra-spills.c (working copy) @@ -279,8 +279,8 @@ assign_spill_hard_regs (int *pseudo_regn && (hard_regno = lra_get_regno_hard_regno (i)) >= 0) for (r = lra_reg_info[i].live_ranges; r != NULL; r = r->next) for (p = r->start; p <= r->finish; p++) - lra_add_hard_reg_set (hard_regno, lra_reg_info[i].biggest_mode, - &reserved_hard_regs[p]); + add_to_hard_reg_set (&reserved_hard_regs[p], + lra_reg_info[i].biggest_mode, hard_regno); bitmap_initialize (&ok_insn_bitmap, ®_obstack); FOR_EACH_BB (bb) FOR_BB_INSNS (bb, insn) @@ -314,8 +314,7 @@ assign_spill_hard_regs (int *pseudo_regn for (k = 0; k < spill_class_size; k++) { hard_regno = ira_class_hard_regs[spill_class][k]; - if (! lra_hard_reg_set_intersection_p (hard_regno, mode, - conflict_hard_regs)) + if (! overlaps_hard_reg_set_p (conflict_hard_regs, mode, hard_regno)) break; } if (k >= spill_class_size) @@ -329,8 +328,8 @@ assign_spill_hard_regs (int *pseudo_regn /* Update reserved_hard_regs. */ for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next) for (p = r->start; p <= r->finish; p++) - lra_add_hard_reg_set (hard_regno, lra_reg_info[regno].biggest_mode, - &reserved_hard_regs[p]); + add_to_hard_reg_set (&reserved_hard_regs[p], + lra_reg_info[regno].biggest_mode, hard_regno); spill_hard_reg[regno] = gen_raw_REG (PSEUDO_REGNO_MODE (regno), hard_regno); for (nr = 0; Index: lra.c =================================================================== --- lra.c (revision 192534) +++ lra.c (working copy) @@ -138,11 +138,12 @@ expand_reg_data (void) ira_expand_reg_equiv (); } -/* Create and return a new reg from register FROM corresponding to - machine description operand of mode MD_MODE. Initialize its +/* Create and return a new reg of ORIGINAL mode. If ORIGINAL is NULL + or of VOIDmode, use MD_MODE for the new reg. Initialize its register class to RCLASS. Print message about assigning class - RCLASS containing new register name TITLE unless it is NULL. The - created register will have unique held value. */ + RCLASS containing new register name TITLE unless it is NULL. Use + attributes of ORIGINAL if it is a register. The created register + will have unique held value. */ rtx lra_create_new_reg_with_unique_value (enum machine_mode md_mode, rtx original, enum reg_class rclass, const char *title) @@ -247,8 +248,11 @@ lra_delete_dead_insn (rtx insn) which are frequent results of elimination. Emit insns for x = y + z. X can be used to store intermediate - values and should be not in Y and Z when we use x to store an - intermediate value. */ + values and should be not in Y and Z when we use X to store an + intermediate value. Y + Z should form [base] [+ index[ * scale]] [ + + disp] where base and index are registers, disp and scale are + constants. Y should contain base if it is present, Z should + contain disp if any. index[*scale] can be part of Y or Z. */ void lra_emit_add (rtx x, rtx y, rtx z) { @@ -496,16 +500,15 @@ finish_insn_regs (void) /* This page contains code dealing LRA insn info (or in other words LRA internal insn representation). */ +struct target_lra_int default_target_lra_int; +#if SWITCHABLE_TARGET +struct target_lra_int *this_target_lra_int = &default_target_lra_int; +#endif /* Map INSN_CODE -> the static insn data. This info is valid during all translation unit. */ struct lra_static_insn_data *insn_code_data[LAST_INSN_CODE]; -/* Map INSN_UID -> the operand alternative data (NULL if unknown). We - assume that this data is valid until register info is changed - because classes in the data can be changed. */ -struct operand_alternative *op_alt_data[LAST_INSN_CODE]; - /* Debug insns are represented as a special insn with one input operand which is RTL expression in var_location. */ @@ -918,10 +921,16 @@ collect_non_operand_hard_regs (rtx *x, l if (! TEST_HARD_REG_BIT (lra_no_alloc_regs, regno)) { for (curr = list; curr != NULL; curr = curr->next) - if (curr->regno == regno) - break; - if (curr == NULL || curr->subreg_p != subreg_p - || curr->biggest_mode != mode) + if (curr->regno == regno && curr->subreg_p == subreg_p + && curr->biggest_mode == mode) + { + if (curr->type != type) + curr->type = OP_INOUT; + if (curr->early_clobber != early_clobber) + curr->early_clobber = true; + break; + } + if (curr == NULL) { /* This is a new hard regno or the info can not be integrated into the found structure. */ @@ -936,13 +945,6 @@ collect_non_operand_hard_regs (rtx *x, l list = new_insn_reg (regno, type, mode, subreg_p, early_clobber, list); } - else - { - if (curr->type != type) - curr->type = OP_INOUT; - if (curr->early_clobber != early_clobber) - curr->early_clobber = true; - } } return list; } @@ -1005,7 +1007,7 @@ lra_set_insn_recog_data (rtx insn) icode = INSN_CODE (insn); if (icode < 0) /* It might be a new simple insn which is not recognized yet. */ - INSN_CODE (insn) = icode = recog (PATTERN (insn), insn, 0); + INSN_CODE (insn) = icode = recog_memoized (insn); } data = XNEW (struct lra_insn_recog_data); lra_insn_recog_data[uid] = data; @@ -1231,7 +1233,7 @@ invalidate_insn_recog_data (int uid) } /* Update all the insn info about INSN. It is usually called when - something in the insn was changed. Return the udpated info. */ + something in the insn was changed. Return the updated info. */ lra_insn_recog_data_t lra_update_insn_recog_data (rtx insn) { @@ -1379,6 +1381,27 @@ DEF_VEC_ALLOC_P(lra_copy_t, heap); /* Vec referring to pseudo copies. */ static VEC(lra_copy_t,heap) *copy_vec; +/* Initialize I-th element of lra_reg_info. */ +static inline void +initialize_lra_reg_info_element (int i) +{ + bitmap_initialize (&lra_reg_info[i].insn_bitmap, ®_obstack); +#ifdef STACK_REGS + lra_reg_info[i].no_stack_p = false; +#endif + CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs); + lra_reg_info[i].preferred_hard_regno1 = -1; + lra_reg_info[i].preferred_hard_regno2 = -1; + lra_reg_info[i].preferred_hard_regno_profit1 = 0; + lra_reg_info[i].preferred_hard_regno_profit2 = 0; + lra_reg_info[i].live_ranges = NULL; + lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0; + lra_reg_info[i].last_reload = 0; + lra_reg_info[i].restore_regno = -1; + lra_reg_info[i].val = get_new_reg_value (); + lra_reg_info[i].copies = NULL; +} + /* Initialize common reg info and copies. */ static void init_reg_info (void) @@ -1389,23 +1412,7 @@ init_reg_info (void) reg_info_size = max_reg_num () * 3 / 2 + 1; lra_reg_info = XNEWVEC (struct lra_reg, reg_info_size); for (i = 0; i < reg_info_size; i++) - { - bitmap_initialize (&lra_reg_info[i].insn_bitmap, ®_obstack); -#ifdef STACK_REGS - lra_reg_info[i].no_stack_p = false; -#endif - CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs); - lra_reg_info[i].preferred_hard_regno1 = -1; - lra_reg_info[i].preferred_hard_regno2 = -1; - lra_reg_info[i].preferred_hard_regno_profit1 = 0; - lra_reg_info[i].preferred_hard_regno_profit2 = 0; - lra_reg_info[i].live_ranges = NULL; - lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0; - lra_reg_info[i].last_reload = 0; - lra_reg_info[i].restore_regno = -1; - lra_reg_info[i].val = get_new_reg_value (); - lra_reg_info[i].copies = NULL; - } + initialize_lra_reg_info_element (i); copy_pool = create_alloc_pool ("lra copies", sizeof (struct lra_copy), 100); copy_vec = VEC_alloc (lra_copy_t, heap, 100); @@ -1437,23 +1444,7 @@ expand_reg_info (void) reg_info_size = max_reg_num () * 3 / 2 + 1; lra_reg_info = XRESIZEVEC (struct lra_reg, lra_reg_info, reg_info_size); for (i = old; i < reg_info_size; i++) - { - bitmap_initialize (&lra_reg_info[i].insn_bitmap, ®_obstack); -#ifdef STACK_REGS - lra_reg_info[i].no_stack_p = false; -#endif - CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs); - lra_reg_info[i].preferred_hard_regno1 = -1; - lra_reg_info[i].preferred_hard_regno2 = -1; - lra_reg_info[i].preferred_hard_regno_profit1 = 0; - lra_reg_info[i].preferred_hard_regno_profit2 = 0; - lra_reg_info[i].live_ranges = NULL; - lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0; - lra_reg_info[i].last_reload = 0; - lra_reg_info[i].restore_regno = -1; - lra_reg_info[i].val = get_new_reg_value (); - lra_reg_info[i].copies = NULL; - } + initialize_lra_reg_info_element (i); } /* Free all copies. */ @@ -1551,28 +1542,32 @@ add_regs_to_insn_regno_info (lra_insn_re regno = REGNO (x); expand_reg_info (); if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, uid)) - data->regs = new_insn_reg (regno, type, mode, subreg_p, early_clobber, - data->regs); + { + data->regs = new_insn_reg (regno, type, mode, subreg_p, + early_clobber, data->regs); + return; + } else { for (curr = data->regs; curr != NULL; curr = curr->next) if (curr->regno == regno) - break; - if (curr->subreg_p != subreg_p || curr->biggest_mode != mode) - /* The info can not be integrated into the found - structure. */ - data->regs = new_insn_reg (regno, type, mode, subreg_p, - early_clobber, data->regs); - else - { - if (curr->type != type) - curr->type = OP_INOUT; - if (curr->early_clobber != early_clobber) - curr->early_clobber = true; - } - lra_assert (curr != NULL); + { + if (curr->subreg_p != subreg_p || curr->biggest_mode != mode) + /* The info can not be integrated into the found + structure. */ + data->regs = new_insn_reg (regno, type, mode, subreg_p, + early_clobber, data->regs); + else + { + if (curr->type != type) + curr->type = OP_INOUT; + if (curr->early_clobber != early_clobber) + curr->early_clobber = true; + } + return; + } + gcc_unreachable (); } - return; } switch (code) @@ -2039,13 +2034,7 @@ check_rtl (bool final_p) as legitimate. Although they are legitimate if they satisfies the constraints and will be checked by insn constraints which we ignore here. */ - && GET_CODE (XEXP (op, 0)) != UNSPEC - && GET_CODE (XEXP (op, 0)) != PRE_DEC - && GET_CODE (XEXP (op, 0)) != PRE_INC - && GET_CODE (XEXP (op, 0)) != POST_DEC - && GET_CODE (XEXP (op, 0)) != POST_INC - && GET_CODE (XEXP (op, 0)) != PRE_MODIFY - && GET_CODE (XEXP (op, 0)) != POST_MODIFY) + && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) == RTX_AUTOINC) fatal_insn_not_found (insn); } } @@ -2081,7 +2070,12 @@ has_nonexceptional_receiver (void) bb = *--tos; FOR_EACH_EDGE (e, ei, bb->preds) - if (!(e->flags & EDGE_ABNORMAL)) + if (e->flags & EDGE_ABNORMAL) + { + free (worklist); + return true; + } + else { basic_block src = e->src; @@ -2093,15 +2087,6 @@ has_nonexceptional_receiver (void) } } free (worklist); - - /* Now see if there's a reachable block with an exceptional incoming - edge. */ - FOR_EACH_BB (bb) - if (bb->flags & BB_REACHABLE) - FOR_EACH_EDGE (e, ei, bb->preds) - if (e->flags & EDGE_ABNORMAL) - return true; - /* No exceptional block reached exit unexceptionally. */ return false; } @@ -2141,7 +2126,7 @@ add_auto_inc_notes (rtx insn, rtx x) that can make the notes obsolete. DF-infrastructure does not deal with REG_INC notes -- so we should regenerate them here. */ static void -update_reg_notes (void) +update_inc_notes (void) { rtx *pnote; basic_block bb; @@ -2154,9 +2139,7 @@ update_reg_notes (void) pnote = ®_NOTES (insn); while (*pnote != 0) { - if (REG_NOTE_KIND (*pnote) == REG_DEAD - || REG_NOTE_KIND (*pnote) == REG_UNUSED - || REG_NOTE_KIND (*pnote) == REG_INC) + if (REG_NOTE_KIND (*pnote) == REG_INC) *pnote = XEXP (*pnote, 1); else pnote = &XEXP (*pnote, 1); @@ -2361,7 +2344,7 @@ lra (FILE *f) regstat_free_n_sets_and_refs (); regstat_free_ri (); reload_completed = 1; - update_reg_notes (); + update_inc_notes (); inserted_p = fixup_abnormal_edges (); @@ -2397,7 +2380,7 @@ lra_init_once (void) init_insn_code_data_once (); } -/* Initialize LRA data once per function. */ +/* Initialize LRA whenever register-related information is changed. */ void lra_init (void) { Index: target-globals.c =================================================================== --- target-globals.c (revision 192534) +++ target-globals.c (working copy) @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. #include "libfuncs.h" #include "cfgloop.h" #include "ira-int.h" +#include "lra-int.h" #include "builtins.h" #include "gcse.h" #include "bb-reorder.h" @@ -55,6 +56,7 @@ struct target_globals default_target_glo &default_target_cfgloop, &default_target_ira, &default_target_ira_int, + &default_target_lra_int, &default_target_builtins, &default_target_gcse, &default_target_bb_reorder, Index: target-globals.h =================================================================== --- target-globals.h (revision 192534) +++ target-globals.h (working copy) @@ -32,6 +32,7 @@ extern struct target_libfuncs *this_targ extern struct target_cfgloop *this_target_cfgloop; extern struct target_ira *this_target_ira; extern struct target_ira_int *this_target_ira_int; +extern struct target_lra_int *this_target_lra_int; extern struct target_builtins *this_target_builtins; extern struct target_gcse *this_target_gcse; extern struct target_bb_reorder *this_target_bb_reorder; @@ -49,6 +50,7 @@ struct GTY(()) target_globals { struct target_cfgloop *GTY((skip)) cfgloop; struct target_ira *GTY((skip)) ira; struct target_ira_int *GTY((skip)) ira_int; + struct target_lra_int *GTY((skip)) lra_int; struct target_builtins *GTY((skip)) builtins; struct target_gcse *GTY((skip)) gcse; struct target_bb_reorder *GTY((skip)) bb_reorder; @@ -73,6 +75,7 @@ restore_target_globals (struct target_gl this_target_cfgloop = g->cfgloop; this_target_ira = g->ira; this_target_ira_int = g->ira_int; + this_target_lra_int = g->lra_int; this_target_builtins = g->builtins; this_target_gcse = g->gcse; this_target_bb_reorder = g->bb_reorder;