/* Local Register Allocator (LRA) intercommunication header file.
- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+ Copyright (C) 2010-2015 Free Software Foundation, Inc.
Contributed by Vladimir Makarov <vmakarov@redhat.com>.
This file is part of GCC.
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#ifndef GCC_LRA_INT_H
+#define GCC_LRA_INT_H
+
#include "lra.h"
#include "bitmap.h"
#include "recog.h"
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.
lra_live_range_t next;
/* Pointer to structures with the same start. */
lra_live_range_t start_next;
+
+ /* Pool allocation new operator. */
+ inline void *operator new (size_t)
+ {
+ return pool.allocate ();
+ }
+
+ /* Delete operator utilizing pool allocation. */
+ inline void operator delete (void *ptr)
+ {
+ pool.remove ((lra_live_range *) ptr);
+ }
+
+ /* Memory allocation pool. */
+ static pool_allocator<lra_live_range> pool;
};
typedef struct lra_copy *lra_copy_t;
int regno1, regno2;
/* Next copy with correspondingly REGNO1 and REGNO2. */
lra_copy_t regno1_next, regno2_next;
+
+ /* Pool allocation new operator. */
+ inline void *operator new (size_t)
+ {
+ return pool.allocate ();
+ }
+
+ /* Delete operator utilizing pool allocation. */
+ inline void operator delete (void *ptr)
+ {
+ pool.remove ((lra_copy *) ptr);
+ }
+
+ /* Memory allocation pool. */
+ static pool_allocator<lra_copy> pool;
+
};
/* Common info about a register (pseudo or hard register). */
/* The following fields are defined only for pseudos. */
/* Hard registers with which the pseudo conflicts. */
HARD_REG_SET conflict_hard_regs;
+ /* Call used registers with which the pseudo conflicts, taking into account
+ the registers used by functions called from calls which cross the
+ pseudo. */
+ HARD_REG_SET actual_call_used_reg_set;
/* 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
/* 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;
+ 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
int regno;
/* Next reg info of the same insn. */
struct lra_insn_reg *next;
+
+ /* Pool allocation new operator. */
+ inline void *operator new (size_t)
+ {
+ return pool.allocate ();
+ }
+
+ /* Delete operator utilizing pool allocation. */
+ inline void operator delete (void *ptr)
+ {
+ pool.remove ((lra_insn_reg *) ptr);
+ }
+
+ /* Memory allocation pool. */
+ static pool_allocator<lra_insn_reg> pool;
};
/* Static part (common info for insns with the same ICODE) of LRA
/* 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;
+ const struct operand_alternative *operand_alternative;
};
/* LRA internal info about an insn (LRA internal insn
{
/* 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;
+ rtx_insn *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;
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 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;
+ /* Cached value of get_preferred_alternatives. */
+ alternative_mask preferred_alternatives;
/* The following member value is always NULL for a debug insn. */
struct lra_insn_reg *regs;
};
#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
+/* Maximum allowed number of assignment pass iterations after the
+ latest spill pass when any former reload pseudo was spilled. It is
+ for preventing LRA cycling in a bug case. */
+#define LRA_MAX_ASSIGNMENT_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
#define LRA_MAX_INHERITANCE_PASSES 2
#if LRA_MAX_INHERITANCE_PASSES <= 0 \
- || LRA_MAX_INHERITANCE_PASSES >= LRA_MAX_CONSTRAINT_ITERATION_NUMBER - 8
+ || LRA_MAX_INHERITANCE_PASSES >= LRA_MAX_ASSIGNMENT_ITERATION_NUMBER - 8
#error wrong LRA_MAX_INHERITANCE_PASSES value
#endif
+/* Analogous macro to the above one but for rematerialization. */
+#define LRA_MAX_REMATERIALIZATION_PASSES 2
+
+#if LRA_MAX_REMATERIALIZATION_PASSES <= 0 \
+ || LRA_MAX_REMATERIALIZATION_PASSES >= LRA_MAX_ASSIGNMENT_ITERATION_NUMBER - 8
+#error wrong LRA_MAX_REMATERIALIZATION_PASSES value
+#endif
+
/* lra.c: */
extern FILE *lra_dump_file;
extern int lra_curr_reload_num;
-extern void lra_push_insn (rtx);
+extern void lra_dump_bitmap_with_title (const char *, bitmap, int);
+extern void lra_push_insn (rtx_insn *);
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 void lra_push_insn_and_update_insn_regno_info (rtx_insn *);
+extern rtx_insn *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,
+extern rtx lra_create_new_reg_with_unique_value (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_invalidate_insn_data (rtx_insn *);
+extern void lra_set_insn_deleted (rtx_insn *);
+extern void lra_delete_dead_insn (rtx_insn *);
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 void lra_process_new_insns (rtx_insn *, rtx_insn *, rtx_insn *,
+ const char *);
+
+extern bool lra_substitute_pseudo (rtx *, int, rtx);
+extern bool lra_substitute_pseudo_within_insn (rtx_insn *, int, rtx);
-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 lra_insn_recog_data_t lra_set_insn_recog_data (rtx_insn *);
+extern lra_insn_recog_data_t lra_update_insn_recog_data (rtx_insn *);
+extern void lra_set_used_insn_alternative (rtx_insn *, 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 void lra_invalidate_insn_regno_info (rtx_insn *);
+extern void lra_update_insn_regno_info (rtx_insn *);
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 bool lra_former_scratch_operand_p (rtx_insn *, int);
+extern void lra_register_new_scratch_op (rtx_insn *, int);
extern int lra_new_regno_start;
extern int lra_constraint_new_regno_start;
+extern int lra_bad_spill_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 int lra_constraint_offset (int, enum machine_mode);
+extern void lra_init_equiv (void);
+extern int lra_constraint_offset (int, 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_constrain_insn (rtx_insn *);
extern bool lra_constraints (bool);
extern void lra_constraints_init (void);
extern void lra_constraints_finish (void);
extern int lra_hard_reg_usage[FIRST_PSEUDO_REGISTER];
extern int lra_live_range_iter;
-extern void lra_create_live_ranges (bool);
+extern void lra_create_live_ranges (bool, 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);
/* lra-assigns.c: */
+extern int lra_assignment_iter;
+extern int lra_assignment_iter_after_spill;
extern void lra_setup_reg_renumber (int, int, bool);
extern bool lra_assign (void);
extern void lra_spill (void);
extern void lra_final_code_change (void);
+/* lra-remat.c: */
+
+extern int lra_rematerialization_iter;
+extern bool lra_remat (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 rtx lra_eliminate_regs_1 (rtx_insn *, rtx, machine_mode,
+ bool, bool, HOST_WIDE_INT, bool);
+extern void eliminate_regs_in_insn (rtx_insn *insn, bool, bool, HOST_WIDE_INT);
+extern void lra_eliminate (bool, bool);
extern void lra_eliminate_reg_if_possible (rtx *);
\f
+/* 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
/* 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_get_insn_recog_data (rtx_insn *insn)
{
lra_insn_recog_data_t data;
unsigned int uid = INSN_UID (insn);
return lra_set_insn_recog_data (insn);
}
-\f
+/* 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;
+ }
+}
-struct target_lra_int
+/* 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)
{
- /* 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];
-};
+ if (lra_reg_info[regno].val == val
+ && lra_reg_info[regno].offset == offset)
+ return true;
-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
+ 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;
+}
-#define op_alt_data (this_target_lra_int->x_op_alt_data)
+#endif /* GCC_LRA_INT_H */