OSDN Git Service

PR c++/48930
[pf3gnuchains/gcc-fork.git] / gcc / ira-conflicts.c
index c75069d..be00283 100644 (file)
@@ -33,7 +33,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "insn-config.h"
 #include "recog.h"
 #include "diagnostic-core.h"
 #include "insn-config.h"
 #include "recog.h"
 #include "diagnostic-core.h"
-#include "toplev.h"
 #include "params.h"
 #include "df.h"
 #include "sparseset.h"
 #include "params.h"
 #include "df.h"
 #include "sparseset.h"
@@ -48,11 +47,11 @@ along with GCC; see the file COPYING3.  If not see
    allocno's conflict (can't go in the same hardware register).
 
    Some arrays will be used as conflict bit vector of the
    allocno's conflict (can't go in the same hardware register).
 
    Some arrays will be used as conflict bit vector of the
-   corresponding allocnos see function build_allocno_conflicts.  */
+   corresponding allocnos see function build_object_conflicts.  */
 static IRA_INT_TYPE **conflicts;
 
 /* Macro to test a conflict of C1 and C2 in `conflicts'.  */
 static IRA_INT_TYPE **conflicts;
 
 /* Macro to test a conflict of C1 and C2 in `conflicts'.  */
-#define OBJECTS_CONFLICT_P(C1, C2)                             \
+#define OBJECTS_CONFLICT_P(C1, C2)                                     \
   (OBJECT_MIN (C1) <= OBJECT_CONFLICT_ID (C2)                          \
    && OBJECT_CONFLICT_ID (C2) <= OBJECT_MAX (C1)                       \
    && TEST_MINMAX_SET_BIT (conflicts[OBJECT_CONFLICT_ID (C1)],         \
   (OBJECT_MIN (C1) <= OBJECT_CONFLICT_ID (C2)                          \
    && OBJECT_CONFLICT_ID (C2) <= OBJECT_MAX (C1)                       \
    && TEST_MINMAX_SET_BIT (conflicts[OBJECT_CONFLICT_ID (C1)],         \
@@ -60,6 +59,36 @@ static IRA_INT_TYPE **conflicts;
                           OBJECT_MIN (C1), OBJECT_MAX (C1)))
 
 \f
                           OBJECT_MIN (C1), OBJECT_MAX (C1)))
 
 \f
+/* Record a conflict between objects OBJ1 and OBJ2.  If necessary,
+   canonicalize the conflict by recording it for lower-order subobjects
+   of the corresponding allocnos. */
+static void
+record_object_conflict (ira_object_t obj1, ira_object_t obj2)
+{
+  ira_allocno_t a1 = OBJECT_ALLOCNO (obj1);
+  ira_allocno_t a2 = OBJECT_ALLOCNO (obj2);
+  int w1 = OBJECT_SUBWORD (obj1);
+  int w2 = OBJECT_SUBWORD (obj2);
+  int id1, id2;
+
+  /* Canonicalize the conflict.  If two identically-numbered words
+     conflict, always record this as a conflict between words 0.  That
+     is the only information we need, and it is easier to test for if
+     it is collected in each allocno's lowest-order object.  */
+  if (w1 == w2 && w1 > 0)
+    {
+      obj1 = ALLOCNO_OBJECT (a1, 0);
+      obj2 = ALLOCNO_OBJECT (a2, 0);
+    }
+  id1 = OBJECT_CONFLICT_ID (obj1);
+  id2 = OBJECT_CONFLICT_ID (obj2);
+
+  SET_MINMAX_SET_BIT (conflicts[id1], id2, OBJECT_MIN (obj1),
+                     OBJECT_MAX (obj1));
+  SET_MINMAX_SET_BIT (conflicts[id2], id1, OBJECT_MIN (obj2),
+                     OBJECT_MAX (obj2));
+}
+
 /* Build allocno conflict table by processing allocno live ranges.
    Return true if the table was built.  The table is not built if it
    is too big.  */
 /* Build allocno conflict table by processing allocno live ranges.
    Return true if the table was built.  The table is not built if it
    is too big.  */
