]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/rtl.c
Update copyright years.
[thirdparty/gcc.git] / gcc / rtl.c
index 2f32c649b4d128cd5f18f83d57886d1d277da258..4d527cf078e48e5e1ae3c1947e09b4f6312f4fe7 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -1,5 +1,5 @@
 /* RTL utility routines.
-   Copyright (C) 1987-2015 Free Software Foundation, Inc.
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -89,7 +89,8 @@ const char * const rtx_format[NUM_RTX_CODE] = {
      "b" is a pointer to a bitmap header.
      "B" is a basic block pointer.
      "t" is a tree pointer.
-     "r" a register.  */
+     "r" a register.
+     "p" is a poly_uint16 offset.  */
 
 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   FORMAT ,
 #include "rtl.def"             /* rtl expressions are defined here */
@@ -105,12 +106,23 @@ const enum rtx_class rtx_class[NUM_RTX_CODE] = {
 #undef DEF_RTL_EXPR
 };
 
+/* Whether rtxs with the given code code store data in the hwint field.  */
+
+#define RTX_CODE_HWINT_P_1(ENUM)                                       \
+    ((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE                     \
+     || (ENUM) == CONST_FIXED || (ENUM) == CONST_WIDE_INT)
+#ifdef GENERATOR_FILE
+#define RTX_CODE_HWINT_P(ENUM)                                         \
+    (RTX_CODE_HWINT_P_1 (ENUM) || (ENUM) == EQ_ATTR_ALT)
+#else
+#define RTX_CODE_HWINT_P RTX_CODE_HWINT_P_1
+#endif
+
 /* Indexed by rtx code, gives the size of the rtx in bytes.  */
 
 const unsigned char rtx_code_size[NUM_RTX_CODE] = {
 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)                                \
-  (((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE                      \
-    || (ENUM) == CONST_FIXED || (ENUM) == CONST_WIDE_INT)              \
+  (RTX_CODE_HWINT_P (ENUM)                                             \
    ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT)       \
    : (ENUM) == REG                                                     \
    ? RTX_HDR_SIZE + sizeof (reg_info)                                  \
@@ -136,10 +148,10 @@ const char * const reg_note_name[REG_NOTE_MAX] =
 #undef DEF_REG_NOTE
 };
 
-static int rtx_alloc_counts[(int) LAST_AND_UNUSED_RTX_CODE];
-static int rtx_alloc_sizes[(int) LAST_AND_UNUSED_RTX_CODE];
-static int rtvec_alloc_counts;
-static int rtvec_alloc_sizes;
+static size_t rtx_alloc_counts[(int) LAST_AND_UNUSED_RTX_CODE];
+static size_t rtx_alloc_sizes[(int) LAST_AND_UNUSED_RTX_CODE];
+static size_t rtvec_alloc_counts;
+static size_t rtvec_alloc_sizes;
 
 \f
 /* Allocate an rtx vector of N elements.
@@ -189,6 +201,10 @@ rtx_size (const_rtx x)
            + sizeof (struct hwivec_def)
            + ((CONST_WIDE_INT_NUNITS (x) - 1)
               * sizeof (HOST_WIDE_INT)));
+  if (CONST_POLY_INT_P (x))
+    return (RTX_HDR_SIZE
+           + sizeof (struct const_poly_int_def)
+           + CONST_POLY_INT_COEFFS (x).extra_size ());
   if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_HAS_BLOCK_INFO_P (x))
     return RTX_HDR_SIZE + sizeof (struct block_symbol);
   return RTX_CODE_SIZE (GET_CODE (x));
@@ -203,12 +219,7 @@ rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
   rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra
                                   PASS_MEM_STAT);
 
-  /* We want to clear everything up to the FLD array.  Normally, this
-     is one int, but we don't want to assume that and it isn't very
-     portable anyway; this is.  */
-
-  memset (rt, 0, RTX_HDR_SIZE);
-  PUT_CODE (rt, code);
+  rtx_init (rt, code);
 
   if (GATHER_STATISTICS)
     {
@@ -223,7 +234,7 @@ rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
    all the rest is initialized to zero.  */
 
 rtx
-rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL)
+rtx_alloc (RTX_CODE code MEM_STAT_DECL)
 {
   return rtx_alloc_stat_v (code PASS_MEM_STAT, 0);
 }
@@ -254,9 +265,10 @@ shared_const_p (const_rtx orig)
 
   /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
      a LABEL_REF, it isn't sharable.  */
+  poly_int64 offset;
   return (GET_CODE (XEXP (orig, 0)) == PLUS
          && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
-         && CONST_INT_P (XEXP (XEXP (orig, 0), 1)));
+         && poly_int_rtx_p (XEXP (XEXP (orig, 0), 1), &offset));
 }
 
 
