This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH RFA: Permit macro attributes to set modes


I'm working on a backend which supports two different sizes of
vectors.  There are some instructions which operate on both vector
sizes.  Either vector may have elements of type int, short, etc., but
naturally both vectors need to have the same subtype.

Now that we have .md file macros, it would sure be nice to be able to
use them to write insn patterns in which setting one of the modes
determined the other modes.  That would let me write a single pattern
which used vectors of different sizes, and used a macro to iterate
over all the possible element types.  For example, VD is a macro for
all the double vector modes.  I would like to be able to define an
attribute VSMODE for the corresponding single vector modes, and then
write:

  (set (match_operand:VD 0 "register_operand" "=v")
       (vec_concat:VD (match_operand:<VSMODE> 1 "register_operand" "v")
                      (match_operand:<VSMODE> 2 "register_operand" "v")))

In fact, that would be so nice, that I implemented it.

Tested by verifying that none of the insn-*.[ch] files changed on
i686-pc-linux-gnu.  For safety, I'm also running a bootstrap, which I
am confident will complete successfully.

OK for mainline?

Ian


2005-05-10  Ian Lance Taylor  <ian@airs.com>

	* read-rtl.c (struct macro_traverse_data): Define.
	(map_attr_string): New static function, broken out of
	apply_macro_to_string.
	(mode_attr_index, apply_mode_maps): New static functions.
	(apply_macro_to_string): Call map_attr_string.
	(apply_macro_to_rtx): Add mode_maps and infile parameters.  Change
	all callers.
	(apply_macro_traverse): Expect data to point to a struct
	macro_traverse_data.
	(read_rtx): Add mode_maps local variable.  Use mode_traverse_data
	to pass data through htab_traverse.
	(read_rtx_1): Add mode_maps parameter.  Change all callers.
	Handle mode names which are attribute strings.
	* doc/md.texi (Substitutions): Rename from String Substitutions.
	Change references.  Document using attributes as modes.


Index: read-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/read-rtl.c,v
retrieving revision 1.36
diff -p -u -r1.36 read-rtl.c
--- read-rtl.c	21 Apr 2005 18:05:16 -0000	1.36
+++ read-rtl.c	10 May 2005 17:20:09 -0000
@@ -87,6 +87,17 @@ struct ptr_loc {
   int lineno;
 };
 
+/* A structure used to pass data from read_rtx to apply_macro_traverse
+   via htab_traverse.  */
+struct macro_traverse_data {
+  /* Instruction queue.  */
+  rtx queue;
+  /* Attributes seen for modes.  */
+  struct map_value *mode_maps;
+  /* Input file.  */
+  FILE *infile;
+};
+
 /* If CODE is the number of a code macro, return a real rtx code that
    has the same format.  Return CODE otherwise.  */
 #define BELLWETHER_CODE(CODE) \
@@ -102,7 +113,8 @@ static int find_code (const char *, FILE
 static bool uses_code_macro_p (rtx, int);
 static void apply_code_macro (rtx, int);
 static const char *apply_macro_to_string (const char *, struct mapping *, int);
-static rtx apply_macro_to_rtx (rtx, struct mapping *, int);
+static rtx apply_macro_to_rtx (rtx, struct mapping *, int,
+			       struct map_value *, FILE *);
 static bool uses_macro_p (rtx, struct mapping *);
 static const char *add_condition_to_string (const char *, const char *);
 static void add_condition_to_rtx (rtx, const char *);
@@ -128,7 +140,7 @@ static void validate_const_int (FILE *, 
 static int find_macro (struct macro_group *, const char *, FILE *);
 static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *);
 static void check_code_macro (struct mapping *, FILE *);
-static rtx read_rtx_1 (FILE *);
+static rtx read_rtx_1 (FILE *, struct map_value **);
 
 /* The mode and code macro structures.  */
 static struct macro_group modes, codes;
@@ -258,6 +270,115 @@ apply_code_macro (rtx x, int code)
   PUT_CODE (x, code);
 }
 
