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]

Extend mode macros


I've been using mode macros to clean up the altivec.md file.  There is
a shortcoming wrt UNSPEC, and this patch addresses that.

UNSPECs look like
	(UNSPEC:mode [...] MAGIC_CONSTANT)
and altivec has distinct UNSPECS for V4SI, V8HI and V16QI modes, all
with the same template, but different MAGIC_CONSTANTs.  A mode macro could
be used, but for the fact that mode attributes are not substituted into
named constants.  This patch adds that feature to the rtl reader.

I've changed the reader to store named constants in 'i' rtl fields as XSTR's
after parsing and during mode macro substitution.  Following mode macro
substitution, the rtl is scanned, substituting the named constants for
their values.  mode macro substitution does mode attribute substitution on
'i' fields.  Hey, this is just like C++ templates :)

An additonal change is that named constants can be simple summation
expressions of the form
	constant_expr : constant
		      | constant_expr + constant
		      | constant_expr - constant
        constant : name | number
but there can be no spaces in the entire expression. (I did not want
to make the name lexer more complicated, and was not sure if something
like '(+1234 +1234)' already existed in an md file -- we'd not want
to break that.)  The evaluator provides a traceback for unknown, malformed
or recursive constants.  We will lose slightly on the line number
information, as the line number will indicate the end of the toplevel
construct being parsed, rather than the location of the constant itself.

Of course, define_constant values themselves can be such expressions.  This
change is useful with mode macros as it allows the use of
	UNSPEC_base+UNSPEC_MODE_OFFSET<VI_char>
where UNSPEC_base is the base number for a set of vector operations, and
the UNSPEC_MODE_OFFSET<VI_char> expands to the offset for a particular mode.
This patch contains a single sample use for the altivec.md file.  Here
I've kept the base as a numeric literal, because that's what it was in
the original.

This deferred constant expansion change will break an undocumented feature
of the current implementation.  I do not know if it is used.  Currently,
when a name is lexed from the .md file, it is immediately expanded by
chasing the defined constant hash table until no new expansion is found.
Thus named constants could currently refer to symbols.  This could be used
for mapping one scheduler state to another for instance.  The md.texi file
does not mention this feature, only talking about mapping names directly
to numbers.

Obviously, if approved I can continue cleaning up the unspecs in the
altivec md file.

booted and tested on ppc-unknown-linux-gnualtivec. ok?

nathan

--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2004-11-22  Nathan Sidwell  <nathan@codesourcery.com>

	* read-rtl.c (fatal_with_file_and_line): Allow NULL infile.
	(apply_macro_to_rtx): Apply to constants too.
	(rtx_constant_expansion, apply_constant_expansion): New.
	(read_name): Never expand constants here.
	(read_constants): No need to hide the constant table during parsing.
	(validate_const_int): Remove.
	(expand_const): New.
	(read_rtx): Expand constants after applying macros.
	(read_rtx_1): Use expand_const as appropriate.
	* doc/md.texi (Constant Definitions): Document expression
	capability.
	(Constant Substitutions): Document symbolic constant substitutions.

	* config/rs6000/altivec.md (UNSPEC_VEC_OFFSET_b,
	UNSPEC_VEC_OFFSET_h, UNSPEC_VEC_OFFSET_w): New.
	(altivec_addvaddubs, altivec_addvadduhs,
	altivec_addvadduws): Replace with ...
	(altivec_addvaddu<VI_char>s): ... this.

Index: read-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/read-rtl.c,v
retrieving revision 1.32
diff -c -3 -p -r1.32 read-rtl.c
*** read-rtl.c	29 Sep 2004 11:23:11 -0000	1.32
--- read-rtl.c	22 Nov 2004 15:31:26 -0000
*************** static bool uses_macro_p (rtx, struct ma
*** 99,104 ****
--- 99,106 ----
  static const char *add_condition_to_string (const char *, const char *);
  static void add_condition_to_rtx (rtx, const char *);
  static int apply_macro_traverse (void **, void *);
+ static void rtx_constant_expansion (rtx);
+ static void apply_constant_expansion (rtx);
  static struct mapping *add_mapping (struct macro_group *, htab_t t,
  				    const char *, FILE *);
  static struct map_value **add_map_value (struct map_value **,
*************** static void read_escape (FILE *);
*** 112,118 ****
  static hashval_t def_hash (const void *);
  static int def_name_eq_p (const void *, const void *);
  static void read_constants (FILE *infile, char *tmp_char);
! static void validate_const_int (FILE *, const char *);
  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 *);
--- 114,120 ----
  static hashval_t def_hash (const void *);
  static int def_name_eq_p (const void *, const void *);
  static void read_constants (FILE *infile, char *tmp_char);
! static HOST_WIDE_INT expand_const (FILE *infile, char *str, int *);
  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 *);
