x86: Update message for target_clones and unsupported ISAs
[gcc.git] / gcc / reginfo.c
index ccf53bfbc1f10f9c604519d750986d6e7b2fa730..315c5ecabe6d7bb220f3accc8b01674876606605 100644 (file)
@@ -1,5 +1,5 @@
 /* Compute different info about registers.
-   Copyright (C) 1987-2016 Free Software Foundation, Inc.
+   Copyright (C) 1987-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "rtl.h"
 #include "tree.h"
 #include "df.h"
+#include "memmodel.h"
 #include "tm_p.h"
 #include "insn-config.h"
 #include "regs.h"
@@ -449,6 +450,7 @@ init_reg_sets_1 (void)
     }
 
   COPY_HARD_REG_SET (call_fixed_reg_set, fixed_reg_set);
+  COPY_HARD_REG_SET (fixed_nonglobal_reg_set, fixed_reg_set);
 
   /* Preserve global registers if called more than once.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -466,19 +468,29 @@ init_reg_sets_1 (void)
   memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
   for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
     {
-      HARD_REG_SET ok_regs;
+      HARD_REG_SET ok_regs, ok_regs2;
       CLEAR_HARD_REG_SET (ok_regs);
+      CLEAR_HARD_REG_SET (ok_regs2);
       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
-       if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, (machine_mode) m))
-         SET_HARD_REG_BIT (ok_regs, j);
+       if (!TEST_HARD_REG_BIT (fixed_nonglobal_reg_set, j)
+           && targetm.hard_regno_mode_ok (j, (machine_mode) m))
+         {
+           SET_HARD_REG_BIT (ok_regs, j);
+           if (!fixed_regs[j])
+             SET_HARD_REG_BIT (ok_regs2, j);
+         }
 
       for (i = 0; i < N_REG_CLASSES; i++)
        if ((targetm.class_max_nregs ((reg_class_t) i, (machine_mode) m)
             <= reg_class_size[i])
            && hard_reg_set_intersect_p (ok_regs, reg_class_contents[i]))
          {
-            contains_reg_of_mode [i][m] = 1;
-            have_regs_of_mode [m] = 1;
+            contains_reg_of_mode[i][m] = 1;
+            if (hard_reg_set_intersect_p (ok_regs2, reg_class_contents[i]))
+              {
+                have_regs_of_mode[m] = 1;
+                contains_allocatable_reg_of_mode[i][m] = 1;
+              }
          }
      }
 }
@@ -496,7 +508,8 @@ init_reg_modes_target (void)
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     for (j = 0; j < MAX_MACHINE_MODE; j++)
-      hard_regno_nregs[i][j] = HARD_REGNO_NREGS (i, (machine_mode)j);
+      this_target_regs->x_hard_regno_nregs[i][j]
+       = targetm.hard_regno_nregs (i, (machine_mode) j);
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
@@ -506,7 +519,7 @@ init_reg_modes_target (void)
         if it is suitable, otherwise fall back on word_mode.  */
       if (reg_raw_mode[i] == VOIDmode)
        {
-         if (i > 0 && hard_regno_nregs[i][reg_raw_mode[i - 1]] == 1)
+         if (i > 0 && hard_regno_nregs (i, reg_raw_mode[i - 1]) == 1)
            reg_raw_mode[i] = reg_raw_mode[i - 1];
          else
            reg_raw_mode[i] = word_mode;
@@ -618,42 +631,40 @@ choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED,
 
   /* We first look for the largest integer mode that can be validly
      held in REGNO.  If none, we look for the largest floating-point mode.
-     If we still didn't find a valid mode, try CCmode.  */
-
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
-    if ((unsigned) hard_regno_nregs[regno][mode] == nregs
-       && HARD_REGNO_MODE_OK (regno, mode)
-       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
-       && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
+     If we still didn't find a valid mode, try CCmode.
+
+     The tests use maybe_gt rather than known_gt because we want (for example)
+     N V4SFs to win over plain V4SF even though N might be 1.  */
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
+    if (hard_regno_nregs (regno, mode) == nregs
+       && targetm.hard_regno_mode_ok (regno, mode)
+       && (!call_saved
+           || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode))
+       && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode)))
       found_mode = mode;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
-    if ((unsigned) hard_regno_nregs[regno][mode] == nregs
-       && HARD_REGNO_MODE_OK (regno, mode)
-       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
-       && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
+    if (hard_regno_nregs (regno, mode) == nregs
+       && targetm.hard_regno_mode_ok (regno, mode)
+       && (!call_saved
+           || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode))
+       && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode)))
       found_mode = mode;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
-    if ((unsigned) hard_regno_nregs[regno][mode] == nregs
-       && HARD_REGNO_MODE_OK (regno, mode)
-       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
-       && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FLOAT)
+    if (hard_regno_nregs (regno, mode) == nregs
+       && targetm.hard_regno_mode_ok (regno, mode)
+       && (!call_saved
+           || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode))
+       && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode)))
       found_mode = mode;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