@@ -68,57 +97,59 @@ build_conflict_bit_table (void)
 {
   int i;
   unsigned int j;
 {
   int i;
   unsigned int j;
-  enum reg_class cover_class;
+  enum reg_class aclass;
   int object_set_words, allocated_words_num, conflict_bit_vec_words_num;
   live_range_t r;
   ira_allocno_t allocno;
   ira_allocno_iterator ai;
   sparseset objects_live;
   int object_set_words, allocated_words_num, conflict_bit_vec_words_num;
   live_range_t r;
   ira_allocno_t allocno;
   ira_allocno_iterator ai;
   sparseset objects_live;
+  ira_object_t obj;
+  ira_allocno_object_iterator aoi;
 
   allocated_words_num = 0;
   FOR_EACH_ALLOCNO (allocno, ai)
 
   allocated_words_num = 0;
   FOR_EACH_ALLOCNO (allocno, ai)
-    {
-      ira_object_t obj = ALLOCNO_OBJECT (allocno);
-      if (OBJECT_MAX (obj) < OBJECT_MIN (obj))
+    FOR_EACH_ALLOCNO_OBJECT (allocno, obj, aoi)
+      {
+       if (OBJECT_MAX (obj) < OBJECT_MIN (obj))
          continue;
          continue;
-      conflict_bit_vec_words_num
-       = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS)
-          / IRA_INT_BITS);
-      allocated_words_num += conflict_bit_vec_words_num;
-      if ((unsigned long long) allocated_words_num * sizeof (IRA_INT_TYPE)
-         > (unsigned long long) IRA_MAX_CONFLICT_TABLE_SIZE * 1024 * 1024)
-       {
-         if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
-           fprintf
-             (ira_dump_file,
-              "+++Conflict table will be too big(>%dMB) -- don't use it\n",
-              IRA_MAX_CONFLICT_TABLE_SIZE);
-         return false;
-       }
-    }
+       conflict_bit_vec_words_num
+         = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS)
+            / IRA_INT_BITS);
+       allocated_words_num += conflict_bit_vec_words_num;
+       if ((unsigned long long) allocated_words_num * sizeof (IRA_INT_TYPE)
+           > (unsigned long long) IRA_MAX_CONFLICT_TABLE_SIZE * 1024 * 1024)
+         {
+           if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
+             fprintf
+               (ira_dump_file,
+                "+++Conflict table will be too big(>%dMB) -- don't use it\n",
+                IRA_MAX_CONFLICT_TABLE_SIZE);
+           return false;
+         }
+      }
 
   conflicts = (IRA_INT_TYPE **) ira_allocate (sizeof (IRA_INT_TYPE *)
                                              * ira_objects_num);
   allocated_words_num = 0;
   FOR_EACH_ALLOCNO (allocno, ai)
 
   conflicts = (IRA_INT_TYPE **) ira_allocate (sizeof (IRA_INT_TYPE *)
                                              * ira_objects_num);
   allocated_words_num = 0;
   FOR_EACH_ALLOCNO (allocno, ai)
-    {
-      ira_object_t obj = ALLOCNO_OBJECT (allocno);
-      int id = OBJECT_CONFLICT_ID (obj);
-      if (OBJECT_MAX (obj) < OBJECT_MIN (obj))
-       {
-         conflicts[id] = NULL;
-         continue;
-       }
-      conflict_bit_vec_words_num
-       = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS)
-          / IRA_INT_BITS);
-      allocated_words_num += conflict_bit_vec_words_num;
-      conflicts[id]
-       = (IRA_INT_TYPE *) ira_allocate (sizeof (IRA_INT_TYPE)
-                                        * conflict_bit_vec_words_num);
-      memset (conflicts[id], 0,
-             sizeof (IRA_INT_TYPE) * conflict_bit_vec_words_num);
-    }
+    FOR_EACH_ALLOCNO_OBJECT (allocno, obj, aoi)
+      {
+       int id = OBJECT_CONFLICT_ID (obj);
+       if (OBJECT_MAX (obj) < OBJECT_MIN (obj))
+         {
+           conflicts[id] = NULL;
+           continue;
+         }
+       conflict_bit_vec_words_num
+         = ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS)
+            / IRA_INT_BITS);
+       allocated_words_num += conflict_bit_vec_words_num;
+       conflicts[id]
+         = (IRA_INT_TYPE *) ira_allocate (sizeof (IRA_INT_TYPE)
+                                          * conflict_bit_vec_words_num);
+       memset (conflicts[id], 0,
+               sizeof (IRA_INT_TYPE) * conflict_bit_vec_words_num);
+      }
 
   object_set_words = (ira_objects_num + IRA_INT_BITS - 1) / IRA_INT_BITS;
   if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
 
   object_set_words = (ira_objects_num + IRA_INT_BITS - 1) / IRA_INT_BITS;
   if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
@@ -137,33 +168,27 @@ build_conflict_bit_table (void)
          ira_allocno_t allocno = OBJECT_ALLOCNO (obj);
          int id = OBJECT_CONFLICT_ID (obj);
 
          ira_allocno_t allocno = OBJECT_ALLOCNO (obj);
          int id = OBJECT_CONFLICT_ID (obj);
 