*************** const char *read_rtx_filename = "<unknow
*** 138,146 ****
  static void
  fatal_with_file_and_line (FILE *infile, const char *msg, ...)
  {
-   char context[64];
-   size_t i;
-   int c;
    va_list ap;
  
    va_start (ap, msg);
--- 140,145 ----
*************** fatal_with_file_and_line (FILE *infile, 
*** 150,169 ****
    putc ('\n', stderr);
  
    /* Gather some following context.  */
!   for (i = 0; i < sizeof (context)-1; ++i)
      {
!       c = getc (infile);
!       if (c == EOF)
! 	break;
!       if (c == '\r' || c == '\n')
! 	break;
!       context[i] = c;
      }
!   context[i] = '\0';
! 
!   fprintf (stderr, "%s:%d: following context is `%s'\n",
! 	   read_rtx_filename, read_rtx_lineno, context);
! 
    va_end (ap);
    exit (1);
  }
--- 149,175 ----
    putc ('\n', stderr);
  
    /* Gather some following context.  */
!   if (infile)
      {
!       char context[64];
!       size_t i;
!       int c;
!       
!       for (i = 0; i < sizeof (context)-1; ++i)
! 	{
! 	  c = getc (infile);
! 	  if (c == EOF)
! 	    break;
! 	  if (c == '\r' || c == '\n')
! 	    break;
! 	  context[i] = c;
! 	}
!       context[i] = '\0';
!       
!       fprintf (stderr, "%s:%d: following context is `%s'\n",
! 	       read_rtx_filename, read_rtx_lineno, context);
      }
!   
    va_end (ap);
    exit (1);
  }
*************** apply_macro_to_rtx (rtx original, struct
*** 344,349 ****
--- 350,359 ----
  	  }
  	break;
  
+       case 'i':
+ 	XSTR (x, i) = apply_macro_to_string (XSTR (x, i), macro, value);
+ 	break;
+ 	
        default:
  	break;
        }
*************** apply_macro_traverse (void **slot, void 
*** 472,477 ****
--- 482,533 ----
    return 1;
  }
  
+ /* Recursively replace the constant expression strings currently in
+    'i' rtx fields with the value they evaluate to.  */
+ 
+ static void
+ rtx_constant_expansion (rtx x)
+ {
+   const char *format_ptr;
+   int i, j;
+ 
+   if (!x)
+     return;
+   
+   format_ptr = GET_RTX_FORMAT (GET_CODE (x));
+   for (i = 0; format_ptr[i] != 0; i++)
+     switch (format_ptr[i])
+       {
+       case 'e':
+       case 'u':
+ 	rtx_constant_expansion (XEXP (x, i));
+ 	break;
+ 
+       case 'V':
+       case 'E':
+ 	if (XVEC (x, i))
+ 	  for (j = 0; j < XVECLEN (x, i); j++)
+ 	    rtx_constant_expansion (XVECEXP (x, i, j));
+ 	break;
+ 
+       case 'i':
+ 	XINT (x, i) = expand_const (NULL, (char *)XSTR (x, i), NULL);
+ 	break;
+ 	
+       default:
+ 	break;
+       }
+ }
+ 
+ /* Apply constant expansion to the list of rtx's ELEM.  */
+ 
+ static void
+ apply_constant_expansion (rtx elem)
+ {
+   for (; elem; elem = XEXP (elem, 1))
+     rtx_constant_expansion (XEXP (elem, 0));
+ }
+ 
  /* Add a new "mapping" structure to hashtable TABLE.  NAME is the name
     of the mapping, GROUP is the group to which it belongs, and INFILE
     is the file that defined the mapping.  */
