IA MCU psABI support: changes to libraries
[gcc.git] / gcc / lra-int.h
index 98f2ff709b756952c00a490887717662d837bf1f..25bd3cefd818bb0eaca035f93f402008182c1bd4 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
@@ -18,11 +18,16 @@ 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/>.         */
 
+#ifndef GCC_LRA_INT_H
+#define GCC_LRA_INT_H
+
 #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)
 
@@ -31,16 +36,6 @@ along with GCC; see the file COPYING3.       If not see
    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.
@@ -59,6 +54,21 @@ struct lra_live_range
   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;
@@ -74,6 +84,22 @@ struct lra_copy
   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).  */
@@ -85,6 +111,10 @@ struct lra_reg
   /* 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
@@ -116,11 +146,13 @@ struct lra_reg
   /* 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
@@ -175,6 +207,21 @@ struct lra_insn_reg
   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
@@ -204,7 +251,7 @@ struct lra_static_insn_data
   /* 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
@@ -213,8 +260,14 @@ 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;
+  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;
@@ -226,12 +279,8 @@ struct lra_insn_recog_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;
 };
@@ -248,9 +297,10 @@ typedef struct lra_insn_recog_data *lra_insn_recog_data_t;
 #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
@@ -263,10 +313,18 @@ typedef struct lra_insn_recog_data *lra_insn_recog_data_t;
 #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;
@@ -280,55 +338,63 @@ 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_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);
@@ -343,13 +409,15 @@ 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 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);
 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);
@@ -360,6 +428,8 @@ extern void lra_setup_reload_pseudo_preferenced_hard_reg (int, int, int);
 
 /* 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);
 
@@ -375,18 +445,49 @@ extern bool lra_need_for_spills_p (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
@@ -421,7 +522,7 @@ lra_update_operator_dups (lra_insn_recog_data_t id)
 
 /* 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);
@@ -439,21 +540,36 @@ lra_get_insn_recog_data (rtx 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 */