-         cover_class = ALLOCNO_COVER_CLASS (allocno);
+         gcc_assert (id < ira_objects_num);
+
+         aclass = ALLOCNO_CLASS (allocno);
          sparseset_set_bit (objects_live, id);
          EXECUTE_IF_SET_IN_SPARSESET (objects_live, j)
            {
          sparseset_set_bit (objects_live, id);
          EXECUTE_IF_SET_IN_SPARSESET (objects_live, j)
            {
-             ira_object_t live_cr = ira_object_id_map[j];
-             ira_allocno_t live_a = OBJECT_ALLOCNO (live_cr);
-             enum reg_class live_cover_class = ALLOCNO_COVER_CLASS (live_a);
+             ira_object_t live_obj = ira_object_id_map[j];
+             ira_allocno_t live_a = OBJECT_ALLOCNO (live_obj);
+             enum reg_class live_aclass = ALLOCNO_CLASS (live_a);
 
 
-             if (ira_reg_classes_intersect_p[cover_class][live_cover_class]
+             if (ira_reg_classes_intersect_p[aclass][live_aclass]
                  /* Don't set up conflict for the allocno with itself.  */
                  /* Don't set up conflict for the allocno with itself.  */
-                 && id != (int) j)
+                 && live_a != allocno)
                {
                {
-                 SET_MINMAX_SET_BIT (conflicts[id], j,
-                                     OBJECT_MIN (obj),
-                                     OBJECT_MAX (obj));
-                 SET_MINMAX_SET_BIT (conflicts[j], id,
-                                     OBJECT_MIN (live_cr),
-                                     OBJECT_MAX (live_cr));
+                 record_object_conflict (obj, live_obj);
                }
            }
        }
 
       for (r = ira_finish_point_ranges[i]; r != NULL; r = r->finish_next)
                }
            }
        }
 
       for (r = ira_finish_point_ranges[i]; r != NULL; r = r->finish_next)
-       {
-         ira_object_t obj = r->object;
-         sparseset_clear_bit (objects_live, OBJECT_CONFLICT_ID (obj));
-       }
+       sparseset_clear_bit (objects_live, OBJECT_CONFLICT_ID (r->object));
     }
   sparseset_free (objects_live);
   return true;
     }
   sparseset_free (objects_live);
   return true;
@@ -173,10 +198,14 @@ build_conflict_bit_table (void)
    register due to conflicts.  */
 
 static bool
    register due to conflicts.  */
 
 static bool
-allocnos_conflict_p (ira_allocno_t a1, ira_allocno_t a2)
+allocnos_conflict_for_copy_p (ira_allocno_t a1, ira_allocno_t a2)
 {
 {
-  ira_object_t obj1 = ALLOCNO_OBJECT (a1);
-  ira_object_t obj2 = ALLOCNO_OBJECT (a2);
+  /* Due to the fact that we canonicalize conflicts (see
+     record_object_conflict), we only need to test for conflicts of
+     the lowest order words.  */
+  ira_object_t obj1 = ALLOCNO_OBJECT (a1, 0);
+  ira_object_t obj2 = ALLOCNO_OBJECT (a2, 0);
+
   return OBJECTS_CONFLICT_P (obj1, obj2);
 }
 
   return OBJECTS_CONFLICT_P (obj1, obj2);
 }
 
