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  <vmaka...@redhat.com>

    * 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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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 = &REG_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;

Reply via email to