@@ -318,10 +330,6 @@ copy_rtx (rtx orig)
      us to explicitly document why we are *not* copying a flag.  */
   copy = shallow_copy_rtx (orig);
 
-  /* We do not copy the USED flag, which is used as a mark bit during
-     walks over the RTL.  */
-  RTX_FLAG (copy, used) = 0;
-
   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
 
   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
@@ -345,6 +353,7 @@ copy_rtx (rtx orig)
       case 't':
       case 'w':
       case 'i':
+      case 'p':
       case 's':
       case 'S':
       case 'T':
@@ -363,11 +372,33 @@ copy_rtx (rtx orig)
 /* Create a new copy of an rtx.  Only copy just one level.  */
 
 rtx
-shallow_copy_rtx_stat (const_rtx orig MEM_STAT_DECL)
+shallow_copy_rtx (const_rtx orig MEM_STAT_DECL)
 {
   const unsigned int size = rtx_size (orig);
   rtx const copy = ggc_alloc_rtx_def_stat (size PASS_MEM_STAT);
-  return (rtx) memcpy (copy, orig, size);
+  memcpy (copy, orig, size);
+  switch (GET_CODE (orig))
+    {
+      /* RTX codes copy_rtx_if_shared_1 considers are shareable,
+        the used flag is often used for other purposes.  */
+    case REG:
+    case DEBUG_EXPR:
+    case VALUE:
+    CASE_CONST_ANY:
+    case SYMBOL_REF:
+    case CODE_LABEL:
+    case PC:
+    case CC0:
+    case RETURN:
+    case SIMPLE_RETURN:
+    case SCRATCH:
+      break;
+    default:
+      /* For all other RTXes clear the used flag on the copy.  */
+      RTX_FLAG (copy, used) = 0;
+      break;
+    }
+  return copy;
 }
 \f
 /* Nonzero when we are generating CONCATs.  */
@@ -424,7 +455,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
       return (REGNO (x) == REGNO (y));
 
     case LABEL_REF:
-      return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
+      return label_ref_label (x) == label_ref_label (y);
 
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
@@ -441,7 +472,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
 
     case DEBUG_PARAMETER_REF:
       return DEBUG_PARAMETER_REF_DECL (x)
-            == DEBUG_PARAMETER_REF_DECL (x);
+            == DEBUG_PARAMETER_REF_DECL (y);
 
     case ENTRY_VALUE:
       return rtx_equal_p_cb (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y), cb);
@@ -477,6 +508,11 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
            }
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return 0;
+         break;
+
        case 'V':
        case 'E':
          /* Two vectors must have the same length.  */
@@ -561,7 +597,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
       return (REGNO (x) == REGNO (y));
 
     case LABEL_REF:
-      return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
+      return label_ref_label (x) == label_ref_label (y);
 
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
@@ -614,6 +650,11 @@ rtx_equal_p (const_rtx x, const_rtx y)
            }
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return 0;
+         break;
+
        case 'V':
        case 'E':
          /* Two vectors must have the same length.  */
@@ -657,6 +698,31 @@ rtx_equal_p (const_rtx x, const_rtx y)
   return 1;
 }
 