@@ -184,19 +213,22 @@ allocnos_conflict_p (ira_allocno_t a1, ira_allocno_t a2)
 static bool
 commutative_constraint_p (const char *str)
 {
 static bool
 commutative_constraint_p (const char *str)
 {
+  int curr_alt, c;
   bool ignore_p;
   bool ignore_p;
-  int c;
 
 
-  for (ignore_p = false;;)
+  for (ignore_p = false, curr_alt = 0;;)
     {
       c = *str;
       if (c == '\0')
        break;
       str += CONSTRAINT_LEN (c, str);
     {
       c = *str;
       if (c == '\0')
        break;
       str += CONSTRAINT_LEN (c, str);
-      if (c == '#')
+      if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
        ignore_p = true;
       else if (c == ',')
        ignore_p = true;
       else if (c == ',')
-       ignore_p = false;
+       {
+         curr_alt++;
+         ignore_p = false;
+       }
       else if (! ignore_p)
        {
          /* Usually `%' is the first constraint character but the
       else if (! ignore_p)
        {
          /* Usually `%' is the first constraint character but the
@@ -241,7 +273,7 @@ get_dup_num (int op_num, bool use_commut_op_p)
       c = *str;
       if (c == '\0')
        break;
       c = *str;
       if (c == '\0')
        break;
-      if (c == '#')
+      if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
        ignore_p = true;
       else if (c == ',')
        {
        ignore_p = true;
       else if (c == ',')
        {
@@ -361,7 +393,7 @@ process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p,
   int allocno_preferenced_hard_regno, cost, index, offset1, offset2;
   bool only_regs_p;
   ira_allocno_t a;
   int allocno_preferenced_hard_regno, cost, index, offset1, offset2;
   bool only_regs_p;
   ira_allocno_t a;
-  enum reg_class rclass, cover_class;
+  enum reg_class rclass, aclass;
   enum machine_mode mode;
   ira_copy_t cp;
 
   enum machine_mode mode;
   ira_copy_t cp;
 
@@ -387,7 +419,7 @@ process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p,
     {
       ira_allocno_t a1 = ira_curr_regno_allocno_map[REGNO (reg1)];
       ira_allocno_t a2 = ira_curr_regno_allocno_map[REGNO (reg2)];
     {
       ira_allocno_t a1 = ira_curr_regno_allocno_map[REGNO (reg1)];
       ira_allocno_t a2 = ira_curr_regno_allocno_map[REGNO (reg2)];
-      if (!allocnos_conflict_p (a1, a2) && offset1 == offset2)
+      if (!allocnos_conflict_for_copy_p (a1, a2) && offset1 == offset2)
        {
          cp = ira_add_allocno_copy (a1, a2, freq, constraint_p, insn,
                                     ira_curr_loop_tree_node);
        {
          cp = ira_add_allocno_copy (a1, a2, freq, constraint_p, insn,
                                     ira_curr_loop_tree_node);
@@ -398,35 +430,37 @@ process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p,
        return false;
     }
 
        return false;
     }
 
-  if (! IN_RANGE (allocno_preferenced_hard_regno, 0, FIRST_PSEUDO_REGISTER - 1))
+  if (! IN_RANGE (allocno_preferenced_hard_regno,
+                 0, FIRST_PSEUDO_REGISTER - 1))
     /* Can not be tied.  */
     return false;
   rclass = REGNO_REG_CLASS (allocno_preferenced_hard_regno);
   mode = ALLOCNO_MODE (a);
     /* Can not be tied.  */
     return false;
   rclass = REGNO_REG_CLASS (allocno_preferenced_hard_regno);
   mode = ALLOCNO_MODE (a);
-  cover_class = ALLOCNO_COVER_CLASS (a);
+  aclass = ALLOCNO_CLASS (a);
   if (only_regs_p && insn != NULL_RTX
       && reg_class_size[rclass] <= (unsigned) CLASS_MAX_NREGS (rclass, mode))
     /* It is already taken into account in ira-costs.c.  */
     return false;
   if (only_regs_p && insn != NULL_RTX
       && reg_class_size[rclass] <= (unsigned) CLASS_MAX_NREGS (rclass, mode))
     /* It is already taken into account in ira-costs.c.  */
     return false;
-  index = ira_class_hard_reg_index[cover_class][allocno_preferenced_hard_regno];
+  index = ira_class_hard_reg_index[aclass][allocno_preferenced_hard_regno];
   if (index < 0)
   if (index < 0)
-    /* Can not be tied.  It is not in the cover class.  */
+    /* Can not be tied.  It is not in the allocno class.  */
     return false;
     return false;
+  ira_init_register_move_cost_if_necessary (mode);
   if (HARD_REGISTER_P (reg1))
   if (HARD_REGISTER_P (reg1))
-    cost = ira_get_register_move_cost (mode, cover_class, rclass) * freq;
+    cost = ira_register_move_cost[mode][aclass][rclass] * freq;
   else
   else
-    cost = ira_get_register_move_cost (mode, rclass, cover_class) * freq;
+    cost = ira_register_move_cost[mode][rclass][aclass] * freq;
   do
     {
       ira_allocate_and_set_costs
   do
     {
       ira_allocate_and_set_costs
-       (&ALLOCNO_HARD_REG_COSTS (a), cover_class,
-        ALLOCNO_COVER_CLASS_COST (a));
+       (&ALLOCNO_HARD_REG_COSTS (a), aclass,
+        ALLOCNO_CLASS_COST (a));
       ira_allocate_and_set_costs
       ira_allocate_and_set_costs
-       (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), cover_class, 0);
+       (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), aclass, 0);
       ALLOCNO_HARD_REG_COSTS (a)[index] -= cost;
       ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost;
       ALLOCNO_HARD_REG_COSTS (a)[index] -= cost;
       ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost;
-      if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_COVER_CLASS_COST (a))
-       ALLOCNO_COVER_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index];
+      if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a))
+       ALLOCNO_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index];
       a = ira_parent_or_cap_allocno (a);
     }
   while (a != NULL);
       a = ira_parent_or_cap_allocno (a);
     }
   while (a != NULL);