*************** read_name (char *str, FILE *infile)
*** 653,679 ****
      read_rtx_lineno++;
  
    *p = 0;
- 
-   if (md_constants)
-     {
-       /* Do constant expansion.  */
-       struct md_constant *def;
- 
-       p = str;
-       do
- 	{
- 	  struct md_constant tmp_def;
- 
- 	  tmp_def.name = p;
- 	  def = (struct md_constant *) htab_find (md_constants, &tmp_def);
- 	  if (def)
- 	    p = def->value;
- 	} while (def);
-       if (p != str)
- 	strcpy (str, p);
-     }
  }
  
  /* Subroutine of the string readers.  Handles backslash escapes.
     Caller has read the backslash, but not placed it into the obstack.  */
  static void
--- 709,717 ----
      read_rtx_lineno++;
  
    *p = 0;
  }
  
+ 
  /* Subroutine of the string readers.  Handles backslash escapes.
     Caller has read the backslash, but not placed it into the obstack.  */
  static void
*************** static void
*** 898,913 ****
  read_constants (FILE *infile, char *tmp_char)
  {
    int c;
-   htab_t defs;
  
    c = read_skip_spaces (infile);
    if (c != '[')
      fatal_expected_char (infile, '[', c);
!   defs = md_constants;
!   if (! defs)
!     defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0);
!   /* Disable constant expansion during definition processing.  */
!   md_constants = 0;
    while ( (c = read_skip_spaces (infile)) != ']')
      {
        struct md_constant *def;
--- 936,948 ----
  read_constants (FILE *infile, char *tmp_char)
  {
    int c;
  
    c = read_skip_spaces (infile);
    if (c != '[')
      fatal_expected_char (infile, '[', c);
!   if (! md_constants)
!     md_constants = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0);
!   
    while ( (c = read_skip_spaces (infile)) != ']')
      {
        struct md_constant *def;
*************** read_constants (FILE *infile, char *tmp_
*** 918,924 ****
        def = XNEW (struct md_constant);
        def->name = tmp_char;
        read_name (tmp_char, infile);
!       entry_ptr = htab_find_slot (defs, def, INSERT);
        if (! *entry_ptr)
  	def->name = xstrdup (tmp_char);
        c = read_skip_spaces (infile);
--- 953,959 ----
        def = XNEW (struct md_constant);
        def->name = tmp_char;
        read_name (tmp_char, infile);
!       entry_ptr = htab_find_slot (md_constants, def, INSERT);
        if (! *entry_ptr)
  	def->name = xstrdup (tmp_char);
        c = read_skip_spaces (infile);
*************** read_constants (FILE *infile, char *tmp_
*** 941,947 ****
        if (c != ')')
  	fatal_expected_char (infile, ')', c);
      }
-   md_constants = defs;
    c = read_skip_spaces (infile);
    if (c != ')')
      fatal_expected_char (infile, ')', c);
--- 976,981 ----
*************** traverse_md_constants (htab_trav callbac
*** 957,980 ****
      htab_traverse (md_constants, callback, info);
  }
  
! static void
! validate_const_int (FILE *infile, const char *string)
! {
!   const char *cp;
!   int valid = 1;
  
!   cp = string;
!   while (*cp && ISSPACE (*cp))
!     cp++;
!   if (*cp == '-' || *cp == '+')
!     cp++;
!   if (*cp == 0)
!     valid = 0;
!   for (; *cp; cp++)
!     if (! ISDIGIT (*cp))
!       valid = 0;
!   if (!valid)
!     fatal_with_file_and_line (infile, "invalid decimal constant \"%s\"\n", string);
  }
  
  /* Search GROUP for a mode or code called NAME and return its numerical
--- 991,1077 ----
      htab_traverse (md_constants, callback, info);
  }
  
! /* Expand a constant expression, which can consist of a sequence of
!    additions or subtractions of values.  The constant hash is examined
!    for non-numeric values.  Numbers are in decimal  */
! 
! static HOST_WIDE_INT
! expand_const (FILE *infile, char *str, int *errp)
! {
!   HOST_WIDE_INT sum = 0;
!   char *p, *end_p;
!   char c;
! 
!   for (p = str; *p; p = end_p)
!     {
!       int neg = *p == '-';
!       HOST_WIDE_INT v = 0;
!       int sym = 0;
!       
!       if (neg || *p == '+')
! 	p++;
!       for (end_p = p; *end_p; end_p++)
! 	{
! 	  c = *end_p;
! 	  if (ISDIGIT (c))
! 	    v = v * 10 + (c - '0');
! 	  else if (c == '+' || c == '-')
! 	    break;
! 	  else
! 	    sym = 1;
! 	}
!       if (sym)
! 	{
! 	  struct md_constant *def;
! 	  struct md_constant tmp_def;
! 	  int err = 0;
! 	  
! 	  c = *end_p;
! 	  *end_p = 0;
! 	  tmp_def.name = p;
! 	  def = (struct md_constant *) htab_find (md_constants, &tmp_def);
! 	  if (!def)
! 	    {
! 	      fprintf (stderr, "%s:%d: unknown symbolic constant \"%s\"\n",
! 		       read_rtx_filename, read_rtx_lineno, p);
! 	      err = 1;
! 	    }
! 	  else if (!def->value)
! 	    {
! 	      fprintf (stderr, "%s:%d: recursive symbolic constant \"%s\"\n",
! 		       read_rtx_filename, read_rtx_lineno, p);
! 	      err = 1;
! 	    }
! 	  else
! 	    {
! 	      char *expn = (char *)def->value;
  
! 	      def->value = NULL;  /* Detect recursive expansion */
! 	      v = expand_const (infile, expn, &err);
! 	      def->value = expn;
! 	    }
! 	  *end_p = c;
! 	  
! 	  if (err)
! 	    {
! 	      if (errp)
! 		{
! 		  fprintf (stderr, "%s:%d: within expression \"%s\"\n",
! 			   read_rtx_filename, read_rtx_lineno, str);
! 		  *errp = 1;
! 		  return 0;
! 		}
! 	      else
! 		fatal_with_file_and_line (infile,
! 					  "within expression \"%s\"\n", str);
! 	    }
! 	}
!       if (neg)
! 	v = -v;
!       sum += v;
!     }
!   
!   return sum;
  }
  
  /* Search GROUP for a mode or code called NAME and return its numerical
*************** read_rtx (FILE *infile, rtx *x, int *lin
*** 1105,1115 ****
--- 1202,1214 ----
  
        queue_next = queue_head;
        queue_lineno = read_rtx_lineno;
+       
        XEXP (queue_next, 0) = read_rtx_1 (infile);
        XEXP (queue_next, 1) = 0;
  
        htab_traverse (modes.macros, apply_macro_traverse, queue_next);
        htab_traverse (codes.macros, apply_macro_traverse, queue_next);
+       apply_constant_expansion (queue_next);
      }
  
    *x = XEXP (queue_next, 0);
*************** read_rtx (FILE *infile, rtx *x, int *lin
*** 1120,1126 ****
  }
  
  /* Subroutine of read_rtx that reads one construct from INFILE but
!    doesn't apply any macros.  */
  
  static rtx
  read_rtx_1 (FILE *infile)
--- 1219,1226 ----
  }
  
  /* Subroutine of read_rtx that reads one construct from INFILE but
!    doesn't apply any macros.  Also, constants in 'i' fields will be
!    stored symbolically as strings.  They must be converted later.  */
  
  static rtx
  read_rtx_1 (FILE *infile)
*************** read_rtx_1 (FILE *infile)
*** 1134,1141 ****
    char tmp_char[256];
    rtx return_rtx;
    int c;
-   int tmp_int;
-   HOST_WIDE_INT tmp_wide;
  
    /* Linked list structure for making RTXs: */
    struct rtx_list
--- 1234,1239 ----
*************** read_rtx_1 (FILE *infile)
*** 1316,1346 ****
  
        case 'w':
  	read_name (tmp_char, infile);
! 	validate_const_int (infile, tmp_char);
! #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
! 	tmp_wide = atoi (tmp_char);
! #else
! #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
! 	tmp_wide = atol (tmp_char);
! #else
! 	/* Prefer atoll over atoq, since the former is in the ISO C99 standard.
! 	   But prefer not to use our hand-rolled function above either.  */
! #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
! 	tmp_wide = atoll (tmp_char);
! #else
! 	tmp_wide = atoq (tmp_char);
! #endif
! #endif
! #endif
! 	XWINT (return_rtx, i) = tmp_wide;
  	break;
  
-       case 'i':
        case 'n':
  	read_name (tmp_char, infile);
! 	validate_const_int (infile, tmp_char);
! 	tmp_int = atoi (tmp_char);
! 	XINT (return_rtx, i) = tmp_int;
  	break;
  
        default:
--- 1414,1432 ----
  
        case 'w':
  	read_name (tmp_char, infile);
! 	XWINT (return_rtx, i) = expand_const (infile, tmp_char, NULL);
  	break;
  
        case 'n':
  	read_name (tmp_char, infile);
! 	XINT (return_rtx, i) = expand_const (infile, tmp_char, NULL);
! 	break;
! 	
!       case 'i':
! 	/* Save the expression for later evaluation.  */
! 	read_name (tmp_char, infile);
! 	obstack_grow (&string_obstack, tmp_char, strlen (tmp_char) + 1);
! 	XSTR (return_rtx, i) = (char *) obstack_finish (&string_obstack);
  	break;
  
        default:
Index: config/rs6000/altivec.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/altivec.md,v
retrieving revision 1.28
diff -c -3 -p -r1.28 altivec.md
*** config/rs6000/altivec.md	22 Nov 2004 14:56:05 -0000	1.28
--- config/rs6000/altivec.md	22 Nov 2004 15:31:55 -0000
***************
*** 20,26 ****
  ;; MA 02111-1307, USA.
  
  (define_constants
!   [(UNSPEC_VCMPBFP       50)
     (UNSPEC_VCMPEQUB      51)
     (UNSPEC_VCMPEQUH      52)
     (UNSPEC_VCMPEQUW      53)
--- 20,29 ----
  ;; MA 02111-1307, USA.
  
  (define_constants
!   [(UNSPEC_VEC_OFFSET_b  0)
!    (UNSPEC_VEC_OFFSET_h  2)
!    (UNSPEC_VEC_OFFSET_w  4)
!    (UNSPEC_VCMPBFP       50)
     (UNSPEC_VCMPEQUB      51)
     (UNSPEC_VCMPEQUH      52)
     (UNSPEC_VCMPEQUW      53)
***************
*** 245,257 ****
    "vaddcuw %0,%1,%2"
    [(set_attr "type" "vecsimple")])
  
! (define_insn "altivec_vaddubs"
!   [(set (match_operand:V16QI 0 "register_operand" "=v")
!         (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
!                        (match_operand:V16QI 2 "register_operand" "v")] 36))
     (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
    "TARGET_ALTIVEC"
!   "vaddubs %0,%1,%2"
    [(set_attr "type" "vecsimple")])
  
  (define_insn "altivec_vaddsbs"
--- 248,261 ----
    "vaddcuw %0,%1,%2"
    [(set_attr "type" "vecsimple")])
  
! (define_insn "altivec_vaddu<VI_char>s"
!   [(set (match_operand:VI 0 "register_operand" "=v")
!         (unspec:VI [(match_operand:VI 1 "register_operand" "v")
!                     (match_operand:VI 2 "register_operand" "v")]
! 		    36+UNSPEC_VEC_OFFSET_<VI_char>))
     (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
    "TARGET_ALTIVEC"
!   "vaddu<VI_char>s %0,%1,%2"
    [(set_attr "type" "vecsimple")])
  
  (define_insn "altivec_vaddsbs"
***************
*** 263,277 ****
    "vaddsbs %0,%1,%2"
    [(set_attr "type" "vecsimple")])
  
- (define_insn "altivec_vadduhs"
-   [(set (match_operand:V8HI 0 "register_operand" "=v")
-         (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
-                       (match_operand:V8HI 2 "register_operand" "v")] 38))
-    (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
-   "TARGET_ALTIVEC"
-   "vadduhs %0,%1,%2"
-   [(set_attr "type" "vecsimple")])
- 
  (define_insn "altivec_vaddshs"
    [(set (match_operand:V8HI 0 "register_operand" "=v")
          (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
--- 267,272 ----
***************
*** 281,295 ****
    "vaddshs %0,%1,%2"
    [(set_attr "type" "vecsimple")])
  
- (define_insn "altivec_vadduws"
-   [(set (match_operand:V4SI 0 "register_operand" "=v")
-         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
-                       (match_operand:V4SI 2 "register_operand" "v")] 40))
-    (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
-   "TARGET_ALTIVEC"
-   "vadduws %0,%1,%2"
-   [(set_attr "type" "vecsimple")])
- 
  (define_insn "altivec_vaddsws"
    [(set (match_operand:V4SI 0 "register_operand" "=v")
          (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
--- 276,281 ----
Index: doc/md.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/md.texi,v
retrieving revision 1.119
diff -c -3 -p -r1.119 md.texi
*** doc/md.texi	13 Nov 2004 22:28:46 -0000	1.119
--- doc/md.texi	22 Nov 2004 15:32:36 -0000
*************** generates a new pattern
*** 6388,6395 ****
  Using literal constants inside instruction patterns reduces legibility and
  can be a maintenance problem.
  
! To overcome this problem, you may use the @code{define_constants}
! expression.  It contains a vector of name-value pairs.  From that
  point on, wherever any of the names appears in the MD file, it is as
  if the corresponding value had been written instead.  You may use
  @code{define_constants} multiple times; each appearance adds more
--- 6388,6400 ----
  Using literal constants inside instruction patterns reduces legibility and
  can be a maintenance problem.
  
! Whereever a constant is required, you may have a simple expression
! constructed of sum or difference terms.  Each term can be a literal
! number, or a symbolic constant.  There must be no spaces in the expression.
! 
! Symbolic constants are defined with the @code{define_constants}
! expression.  It contains a vector of name-value pairs.  The value can be
! an expression involving other constants or literal values.  From that
  point on, wherever any of the names appears in the MD file, it is as
  if the corresponding value had been written instead.  You may use
  @code{define_constants} multiple times; each appearance adds more
*************** rtx-based construct, such as a @code{def
*** 6473,6478 ****
--- 6478,6484 ----
  @menu
  * Defining Mode Macros:: Defining a new mode macro.
  * String Substitutions:: Combining mode macros with string substitutions
+ * Constant Substitutions:: Combining mode macros with constant substitutions
  * Examples::             Examples
  @end menu
  
*************** This is exactly equivalent to:
*** 6619,6624 ****
--- 6625,6653 ----
     (set_attr "mode" "DI")])
  @end smallexample
  
+ @node Constant Substitutions
+ @subsubsection Constant Substitution in Mode Macros
+ @findex define_mode_attr
+ 
+ As with string substitutions, symbolic constants can also be
+ substituted.  This is useful when using a mode macro to expand a set of
+ UNSPEC builtins.  For instance, this from the @file{altivec.md} file.
+ 
+ @smallexample
+ (define_insn "altivec_vaddu<VI_char>s"
+   [(set (match_operand:VI 0 "register_operand" "=v")
+         (unspec:VI [(match_operand:VI 1 "register_operand" "v")
+                     (match_operand:VI 2 "register_operand" "v")]
+ 		    36+UNSPEC_VEC_OFFSET_<VI_char>))
+    (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+   "TARGET_ALTIVEC"
+   "vaddu<VI_char>s %0,%1,%2"
+   [(set_attr "type" "vecsimple")])
+ @end smallexample
+ 
+ Here, the @code{36+UNSPEC_VEC_OFFSET_<VI_char>} expands to the
+ appropriate symbolic constant, which is then added to the literal 36.
+ 
  @node Code Macros
  @subsection Code Macros
  @cindex code macros in @file{.md} files

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