diff gcc/rtl.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/rtl.c	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/rtl.c	Fri Oct 27 22:46:09 2017 +0900
@@ -1,7 +1,5 @@
 /* RTL utility routines.
-   Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 1987-2017 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -31,10 +29,10 @@
 #include "coretypes.h"
 #include "tm.h"
 #include "rtl.h"
-#include "ggc.h"
 #ifdef GENERATOR_FILE
 # include "errors.h"
 #else
+# include "rtlhash.h"
 # include "diagnostic-core.h"
 #endif
 
@@ -90,7 +88,8 @@
          prints the uid of the insn.
      "b" is a pointer to a bitmap header.
      "B" is a basic block pointer.
-     "t" is a tree pointer.  */
+     "t" is a tree pointer.
+     "r" a register.  */
 
 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   FORMAT ,
 #include "rtl.def"		/* rtl expressions are defined here */
@@ -110,8 +109,11 @@
 
 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_INT || (ENUM) == CONST_DOUBLE			\
+    || (ENUM) == CONST_FIXED || (ENUM) == CONST_WIDE_INT)		\
    ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT)	\
+   : (ENUM) == REG							\
+   ? RTX_HDR_SIZE + sizeof (reg_info)					\
    : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)),
 
 #include "rtl.def"
@@ -134,12 +136,10 @@
 #undef DEF_REG_NOTE
 };
 
-#ifdef GATHER_STATISTICS
 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;
-#endif
 
 
 /* Allocate an rtx vector of N elements.
@@ -156,10 +156,11 @@
 
   PUT_NUM_ELEM (rt, n);
 
-#ifdef GATHER_STATISTICS
-  rtvec_alloc_counts++;
-  rtvec_alloc_sizes += n * sizeof (rtx);
-#endif
+  if (GATHER_STATISTICS)
+    {
+      rtvec_alloc_counts++;
+      rtvec_alloc_sizes += n * sizeof (rtx);
+    }
 
   return rt;
 }
@@ -183,19 +184,24 @@
 unsigned int
 rtx_size (const_rtx x)
 {
+  if (CONST_WIDE_INT_P (x))
+    return (RTX_HDR_SIZE
+	    + sizeof (struct hwivec_def)
+	    + ((CONST_WIDE_INT_NUNITS (x) - 1)
+	       * sizeof (HOST_WIDE_INT)));
   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));
 }
 
-/* Allocate an rtx of code CODE.  The CODE is stored in the rtx;
-   all the rest is initialized to zero.  */
+/* Allocate an rtx of code CODE with EXTRA bytes in it.  The CODE is
+   stored in the rtx; all the rest is initialized to zero.  */
 
 rtx
-rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL)
+rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
 {
-  rtx rt = ggc_alloc_zone_rtx_def_stat (&rtl_zone, RTX_CODE_SIZE (code)
-                                        PASS_MEM_STAT);
+  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
@@ -204,14 +210,40 @@
   memset (rt, 0, RTX_HDR_SIZE);
   PUT_CODE (rt, code);
 
-#ifdef GATHER_STATISTICS
-  rtx_alloc_counts[code]++;
-  rtx_alloc_sizes[code] += RTX_CODE_SIZE (code);
-#endif
+  if (GATHER_STATISTICS)
+    {
+      rtx_alloc_counts[code]++;
+      rtx_alloc_sizes[code] += RTX_CODE_SIZE (code);
+    }
 
   return rt;
 }
 
+/* Allocate an rtx of code CODE.  The CODE is stored in the rtx;
+   all the rest is initialized to zero.  */
+
+rtx
+rtx_alloc (RTX_CODE code MEM_STAT_DECL)
+{
+  return rtx_alloc_stat_v (code PASS_MEM_STAT, 0);
+}
+
+/* Write the wide constant X to OUTFILE.  */
+
+void
+cwi_output_hex (FILE *outfile, const_rtx x)
+{
+  int i = CWI_GET_NUM_ELEM (x);
+  gcc_assert (i > 0);
+  if (CWI_ELT (x, i - 1) == 0)
+    /* The HOST_WIDE_INT_PRINT_HEX prepends a 0x only if the val is
+       non zero.  We want all numbers to have a 0x prefix.  */
+    fprintf (outfile, "0x");
+  fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, CWI_ELT (x, --i));
+  while (--i >= 0)
+    fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX, CWI_ELT (x, i));
+}
+
 
 /* Return true if ORIG is a sharable CONST.  */
 
@@ -224,7 +256,7 @@
      a LABEL_REF, it isn't sharable.  */
   return (GET_CODE (XEXP (orig, 0)) == PLUS
 	  && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
-	  && CONST_INT_P(XEXP (XEXP (orig, 0), 1)));
+	  && CONST_INT_P (XEXP (XEXP (orig, 0), 1)));
 }
 
 