@@ -479,7 +513,8 @@ add_insn_allocno_copies (rtx insn)
                        ? SET_SRC (set)
                        : SUBREG_REG (SET_SRC (set))) != NULL_RTX)
     {
                        ? SET_SRC (set)
                        : SUBREG_REG (SET_SRC (set))) != NULL_RTX)
     {
-      process_regs_for_copy (SET_DEST (set), SET_SRC (set), false, insn, freq);
+      process_regs_for_copy (SET_DEST (set), SET_SRC (set),
+                            false, insn, freq);
       return;
     }
   /* Fast check of possibility of constraint or shuffle copies.  If
       return;
     }
   /* Fast check of possibility of constraint or shuffle copies.  If
@@ -560,7 +595,7 @@ propagate_copies (void)
       parent_a1 = ira_parent_or_cap_allocno (a1);
       parent_a2 = ira_parent_or_cap_allocno (a2);
       ira_assert (parent_a1 != NULL && parent_a2 != NULL);
       parent_a1 = ira_parent_or_cap_allocno (a1);
       parent_a2 = ira_parent_or_cap_allocno (a2);
       ira_assert (parent_a1 != NULL && parent_a2 != NULL);
-      if (! allocnos_conflict_p (parent_a1, parent_a2))
+      if (! allocnos_conflict_for_copy_p (parent_a1, parent_a2))
        ira_add_allocno_copy (parent_a1, parent_a2, cp->freq,
                              cp->constraint_p, cp->insn, cp->loop_tree_node);
     }
        ira_add_allocno_copy (parent_a1, parent_a2, cp->freq,
                              cp->constraint_p, cp->insn, cp->loop_tree_node);
     }
@@ -570,33 +605,33 @@ propagate_copies (void)
 static ira_object_t *collected_conflict_objects;
 
 /* Build conflict vectors or bit conflict vectors (whatever is more
 static ira_object_t *collected_conflict_objects;
 
 /* Build conflict vectors or bit conflict vectors (whatever is more
-   profitable) for allocno A from the conflict table and propagate the
-   conflicts to upper level allocno.  */
+   profitable) for object OBJ from the conflict table.  */
 static void
 static void