+/* Map a code or mode attribute string P to the underlying string for
+   MACRO and VALUE.  */
+
+static struct map_value *
+map_attr_string (const char *p, struct mapping *macro, int value)
+{
+  const char *attr;
+  struct mapping *m;
+  struct map_value *v;
+
+  /* If there's a "macro:" prefix, check whether the macro name matches.
+     Set ATTR to the start of the attribute name.  */
+  attr = strchr (p, ':');
+  if (attr == 0)
+    attr = p;
+  else
+    {
+      if (strncmp (p, macro->name, attr - p) != 0
+	  || macro->name[attr - p] != 0)
+	return 0;
+      attr++;
+    }
+
+  /* Find the attribute specification.  */
+  m = (struct mapping *) htab_find (macro->group->attrs, &attr);
+  if (m == 0)
+    return 0;
+
+  /* Find the attribute value for VALUE.  */
+  for (v = m->values; v != 0; v = v->next)
+    if (v->number == value)
+      break;
+
+  return v;
+}
+
+/* Given an attribute string used as a machine mode, return an index
+   to store in the machine mode to be translated by
+   apply_macro_to_rtx.  */
+
+static unsigned int
+mode_attr_index (struct map_value **mode_maps, const char *string,
+		 FILE *infile)
+{
+  char *p;
+  char *attr;
+  struct map_value *mv;
+
+  /* Copy the attribute string into permanent storage, without the
+     angle brackets around it.  */
+  obstack_grow (&string_obstack, string + 1, strlen (string) - 2);
+  p = (char *) obstack_finish (&string_obstack);
+
+  /* Make sure the attribute is defined as either a code attribute or
+     a mode attribute.  */
+  attr = strchr (p, ':');
+  if (attr == 0)
+    attr = p;
+  else
+    ++attr;
+
+  if (!htab_find (modes.attrs, &attr) && !htab_find (codes.attrs, &attr))
+    fatal_with_file_and_line (infile,
+			      "undefined attribute '%s' used for mode",
+			      p);
+
+  mv = XNEW (struct map_value);
+  mv->number = *mode_maps == 0 ? 0 : (*mode_maps)->number + 1;
+  mv->string = p;
+  mv->next = *mode_maps;
+  *mode_maps = mv;
+
+  /* We return a code which we can map back into this string: the
+     number of machine modes + the number of mode macros + the index
+     we just used.  */
+  return MAX_MACHINE_MODE + htab_elements (modes.macros) + mv->number;
+}
+
+/* Apply MODE_MAPS to the top level of X.  */
+
+static void
+apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *macro,
+		 int value, FILE *infile)
+{
+  unsigned int offset;
+  int indx;
+  struct map_value *pm;
+
+  offset = MAX_MACHINE_MODE + htab_elements (modes.macros);
+  if (GET_MODE (x) < offset)
+    return;
+
+  indx = GET_MODE (x) - offset;
+  for (pm = mode_maps; pm; pm = pm->next)
+    {
+      if (pm->number == indx)
+	{
+	  struct map_value *v;
+
+	  v = map_attr_string (pm->string, macro, value);
+	  if (v)
+	    {
+	      PUT_MODE (x, find_mode (v->string, infile));
+	      return;
+	    }
+	}
+    }
+}
+
 /* Given that MACRO is being expanded as VALUE, apply the appropriate
    string substitutions to STRING.  Return the new string if any changes
    were needed, otherwise return STRING itself.  */
