I am about to submit the ARCompact target port; this port needs a few patches to target-independent code.
There is a move pattern with 20 alternatives; a few of them need a simple function call to decide which output pattern to use. With the '@'-syntax for multi-alternative templates, each alternative is still a one-liner. Requiring to transform this into some switch statement would make the thing several times as big, and very hard to take in; besides, it is generally a maintenance issue if you have to completely rewrite a multi-alternative template if you just change one alternative from a constant to some C-code, or vice versa for the last non-literal alternative. The attached patch makes the '*' syntax for C code fragments available for individual alternatives of an '@' multi-alternative output template. It does this by translating the input into a switch statement in the generated file, so in a way this is just syntactic sugar, but it's syntactic sugar that makes some machine descriptions easier to write and change. Bootstrapped in revision 191429 for i686-pc-linux-gnu. I've been wondering if it'd make sense to also support for '{' / '}' , but at least in the ARCompact context, I think the use of that syntax inside a multi-alternative template would reduce rather than improve legibility, so, having no application for the '{' / '}' in that place, there seems to be no use in adding support for that at this point in time.
2008-11-19 J"orn Rennecke <joern.renne...@arc.com> * genoutput.c (process_template): Process '*' in '@' alternatives. 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 {