-build_allocno_conflicts (ira_allocno_t a)
+build_object_conflicts (ira_object_t obj)
 {
   int i, px, parent_num;
 {
   int i, px, parent_num;
-  int conflict_bit_vec_words_num;
   ira_allocno_t parent_a, another_parent_a;
   ira_allocno_t parent_a, another_parent_a;
-  ira_object_t *vec;
-  IRA_INT_TYPE *allocno_conflicts;
-  ira_object_t obj, parent_obj;
+  ira_object_t parent_obj;
+  ira_allocno_t a = OBJECT_ALLOCNO (obj);
+  IRA_INT_TYPE *object_conflicts;
   minmax_set_iterator asi;
   minmax_set_iterator asi;
+  int parent_min, parent_max ATTRIBUTE_UNUSED;
 
 
-  obj = ALLOCNO_OBJECT (a);
-  allocno_conflicts = conflicts[OBJECT_CONFLICT_ID (obj)];
+  object_conflicts = conflicts[OBJECT_CONFLICT_ID (obj)];
   px = 0;
   px = 0;
-  FOR_EACH_BIT_IN_MINMAX_SET (allocno_conflicts,
+  FOR_EACH_BIT_IN_MINMAX_SET (object_conflicts,
                              OBJECT_MIN (obj), OBJECT_MAX (obj), i, asi)
     {
       ira_object_t another_obj = ira_object_id_map[i];
       ira_allocno_t another_a = OBJECT_ALLOCNO (obj);
                              OBJECT_MIN (obj), OBJECT_MAX (obj), i, asi)
     {
       ira_object_t another_obj = ira_object_id_map[i];
       ira_allocno_t another_a = OBJECT_ALLOCNO (obj);
+
       ira_assert (ira_reg_classes_intersect_p
       ira_assert (ira_reg_classes_intersect_p
-                 [ALLOCNO_COVER_CLASS (a)][ALLOCNO_COVER_CLASS (another_a)]);
+                 [ALLOCNO_CLASS (a)][ALLOCNO_CLASS (another_a)]);
       collected_conflict_objects[px++] = another_obj;
     }
   if (ira_conflict_vector_profitable_p (obj, px))
     {
       collected_conflict_objects[px++] = another_obj;
     }
   if (ira_conflict_vector_profitable_p (obj, px))
     {
+      ira_object_t *vec;
       ira_allocate_conflict_vec (obj, px);
       vec = OBJECT_CONFLICT_VEC (obj);
       memcpy (vec, collected_conflict_objects, sizeof (ira_object_t) * px);
       ira_allocate_conflict_vec (obj, px);
       vec = OBJECT_CONFLICT_VEC (obj);
       memcpy (vec, collected_conflict_objects, sizeof (ira_object_t) * px);
@@ -605,7 +640,9 @@ build_allocno_conflicts (ira_allocno_t a)
     }
   else
     {
     }
   else
     {
-      OBJECT_CONFLICT_ARRAY (obj) = allocno_conflicts;
+      int conflict_bit_vec_words_num;
+
+      OBJECT_CONFLICT_ARRAY (obj) = object_conflicts;
       if (OBJECT_MAX (obj) < OBJECT_MIN (obj))
        conflict_bit_vec_words_num = 0;
       else
       if (OBJECT_MAX (obj) < OBJECT_MIN (obj))
        conflict_bit_vec_words_num = 0;
       else
@@ -615,30 +652,38 @@ build_allocno_conflicts (ira_allocno_t a)
       OBJECT_CONFLICT_ARRAY_SIZE (obj)
        = conflict_bit_vec_words_num * sizeof (IRA_INT_TYPE);
     }
       OBJECT_CONFLICT_ARRAY_SIZE (obj)
        = conflict_bit_vec_words_num * sizeof (IRA_INT_TYPE);
     }
+
   parent_a = ira_parent_or_cap_allocno (a);
   if (parent_a == NULL)
     return;
   parent_a = ira_parent_or_cap_allocno (a);
   if (parent_a == NULL)
     return;
-  ira_assert (ALLOCNO_COVER_CLASS (a) == ALLOCNO_COVER_CLASS (parent_a));
-  parent_obj = ALLOCNO_OBJECT (parent_a);
+  ira_assert (ALLOCNO_CLASS (a) == ALLOCNO_CLASS (parent_a));
+  ira_assert (ALLOCNO_NUM_OBJECTS (a) == ALLOCNO_NUM_OBJECTS (parent_a));
+  parent_obj = ALLOCNO_OBJECT (parent_a, OBJECT_SUBWORD (obj));
   parent_num = OBJECT_CONFLICT_ID (parent_obj);
   parent_num = OBJECT_CONFLICT_ID (parent_obj);
-  FOR_EACH_BIT_IN_MINMAX_SET (allocno_conflicts,
+  parent_min = OBJECT_MIN (parent_obj);
+  parent_max = OBJECT_MAX (parent_obj);
+  FOR_EACH_BIT_IN_MINMAX_SET (object_conflicts,
                              OBJECT_MIN (obj), OBJECT_MAX (obj), i, asi)
     {
       ira_object_t another_obj = ira_object_id_map[i];
       ira_allocno_t another_a = OBJECT_ALLOCNO (another_obj);
                              OBJECT_MIN (obj), OBJECT_MAX (obj), i, asi)
     {
       ira_object_t another_obj = ira_object_id_map[i];
       ira_allocno_t another_a = OBJECT_ALLOCNO (another_obj);
+      int another_word = OBJECT_SUBWORD (another_obj);
 
       ira_assert (ira_reg_classes_intersect_p
 
       ira_assert (ira_reg_classes_intersect_p
-                 [ALLOCNO_COVER_CLASS (a)][ALLOCNO_COVER_CLASS (another_a)]);
+                 [ALLOCNO_CLASS (a)][ALLOCNO_CLASS (another_a)]);
+
       another_parent_a = ira_parent_or_cap_allocno (another_a);
       if (another_parent_a == NULL)
        continue;
       ira_assert (ALLOCNO_NUM (another_parent_a) >= 0);
       another_parent_a = ira_parent_or_cap_allocno (another_a);
       if (another_parent_a == NULL)
        continue;
       ira_assert (ALLOCNO_NUM (another_parent_a) >= 0);
-      ira_assert (ALLOCNO_COVER_CLASS (another_a)
-                 == ALLOCNO_COVER_CLASS (another_parent_a));
+      ira_assert (ALLOCNO_CLASS (another_a)
+                 == ALLOCNO_CLASS (another_parent_a));
+      ira_assert (ALLOCNO_NUM_OBJECTS (another_a)
+                 == ALLOCNO_NUM_OBJECTS (another_parent_a));
       SET_MINMAX_SET_BIT (conflicts[parent_num],
       SET_MINMAX_SET_BIT (conflicts[parent_num],
-                         OBJECT_CONFLICT_ID (ALLOCNO_OBJECT (another_parent_a)),
-                         OBJECT_MIN (parent_obj),
-                         OBJECT_MAX (parent_obj));
+                         OBJECT_CONFLICT_ID (ALLOCNO_OBJECT (another_parent_a,
+                                                             another_word)),
+                         parent_min, parent_max);
     }
 }
 
     }
 }
 
@@ -658,9 +703,18 @@ build_conflicts (void)
         a != NULL;
         a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
       {
         a != NULL;
         a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
       {
-       build_allocno_conflicts (a);
-       for (cap = ALLOCNO_CAP (a); cap != NULL; cap = ALLOCNO_CAP (cap))
-         build_allocno_conflicts (cap);
+       int j, nregs = ALLOCNO_NUM_OBJECTS (a);
+       for (j = 0; j < nregs; j++)
+         {
+           ira_object_t obj = ALLOCNO_OBJECT (a, j);
+           build_object_conflicts (obj);
+           for (cap = ALLOCNO_CAP (a); cap != NULL; cap = ALLOCNO_CAP (cap))
+             {
+               ira_object_t cap_obj = ALLOCNO_OBJECT (cap, j);
+               gcc_assert (ALLOCNO_NUM_OBJECTS (cap) == ALLOCNO_NUM_OBJECTS (a));
+               build_object_conflicts (cap_obj);
+             }
+         }
       }
   ira_free (collected_conflict_objects);
 }
       }
   ira_free (collected_conflict_objects);
 }