@@ -265,8 +386,7 @@ apply_code_macro (rtx x, int code)
 static const char *
 apply_macro_to_string (const char *string, struct mapping *macro, int value)
 {
-  char *base, *copy, *p, *attr, *start, *end;
-  struct mapping *m;
+  char *base, *copy, *p, *start, *end;
   struct map_value *v;
 
   if (string == 0)
@@ -277,30 +397,9 @@ apply_macro_to_string (const char *strin
     {
       p = start + 1;
 
-      /* If there's a "macro:" prefix, check whether the macro name matches.
-	 Set ATTR to the start of the attribute name.  */
-      attr = strchr (p, ':');
-      if (attr == 0 || attr > end)
-	attr = p;
-      else
-	{
-	  if (strncmp (p, macro->name, attr - p) != 0
-	      || macro->name[attr - p] != 0)
-	    continue;
-	  attr++;
-	}
-
-      /* Find the attribute specification.  */
       *end = 0;
-      m = (struct mapping *) htab_find (macro->group->attrs, &attr);
+      v = map_attr_string (p, macro, value);
       *end = '>';
-      if (m == 0)
-	continue;
-
-      /* Find the attribute value for VALUE.  */
-      for (v = m->values; v != 0; v = v->next)
-	if (v->number == value)
-	  break;
       if (v == 0)
 	continue;
 
@@ -324,7 +423,8 @@ apply_macro_to_string (const char *strin
    replaced by VALUE.  */
 
 static rtx
-apply_macro_to_rtx (rtx original, struct mapping *macro, int value)
+apply_macro_to_rtx (rtx original, struct mapping *macro, int value,
+		    struct map_value *mode_maps, FILE *infile)
 {
   struct macro_group *group;
   const char *format_ptr;
@@ -345,6 +445,9 @@ apply_macro_to_rtx (rtx original, struct
   if (group->uses_macro_p (x, macro->index + group->num_builtins))
     group->apply_macro (x, value);
 
+  if (mode_maps)
+    apply_mode_maps (x, mode_maps, macro, value, infile);
+
   /* Change each string and recursively change each rtx.  */
   format_ptr = GET_RTX_FORMAT (bellwether_code);
   for (i = 0; format_ptr[i] != 0; i++)
@@ -360,7 +463,8 @@ apply_macro_to_rtx (rtx original, struct
 	break;
 
       case 'e':
-	XEXP (x, i) = apply_macro_to_rtx (XEXP (x, i), macro, value);
+	XEXP (x, i) = apply_macro_to_rtx (XEXP (x, i), macro, value,
+					  mode_maps, infile);
 	break;
 
       case 'V':
@@ -370,7 +474,8 @@ apply_macro_to_rtx (rtx original, struct
 	    XVEC (x, i) = rtvec_alloc (XVECLEN (original, i));
 	    for (j = 0; j < XVECLEN (x, i); j++)
 	      XVECEXP (x, i, j) = apply_macro_to_rtx (XVECEXP (original, i, j),
-						      macro, value);
+						      macro, value, mode_maps,
+						      infile);
 	  }
 	break;
 
@@ -467,18 +572,20 @@ add_condition_to_rtx (rtx x, const char 
 static int
 apply_macro_traverse (void **slot, void *data)
 {
+  struct macro_traverse_data *mtd = (struct macro_traverse_data *) data;
   struct mapping *macro;
   struct map_value *v;
   rtx elem, new_elem, original, x;
 
   macro = (struct mapping *) *slot;
-  for (elem = (rtx) data; elem != 0; elem = XEXP (elem, 1))
+  for (elem = mtd->queue; elem != 0; elem = XEXP (elem, 1))
     if (uses_macro_p (XEXP (elem, 0), macro))
       {
 	original = XEXP (elem, 0);
 	for (v = macro->values; v != 0; v = v->next)
 	  {
-	    x = apply_macro_to_rtx (original, macro, v->number);
+	    x = apply_macro_to_rtx (original, macro, v->number,
+				    mtd->mode_maps, mtd->infile);
 	    add_condition_to_rtx (x, v->string);
 	    if (v != macro->values)
 	      {
@@ -1238,6 +1345,9 @@ read_rtx (FILE *infile, rtx *x, int *lin
 
   if (queue_next == 0)
     {
+      struct map_value *mode_maps;
+      struct macro_traverse_data mtd;
+
       c = read_skip_spaces (infile);
       if (c == EOF)
 	return false;
@@ -1245,11 +1355,15 @@ read_rtx (FILE *infile, rtx *x, int *lin
 
       queue_next = queue_head;
       queue_lineno = read_rtx_lineno;
-      XEXP (queue_next, 0) = read_rtx_1 (infile);
+      mode_maps = 0;
+      XEXP (queue_next, 0) = read_rtx_1 (infile, &mode_maps);
       XEXP (queue_next, 1) = 0;
 
-      htab_traverse (modes.macros, apply_macro_traverse, queue_next);
-      htab_traverse (codes.macros, apply_macro_traverse, queue_next);
+      mtd.queue = queue_next;
+      mtd.mode_maps = mode_maps;
+      mtd.infile = infile;
+      htab_traverse (modes.macros, apply_macro_traverse, &mtd);
+      htab_traverse (codes.macros, apply_macro_traverse, &mtd);
     }
 
   *x = XEXP (queue_next, 0);
@@ -1263,7 +1377,7 @@ read_rtx (FILE *infile, rtx *x, int *lin
    doesn't apply any macros.  */
 
 static rtx
-read_rtx_1 (FILE *infile)
+read_rtx_1 (FILE *infile, struct map_value **mode_maps)
 {
   int i;
   RTX_CODE real_code, bellwether_code;
@@ -1337,8 +1451,16 @@ read_rtx_1 (FILE *infile)
   i = read_skip_spaces (infile);
   if (i == ':')
     {
+      unsigned int mode;
+
       read_name (tmp_char, infile);
-      PUT_MODE (return_rtx, find_macro (&modes, tmp_char, infile));
+      if (tmp_char[0] != '<' || tmp_char[strlen (tmp_char) - 1] != '>')
+	mode = find_macro (&modes, tmp_char, infile);
+      else
+	mode = mode_attr_index (mode_maps, tmp_char, infile);
+      PUT_MODE (return_rtx, mode);
+      if (GET_MODE (return_rtx) != mode)
+	fatal_with_file_and_line (infile, "mode too large");
     }
   else
     ungetc (i, infile);
@@ -1353,7 +1475,7 @@ read_rtx_1 (FILE *infile)
 
       case 'e':
       case 'u':
-	XEXP (return_rtx, i) = read_rtx_1 (infile);
+	XEXP (return_rtx, i) = read_rtx_1 (infile, mode_maps);
 	break;
 
       case 'V':
@@ -1385,7 +1507,7 @@ read_rtx_1 (FILE *infile)
 	    {
 	      ungetc (c, infile);
 	      list_counter++;
-	      obstack_ptr_grow (&vector_stack, read_rtx_1 (infile));
+	      obstack_ptr_grow (&vector_stack, read_rtx_1 (infile, mode_maps));
 	    }
 	  if (list_counter > 0)
 	    {
Index: doc/md.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/md.texi,v
retrieving revision 1.132
diff -p -u -r1.132 md.texi
--- doc/md.texi	23 Apr 2005 04:27:48 -0000	1.132
+++ doc/md.texi	10 May 2005 17:20:10 -0000
@@ -6718,7 +6718,7 @@ rtx-based construct, such as a @code{def
 
 @menu
 * Defining Mode Macros:: Defining a new mode macro.
-* String Substitutions:: Combining mode macros with string substitutions
+* Substitutions::	 Combining mode macros with substitutions
 * Examples::             Examples
 @end menu
 
@@ -6764,14 +6764,15 @@ but that the @code{:SI} expansion has no
 
 Macros are applied in the order they are defined.  This can be
 significant if two macros are used in a construct that requires
-string substitutions.  @xref{String Substitutions}.
+substitutions.  @xref{Substitutions}.
 
-@node String Substitutions
-@subsubsection String Substitution in Mode Macros
+@node Substitutions
+@subsubsection Substitution in Mode Macros
 @findex define_mode_attr
 
 If an @file{.md} file construct uses mode macros, each version of the
-construct will often need slightly different strings.  For example:
+construct will often need slightly different strings or modes.  For
+example:
 
 @itemize @bullet
 @item
@@ -6782,6 +6783,11 @@ appropriate mode name for @var{m}.
 @item
 When a @code{define_insn} defines several instruction patterns,
 each instruction will often use a different assembler mnemonic.
+
+@item
+When a @code{define_insn} requires operands with different modes,
+using a macro for one of the operand modes usually requires a specific
+mode for the other operand(s).
 @end itemize
 
 GCC supports such variations through a system of ``mode attributes''.
@@ -6796,12 +6802,12 @@ upper case.  You can define other attrib
 where @var{name} is the name of the attribute and @var{valuei}
 is the value associated with @var{modei}.
 
-When GCC replaces some @var{:macro} with @var{:mode}, it will
-scan each string in the pattern for sequences of the form
-@code{<@var{macro}:@var{attr}>}, where @var{attr} is the name of
-a mode attribute.  If the attribute is defined for @var{mode}, the
-whole @code{<...>} sequence will be replaced by the appropriate
-attribute value.
+When GCC replaces some @var{:macro} with @var{:mode}, it will scan
+each string and mode in the pattern for sequences of the form
+@code{<@var{macro}:@var{attr}>}, where @var{attr} is the name of a
+mode attribute.  If the attribute is defined for @var{mode}, the whole
+@code{<...>} sequence will be replaced by the appropriate attribute
+value.
 
 For example, suppose an @file{.md} file has:
 
@@ -6815,6 +6821,15 @@ If one of the patterns that uses @code{:
 will use @code{"lw\t%0,%1"} and the @code{DI} version will use
 @code{"ld\t%0,%1"}.
 
+Here is an example of using an attribute for a mode:
+
+@smallexample
+(define_mode_macro LONG [SI DI])
+(define_mode_attr SHORT [(SI "HI") (DI "SI")])
+(define_insn ...
+  (sign_extend:LONG (match_operand:<LONG:SHORT> ...)) ...)
+@end smallexample
+
 The @code{@var{macro}:} prefix may be omitted, in which case the
 substitution will be attempted for every macro expansion.
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]