@@ -247,19 +279,22 @@
     case REG:
     case DEBUG_EXPR:
     case VALUE:
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST_FIXED:
-    case CONST_VECTOR:
+    CASE_CONST_ANY:
     case SYMBOL_REF:
     case CODE_LABEL:
     case PC:
     case CC0:
+    case RETURN:
+    case SIMPLE_RETURN:
     case SCRATCH:
       /* SCRATCH must be shared because they represent distinct values.  */
       return orig;
     case CLOBBER:
-      if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER)
+      /* Share clobbers of hard registers (like cc0), but do not share pseudo reg
+         clobbers or clobbers of hard registers that originated as pseudos.
+         This is needed to allow safe register renaming.  */
+      if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER
+	  && ORIGINAL_REGNO (XEXP (orig, 0)) == REGNO (XEXP (orig, 0)))
 	return orig;
       break;
 
@@ -283,16 +318,6 @@
      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;
-
-  /* We do not copy FRAME_RELATED for INSNs.  */
-  if (INSN_P (orig))
-    RTX_FLAG (copy, frame_related) = 0;
-  RTX_FLAG (copy, jump) = RTX_FLAG (orig, jump);
-  RTX_FLAG (copy, call) = RTX_FLAG (orig, call);
-
   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
 
   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
@@ -334,11 +359,33 @@
 /* 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_zone_rtx_def_stat (&rtl_zone, size PASS_MEM_STAT);
-  return (rtx) memcpy (copy, orig, size);
+  rtx const copy = ggc_alloc_rtx_def_stat (size PASS_MEM_STAT);
+  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;
 }
 
 /* Nonzero when we are generating CONCATs.  */
@@ -384,7 +431,7 @@
   if (GET_MODE (x) != GET_MODE (y))
     return 0;
 
-  /* MEMs refering to different address space are not equivalent.  */
+  /* MEMs referring to different address space are not equivalent.  */
   if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
     return 0;
 
@@ -395,7 +442,7 @@
       return (REGNO (x) == REGNO (y));
 
     case LABEL_REF:
-      return XEXP (x, 0) == XEXP (y, 0);
+      return label_ref_label (x) == label_ref_label (y);
 
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
@@ -403,15 +450,20 @@
     case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
-    case CONST_DOUBLE:
-    case CONST_INT:
-    case CONST_FIXED:
+    CASE_CONST_UNIQUE:
       return 0;
 
     case DEBUG_IMPLICIT_PTR:
       return DEBUG_IMPLICIT_PTR_DECL (x)
 	     == DEBUG_IMPLICIT_PTR_DECL (y);
 
+    case DEBUG_PARAMETER_REF:
+      return 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);
+
     default:
       break;
     }
@@ -436,7 +488,7 @@
 #ifndef GENERATOR_FILE
 	      if (((code == ASM_OPERANDS && i == 6)
 		   || (code == ASM_INPUT && i == 1))
-		  && locator_eq (XINT (x, i), XINT (y, i)))
+		  && XINT (x, i) == XINT (y, i))
 		break;
 #endif
 	      return 0;
@@ -516,7 +568,7 @@
   if (GET_MODE (x) != GET_MODE (y))
     return 0;
 
-  /* MEMs refering to different address space are not equivalent.  */
+  /* MEMs referring to different address space are not equivalent.  */
   if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
     return 0;
 
@@ -527,7 +579,7 @@
       return (REGNO (x) == REGNO (y));
 
     case LABEL_REF:
-      return XEXP (x, 0) == XEXP (y, 0);
+      return label_ref_label (x) == label_ref_label (y);
 
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
@@ -535,15 +587,20 @@
     case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
-    case CONST_DOUBLE:
-    case CONST_INT:
-    case CONST_FIXED:
+    CASE_CONST_UNIQUE:
       return 0;
 
     case DEBUG_IMPLICIT_PTR:
       return DEBUG_IMPLICIT_PTR_DECL (x)
 	     == DEBUG_IMPLICIT_PTR_DECL (y);
 
+    case DEBUG_PARAMETER_REF:
+      return DEBUG_PARAMETER_REF_DECL (x)
+	     == DEBUG_PARAMETER_REF_DECL (y);
+
+    case ENTRY_VALUE:
+      return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y));
+
     default:
       break;
     }
@@ -568,7 +625,7 @@
 #ifndef GENERATOR_FILE
 	      if (((code == ASM_OPERANDS && i == 6)
 		   || (code == ASM_INPUT && i == 1))
-		  && locator_eq (XINT (x, i), XINT (y, i)))
+		  && XINT (x, i) == XINT (y, i))
 		break;
 #endif
 	      return 0;
@@ -618,86 +675,97 @@
   return 1;
 }
 
-/* Iteratively hash rtx X.  */
+/* Return true if all elements of VEC are equal.  */
 
