Patchwork RFA: Process '*' in '@'-output-template alternatives

login
register
mail settings
Submitter Joern Rennecke
Date Sept. 19, 2012, 3:27 p.m.
Message ID <20120919112754.aj5o7ugam84gkg8g-nzlynne@webmail.spamcop.net>
Download mbox | patch
Permalink /patch/185083/
State New
Headers show

Comments

Joern Rennecke - Sept. 19, 2012, 3:27 p.m.
Quoting Richard Guenther <richard.guenther@gmail.com>:

> Something smaller (but pointless) woudl be nice.

I have attached the patch with the example added to the documentation.
Again, bootstrapped on i686-pc-linux-gnu.
2011-09-19  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.
Georg-Johann Lay - Sept. 19, 2012, 8:22 p.m.
Joern Rennecke a écrit:
> Index: doc/md.texi
> ===================================================================
> --- doc/md.texi	(revision 191429)
> +++ doc/md.texi	(working copy)
> @@ -665,6 +665,22 @@ (define_insn ""
>  @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\";
---------------------------------------------------^

Isn't there a backslash missing?


> +   clrmem %0")
> +@end group
> +@end smallexample
> +
>  @node Predicates
>  @section Predicates
>  @cindex predicates
> Index: genoutput.c
> ===================================================================
> --- genoutput.c	(revision 191429)
> +++ genoutput.c	(working copy)
> @@ -662,19 +662,55 @@ process_template (struct data *d, const
>       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
>  	      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
>  	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
>      {
Joern Rennecke - Sept. 19, 2012, 10:35 p.m.
Quoting Georg-Johann Lay <gjl@gcc.gnu.org>:

>> +   * return stack_mem_p (operands[0]) ? \"push 0" : \"clrmem %0\";
> ---------------------------------------------------^
>
> Isn't there a backslash missing?

Oops, yes, there is.

Patch

Index: doc/md.texi
===================================================================
--- doc/md.texi	(revision 191429)
+++ doc/md.texi	(working copy)
@@ -665,6 +665,22 @@  (define_insn ""
 @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: genoutput.c
===================================================================
--- genoutput.c	(revision 191429)
+++ genoutput.c	(working copy)
@@ -662,19 +662,55 @@  process_template (struct data *d, const
      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
 	      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
 	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
     {