@@ -700,9 +754,8 @@ static void
 print_allocno_conflicts (FILE * file, bool reg_p, ira_allocno_t a)
 {
   HARD_REG_SET conflicting_hard_regs;
 print_allocno_conflicts (FILE * file, bool reg_p, ira_allocno_t a)
 {
   HARD_REG_SET conflicting_hard_regs;
-  ira_object_t obj, conflict_obj;
-  ira_object_conflict_iterator oci;
   basic_block bb;
   basic_block bb;
+  int n, i;
 
   if (reg_p)
     fprintf (file, ";; r%d", ALLOCNO_REGNO (a));
 
   if (reg_p)
     fprintf (file, ";; r%d", ALLOCNO_REGNO (a));
@@ -717,39 +770,52 @@ print_allocno_conflicts (FILE * file, bool reg_p, ira_allocno_t a)
     }
 
   fputs (" conflicts:", file);
     }
 
   fputs (" conflicts:", file);
-  obj = ALLOCNO_OBJECT (a);
-  if (OBJECT_CONFLICT_ARRAY (obj) != NULL)
-    FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
-      {
-       ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
-        if (reg_p)
-          fprintf (file, " r%d,", ALLOCNO_REGNO (conflict_a));
-        else
-          {
-           fprintf (file, " a%d(r%d,", ALLOCNO_NUM (conflict_a),
-                    ALLOCNO_REGNO (conflict_a));
-           if ((bb = ALLOCNO_LOOP_TREE_NODE (conflict_a)->bb) != NULL)
-             fprintf (file, "b%d)", bb->index);
-           else
-             fprintf (file, "l%d)",
-                      ALLOCNO_LOOP_TREE_NODE (conflict_a)->loop->num);
-         }
-      }
+  n = ALLOCNO_NUM_OBJECTS (a);
+  for (i = 0; i < n; i++)
+    {
+      ira_object_t obj = ALLOCNO_OBJECT (a, i);
+      ira_object_t conflict_obj;
+      ira_object_conflict_iterator oci;
+
+      if (OBJECT_CONFLICT_ARRAY (obj) == NULL)
+       continue;
+      if (n > 1)
+       fprintf (file, "\n;;   subobject %d:", i);
+      FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
+       {
+         ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
+         if (reg_p)
+           fprintf (file, " r%d,", ALLOCNO_REGNO (conflict_a));
+         else
+           {
+             fprintf (file, " a%d(r%d", ALLOCNO_NUM (conflict_a),
+                      ALLOCNO_REGNO (conflict_a));
+             if (ALLOCNO_NUM_OBJECTS (conflict_a) > 1)
+               fprintf (file, ",w%d", OBJECT_SUBWORD (conflict_obj));
+             if ((bb = ALLOCNO_LOOP_TREE_NODE (conflict_a)->bb) != NULL)
+               fprintf (file, ",b%d", bb->index);
+             else
+               fprintf (file, ",l%d",
+                        ALLOCNO_LOOP_TREE_NODE (conflict_a)->loop->num);
+             putc (')', file);
+           }
+       }
+      COPY_HARD_REG_SET (conflicting_hard_regs, OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
+      AND_COMPL_HARD_REG_SET (conflicting_hard_regs, ira_no_alloc_regs);
+      AND_HARD_REG_SET (conflicting_hard_regs,
+                       reg_class_contents[ALLOCNO_CLASS (a)]);
+      print_hard_reg_set (file, "\n;;     total conflict hard regs:",
+                         conflicting_hard_regs);
+
+      COPY_HARD_REG_SET (conflicting_hard_regs, OBJECT_CONFLICT_HARD_REGS (obj));
+      AND_COMPL_HARD_REG_SET (conflicting_hard_regs, ira_no_alloc_regs);
+      AND_HARD_REG_SET (conflicting_hard_regs,
+                       reg_class_contents[ALLOCNO_CLASS (a)]);
+      print_hard_reg_set (file, ";;     conflict hard regs:",
+                         conflicting_hard_regs);
+      putc ('\n', file);
+    }
 
 
-  COPY_HARD_REG_SET (conflicting_hard_regs, OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
-  AND_COMPL_HARD_REG_SET (conflicting_hard_regs, ira_no_alloc_regs);
-  AND_HARD_REG_SET (conflicting_hard_regs,
-                   reg_class_contents[ALLOCNO_COVER_CLASS (a)]);
-  print_hard_reg_set (file, "\n;;     total conflict hard regs:",
-                     conflicting_hard_regs);
-
-  COPY_HARD_REG_SET (conflicting_hard_regs, OBJECT_CONFLICT_HARD_REGS (obj));
-  AND_COMPL_HARD_REG_SET (conflicting_hard_regs, ira_no_alloc_regs);
-  AND_HARD_REG_SET (conflicting_hard_regs,
-                   reg_class_contents[ALLOCNO_COVER_CLASS (a)]);
-  print_hard_reg_set (file, ";;     conflict hard regs:",
-                     conflicting_hard_regs);
-  putc ('\n', file);
 }
 
 /* Print information about allocno or only regno (if REG_P) conflicts
 }
 
 /* Print information about allocno or only regno (if REG_P) conflicts
@@ -799,7 +865,7 @@ ira_build_conflicts (void)
            propagate_copies ();
 
          /* Now we can free memory for the conflict table (see function
            propagate_copies ();
 
          /* Now we can free memory for the conflict table (see function
-            build_allocno_conflicts for details).  */
+            build_object_conflicts for details).  */
          FOR_EACH_OBJECT (obj, oi)
            {
              if (OBJECT_CONFLICT_ARRAY (obj) != conflicts[OBJECT_CONFLICT_ID (obj)])
          FOR_EACH_OBJECT (obj, oi)
            {
              if (OBJECT_CONFLICT_ARRAY (obj) != conflicts[OBJECT_CONFLICT_ID (obj)])
@@ -808,7 +874,8 @@ ira_build_conflicts (void)
          ira_free (conflicts);
        }
     }
          ira_free (conflicts);
        }
     }
