diff gcc/stor-layout.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/stor-layout.c	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/stor-layout.c	Thu Feb 13 11:34:05 2020 +0900
@@ -1,5 +1,5 @@
 /* C-compiler utilities for types and variables storage layout
-   Copyright (C) 1987-2018 Free Software Foundation, Inc.
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -42,6 +42,7 @@
 #include "gimplify.h"
 #include "attribs.h"
 #include "debug.h"
+#include "calls.h"
 
 /* Data type for the expressions representing sizes of data types.
    It is the first integer type laid out.  */
@@ -514,18 +515,43 @@
   return opt_machine_mode ();
 }
 
-/* Return the mode for a vector that has NUNITS integer elements of
-   INT_BITS bits each, if such a mode exists.  The mode can be either
-   an integer mode or a vector mode.  */
+/* If a piece of code is using vector mode VECTOR_MODE and also wants
+   to operate on elements of mode ELEMENT_MODE, return the vector mode
+   it should use for those elements.  If NUNITS is nonzero, ensure that
+   the mode has exactly NUNITS elements, otherwise pick whichever vector
+   size pairs the most naturally with VECTOR_MODE; this may mean choosing
+   a mode with a different size and/or number of elements, depending on
+   what the target prefers.  Return an empty opt_machine_mode if there
+   is no supported vector mode with the required properties.
+
+   Unlike mode_for_vector. any returned mode is guaranteed to satisfy
+   both VECTOR_MODE_P and targetm.vector_mode_supported_p.  */
 
 opt_machine_mode
-mode_for_int_vector (unsigned int int_bits, poly_uint64 nunits)
+related_vector_mode (machine_mode vector_mode, scalar_mode element_mode,
+		     poly_uint64 nunits)
 {
+  gcc_assert (VECTOR_MODE_P (vector_mode));
+  return targetm.vectorize.related_mode (vector_mode, element_mode, nunits);
+}
+
+/* If a piece of code is using vector mode VECTOR_MODE and also wants
+   to operate on integer vectors with the same element size and number
+   of elements, return the vector mode it should use.  Return an empty
+   opt_machine_mode if there is no supported vector mode with the
+   required properties.
+
+   Unlike mode_for_vector. any returned mode is guaranteed to satisfy
+   both VECTOR_MODE_P and targetm.vector_mode_supported_p.  */
+
+opt_machine_mode
+related_int_vector_mode (machine_mode vector_mode)
+{
+  gcc_assert (VECTOR_MODE_P (vector_mode));
   scalar_int_mode int_mode;
-  machine_mode vec_mode;
-  if (int_mode_for_size (int_bits, 0).exists (&int_mode)
-      && mode_for_vector (int_mode, nunits).exists (&vec_mode))
-    return vec_mode;
+  if (int_mode_for_mode (GET_MODE_INNER (vector_mode)).exists (&int_mode))
+    return related_vector_mode (vector_mode, int_mode,
+				GET_MODE_NUNITS (vector_mode));
   return opt_machine_mode ();
 }
 
@@ -1810,7 +1836,8 @@
      line.  */
   SET_TYPE_MODE (type, BLKmode);
 
-  if (! tree_fits_uhwi_p (TYPE_SIZE (type)))
+  poly_uint64 type_size;
+  if (!poly_int_tree_p (TYPE_SIZE (type), &type_size))
     return;
 
   /* A record which has any BLKmode members must itself be
@@ -1821,20 +1848,27 @@
       if (TREE_CODE (field) != FIELD_DECL)
 	continue;
 
+      poly_uint64 field_size;
       if (TREE_CODE (TREE_TYPE (field)) == ERROR_MARK
 	  || (TYPE_MODE (TREE_TYPE (field)) == BLKmode
 	      && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field))
 	      && !(TYPE_SIZE (TREE_TYPE (field)) != 0
 		   && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))))
-	  || ! tree_fits_uhwi_p (bit_position (field))
+	  || !tree_fits_poly_uint64_p (bit_position (field))
 	  || DECL_SIZE (field) == 0
-	  || ! tree_fits_uhwi_p (DECL_SIZE (field)))
+	  || !poly_int_tree_p (DECL_SIZE (field), &field_size))
 	return;
 
       /* If this field is the whole struct, remember its mode so
 	 that, say, we can put a double in a class into a DF
 	 register instead of forcing it to live in the stack.  */
-      if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
+      if (known_eq (field_size, type_size)
+	  /* Partial int types (e.g. __int20) may have TYPE_SIZE equal to
+	     wider types (e.g. int32), despite precision being less.  Ensure
+	     that the TYPE_MODE of the struct does not get set to the partial
+	     int mode if there is a wider type also in the struct.  */
+	  && known_gt (GET_MODE_PRECISION (DECL_MODE (field)),
+		       GET_MODE_PRECISION (mode)))
 	mode = DECL_MODE (field);
 
       /* With some targets, it is sub-optimal to access an aligned
@@ -1844,12 +1878,18 @@
     }
 
   /* If we only have one real field; use its mode if that mode's size
-     matches the type's size.  This only applies to RECORD_TYPE.  This
-     does not apply to unions.  */
-  poly_uint64 type_size;
-  if (TREE_CODE (type) == RECORD_TYPE
+     matches the type's size.  This generally only applies to RECORD_TYPE.
+     For UNION_TYPE, if the widest field is MODE_INT then use that mode.
+     If the widest field is MODE_PARTIAL_INT, and the union will be passed
+     by reference, then use that mode.  */
+  if ((TREE_CODE (type) == RECORD_TYPE
+       || (TREE_CODE (type) == UNION_TYPE
+	   && (GET_MODE_CLASS (mode) == MODE_INT
+	       || (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
+		   && (targetm.calls.pass_by_reference
+		       (pack_cumulative_args (0),
+			function_arg_info (type, mode, /*named=*/false)))))))
       && mode != VOIDmode
-      && poly_int_tree_p (TYPE_SIZE (type), &type_size)
       && known_eq (GET_MODE_BITSIZE (mode), type_size))
     ;
   else
@@ -2703,10 +2743,12 @@
       for (i = 0; i < NUM_INT_N_ENTS; i++)
 	if (int_n_enabled_p[i])
 	  {
-	    char name[50];
+	    char name[50], altname[50];
 	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
-
-	    if (strcmp (name, SIZETYPE) == 0)
+	    sprintf (altname, "__int%d__ unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZETYPE) == 0
+		|| strcmp (altname, SIZETYPE) == 0)
 	      {
 		precision = int_n_data[i].bitsize;
 	      }