diff options
author | Ben Cheng <bccheng@google.com> | 2014-03-25 22:37:19 -0700 |
---|---|---|
committer | Ben Cheng <bccheng@google.com> | 2014-03-25 22:37:19 -0700 |
commit | 1bc5aee63eb72b341f506ad058502cd0361f0d10 (patch) | |
tree | c607e8252f3405424ff15bc2d00aa38dadbb2518 /gcc-4.9/gcc/lra-int.h | |
parent | 283a0bf58fcf333c58a2a92c3ebbc41fb9eb1fdb (diff) | |
download | toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.gz toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.bz2 toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.zip |
Initial checkin of GCC 4.9.0 from trunk (r208799).
Change-Id: I48a3c08bb98542aa215912a75f03c0890e497dba
Diffstat (limited to 'gcc-4.9/gcc/lra-int.h')
-rw-r--r-- | gcc-4.9/gcc/lra-int.h | 515 |
1 files changed, 515 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/lra-int.h b/gcc-4.9/gcc/lra-int.h new file mode 100644 index 000000000..b2f5cf7d0 --- /dev/null +++ b/gcc-4.9/gcc/lra-int.h @@ -0,0 +1,515 @@ +/* Local Register Allocator (LRA) intercommunication header file. + Copyright (C) 2010-2014 Free Software Foundation, Inc. + Contributed by Vladimir Makarov <vmakarov@redhat.com>. + +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 +<http://www.gnu.org/licenses/>. */ + +#include "lra.h" +#include "bitmap.h" +#include "recog.h" +#include "insn-attr.h" +#include "insn-codes.h" +#include "insn-config.h" +#include "regs.h" + +#define lra_assert(c) gcc_checking_assert (c) + +/* 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) + +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; + /* Offset from relative eliminate register to pesudo reg. */ + int offset; + /* 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 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; + /* SP offset before the insn relative to one at the func start. */ + HOST_WIDE_INT sp_offset; + /* 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; + /* Alternative enabled for the insn. NULL for debug insns. */ + bool *alternative_enabled_p; + /* 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; + +/* Whether the clobber is used temporary in LRA. */ +#define LRA_TEMP_CLOBBER_P(x) \ + (RTL_FLAG_CHECK1 ("TEMP_CLOBBER_P", (x), CLOBBER)->unchanging) + +/* Cost factor for each additional reload and maximal cost reject for + insn reloads. One might ask about such strange numbers. Their + values occurred historically from former reload pass. */ +#define LRA_LOSER_COST_FACTOR 6 +#define LRA_MAX_REJECT 600 + +/* Maximum allowed number of constraint pass iterations after the last + spill pass. It is for preventing LRA cycling in a bug case. */ +#define LRA_MAX_CONSTRAINT_ITERATION_NUMBER 30 + +/* The maximal number of inheritance/split passes in LRA. It should + be more 1 in order to perform caller saves transformations and much + less MAX_CONSTRAINT_ITERATION_NUMBER to prevent LRA to do as many + as permitted constraint passes in some complicated cases. The + first inheritance/split pass has a biggest impact on generated code + quality. Each subsequent affects generated code in less degree. + For example, the 3rd pass does not change generated SPEC2000 code + at all on x86-64. */ +#define LRA_MAX_INHERITANCE_PASSES 2 + +#if LRA_MAX_INHERITANCE_PASSES <= 0 \ + || LRA_MAX_INHERITANCE_PASSES >= LRA_MAX_CONSTRAINT_ITERATION_NUMBER - 8 +#error wrong LRA_MAX_INHERITANCE_PASSES value +#endif + +/* 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_new_regno_start; +extern int lra_constraint_new_regno_start; +extern bitmap_head lra_inheritance_pseudos; +extern bitmap_head lra_split_regs; +extern bitmap_head lra_subreg_reload_pseudos; +extern bitmap_head lra_optional_reload_pseudos; +extern int lra_constraint_new_insn_uid_start; + +/* lra-constraints.c: */ + +extern void lra_init_equiv (void); +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 debug (lra_live_range &ref); +extern void debug (lra_live_range *ptr); +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_final_code_change (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, rtx, enum machine_mode, bool, bool, bool); +extern void lra_eliminate (bool, bool); + +extern void lra_eliminate_reg_if_possible (rtx *); + + + +/* 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]; +} + +/* Change class of pseudo REGNO to NEW_CLASS. Print info about it + using TITLE. Output a new line if NL_P. */ +static void inline +lra_change_class (int regno, enum reg_class new_class, + const char *title, bool nl_p) +{ + lra_assert (regno >= FIRST_PSEUDO_REGISTER); + if (lra_dump_file != NULL) + fprintf (lra_dump_file, "%s class %s for r%d", + title, reg_class_names[new_class], regno); + setup_reg_classes (regno, new_class, NO_REGS, new_class); + if (lra_dump_file != NULL && nl_p) + fprintf (lra_dump_file, "\n"); +} + +/* 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); +} + +/* Update offset from pseudos with VAL by INCR. */ +static inline void +lra_update_reg_val_offset (int val, int incr) +{ + int i; + + for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++) + { + if (lra_reg_info[i].val == val) + lra_reg_info[i].offset += incr; + } +} + +/* Return true if register content is equal to VAL with OFFSET. */ +static inline bool +lra_reg_val_equal_p (int regno, int val, int offset) +{ + if (lra_reg_info[regno].val == val + && lra_reg_info[regno].offset == offset) + return true; + + return false; +} + +/* Assign value of register FROM to TO. */ +static inline void +lra_assign_reg_val (int from, int to) +{ + lra_reg_info[to].val = lra_reg_info[from].val; + lra_reg_info[to].offset = lra_reg_info[from].offset; +} + + +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) |