]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
genoutput.c (process_template): Process '*' in '@' alternatives.
authorJ"orn Rennecke <joern.rennecke@arc.com>
Mon, 15 Oct 2012 12:44:40 +0000 (12:44 +0000)
committerJoern Rennecke <amylaar@gcc.gnu.org>
Mon, 15 Oct 2012 12:44:40 +0000 (13:44 +0100)
* genoutput.c (process_template): Process '*' in '@' alternatives.
* doc/md.texi (node Output Statement): Provide example for the above.

From-SVN: r192457

gcc/ChangeLog
gcc/doc/md.texi
gcc/genoutput.c

index 7447694b610858ac75f744781f0d3e49f89c0305..37d9b001a3c929c3cd2f072c9ccc2d282b0db413 100644 (file)
@@ -1,3 +1,8 @@
+2012-10-15  J"orn Rennecke  <joern.rennecke@arc.com>
+
+       * genoutput.c (process_template): Process '*' in '@' alternatives.
+       * doc/md.texi (node Output Statement): Provide example for the above.
+
 2012-10-15  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/54920
index f17d55e292c81836a364e303a115aa376e24b756..6a1db6ad607d2fb22374aa9264294a20e65f2b9f 100644 (file)
@@ -665,6 +665,22 @@ as follows, having the output control string start with a @samp{@@}:
 @end group
 @end smallexample
 
+If you just need a little bit of C code in one (or a few) alternatives,
+you can use @samp{*} inside of a @samp{@@} multi-alternative template:
+
+@smallexample
+@group
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=r,<,m")
+        (const_int 0))]
+  ""
+  "@@
+   clrreg %0
+   * return stack_mem_p (operands[0]) ? \"push 0\" : \"clrmem %0\";
+   clrmem %0")
+@end group
+@end smallexample
+
 @node Predicates
 @section Predicates
 @cindex predicates
index 2c6104cb25a9fbcbc240a89162f644c011247f98..d736d2c027f0827d4f7c0698ef33d0519a3fd086 100644 (file)
@@ -1,6 +1,6 @@
 /* Generate code from to output assembler insns as recognized from rtl.
    Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2002,
-   2003, 2004, 2005, 2007, 2008, 2009, 2010, 2012
+   2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -662,19 +662,55 @@ process_template (struct data *d, const char *template_code)
      list of assembler code templates, one for each alternative.  */
   else if (template_code[0] == '@')
     {
-      d->template_code = 0;
-      d->output_format = INSN_OUTPUT_FORMAT_MULTI;
+      int found_star = 0;
 
-      printf ("\nstatic const char * const output_%d[] = {\n", d->code_number);
+      for (cp = &template_code[1]; *cp; )
+       {
+         while (ISSPACE (*cp))
+           cp++;
+         if (*cp == '*')
+           found_star = 1;
+         while (!IS_VSPACE (*cp) && *cp != '\0')
+           ++cp;
+       }
+      d->template_code = 0;
+      if (found_star)
+       {
+         d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
+         puts ("\nstatic const char *");
+         printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, "
+                 "rtx insn ATTRIBUTE_UNUSED)\n", d->code_number);
+         puts ("{");
+         puts ("  switch (which_alternative)\n    {");
+       }
+      else
+       {
+         d->output_format = INSN_OUTPUT_FORMAT_MULTI;
+         printf ("\nstatic const char * const output_%d[] = {\n",
+                 d->code_number);
+       }
 
       for (i = 0, cp = &template_code[1]; *cp; )
        {
-         const char *ep, *sp;
+         const char *ep, *sp, *bp;
 
          while (ISSPACE (*cp))
            cp++;
 
-         printf ("  \"");
+         bp = cp;
+         if (found_star)
+           {
+             printf ("    case %d:", i);
+             if (*cp == '*')
+               {
+                 printf ("\n      ");
+                 cp++;
+               }
+             else
+               printf (" return \"");
+           }
+         else
+           printf ("  \"");
 
          for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
            if (!ISSPACE (*ep))
@@ -690,7 +726,18 @@ process_template (struct data *d, const char *template_code)
              cp++;
            }
 
-         printf ("\",\n");
+         if (!found_star)
+           puts ("\",");
+         else if (*bp != '*')
+           puts ("\";");
+         else
+           {
+             /* The usual action will end with a return.
+                If there is neither break or return at the end, this is
+                assumed to be intentional; this allows to have multiple
+                consecutive alternatives share some code.  */
+             puts ("");
+           }
          i++;
        }
       if (i == 1)
@@ -700,7 +747,10 @@ process_template (struct data *d, const char *template_code)
        error_with_line (d->lineno,
                         "wrong number of alternatives in the output template");
 
-      printf ("};\n");
+      if (found_star)
+       puts ("      default: gcc_unreachable ();\n    }\n}");
+      else
+       printf ("};\n");
     }
   else
     {