+/* Return true if all elements of VEC are equal.  */
+
+bool
+rtvec_all_equal_p (const_rtvec vec)
+{
+  const_rtx first = RTVEC_ELT (vec, 0);
+  /* Optimize the important special case of a vector of constants.
+     The main use of this function is to detect whether every element
+     of CONST_VECTOR is the same.  */
+  switch (GET_CODE (first))
+    {
+    CASE_CONST_UNIQUE:
+      for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i)
+       if (first != RTVEC_ELT (vec, i))
+         return false;
+      return true;
+
+    default:
+      for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i)
+       if (!rtx_equal_p (first, RTVEC_ELT (vec, i)))
+         return false;
+      return true;
+    }
+}
+
 /* Return an indication of which type of insn should have X as a body.
    In generator files, this can be UNKNOWN if the answer is only known
    at (GCC) runtime.  Otherwise the value is CODE_LABEL, INSN, CALL_INSN
@@ -671,6 +737,8 @@ classify_insn (rtx x)
     return CALL_INSN;
   if (ANY_RETURN_P (x))
     return JUMP_INSN;
+  if (GET_CODE (x) == ASM_OPERANDS && ASM_OPERANDS_LABEL_VEC (x))
+    return JUMP_INSN;
   if (GET_CODE (x) == SET)
     {
       if (GET_CODE (SET_DEST (x)) == PC)
@@ -683,17 +751,23 @@ classify_insn (rtx x)
   if (GET_CODE (x) == PARALLEL)
     {
       int j;
+      bool has_return_p = false;
       for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
        if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
          return CALL_INSN;
        else if (ANY_RETURN_P (XVECEXP (x, 0, j)))
-         return JUMP_INSN;
+         has_return_p = true;
        else if (GET_CODE (XVECEXP (x, 0, j)) == SET
                 && GET_CODE (SET_DEST (XVECEXP (x, 0, j))) == PC)
          return JUMP_INSN;
        else if (GET_CODE (XVECEXP (x, 0, j)) == SET
                 && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL)
          return CALL_INSN;
+      if (has_return_p)
+       return JUMP_INSN;
+      if (GET_CODE (XVECEXP (x, 0, 0)) == ASM_OPERANDS
+         && ASM_OPERANDS_LABEL_VEC (XVECEXP (x, 0, 0)))
+       return JUMP_INSN;
     }
 #ifdef GENERATOR_FILE
   if (GET_CODE (x) == MATCH_OPERAND
@@ -707,10 +781,20 @@ classify_insn (rtx x)
   return INSN;
 }
 
+/* Comparator of indices based on rtx_alloc_counts.  */
+
+static int
+rtx_count_cmp (const void *p1, const void *p2)
+{
+  const unsigned *n1 = (const unsigned *)p1;
+  const unsigned *n2 = (const unsigned *)p2;
+
+  return rtx_alloc_counts[*n1] - rtx_alloc_counts[*n2];
+}
+
 void
 dump_rtx_statistics (void)
 {
-  int i;
   int total_counts = 0;
   int total_sizes = 0;
 
@@ -720,27 +804,41 @@ dump_rtx_statistics (void)
       return;
     }
 
-  fprintf (stderr, "\nRTX Kind               Count      Bytes\n");
-  fprintf (stderr, "---------------------------------------\n");
-  for (i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++)
-    if (rtx_alloc_counts[i])
-      {
-        fprintf (stderr, "%-20s %7d %10d\n", GET_RTX_NAME (i),
-                 rtx_alloc_counts[i], rtx_alloc_sizes[i]);
-        total_counts += rtx_alloc_counts[i];
-        total_sizes += rtx_alloc_sizes[i];
-      }
+  fprintf (stderr, "\nRTX Kind                   Count     Bytes\n");
+  fprintf (stderr, "-------------------------------------------\n");
+
+  auto_vec<unsigned> indices (LAST_AND_UNUSED_RTX_CODE);
+  for (unsigned i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++)
+    indices.quick_push (i);
+  indices.qsort (rtx_count_cmp);
+
+  for (unsigned i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++)
+    {
+      unsigned j = indices[i];
+      if (rtx_alloc_counts[j])
+       {
+         fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n",
+                  GET_RTX_NAME (j),
+                  SIZE_AMOUNT (rtx_alloc_counts[j]),
+                  SIZE_AMOUNT (rtx_alloc_sizes[j]));
+         total_counts += rtx_alloc_counts[j];
+         total_sizes += rtx_alloc_sizes[j];
+       }
+    }
+
   if (rtvec_alloc_counts)
     {
-      fprintf (stderr, "%-20s %7d %10d\n", "rtvec",
-               rtvec_alloc_counts, rtvec_alloc_sizes);
+      fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n", "rtvec",
+              SIZE_AMOUNT (rtvec_alloc_counts),
+              SIZE_AMOUNT (rtvec_alloc_sizes));
       total_counts += rtvec_alloc_counts;
       total_sizes += rtvec_alloc_sizes;
     }
-  fprintf (stderr, "---------------------------------------\n");
-  fprintf (stderr, "%-20s %7d %10d\n",
-           "Total", total_counts, total_sizes);
-  fprintf (stderr, "---------------------------------------\n");
+  fprintf (stderr, "-----------------------------------------------\n");
+  fprintf (stderr, "%-24s " PRsa (6) " " PRsa (9) "\n",
+          "Total", SIZE_AMOUNT (total_counts),
+          SIZE_AMOUNT (total_sizes));
+  fprintf (stderr, "-----------------------------------------------\n");
 }
 \f
 #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)
@@ -793,6 +891,17 @@ rtl_check_failed_code2 (const_rtx r, enum rtx_code code1, enum rtx_code code2,
      func, trim_filename (file), line);
 }
 
+void
+rtl_check_failed_code3 (const_rtx r, enum rtx_code code1, enum rtx_code code2,
+                       enum rtx_code code3, const char *file, int line,
+                       const char *func)
+{
+  internal_error
+    ("RTL check: expected code '%s', '%s' or '%s', have '%s' in %s, at %s:%d",
+     GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (code3),
+     GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line);
+}
+
 void
 rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, machine_mode mode,
                            bool not_mode, const char *file, int line,