-  if (! CLASS_LIKELY_SPILLED_P (base_reg_class (VOIDmode, ADDRESS, SCRATCH)))
+  if (! targetm.class_likely_spilled_p (base_reg_class (VOIDmode, ADDRESS,
+                                                       SCRATCH)))
     CLEAR_HARD_REG_SET (temp_hard_reg_set);
   else
     {
     CLEAR_HARD_REG_SET (temp_hard_reg_set);
   else
     {
@@ -819,29 +886,56 @@ ira_build_conflicts (void)
     }
   FOR_EACH_ALLOCNO (a, ai)
     {
     }
   FOR_EACH_ALLOCNO (a, ai)
     {
-      ira_object_t obj = ALLOCNO_OBJECT (a);
-      reg_attrs *attrs;
-      tree decl;
-
-      if ((! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
-         /* For debugging purposes don't put user defined variables in
-            callee-clobbered registers.  */
-         || (optimize == 0
-             && (attrs = REG_ATTRS (regno_reg_rtx [ALLOCNO_REGNO (a)])) != NULL
-             && (decl = attrs->decl) != NULL
-             && VAR_OR_FUNCTION_DECL_P (decl)
-             && ! DECL_ARTIFICIAL (decl)))
-       {
-         IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), call_used_reg_set);
-         IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), call_used_reg_set);
-       }
-      else if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
+      int i, n = ALLOCNO_NUM_OBJECTS (a);
+
+      for (i = 0; i < n; i++)
        {
        {
-         IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
-                           no_caller_save_reg_set);
-         IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), temp_hard_reg_set);
-         IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), no_caller_save_reg_set);
-         IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), temp_hard_reg_set);
+         ira_object_t obj = ALLOCNO_OBJECT (a, i);
+         reg_attrs *attrs = REG_ATTRS (regno_reg_rtx [ALLOCNO_REGNO (a)]);
+         tree decl;
+
+         if ((! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
+             /* For debugging purposes don't put user defined variables in
+                callee-clobbered registers.  */
+             || (optimize == 0
+                 && attrs != NULL
+                 && (decl = attrs->decl) != NULL
+                 && VAR_OR_FUNCTION_DECL_P (decl)
+                 && ! DECL_ARTIFICIAL (decl)))
+           {
+             IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
+                               call_used_reg_set);
+             IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
+                               call_used_reg_set);
+           }
+         else if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
+           {
+             IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
+                               no_caller_save_reg_set);
+             IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
+                               temp_hard_reg_set);
+             IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
+                               no_caller_save_reg_set);
+             IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
+                               temp_hard_reg_set);
+           }
+
+         if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
+           {
+             int regno;
+
+             /* Allocnos bigger than the saved part of call saved
+                regs must conflict with them.  */
+             for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+               if (!TEST_HARD_REG_BIT (call_used_reg_set, regno)
+                   && HARD_REGNO_CALL_PART_CLOBBERED (regno,
+                                                      obj->allocno->mode))
+                 {
+                   SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), regno);
+                   SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
+                                     regno);
+                 }
+           }
        }
     }
   if (optimize && ira_conflicts_p
        }
     }
   if (optimize && ira_conflicts_p