-hashval_t
-iterative_hash_rtx (const_rtx x, hashval_t hash)
+bool
+rtvec_all_equal_p (const_rtvec vec)
 {
-  enum rtx_code code;
-  enum machine_mode mode;
-  int i, j;
-  const char *fmt;
-
-  if (x == NULL_RTX)
-    return hash;
-  code = GET_CODE (x);
-  hash = iterative_hash_object (code, hash);
-  mode = GET_MODE (x);
-  hash = iterative_hash_object (mode, hash);
-  switch (code)
+  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 REG:
-      i = REGNO (x);
-      return iterative_hash_object (i, hash);
-    case CONST_INT:
-      return iterative_hash_object (INTVAL (x), hash);
-    case SYMBOL_REF:
-      if (XSTR (x, 0))
-	return iterative_hash (XSTR (x, 0), strlen (XSTR (x, 0)) + 1,
-			       hash);
-      return hash;
-    case LABEL_REF:
-    case DEBUG_EXPR:
-    case VALUE:
-    case SCRATCH:
-    case CONST_DOUBLE:
-    case CONST_FIXED:
-    case DEBUG_IMPLICIT_PTR:
-      return hash;
+    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:
-      break;
+      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
+   or JUMP_INSN.  */
 
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    switch (fmt[i])
-      {
-      case 'w':
-	hash = iterative_hash_object (XWINT (x, i), hash);
-	break;
-      case 'n':
-      case 'i':
-	hash = iterative_hash_object (XINT (x, i), hash);
-	break;
-      case 'V':
-      case 'E':
-	j = XVECLEN (x, i);
-	hash = iterative_hash_object (j, hash);
-	for (j = 0; j < XVECLEN (x, i); j++)
-	  hash = iterative_hash_rtx (XVECEXP (x, i, j), hash);
-	break;
-      case 'e':
-	hash = iterative_hash_rtx (XEXP (x, i), hash);
-	break;
-      case 'S':
-      case 's':
-	if (XSTR (x, i))
-	  hash = iterative_hash (XSTR (x, 0), strlen (XSTR (x, 0)) + 1,
-				 hash);
-	break;
-      default:
-	break;
-      }
-  return hash;
+enum rtx_code
+classify_insn (rtx x)
+{
+  if (LABEL_P (x))
+    return CODE_LABEL;
+  if (GET_CODE (x) == CALL)
+    return CALL_INSN;
+  if (ANY_RETURN_P (x))
+    return JUMP_INSN;
+  if (GET_CODE (x) == SET)
+    {
+      if (GET_CODE (SET_DEST (x)) == PC)
+	return JUMP_INSN;
+      else if (GET_CODE (SET_SRC (x)) == CALL)
+	return CALL_INSN;
+      else
+	return INSN;
+    }
+  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)))
+	  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;
+    }
+#ifdef GENERATOR_FILE
+  if (GET_CODE (x) == MATCH_OPERAND
+      || GET_CODE (x) == MATCH_OPERATOR
+      || GET_CODE (x) == MATCH_PARALLEL
+      || GET_CODE (x) == MATCH_OP_DUP
+      || GET_CODE (x) == MATCH_DUP
+      || GET_CODE (x) == PARALLEL)
+    return UNKNOWN;
+#endif
+  return INSN;
 }
 
 void
 dump_rtx_statistics (void)
 {
-#ifdef GATHER_STATISTICS
   int i;
   int total_counts = 0;
   int total_sizes = 0;
+
+  if (! GATHER_STATISTICS)
+    {
+      fprintf (stderr, "No RTX statistics\n");
+      return;
+    }
+
   fprintf (stderr, "\nRTX Kind               Count      Bytes\n");
   fprintf (stderr, "---------------------------------------\n");
   for (i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++)
@@ -719,7 +787,6 @@
   fprintf (stderr, "%-20s %7d %10d\n",
            "Total", total_counts, total_sizes);
   fprintf (stderr, "---------------------------------------\n");
-#endif
 }
 
 #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)
@@ -773,7 +840,7 @@
 }
 
 void
-rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, enum machine_mode mode,
+rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, machine_mode mode,
 			    bool not_mode, const char *file, int line,
 			    const char *func)
 {
@@ -800,6 +867,16 @@
 
 /* XXX Maybe print the vector?  */
 void
+cwi_check_failed_bounds (const_rtx x, int n, const char *file, int line,
+			 const char *func)
+{
+  internal_error
+    ("RTL check: access of hwi elt %d of vector with last elt %d in %s, at %s:%d",
+     n, CWI_GET_NUM_ELEM (x) - 1, func, trim_filename (file), line);
+}
+
+/* XXX Maybe print the vector?  */
+void
 rtvec_check_failed_bounds (const_rtvec r, int n, const char *file, int line,
 			   const char *func)
 {