-    if ((unsigned) hard_regno_nregs[regno][mode] == nregs
-       && HARD_REGNO_MODE_OK (regno, mode)
-       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
-       && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
+    if (hard_regno_nregs (regno, mode) == nregs
+       && targetm.hard_regno_mode_ok (regno, mode)
+       && (!call_saved
+           || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode))
+       && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode)))
       found_mode = mode;
 
   if (found_mode != VOIDmode)
@@ -663,9 +674,10 @@ choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED,
   for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m)
     {
       mode = (machine_mode) m;
-      if ((unsigned) hard_regno_nregs[regno][mode] == nregs
-         && HARD_REGNO_MODE_OK (regno, mode)
-         && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
+      if (hard_regno_nregs (regno, mode) == nregs
+         && targetm.hard_regno_mode_ok (regno, mode)
+         && (!call_saved
+             || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode)))
        return mode;
     }
 
@@ -770,6 +782,7 @@ globalize_reg (tree decl, int i)
 
   if (global_regs[i])
     {
+      auto_diagnostic_group d;
       warning_at (loc, 0, 
                  "register of %qD used for multiple global register variables",
                  decl);
@@ -1088,6 +1101,10 @@ reg_scan_mark_refs (rtx x, rtx_insn *insn)
        reg_scan_mark_refs (XEXP (XEXP (x, 0), 0), insn);
       break;
 
+    case CLOBBER_HIGH:
+      gcc_assert (!(MEM_P (XEXP (x, 0))));
+      break;
+
     case SET:
       /* Count a set of the destination if it is a register.  */
       for (dest = SET_DEST (x);
@@ -1148,7 +1165,7 @@ reg_scan_mark_refs (rtx x, rtx_insn *insn)
       if (REG_P (dest) && !REG_ATTRS (dest))
        set_reg_attrs_from_value (dest, SET_SRC (x));
 
-      /* ... fall through ...  */
+      /* fall through */
 
     default:
       {
@@ -1196,7 +1213,9 @@ reg_classes_intersect_p (reg_class_t c1, reg_class_t c2)
 inline hashval_t
 simplifiable_subregs_hasher::hash (const simplifiable_subreg *value)
 {
-  return value->shape.unique_id ();
+  inchash::hash h;
+  h.add_hwi (value->shape.unique_id ());
+  return h.end ();
 }
 
 inline bool
@@ -1221,15 +1240,17 @@ simplifiable_subregs (const subreg_shape &shape)
   if (!this_target_hard_regs->x_simplifiable_subregs)
     this_target_hard_regs->x_simplifiable_subregs
       = new hash_table <simplifiable_subregs_hasher> (30);
+  inchash::hash h;
+  h.add_hwi (shape.unique_id ());
   simplifiable_subreg **slot
     = (this_target_hard_regs->x_simplifiable_subregs
-       ->find_slot_with_hash (&shape, shape.unique_id (), INSERT));
+       ->find_slot_with_hash (&shape, h.end (), INSERT));
 
   if (!*slot)
     {
       simplifiable_subreg *info = new simplifiable_subreg (shape);
       for (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
-       if (HARD_REGNO_MODE_OK (i, shape.inner_mode)
+       if (targetm.hard_regno_mode_ok (i, shape.inner_mode)
            && simplify_subreg_regno (i, shape.inner_mode, shape.offset,
                                      shape.outer_mode) >= 0)
          SET_HARD_REG_BIT (info->simplifiable_regs, i);
@@ -1280,11 +1301,15 @@ record_subregs_of_mode (rtx subreg, bool partial_def)
         subregs will be invalid.
 
         This relies on the fact that we've already been passed
-        SUBREG with PARTIAL_DEF set to false.  */
-      unsigned int size = MAX (REGMODE_NATURAL_SIZE (shape.inner_mode),
-                              GET_MODE_SIZE (shape.outer_mode));
-      gcc_checking_assert (size < GET_MODE_SIZE (shape.inner_mode));
-      if (shape.offset >= size)
+        SUBREG with PARTIAL_DEF set to false.
+
+        The size of the outer mode must ordered wrt the size of the
+        inner mode's registers, since otherwise we wouldn't know at
+        compile time how many registers the outer mode occupies.  */
+      poly_uint64 size = ordered_max (REGMODE_NATURAL_SIZE (shape.inner_mode),
+                                     GET_MODE_SIZE (shape.outer_mode));
+      gcc_checking_assert (known_lt (size, GET_MODE_SIZE (shape.inner_mode)));
+      if (known_ge (shape.offset, size))
        shape.offset -= size;
       else
        shape.offset += size;
@@ -1344,7 +1369,7 @@ init_subregs_of_mode (void)
          df_ref def;
          FOR_EACH_INSN_DEF (def, insn)
            if (DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL)
-               && df_read_modify_subreg_p (DF_REF_REG (def)))
+               && read_modify_subreg_p (DF_REF_REG (def)))
              record_subregs_of_mode (DF_REF_REG (def), true);
        }
 }