From c6a6cdaaea571860c94f9a9fe0f98c597fef7c81 Mon Sep 17 00:00:00 2001 From: vmakarov Date: Tue, 23 Oct 2012 15:51:41 +0000 Subject: 2012-10-23 Vladimir Makarov MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * dbxout.c (dbxout_symbol_location): Pass new argument to alter_subreg. * dwarf2out.c: Include ira.h and lra.h. (based_loc_descr, compute_frame_pointer_to_fb_displacement): Use lra_eliminate_regs for LRA instead of eliminate_regs. * expr.c (emit_move_insn_1): Pass an additional argument to emit_move_via_integer. Use emit_move_via_integer for LRA only if the insn is recognized. * emit-rtl.c (gen_rtx_REG): Add lra_in_progress. (validate_subreg): Don't check offset for LRA and floating point modes. * final.c (final_scan_insn, cleanup_subreg_operands): Pass new argument to alter_subreg. (walk_alter_subreg, output_operand): Ditto. (alter_subreg): Add new argument. * gcse.c (calculate_bb_reg_pressure): Add parameter to ira_setup_eliminable_regset call. * ira.c: Include lra.h. (ira_init_once, ira_init, ira_finish_once): Call lra_start_once, lra_init, lra_finish_once in anyway. (ira_setup_eliminable_regset): Add parameter. Remove need_fp. Call lra_init_elimination and mark HARD_FRAME_POINTER_REGNUM as living forever if frame_pointer_needed. (setup_reg_class_relations): Set up ira_reg_class_subset. (ira_reg_equiv_invariant_p, ira_reg_equiv_const): Remove. (find_reg_equiv_invariant_const): Ditto. (setup_reg_renumber): Use ira_equiv_no_lvalue_p instead of ira_reg_equiv_invariant_p. Skip caps for LRA. (setup_reg_equiv_init, ira_update_equiv_info_by_shuffle_insn): New functions. (ira_reg_equiv_len, ira_reg_equiv): New externals. (ira_reg_equiv): New. (ira_expand_reg_equiv, init_reg_equiv, finish_reg_equiv): New functions. (no_equiv, update_equiv_regs): Use ira_reg_equiv instead of reg_equiv_init. (setup_reg_equiv): New function. (ira_use_lra_p): New global. (ira): Set up lra_simple_p and ira_conflicts_p. Set up and restore flag_caller_saves and flag_ira_region. Move initialization of ira_obstack and ira_bitmap_obstack upper. Call init_reg_equiv, setup_reg_equiv, and setup_reg_equiv_init instead of initialization of ira_reg_equiv_len, ira_reg_equiv_invariant_p, and ira_reg_equiv_const. Call ira_setup_eliminable_regset with a new argument. Don't flatten IRA IRA for LRA. Don't reassign conflict allocnos for LRA. Call finish_reg_equiv. (do_reload): Prepare code for LRA call. Call LRA. * ira.h (ira_use_lra_p): New external. (struct target_ira): Add members x_ira_class_subset_p x_ira_reg_class_subset, and x_ira_reg_classes_intersect_p. (ira_class_subset_p, ira_reg_class_subset): New macros. (ira_reg_classes_intersect_p): New macro. (struct ira_reg_equiv): New. (ira_setup_eliminable_regset): Add an argument. (ira_expand_reg_equiv, ira_update_equiv_info_by_shuffle_insn): New prototypes. * ira-color.c (color_pass, move_spill_restore, coalesce_allocnos): Use ira_equiv_no_lvalue_p. (coalesce_spill_slots, ira_sort_regnos_for_alter_reg): Ditto. * ira-emit.c (ira_create_new_reg): Call ira_expand_reg_equiv. (generate_edge_moves, change_loop) Use ira_equiv_no_lvalue_p. (emit_move_list): Simplify code. Call ira_update_equiv_info_by_shuffle_insn. Use ira_reg_equiv instead of ira_reg_equiv_invariant_p and ira_reg_equiv_const. Change assert. * ira-int.h (struct target_ira_int): Remove x_ira_class_subset_p and x_ira_reg_classes_intersect_p. (ira_class_subset_p, ira_reg_classes_intersect_p): Remove. (ira_reg_equiv_len, ira_reg_equiv_invariant_p): Ditto. (ira_reg_equiv_const): Ditto. (ira_equiv_no_lvalue_p): New function. * jump.c (true_regnum): Always use hard_regno for subreg_get_info when lra is in progress. * haifa-sched.c (sched_init): Pass new argument to ira_setup_eliminable_regset. * loop-invariant.c (calculate_loop_reg_pressure): Pass new argument to ira_setup_eliminable_regset. * lra.h: New. * lra-int.h: Ditto. * lra.c: Ditto. * lra-assigns.c: Ditto. * lra-constraints.c: Ditto. * lra-coalesce.c: Ditto. * lra-eliminations.c: Ditto. * lra-lives.c: Ditto. * lra-spills.c: Ditto. * Makefile.in (LRA_INT_H): New. (OBJS): Add lra.o, lra-assigns.o, lra-coalesce.o, lra-constraints.o, lra-eliminations.o, lra-lives.o, and lra-spills.o. (dwarf2out.o): Add dependence on ira.h and lra.h. (ira.o): Add dependence on lra.h. (lra.o, lra-assigns.o, lra-coalesce.o, lra-constraints.o): New entries. (lra-eliminations.o, lra-lives.o, lra-spills.o): Ditto. * output.h (alter_subreg): Add new argument. * rtlanal.c (simplify_subreg_regno): Permit mode changes for LRA. Permit ARG_POINTER_REGNUM and STACK_POINTER_REGNUM for LRA. * recog.c (general_operand, register_operand): Accept paradoxical FLOAT_MODE subregs for LRA. (scratch_operand): Accept pseudos for LRA. * rtl.h (lra_in_progress): New external. (debug_bb_n_slim, debug_bb_slim, print_value_slim): New prototypes. (debug_rtl_slim, debug_insn_slim): Ditto. * sdbout.c (sdbout_symbol): Pass new argument to alter_subreg. * sched-vis.c (print_value_slim): New. * target.def (lra_p): New hook. (register_priority): Ditto. (different_addr_displacement_p): Ditto. (spill_class): 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. * targhooks.c (default_lra_p): New function. (default_register_priority): Ditto. (default_different_addr_displacement_p): Ditto. * targhooks.h (default_lra_p): Declare. (default_register_priority): Ditto. (default_different_addr_displacement_p): Ditto. * timevar.def (TV_LRA, TV_LRA_ELIMINATE, TV_LRA_INHERITANCE): New. (TV_LRA_CREATE_LIVE_RANGES, TV_LRA_ASSIGN, TV_LRA_COALESCE): New. * config/arm/arm.c (load_multiple_sequence): Pass new argument toOB alter_subreg. (store_multiple_sequence): Ditto. * config/i386/i386.h (enum ix86_tune_indices): Add X86_TUNE_GENERAL_REGS_SSE_SPILL. (TARGET_GENERAL_REGS_SSE_SPILL): New macro. * config/i386/i386.c (initial_ix86_tune_features): Set up X86_TUNE_GENERAL_REGS_SSE_SPILL for m_COREI7 and m_CORE2I7. (ix86_lra_p, ix86_register_priority): New functions. (ix86_secondary_reload): Add NON_Q_REGS, SIREG, DIREG. (inline_secondary_memory_needed): Change assert. (ix86_spill_class): New function. (TARGET_LRA_P, TARGET_REGISTER_BANK, TARGET_SPILL_CLASS): New macros. * config/m68k/m68k.c (emit_move_sequence): Pass new argument to alter_subreg. * config/m32r/m32r.c (gen_split_move_double): Ditto. * config/pa/pa.c (pa_emit_move_sequence): Ditto. * config/sh/sh.md: Ditto. * config/v850/v850.c (v850_reorg): Ditto. * config/xtensa/xtensa.c (fixup_subreg_mem): Ditto. * doc/md.texi: Add new interpretation of hint * for LRA. * doc/passes.texi: Describe LRA pass. * doc/tm.texi.in: Add TARGET_LRA_P, TARGET_REGISTER_PRIORITY, TARGET_DIFFERENT_ADDR_DISPLACEMENT_P, and TARGET_SPILL_CLASS. * doc/tm.texi: Update. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@192719 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/lra-int.h | 438 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 438 insertions(+) create mode 100644 gcc/lra-int.h (limited to 'gcc/lra-int.h') diff --git a/gcc/lra-int.h b/gcc/lra-int.h new file mode 100644 index 00000000000..d00cc12feff --- /dev/null +++ b/gcc/lra-int.h @@ -0,0 +1,438 @@ +/* Local Register Allocator (LRA) intercommunication header file. + Copyright (C) 2010, 2011, 2012 + Free Software Foundation, Inc. + Contributed by Vladimir Makarov . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#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) +#else +/* Always define and include C, so that warnings for empty body in an + ‘if’ statement and unused variable do not occur. */ +#define lra_assert(c) ((void)(0 && (c))) +#endif + +/* The parameter used to prevent infinite reloading for an insn. Each + insn operands might require a reload and, if it is a memory, its + base and index registers might require a reload too. */ +#define LRA_MAX_INSN_RELOADS (MAX_RECOG_OPERANDS * 3) + +/* Return the hard register which given pseudo REGNO assigned to. + Negative value means that the register got memory or we don't know + allocation yet. */ +static inline int +lra_get_regno_hard_regno (int regno) +{ + resize_reg_info (); + return reg_renumber[regno]; +} + +typedef struct lra_live_range *lra_live_range_t; + +/* The structure describes program points where a given pseudo lives. + The live ranges can be used to find conflicts with other pseudos. + If the live ranges of two pseudos are intersected, the pseudos are + in conflict. */ +struct lra_live_range +{ + /* Pseudo regno whose live range is described by given + structure. */ + int regno; + /* Program point range. */ + int start, finish; + /* Next structure describing program points where the pseudo + lives. */ + lra_live_range_t next; + /* Pointer to structures with the same start. */ + lra_live_range_t start_next; +}; + +typedef struct lra_copy *lra_copy_t; + +/* Copy between pseudos which affects assigning hard registers. */ +struct lra_copy +{ + /* True if regno1 is the destination of the copy. */ + bool regno1_dest_p; + /* Execution frequency of the copy. */ + int freq; + /* Pseudos connected by the copy. REGNO1 < REGNO2. */ + int regno1, regno2; + /* Next copy with correspondingly REGNO1 and REGNO2. */ + lra_copy_t regno1_next, regno2_next; +}; + +/* Common info about a register (pseudo or hard register). */ +struct lra_reg +{ + /* Bitmap of UIDs of insns (including debug insns) referring the + reg. */ + bitmap_head insn_bitmap; + /* The following fields are defined only for pseudos. */ + /* Hard registers with which the pseudo conflicts. */ + HARD_REG_SET conflict_hard_regs; + /* We assign hard registers to reload pseudos which can occur in few + places. So two hard register preferences are enough for them. + The following fields define the preferred hard registers. If + there are no such hard registers the first field value is + negative. If there is only one preferred hard register, the 2nd + field is negative. */ + int preferred_hard_regno1, preferred_hard_regno2; + /* Profits to use the corresponding preferred hard registers. If + the both hard registers defined, the first hard register has not + less profit than the second one. */ + int preferred_hard_regno_profit1, preferred_hard_regno_profit2; +#ifdef STACK_REGS + /* True if the pseudo should not be assigned to a stack register. */ + bool no_stack_p; +#endif +#ifdef ENABLE_CHECKING + /* True if the pseudo crosses a call. It is setup in lra-lives.c + and used to check that the pseudo crossing a call did not get a + call used hard register. */ + bool call_p; +#endif + /* Number of references and execution frequencies of the register in + *non-debug* insns. */ + int nrefs, freq; + int last_reload; + /* Regno used to undo the inheritance. It can be non-zero only + between couple of inheritance and undo inheritance passes. */ + int restore_regno; + /* Value holding by register. If the pseudos have the same value + they do not conflict. */ + int val; + /* These members are set up in lra-lives.c and updated in + lra-coalesce.c. */ + /* The biggest size mode in which each pseudo reg is referred in + whole function (possibly via subreg). */ + enum machine_mode biggest_mode; + /* Live ranges of the pseudo. */ + lra_live_range_t live_ranges; + /* This member is set up in lra-lives.c for subsequent + assignments. */ + lra_copy_t copies; +}; + +/* References to the common info about each register. */ +extern struct lra_reg *lra_reg_info; + +/* Static info about each insn operand (common for all insns with the + same ICODE). Warning: if the structure definition is changed, the + initializer for debug_operand_data in lra.c should be changed + too. */ +struct lra_operand_data +{ + /* The machine description constraint string of the operand. */ + const char *constraint; + /* It is taken only from machine description (which is different + from recog_data.operand_mode) and can be of VOIDmode. */ + ENUM_BITFIELD(machine_mode) mode : 16; + /* The type of the operand (in/out/inout). */ + ENUM_BITFIELD (op_type) type : 8; + /* Through if accessed through STRICT_LOW. */ + unsigned int strict_low : 1; + /* True if the operand is an operator. */ + unsigned int is_operator : 1; + /* True if there is an early clobber alternative for this operand. + This field is set up every time when corresponding + operand_alternative in lra_static_insn_data is set up. */ + unsigned int early_clobber : 1; + /* True if the operand is an address. */ + unsigned int is_address : 1; +}; + +/* Info about register occurrence in an insn. */ +struct lra_insn_reg +{ + /* The biggest mode through which the insn refers to the register + 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; + /* True if the reg is accessed through a subreg and the subreg is + just a part of the register. */ + unsigned int subreg_p : 1; + /* True if there is an early clobber alternative for this + operand. */ + unsigned int early_clobber : 1; + /* The corresponding regno of the register. */ + int regno; + /* Next reg info of the same insn. */ + struct lra_insn_reg *next; +}; + +/* 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. 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. */ + struct lra_operand_data *operand; + /* Each duplication refers to the number of the corresponding + operand which is duplicated. */ + int *dup_num; + /* The number of an operand marked as commutative, -1 otherwise. */ + int commutative; + /* Number of operands, duplications, and alternatives of the + insn. */ + char n_operands; + char n_dups; + char n_alternatives; + /* Insns in machine description (or clobbers in asm) may contain + explicit hard regs which are not operands. The following list + describes such hard registers. */ + struct lra_insn_reg *hard_regs; + /* Array [n_alternatives][n_operand] of static constraint info for + given operand in given alternative. This info can be changed if + the target reg info is changed. */ + struct operand_alternative *operand_alternative; +}; + +/* LRA internal info about an insn (LRA internal insn + representation). */ +struct lra_insn_recog_data +{ + /* 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: */ + rtx **operand_loc; /* The operand locations, NULL if no operands. */ + rtx **dup_loc; /* The dup locations, NULL if no dups. */ + /* Number of hard registers implicitly used in given call insn. The + value can be NULL or points to array of the hard register numbers + ending with a negative value. */ + int *arg_hard_regs; +#ifdef HAVE_ATTR_enabled + /* Alternative enabled for the insn. NULL for debug insns. */ + bool *alternative_enabled_p; +#endif + /* The alternative should be used for the insn, -1 if invalid, or we + should try to use any alternative, or the insn is a debug + insn. */ + int used_insn_alternative; + /* 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; + +/* lra.c: */ + +extern FILE *lra_dump_file; + +extern bool lra_reg_spill_p; + +extern HARD_REG_SET lra_no_alloc_regs; + +extern int lra_insn_recog_data_len; +extern lra_insn_recog_data_t *lra_insn_recog_data; + +extern int lra_curr_reload_num; + +extern void lra_push_insn (rtx); +extern void lra_push_insn_by_uid (unsigned int); +extern void lra_push_insn_and_update_insn_regno_info (rtx); +extern rtx lra_pop_insn (void); +extern unsigned int lra_insn_stack_length (void); + +extern rtx lra_create_new_reg_with_unique_value (enum machine_mode, rtx, + enum reg_class, const char *); +extern void lra_set_regno_unique_value (int); +extern void lra_invalidate_insn_data (rtx); +extern void lra_set_insn_deleted (rtx); +extern void lra_delete_dead_insn (rtx); +extern void lra_emit_add (rtx, rtx, rtx); +extern void lra_emit_move (rtx, rtx); +extern void lra_update_dups (lra_insn_recog_data_t, signed char *); + +extern void lra_process_new_insns (rtx, rtx, rtx, const char *); + +extern lra_insn_recog_data_t lra_set_insn_recog_data (rtx); +extern lra_insn_recog_data_t lra_update_insn_recog_data (rtx); +extern void lra_set_used_insn_alternative (rtx, int); +extern void lra_set_used_insn_alternative_by_uid (int, int); + +extern void lra_invalidate_insn_regno_info (rtx); +extern void lra_update_insn_regno_info (rtx); +extern struct lra_insn_reg *lra_get_insn_regs (int); + +extern void lra_free_copies (void); +extern void lra_create_copy (int, int, int); +extern lra_copy_t lra_get_copy (int); +extern bool lra_former_scratch_p (int); +extern bool lra_former_scratch_operand_p (rtx, int); + +extern int lra_constraint_new_regno_start; +extern bitmap_head lra_inheritance_pseudos; +extern bitmap_head lra_split_regs; +extern bitmap_head lra_optional_reload_pseudos; +extern int lra_constraint_new_insn_uid_start; + +/* lra-constraints.c: */ + +extern int lra_constraint_offset (int, enum machine_mode); + +extern int lra_constraint_iter; +extern int lra_constraint_iter_after_spill; +extern bool lra_risky_transformations_p; +extern int lra_inheritance_iter; +extern int lra_undo_inheritance_iter; +extern bool lra_constraints (bool); +extern void lra_constraints_init (void); +extern void lra_constraints_finish (void); +extern void lra_inheritance (void); +extern bool lra_undo_inheritance (void); + +/* lra-lives.c: */ + +extern int lra_live_max_point; +extern int *lra_point_freq; + +extern int lra_hard_reg_usage[FIRST_PSEUDO_REGISTER]; + +extern int lra_live_range_iter; +extern void lra_create_live_ranges (bool); +extern lra_live_range_t lra_copy_live_range_list (lra_live_range_t); +extern lra_live_range_t lra_merge_live_ranges (lra_live_range_t, + lra_live_range_t); +extern bool lra_intersected_live_ranges_p (lra_live_range_t, + lra_live_range_t); +extern void lra_print_live_range_list (FILE *, lra_live_range_t); +extern void lra_debug_live_range_list (lra_live_range_t); +extern void lra_debug_pseudo_live_ranges (int); +extern void lra_debug_live_ranges (void); +extern void lra_clear_live_ranges (void); +extern void lra_live_ranges_init (void); +extern void lra_live_ranges_finish (void); +extern void lra_setup_reload_pseudo_preferenced_hard_reg (int, int, int); + +/* lra-assigns.c: */ + +extern void lra_setup_reg_renumber (int, int, bool); +extern bool lra_assign (void); + + +/* lra-coalesce.c: */ + +extern int lra_coalesce_iter; +extern bool lra_coalesce (void); + +/* lra-spills.c: */ + +extern bool lra_need_for_spills_p (void); +extern void lra_spill (void); +extern void lra_hard_reg_substitution (void); + + +/* lra-elimination.c: */ + +extern void lra_debug_elim_table (void); +extern int lra_get_elimination_hard_regno (int); +extern rtx lra_eliminate_regs_1 (rtx, enum machine_mode, bool, bool, bool); +extern void lra_eliminate (bool); + +extern void lra_eliminate_reg_if_possible (rtx *); + + + +/* Update insn operands which are duplication of NOP operand. The + insn is represented by its LRA internal representation ID. */ +static inline void +lra_update_dup (lra_insn_recog_data_t id, int nop) +{ + int i; + struct lra_static_insn_data *static_id = id->insn_static_data; + + for (i = 0; i < static_id->n_dups; i++) + if (static_id->dup_num[i] == nop) + *id->dup_loc[i] = *id->operand_loc[nop]; +} + +/* Process operator duplications in insn with ID. We do it after the + operands processing. Generally speaking, we could do this probably + simultaneously with operands processing because a common practice + is to enumerate the operators after their operands. */ +static inline void +lra_update_operator_dups (lra_insn_recog_data_t id) +{ + int i; + struct lra_static_insn_data *static_id = id->insn_static_data; + + for (i = 0; i < static_id->n_dups; i++) + { + int ndup = static_id->dup_num[i]; + + if (static_id->operand[ndup].is_operator) + *id->dup_loc[i] = *id->operand_loc[ndup]; + } +} + +/* Return info about INSN. Set up the info if it is not done yet. */ +static inline lra_insn_recog_data_t +lra_get_insn_recog_data (rtx insn) +{ + lra_insn_recog_data_t data; + unsigned int uid = INSN_UID (insn); + + if (lra_insn_recog_data_len > (int) uid + && (data = lra_insn_recog_data[uid]) != NULL) + { + /* Check that we did not change insn without updating the insn + info. */ + lra_assert (data->insn == insn + && (INSN_CODE (insn) < 0 + || data->icode == INSN_CODE (insn))); + return data; + } + 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) -- cgit v1.2.1