Patchwork Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)

login
register
mail settings
Submitter Stefan Kristiansson
Date July 10, 2013, 1:14 a.m.
Message ID <20130710011456.GA25947@chokladfabriken.org>
Download mbox | patch
Permalink /patch/257932/
State New
Headers show

Comments

Stefan Kristiansson - July 10, 2013, 1:14 a.m.
The (static arg) generator functions are casted to a var arg
function pointer, making the assumption that the ABI for passing
the arguments will be the same as for static arguments.
This isn't a valid assumption on all architectures, var args might for
example be passed on the stack, even if there would be function argument
registers still available.

There exists a bugreport for the problem here:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12081

This patch is taken from the suggestion by Rask Ingemann Lambertsen
and updated to the current svn tip of trunk.

gcc/Changelog:

2013-07-10  Stefan Kristiansson  <stefan.kristiansson@saunalahti.fi>

	    PR target/12081
	    * recog.h (rtx (*insn_gen_fn) (rtx, ...)): Remove typedef.
	    (genfun): Replace var arg function pointer with static argument
	    function pointers.
	    * optabs.h (GEN_FCN): Replace single define with ones of the
	    form GEN_FCN?, where ? is the number of arguments.
	    * reload1.c: Use GEN_FCN? instead of GEN_FCN
	    * config/frv/frv.c: Likewise.
	    * config/mep/mep.c: Likewise.
	    * config/picochip/picochip.c: Likewise.
	    * config/alpha/alpha.c: Likewise.
	    * config/sparc/sparc.c: Likewise.
	    * config/aarch64/aarch64-builtins.c: Likewise.
	    * config/bfin/bfin.c: Likewise.
	    * config/bfin/bfin.md: Likewise.
	    * config/arm/arm.md: Likewise.
	    * config/arm/arm.c: Likewise.
	    * config/spu/spu.c: Likewise.
	    * config/avr/avr.c: Likewise.
	    * config/ia64/ia64.c: Likewise.
	    * config/tilegx/tilegx.c: Likewise.
	    * config/sh/sh.c: Likewise.
	    * config/c6x/c6x.c: Likewise.
	    * config/iq2000/iq2000.c: Likewise.
	    * config/tilepro/tilepro.c: Likewise.
	    * config/s390/s390.c: Likewise.
	    * config/i386/i386.c: Likewise.
	    * expr.c: Likewise.
	    * lra-constraints.c: Likewise.
	    * optabs.c: Likewise.
	    * genoutput.c (output_insn_data): Output gen_? functions with
	    their correct number of arguments.
Andreas Schwab - July 10, 2013, 7:18 a.m.
Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> writes:

> @@ -291,14 +290,41 @@
>      const char *const *multi;
>      insn_output_fn function;
>    } output;
> +  union {
> +    rtx (*argc0)	(void);
> +    rtx (*argc1)	(rtx);
> +    rtx (*argc2)	(rtx, rtx);
> +    rtx (*argc3)	(rtx, rtx, rtx);
> +    rtx (*argc4)	(rtx, rtx, rtx, rtx);
> +    rtx (*argc5)	(rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc6)	(rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc7)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc8)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc9)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc10)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc11)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  } genfun;
>  #else
>    struct {
>      const char *single;
>      const char *const *multi;
>      insn_output_fn function;
>    } output;
> +  struct {
> +    rtx (*argc0)	(void);
> +    rtx (*argc1)	(rtx);
> +    rtx (*argc2)	(rtx, rtx);
> +    rtx (*argc3)	(rtx, rtx, rtx);
> +    rtx (*argc4)	(rtx, rtx, rtx, rtx);
> +    rtx (*argc5)	(rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc6)	(rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc7)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc8)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc9)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc10)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc11)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  } genfun;

I don't think there is a need to conditionalize this on
HAVE_DESIGNATED_UNION_INITIALIZERS.  All function pointers are alike, so
it should be good enough to cast on assignment and use the right
alternative on call.

Andreas.
Stefan Kristiansson - July 11, 2013, 6:50 a.m.
On Wed, Jul 10, 2013 at 09:18:53AM +0200, Andreas Schwab wrote:
> 
> I don't think there is a need to conditionalize this on
> HAVE_DESIGNATED_UNION_INITIALIZERS.  All function pointers are alike, so
> it should be good enough to cast on assignment and use the right
> alternative on call.

You mean something like this?

gcc/recog.h:
@@ -298,7 +297,21 @@
     insn_output_fn function;
   } output;
 #endif
-  const insn_gen_fn genfun;
+  union {
+    rtx (*argc0)	(void);
+    rtx (*argc1)	(rtx);
+    rtx (*argc2)	(rtx, rtx);
+    rtx (*argc3)	(rtx, rtx, rtx);
+    rtx (*argc4)	(rtx, rtx, rtx, rtx);
+    rtx (*argc5)	(rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc6)	(rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc7)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc8)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc9)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc10)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc11)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  } genfun;
+
   const struct insn_operand_data *const operand;
 
   const char n_generator_args;

gcc/genoutput.c:
@@ -404,9 +404,9 @@
 	}
 
       if (d->name && d->name[0] != '*')
-	printf ("    (insn_gen_fn) gen_%s,\n", d->name);
+	printf ("    { (rtx (*) (void)) gen_%s },\n", d->name);
       else
-	printf ("    0,\n");
+	printf ("    { 0 },\n");
 
       printf ("    &operand_data[%d],\n", d->operand_number);
       printf ("    %d,\n", d->n_generator_args);

Fair enough, that makes the printing routine a bit more clean and
removes some code duplication in the declaration.

Stefan
Andreas Schwab - July 11, 2013, 8:42 a.m.
Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> writes:

> You mean something like this?

Yes, that's what I had in mind.

Andreas.
Richard Guenther - Aug. 27, 2013, 9:03 a.m.
On Wed, Jul 10, 2013 at 3:14 AM, Stefan Kristiansson
<stefan.kristiansson@saunalahti.fi> wrote:
> The (static arg) generator functions are casted to a var arg
> function pointer, making the assumption that the ABI for passing
> the arguments will be the same as for static arguments.
> This isn't a valid assumption on all architectures, var args might for
> example be passed on the stack, even if there would be function argument
> registers still available.
>
> There exists a bugreport for the problem here:
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12081
>
> This patch is taken from the suggestion by Rask Ingemann Lambertsen
> and updated to the current svn tip of trunk.
>
> gcc/Changelog:
>
> 2013-07-10  Stefan Kristiansson  <stefan.kristiansson@saunalahti.fi>
>
>             PR target/12081
>             * recog.h (rtx (*insn_gen_fn) (rtx, ...)): Remove typedef.
>             (genfun): Replace var arg function pointer with static argument
>             function pointers.
>             * optabs.h (GEN_FCN): Replace single define with ones of the
>             form GEN_FCN?, where ? is the number of arguments.
>             * reload1.c: Use GEN_FCN? instead of GEN_FCN

Can't we use a template for all this to avoid the union and *[12345] mess?

Richard.

>             * config/frv/frv.c: Likewise.
>             * config/mep/mep.c: Likewise.
>             * config/picochip/picochip.c: Likewise.
>             * config/alpha/alpha.c: Likewise.
>             * config/sparc/sparc.c: Likewise.
>             * config/aarch64/aarch64-builtins.c: Likewise.
>             * config/bfin/bfin.c: Likewise.
>             * config/bfin/bfin.md: Likewise.
>             * config/arm/arm.md: Likewise.
>             * config/arm/arm.c: Likewise.
>             * config/spu/spu.c: Likewise.
>             * config/avr/avr.c: Likewise.
>             * config/ia64/ia64.c: Likewise.
>             * config/tilegx/tilegx.c: Likewise.
>             * config/sh/sh.c: Likewise.
>             * config/c6x/c6x.c: Likewise.
>             * config/iq2000/iq2000.c: Likewise.
>             * config/tilepro/tilepro.c: Likewise.
>             * config/s390/s390.c: Likewise.
>             * config/i386/i386.c: Likewise.
>             * expr.c: Likewise.
>             * lra-constraints.c: Likewise.
>             * optabs.c: Likewise.
>             * genoutput.c (output_insn_data): Output gen_? functions with
>             their correct number of arguments.
>
> Index: gcc/recog.h
> ===================================================================
> --- gcc/recog.h (revision 200820)
> +++ gcc/recog.h (working copy)
> @@ -256,7 +256,6 @@
>
>  typedef int (*insn_operand_predicate_fn) (rtx, enum machine_mode);
>  typedef const char * (*insn_output_fn) (rtx *, rtx);
> -typedef rtx (*insn_gen_fn) (rtx, ...);
>
>  struct insn_operand_data
>  {
> @@ -291,14 +290,41 @@
>      const char *const *multi;
>      insn_output_fn function;
>    } output;
> +  union {
> +    rtx (*argc0)       (void);
> +    rtx (*argc1)       (rtx);
> +    rtx (*argc2)       (rtx, rtx);
> +    rtx (*argc3)       (rtx, rtx, rtx);
> +    rtx (*argc4)       (rtx, rtx, rtx, rtx);
> +    rtx (*argc5)       (rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc6)       (rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc7)       (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc8)       (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc9)       (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc10)      (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc11)      (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  } genfun;
>  #else
>    struct {
>      const char *single;
>      const char *const *multi;
>      insn_output_fn function;
>    } output;
> +  struct {
> +    rtx (*argc0)       (void);
> +    rtx (*argc1)       (rtx);
> +    rtx (*argc2)       (rtx, rtx);
> +    rtx (*argc3)       (rtx, rtx, rtx);
> +    rtx (*argc4)       (rtx, rtx, rtx, rtx);
> +    rtx (*argc5)       (rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc6)       (rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc7)       (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc8)       (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc9)       (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc10)      (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +    rtx (*argc11)      (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  } genfun;
>  #endif
> -  const insn_gen_fn genfun;
>    const struct insn_operand_data *const operand;
>
>    const char n_generator_args;
> Index: gcc/config/frv/frv.c
> ===================================================================
> --- gcc/config/frv/frv.c        (revision 200820)
> +++ gcc/config/frv/frv.c        (working copy)
> @@ -8860,7 +8860,7 @@
>      return NULL_RTX;
>
>    target = frv_legitimize_target (icode, target);
> -  pat = GEN_FCN (icode) (target, op0);
> +  pat = GEN_FCN2 (icode) (target, op0);
>    if (! pat)
>      return NULL_RTX;
>
> @@ -8878,7 +8878,7 @@
>
>    target = frv_legitimize_target (icode, target);
>    op0 = frv_legitimize_argument (icode, 1, op0);
> -  pat = GEN_FCN (icode) (target, op0);
> +  pat = GEN_FCN2 (icode) (target, op0);
>    if (! pat)
>      return NULL_RTX;
>
> @@ -8898,7 +8898,7 @@
>    target = frv_legitimize_target (icode, target);
>    op0 = frv_legitimize_argument (icode, 1, op0);
>    op1 = frv_legitimize_argument (icode, 2, op1);
> -  pat = GEN_FCN (icode) (target, op0, op1);
> +  pat = GEN_FCN3 (icode) (target, op0, op1);
>    if (! pat)
>      return NULL_RTX;
>
> @@ -8931,7 +8931,7 @@
>      op1 = frv_legitimize_argument (icode, 2, op1);
>
>    op2 = frv_matching_accg_for_acc (op0);
> -  pat = GEN_FCN (icode) (target, op0, op1, op2);
> +  pat = GEN_FCN4 (icode) (target, op0, op1, op2);
>    if (! pat)
>      return NULL_RTX;
>
> @@ -8953,7 +8953,7 @@
>
>    target = frv_legitimize_target (icode, target);
>    op0 = frv_legitimize_argument (icode, 1, op0);
> -  pat = GEN_FCN (icode) (target, op0, op1);
> +  pat = GEN_FCN3 (icode) (target, op0, op1);
>    if (! pat)
>      return NULL_RTX;
>
> @@ -8992,7 +8992,7 @@
>
>    op0 = change_address (op0, V4SImode, addr);
>    op1 = frv_legitimize_argument (icode, 1, op1);
> -  pat = GEN_FCN (icode) (op0, op1);
> +  pat = GEN_FCN2 (icode) (op0, op1);
>    if (! pat)
>      return 0;
>
> @@ -9011,7 +9011,7 @@
>
>    op0 = frv_legitimize_argument (icode, 1, op0);
>    op1 = frv_legitimize_argument (icode, 1, op1);
> -  pat = GEN_FCN (icode) (op0, op1);
> +  pat = GEN_FCN2 (icode) (op0, op1);
>    if (! pat)
>      return NULL_RTX;
>
> @@ -9027,7 +9027,7 @@
>    rtx pat;
>    rtx op0 = frv_read_argument (call, 0);
>
> -  pat = GEN_FCN (icode) (force_reg (Pmode, op0));
> +  pat = GEN_FCN1 (icode) (force_reg (Pmode, op0));
>    if (! pat)
>      return 0;
>
> @@ -9056,7 +9056,7 @@
>    op1 = frv_legitimize_argument (icode, 1, op1);
>    op2 = frv_legitimize_argument (icode, 2, op2);
>    op3 = frv_matching_accg_for_acc (op0);
> -  pat = GEN_FCN (icode) (op0, op1, op2, op3);
> +  pat = GEN_FCN4 (icode) (op0, op1, op2, op3);
>    if (! pat)
>      return NULL_RTX;
>
> @@ -9087,7 +9087,7 @@
>
>    op2 = frv_matching_accg_for_acc (op0);
>    op3 = frv_matching_accg_for_acc (op1);
> -  pat = GEN_FCN (icode) (op0, op1, op2, op3);
> +  pat = GEN_FCN4 (icode) (op0, op1, op2, op3);
>    if (! pat)
>      return NULL_RTX;
>
> @@ -9109,7 +9109,7 @@
>      target = gen_reg_rtx (target_mode);
>    op0 = frv_volatile_memref (insn_data[icode].operand[0].mode, op0);
>    convert_move (target, op0, 1);
> -  emit_insn (GEN_FCN (icode) (copy_rtx (op0), cookie, GEN_INT (FRV_IO_READ)));
> +  emit_insn (GEN_FCN3 (icode) (copy_rtx (op0), cookie, GEN_INT (FRV_IO_READ)));
>    cfun->machine->has_membar_p = 1;
>    return target;
>  }
> @@ -9125,7 +9125,7 @@
>
>    op0 = frv_volatile_memref (insn_data[icode].operand[0].mode, op0);
>    convert_move (op0, force_reg (insn_data[icode].operand[0].mode, op1), 1);
> -  emit_insn (GEN_FCN (icode) (copy_rtx (op0), cookie, GEN_INT (FRV_IO_WRITE)));
> +  emit_insn (GEN_FCN3 (icode) (copy_rtx (op0), cookie, GEN_INT (FRV_IO_WRITE)));
>    cfun->machine->has_membar_p = 1;
>    return NULL_RTX;
>  }
> @@ -9160,7 +9160,7 @@
>    emit_move_insn (simplify_gen_subreg (HImode, op1, DImode, 2), arg3);
>    emit_move_insn (simplify_gen_subreg (HImode, op1, DImode, 6), arg4);
>
> -  pat = GEN_FCN (icode) (target, op0, op1);
> +  pat = GEN_FCN3 (icode) (target, op0, op1);
>    if (! pat)
>      return NULL_RTX;
>
> @@ -9182,7 +9182,7 @@
>    if (! op0)
>      return NULL_RTX;
>
> -  pat = GEN_FCN (icode) (op0);
> +  pat = GEN_FCN1 (icode) (op0);
>    if (pat)
>      emit_insn (pat);
>
> @@ -9194,7 +9194,7 @@
>  static rtx
>  frv_expand_noargs_builtin (enum insn_code icode)
>  {
> -  rtx pat = GEN_FCN (icode) (const0_rtx);
> +  rtx pat = GEN_FCN0 (icode) ();
>    if (pat)
>      emit_insn (pat);
>
> @@ -9215,7 +9215,7 @@
>    if (! op0)
>      return NULL_RTX;
>
> -  pat = GEN_FCN (icode) (target, op0);
> +  pat = GEN_FCN2 (icode) (target, op0);
>    if (! pat)
>      return NULL_RTX;
>
> @@ -9239,7 +9239,7 @@
>      return NULL_RTX;
>
>    op1 = frv_legitimize_argument (icode, 1, op1);
> -  pat = GEN_FCN (icode) (op0, op1);
> +  pat = GEN_FCN2 (icode) (op0, op1);
>    if (pat)
>      emit_insn (pat);
>
> Index: gcc/config/mep/mep.c
> ===================================================================
> --- gcc/config/mep/mep.c        (revision 200820)
> +++ gcc/config/mep/mep.c        (working copy)
> @@ -6308,8 +6308,8 @@
>      }
>
>    /* Emit the instruction.  */
> -  pat = idata->genfun (op[0], op[1], op[2], op[3], op[4],
> -                      op[5], op[6], op[7], op[8], op[9]);
> +  pat = idata->genfun.argc10 (op[0], op[1], op[2], op[3], op[4],
> +                             op[5], op[6], op[7], op[8], op[9]);
>
>    if (GET_CODE (pat) == SET
>        && GET_CODE (SET_DEST (pat)) == PC
> @@ -7079,9 +7079,9 @@
>         return false;
>      }
>
> -  emit_insn (idata->genfun (newop[0], newop[1], newop[2],
> -                           newop[3], newop[4], newop[5],
> -                           newop[6], newop[7], newop[8]));
> +  emit_insn (idata->genfun.argc9 (newop[0], newop[1], newop[2],
> +                                 newop[3], newop[4], newop[5],
> +                                 newop[6], newop[7], newop[8]));
>
>    return true;
>  }
> Index: gcc/config/picochip/picochip.c
> ===================================================================
> --- gcc/config/picochip/picochip.c      (revision 200820)
> +++ gcc/config/picochip/picochip.c      (working copy)
> @@ -55,7 +55,7 @@
>  #include "insn-attr.h"         /* For DFA state_t. */
>  #include "insn-config.h"       /* Required by recog.h */
>  #include "insn-codes.h"                /* For CODE_FOR_? */
> -#include "optabs.h"            /* For GEN_FCN */
> +#include "optabs.h"            /* For GEN_FCN? */
>  #include "basic-block.h"       /* UPDATE_LIFE_GLOBAL* for picochip_reorg. */
>  #include "timevar.h"           /* For TV_SCHED2, in picochip_reorg. */
>  #include "libfuncs.h"          /* For memcpy_libfuncs, etc. */
> @@ -3941,7 +3941,7 @@
>      target = gen_reg_rtx (tmode);
>
>    /* Emit and return the new instruction. */
> -  pat = GEN_FCN (icode) (target, op0);
> +  pat = GEN_FCN2 (icode) (target, op0);
>    if (!pat)
>      return 0;
>    emit_insn (pat);
> @@ -3986,7 +3986,7 @@
>      target = gen_reg_rtx (tmode);
>
>    /* Emit and return the new instruction. */
> -  pat = GEN_FCN (icode) (target, op0, op1);
> +  pat = GEN_FCN3 (icode) (target, op0, op1);
>    if (!pat)
>      return 0;
>    emit_insn (pat);
> @@ -4023,7 +4023,7 @@
>      op1 = copy_to_mode_reg (mode1, op1);
>
>    /* Emit and return the new instruction. */
> -  pat = GEN_FCN (icode) (op0, op1);
> +  pat = GEN_FCN2 (icode) (op0, op1);
>    if (!pat)
>      return 0;
>    emit_insn (pat);
> Index: gcc/config/alpha/alpha.c
> ===================================================================
> --- gcc/config/alpha/alpha.c    (revision 200820)
> +++ gcc/config/alpha/alpha.c    (working copy)
> @@ -6615,16 +6615,16 @@
>    switch (arity)
>      {
>      case 0:
> -      pat = GEN_FCN (icode) (target);
> +      pat = GEN_FCN1 (icode) (target);
>        break;
>      case 1:
>        if (nonvoid)
> -        pat = GEN_FCN (icode) (target, op[0]);
> +        pat = GEN_FCN2 (icode) (target, op[0]);
>        else
> -       pat = GEN_FCN (icode) (op[0]);
> +       pat = GEN_FCN1 (icode) (op[0]);
>        break;
>      case 2:
> -      pat = GEN_FCN (icode) (target, op[0], op[1]);
> +      pat = GEN_FCN3 (icode) (target, op[0], op[1]);
>        break;
>      default:
>        gcc_unreachable ();
> Index: gcc/config/sparc/sparc.c
> ===================================================================
> --- gcc/config/sparc/sparc.c    (revision 200820)
> +++ gcc/config/sparc/sparc.c    (working copy)
> @@ -10295,19 +10295,19 @@
>    switch (arg_count)
>      {
>      case 0:
> -      pat = GEN_FCN (icode) (op[0]);
> +      pat = GEN_FCN1 (icode) (op[0]);
>        break;
>      case 1:
>        if (nonvoid)
> -       pat = GEN_FCN (icode) (op[0], op[1]);
> +       pat = GEN_FCN2 (icode) (op[0], op[1]);
>        else
> -       pat = GEN_FCN (icode) (op[1]);
> +       pat = GEN_FCN1 (icode) (op[1]);
>        break;
>      case 2:
> -      pat = GEN_FCN (icode) (op[0], op[1], op[2]);
> +      pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
>        break;
>      case 3:
> -      pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
> +      pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
>        break;
>      default:
>        gcc_unreachable ();
> Index: gcc/config/aarch64/aarch64.c
> ===================================================================
> --- gcc/config/aarch64/aarch64.c        (revision 200820)
> +++ gcc/config/aarch64/aarch64.c        (working copy)
> @@ -6914,7 +6914,7 @@
>        x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, one_var));
>        icode = optab_handler (vec_set_optab, mode);
>        gcc_assert (icode != CODE_FOR_nothing);
> -      emit_insn (GEN_FCN (icode) (target, x, index));
> +      emit_insn (GEN_FCN3 (icode) (target, x, index));
>        return;
>      }
>
> Index: gcc/config/aarch64/aarch64-builtins.c
> ===================================================================
> --- gcc/config/aarch64/aarch64-builtins.c       (revision 200820)
> +++ gcc/config/aarch64/aarch64-builtins.c       (working copy)
> @@ -1016,23 +1016,23 @@
>      switch (argc)
>        {
>        case 1:
> -       pat = GEN_FCN (icode) (target, op[0]);
> +       pat = GEN_FCN2 (icode) (target, op[0]);
>         break;
>
>        case 2:
> -       pat = GEN_FCN (icode) (target, op[0], op[1]);
> +       pat = GEN_FCN3 (icode) (target, op[0], op[1]);
>         break;
>
>        case 3:
> -       pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
> +       pat = GEN_FCN4 (icode) (target, op[0], op[1], op[2]);
>         break;
>
>        case 4:
> -       pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
> +       pat = GEN_FCN5 (icode) (target, op[0], op[1], op[2], op[3]);
>         break;
>
>        case 5:
> -       pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]);
> +       pat = GEN_FCN6 (icode) (target, op[0], op[1], op[2], op[3], op[4]);
>         break;
>
>        default:
> @@ -1042,23 +1042,23 @@
>      switch (argc)
>        {
>        case 1:
> -       pat = GEN_FCN (icode) (op[0]);
> +       pat = GEN_FCN1 (icode) (op[0]);
>         break;
>
>        case 2:
> -       pat = GEN_FCN (icode) (op[0], op[1]);
> +       pat = GEN_FCN2 (icode) (op[0], op[1]);
>         break;
>
>        case 3:
> -       pat = GEN_FCN (icode) (op[0], op[1], op[2]);
> +       pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
>         break;
>
>        case 4:
> -       pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
> +       pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
>         break;
>
>        case 5:
> -       pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
> +       pat = GEN_FCN5 (icode) (op[0], op[1], op[2], op[3], op[4]);
>         break;
>
>        default:
> Index: gcc/config/bfin/bfin.c
> ===================================================================
> --- gcc/config/bfin/bfin.c      (revision 200820)
> +++ gcc/config/bfin/bfin.c      (working copy)
> @@ -5366,9 +5366,9 @@
>      op1 = copy_to_mode_reg (mode1, op1);
>
>    if (macflag == -1)
> -    pat = GEN_FCN (icode) (target, op0, op1);
> +    pat = GEN_FCN3 (icode) (target, op0, op1);
>    else
> -    pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
> +    pat = GEN_FCN4 (icode) (target, op0, op1, GEN_INT (macflag));
>    if (! pat)
>      return 0;
>
> @@ -5407,7 +5407,7 @@
>    if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
>      op0 = copy_to_mode_reg (mode0, op0);
>
> -  pat = GEN_FCN (icode) (target, op0);
> +  pat = GEN_FCN2 (icode) (target, op0);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -5466,7 +5466,7 @@
>        if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
>         op0 = copy_to_mode_reg (mode0, op0);
>
> -      pat = GEN_FCN (icode) (target, op0, op0);
> +      pat = GEN_FCN3 (icode) (target, op0, op0);
>        if (! pat)
>         return 0;
>        emit_insn (pat);
> Index: gcc/config/bfin/bfin.md
> ===================================================================
> --- gcc/config/bfin/bfin.md     (revision 200820)
> +++ gcc/config/bfin/bfin.md     (working copy)
> @@ -984,10 +984,10 @@
>    split_di (operands, 3, lo_half, hi_half);
>    if (!(*insn_data[icode].operand[2].predicate) (lo_half[2], SImode))
>      lo_half[2] = force_reg (SImode, lo_half[2]);
> -  emit_insn (GEN_FCN (icode) (lo_half[0], lo_half[1], lo_half[2]));
> +  emit_insn (GEN_FCN3 (icode) (lo_half[0], lo_half[1], lo_half[2]));
>    if (!(*insn_data[icode].operand[2].predicate) (hi_half[2], SImode))
>      hi_half[2] = force_reg (SImode, hi_half[2]);
> -  emit_insn (GEN_FCN (icode) (hi_half[0], hi_half[1], hi_half[2]));
> +  emit_insn (GEN_FCN3 (icode) (hi_half[0], hi_half[1], hi_half[2]));
>    DONE;
>  })
>
> Index: gcc/config/arm/arm.md
> ===================================================================
> --- gcc/config/arm/arm.md       (revision 200820)
> +++ gcc/config/arm/arm.md       (working copy)
> @@ -9904,8 +9904,8 @@
>      if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
>        operands[2] = force_reg (SImode, operands[2]);
>
> -    emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
> -                                         operands[3], operands[4]));
> +    emit_jump_insn (GEN_FCN4 ((int) code) (operands[0], operands[2],
> +                                          operands[3], operands[4]));
>      DONE;
>    }"
>  )
> Index: gcc/config/arm/arm.c
> ===================================================================
> --- gcc/config/arm/arm.c        (revision 200820)
> +++ gcc/config/arm/arm.c        (working copy)
> @@ -21850,7 +21850,7 @@
>    if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
>      op1 = copy_to_mode_reg (mode1, op1);
>
> -  pat = GEN_FCN (icode) (target, op0, op1);
> +  pat = GEN_FCN3 (icode) (target, op0, op1);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -21884,7 +21884,7 @@
>         op0 = copy_to_mode_reg (mode0, op0);
>      }
>
> -  pat = GEN_FCN (icode) (target, op0);
> +  pat = GEN_FCN2 (icode) (target, op0);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -22043,23 +22043,23 @@
>      switch (argc)
>        {
>        case 1:
> -       pat = GEN_FCN (icode) (target, op[0]);
> +       pat = GEN_FCN2 (icode) (target, op[0]);
>         break;
>
>        case 2:
> -       pat = GEN_FCN (icode) (target, op[0], op[1]);
> +       pat = GEN_FCN3 (icode) (target, op[0], op[1]);
>         break;
>
>        case 3:
> -       pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
> +       pat = GEN_FCN4 (icode) (target, op[0], op[1], op[2]);
>         break;
>
>        case 4:
> -       pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
> +       pat = GEN_FCN5 (icode) (target, op[0], op[1], op[2], op[3]);
>         break;
>
>        case 5:
> -       pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]);
> +       pat = GEN_FCN6 (icode) (target, op[0], op[1], op[2], op[3], op[4]);
>         break;
>
>        default:
> @@ -22069,23 +22069,23 @@
>      switch (argc)
>        {
>        case 1:
> -       pat = GEN_FCN (icode) (op[0]);
> +       pat = GEN_FCN1 (icode) (op[0]);
>         break;
>
>        case 2:
> -       pat = GEN_FCN (icode) (op[0], op[1]);
> +       pat = GEN_FCN2 (icode) (op[0], op[1]);
>         break;
>
>        case 3:
> -       pat = GEN_FCN (icode) (op[0], op[1], op[2]);
> +       pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
>         break;
>
>        case 4:
> -       pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
> +       pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
>         break;
>
>        case 5:
> -       pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
> +       pat = GEN_FCN5 (icode) (op[0], op[1], op[2], op[3], op[4]);
>          break;
>
>        default:
> @@ -22414,7 +22414,7 @@
>           || GET_MODE (target) != tmode
>           || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
>         target = gen_reg_rtx (tmode);
> -      pat = GEN_FCN (icode) (target, op0, op1);
> +      pat = GEN_FCN3 (icode) (target, op0, op1);
>        if (! pat)
>         return 0;
>        emit_insn (pat);
> @@ -22462,7 +22462,7 @@
>           || GET_MODE (target) != tmode
>           || !(*insn_data[icode].operand[0].predicate) (target, tmode))
>         target = gen_reg_rtx (tmode);
> -      pat = GEN_FCN (icode) (target, op0, op1, op2);
> +      pat = GEN_FCN4 (icode) (target, op0, op1, op2);
>        if (!pat)
>         return 0;
>        emit_insn (pat);
> @@ -22521,7 +22521,7 @@
>           || GET_MODE (target) != tmode
>           || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
>         target = gen_reg_rtx (tmode);
> -      pat = GEN_FCN (icode) (target, op0, op1, op2);
> +      pat = GEN_FCN4 (icode) (target, op0, op1, op2);
>        if (! pat)
>         return 0;
>        emit_insn (pat);
> @@ -22540,7 +22540,7 @@
>        mode0 = insn_data[icode].operand[0].mode;
>        if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
>          op0 = copy_to_mode_reg (mode0, op0);
> -      pat = GEN_FCN (icode) (op0);
> +      pat = GEN_FCN1 (icode) (op0);
>        if (!pat)
>         return 0;
>        emit_insn (pat);
> @@ -22559,7 +22559,7 @@
>           || GET_MODE (target) != tmode
>           || !(*insn_data[icode].operand[0].predicate) (target, tmode))
>          target = gen_reg_rtx (tmode);
> -      pat = GEN_FCN (icode) (target);
> +      pat = GEN_FCN1 (icode) (target);
>        if (!pat)
>          return 0;
>        emit_insn (pat);
> @@ -22589,7 +22589,7 @@
>           || GET_MODE (target) != tmode
>           || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
>         target = gen_reg_rtx (tmode);
> -      pat = GEN_FCN (icode) (target, op0, op1);
> +      pat = GEN_FCN3 (icode) (target, op0, op1);
>        if (! pat)
>         return 0;
>        emit_insn (pat);
> @@ -22702,7 +22702,7 @@
>           || GET_MODE (target) != tmode
>           || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
>         target = gen_reg_rtx (tmode);
> -      pat = GEN_FCN (icode) (target, op0, op1, op2);
> +      pat = GEN_FCN4 (icode) (target, op0, op1, op2);
>        if (! pat)
>         return 0;
>        emit_insn (pat);
> Index: gcc/config/stormy16/stormy16.c
> ===================================================================
> --- gcc/config/stormy16/stormy16.c      (revision 200820)
> +++ gcc/config/stormy16/stormy16.c      (working copy)
> @@ -2354,8 +2354,8 @@
>         retval = op[o];
>      }
>
> -  pat = GEN_FCN (code) (op[0], op[1], op[2], op[3], op[4],
> -                       op[5], op[6], op[7], op[8], op[9]);
> +  pat = GEN_FCN10 (code) (op[0], op[1], op[2], op[3], op[4],
> +                         op[5], op[6], op[7], op[8], op[9]);
>    emit_insn (pat);
>
>    for (o = 0; s16builtins[i].arg_ops[o]; o++)
> Index: gcc/config/spu/spu.c
> ===================================================================
> --- gcc/config/spu/spu.c        (revision 200820)
> +++ gcc/config/spu/spu.c        (working copy)
> @@ -878,7 +878,7 @@
>        if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate)
>           (op1, op_mode))
>         op1 = force_reg (op_mode, op1);
> -      comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result,
> +      comp_rtx = GEN_FCN3 (spu_comp_icode[index][scode]) (compare_result,
>                                                          op0, op1);
>        if (comp_rtx == 0)
>         abort ();
> @@ -887,14 +887,14 @@
>        if (eq_test)
>          {
>            eq_result = gen_reg_rtx (comp_mode);
> -          eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result,
> +          eq_rtx = GEN_FCN3 (spu_comp_icode[index][eq_code]) (eq_result,
>                                                              op0, op1);
>            if (eq_rtx == 0)
>             abort ();
>            emit_insn (eq_rtx);
>            ior_code = optab_handler (ior_optab, comp_mode);
>            gcc_assert (ior_code != CODE_FOR_nothing);
> -          emit_insn (GEN_FCN (ior_code)
> +          emit_insn (GEN_FCN3 (ior_code)
>                      (compare_result, compare_result, eq_result));
>          }
>      }
> @@ -4450,7 +4450,7 @@
>         {
>           enum insn_code icode = convert_optab_handler (trunc_optab,
>                                                         mode, imode);
> -         emit_insn (GEN_FCN (icode) (ops[0], from));
> +         emit_insn (GEN_FCN2 (icode) (ops[0], from));
>         }
>        else
>         emit_insn (gen_extend_insn (ops[0], from, mode, imode, 1));
> @@ -6150,7 +6150,7 @@
>
>              nor_code = optab_handler (one_cmpl_optab, dest_mode);
>              gcc_assert (nor_code != CODE_FOR_nothing);
> -            emit_insn (GEN_FCN (nor_code) (mask, rev_mask));
> +            emit_insn (GEN_FCN2 (nor_code) (mask, rev_mask));
>              if (dmode != dest_mode)
>                {
>                  rtx temp = gen_reg_rtx (dest_mode);
> @@ -6185,7 +6185,7 @@
>
>              ior_code = optab_handler (ior_optab, dest_mode);
>              gcc_assert (ior_code != CODE_FOR_nothing);
> -            emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
> +            emit_insn (GEN_FCN3 (ior_code) (mask, c_rtx, eq_rtx));
>              if (dmode != dest_mode)
>                {
>                  rtx temp = gen_reg_rtx (dest_mode);
> @@ -6206,7 +6206,7 @@
>
>              ior_code = optab_handler (ior_optab, dest_mode);
>              gcc_assert (ior_code != CODE_FOR_nothing);
> -            emit_insn (GEN_FCN (ior_code) (mask, lt_rtx, gt_rtx));
> +            emit_insn (GEN_FCN3 (ior_code) (mask, lt_rtx, gt_rtx));
>              if (dmode != dest_mode)
>                {
>                  rtx temp = gen_reg_rtx (dest_mode);
> @@ -6227,7 +6227,7 @@
>
>              and_code = optab_handler (and_optab, dest_mode);
>              gcc_assert (and_code != CODE_FOR_nothing);
> -            emit_insn (GEN_FCN (and_code) (mask, a_rtx, b_rtx));
> +            emit_insn (GEN_FCN3 (and_code) (mask, a_rtx, b_rtx));
>              if (dmode != dest_mode)
>                {
>                  rtx temp = gen_reg_rtx (dest_mode);
> @@ -6256,7 +6256,7 @@
>          }
>      }
>
> -  emit_insn (GEN_FCN (vec_cmp_insn) (mask, op0, op1));
> +  emit_insn (GEN_FCN3 (vec_cmp_insn) (mask, op0, op1));
>    if (dmode != dest_mode)
>      {
>        rtx temp = gen_reg_rtx (dest_mode);
> @@ -6460,7 +6460,7 @@
>                   gen_rtx_NEG (GET_MODE (addr), addr)));
>        op = gen_rtx_MEM (mode, op);
>
> -      pat = GEN_FCN (icode) (target, op);
> +      pat = GEN_FCN2 (icode) (target, op);
>        if (!pat)
>          return 0;
>        emit_insn (pat);
> @@ -6516,25 +6516,25 @@
>    switch (n_operands)
>      {
>      case 0:
> -      pat = GEN_FCN (icode) (0);
> +      pat = GEN_FCN0 (icode) ();
>        break;
>      case 1:
> -      pat = GEN_FCN (icode) (ops[0]);
> +      pat = GEN_FCN1 (icode) (ops[0]);
>        break;
>      case 2:
> -      pat = GEN_FCN (icode) (ops[0], ops[1]);
> +      pat = GEN_FCN2 (icode) (ops[0], ops[1]);
>        break;
>      case 3:
> -      pat = GEN_FCN (icode) (ops[0], ops[1], ops[2]);
> +      pat = GEN_FCN3 (icode) (ops[0], ops[1], ops[2]);
>        break;
>      case 4:
> -      pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]);
> +      pat = GEN_FCN4 (icode) (ops[0], ops[1], ops[2], ops[3]);
>        break;
>      case 5:
> -      pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3], ops[4]);
> +      pat = GEN_FCN5 (icode) (ops[0], ops[1], ops[2], ops[3], ops[4]);
>        break;
>      case 6:
> -      pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3], ops[4], ops[5]);
> +      pat = GEN_FCN6 (icode) (ops[0], ops[1], ops[2], ops[3], ops[4], ops[5]);
>        break;
>      default:
>        abort ();
> Index: gcc/config/avr/avr.c
> ===================================================================
> --- gcc/config/avr/avr.c        (revision 200820)
> +++ gcc/config/avr/avr.c        (working copy)
> @@ -11727,9 +11727,9 @@
>
>    switch (n_args)
>      {
> -    case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
> -    case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
> -    case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
> +    case 1: pat = GEN_FCN2 (icode) (target, xop[0]); break;
> +    case 2: pat = GEN_FCN3 (icode) (target, xop[0], xop[1]); break;
> +    case 3: pat = GEN_FCN4 (icode) (target, xop[0], xop[1], xop[2]); break;
>
>      default:
>        gcc_unreachable();
> @@ -11857,7 +11857,7 @@
>
>    if (d->n_args == 0)
>      {
> -      emit_insn ((GEN_FCN (d->icode)) (target));
> +      emit_insn ((GEN_FCN1 (d->icode)) (target));
>        return NULL_RTX;
>      }
>
> Index: gcc/config/ia64/ia64.c
> ===================================================================
> --- gcc/config/ia64/ia64.c      (revision 200820)
> +++ gcc/config/ia64/ia64.c      (working copy)
> @@ -2335,7 +2335,7 @@
>           gcc_unreachable ();
>         }
>
> -      emit_insn (GEN_FCN (icode) (old_dst, mem, val));
> +      emit_insn (GEN_FCN3 (icode) (old_dst, mem, val));
>
>        if (new_dst)
>         {
> @@ -2426,7 +2426,7 @@
>        gcc_unreachable ();
>      }
>
> -  emit_insn (GEN_FCN (icode) (cmp_reg, mem, ar_ccv, new_reg));
> +  emit_insn (GEN_FCN4 (icode) (cmp_reg, mem, ar_ccv, new_reg));
>
>    emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, NULL, DImode, true, label);
>  }
> Index: gcc/config/tilegx/tilegx.c
> ===================================================================
> --- gcc/config/tilegx/tilegx.c  (revision 200820)
> +++ gcc/config/tilegx/tilegx.c  (working copy)
> @@ -2064,7 +2064,7 @@
>           gcc_assert (shift_count > 0 && shift_count < 64);
>
>           /* Emit the actual instruction.  */
> -         emit_insn (GEN_FCN (opcode)
> +         emit_insn (GEN_FCN3 (opcode)
>                      (out, subexprs[entry->lhs],
>                       gen_rtx_CONST_INT (DImode, shift_count)));
>         }
> @@ -2078,7 +2078,7 @@
>           gcc_assert (entry->rhs < num_subexprs);
>
>           /* Emit the actual instruction.  */
> -         emit_insn (GEN_FCN (opcode)
> +         emit_insn (GEN_FCN3 (opcode)
>                      (out, subexprs[entry->lhs], subexprs[entry->rhs]));
>         }
>
> @@ -3446,7 +3446,6 @@
>    rtx op[MAX_BUILTIN_ARGS + 1], pat;
>    int opnum;
>    bool nonvoid;
> -  insn_gen_fn fn;
>
>    if (fcode >= TILEGX_BUILTIN_max)
>      internal_error ("bad builtin fcode");
> @@ -3517,26 +3516,25 @@
>        op[0] = target;
>      }
>
> -  fn = GEN_FCN (icode);
>    switch (opnum)
>      {
>      case 0:
> -      pat = fn (NULL_RTX);
> +      pat = GEN_FCN0 (icode) ();
>        break;
>      case 1:
> -      pat = fn (op[0]);
> +      pat = GEN_FCN1 (icode) (op[0]);
>        break;
>      case 2:
> -      pat = fn (op[0], op[1]);
> +      pat = GEN_FCN2 (icode) (op[0], op[1]);
>        break;
>      case 3:
> -      pat = fn (op[0], op[1], op[2]);
> +      pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
>        break;
>      case 4:
> -      pat = fn (op[0], op[1], op[2], op[3]);
> +      pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
>        break;
>      case 5:
> -      pat = fn (op[0], op[1], op[2], op[3], op[4]);
> +      pat = GEN_FCN5 (icode) (op[0], op[1], op[2], op[3], op[4]);
>        break;
>      default:
>        gcc_unreachable ();
> Index: gcc/config/sh/sh.c
> ===================================================================
> --- gcc/config/sh/sh.c  (revision 200820)
> +++ gcc/config/sh/sh.c  (working copy)
> @@ -12005,16 +12005,16 @@
>    switch (nop)
>      {
>      case 1:
> -      pat = (*insn_data[d->icode].genfun) (op[0]);
> +      pat = GEN_FCN1 (d->icode) (op[0]);
>        break;
>      case 2:
> -      pat = (*insn_data[d->icode].genfun) (op[0], op[1]);
> +      pat = GEN_FCN2 (d->icode) (op[0], op[1]);
>        break;
>      case 3:
> -      pat = (*insn_data[d->icode].genfun) (op[0], op[1], op[2]);
> +      pat = GEN_FCN3 (d->icode) (op[0], op[1], op[2]);
>        break;
>      case 4:
> -      pat = (*insn_data[d->icode].genfun) (op[0], op[1], op[2], op[3]);
> +      pat = GEN_FCN4 (d->icode) (op[0], op[1], op[2], op[3]);
>        break;
>      default:
>        gcc_unreachable ();
> Index: gcc/config/c6x/c6x.c
> ===================================================================
> --- gcc/config/c6x/c6x.c        (revision 200820)
> +++ gcc/config/c6x/c6x.c        (working copy)
> @@ -1770,7 +1770,7 @@
>         {
>           enum insn_code icode = (srcmode == SImode ? CODE_FOR_movmisalignsi
>                                   : CODE_FOR_movmisaligndi);
> -         emit_insn (GEN_FCN (icode) (reg_lowpart, srcmem));
> +         emit_insn (GEN_FCN2 (icode) (reg_lowpart, srcmem));
>         }
>        else
>         emit_move_insn (reg_lowpart, srcmem);
> @@ -1804,7 +1804,7 @@
>             {
>               enum insn_code icode = (dstmode == SImode ? CODE_FOR_movmisalignsi
>                                       : CODE_FOR_movmisaligndi);
> -             emit_insn (GEN_FCN (icode) (dstmem, dstreg));
> +             emit_insn (GEN_FCN2 (icode) (dstmem, dstreg));
>             }
>           else
>             emit_move_insn (dstmem, dstreg);
> @@ -6583,9 +6583,9 @@
>      op1 = copy_to_mode_reg (mode1, op1);
>
>    if (match_op)
> -    pat = GEN_FCN (icode) (target, target, op0, op1);
> +    pat = GEN_FCN4 (icode) (target, target, op0, op1);
>    else
> -    pat = GEN_FCN (icode) (target, op0, op1);
> +    pat = GEN_FCN3 (icode) (target, op0, op1);
>
>    if (! pat)
>      return 0;
> @@ -6626,7 +6626,7 @@
>    if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
>      op0 = copy_to_mode_reg (mode0, op0);
>
> -  pat = GEN_FCN (icode) (target, op0);
> +  pat = GEN_FCN2 (icode) (target, op0);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> Index: gcc/config/iq2000/iq2000.c
> ===================================================================
> --- gcc/config/iq2000/iq2000.c  (revision 200820)
> +++ gcc/config/iq2000/iq2000.c  (working copy)
> @@ -2611,30 +2611,30 @@
>    switch (argcount)
>      {
>      case 0:
> -       pat = GEN_FCN (icode) (target);
> +       pat = GEN_FCN1 (icode) (target);
>      case 1:
>        if (target)
> -       pat = GEN_FCN (icode) (target, op[0]);
> +       pat = GEN_FCN2 (icode) (target, op[0]);
>        else
> -       pat = GEN_FCN (icode) (op[0]);
> +       pat = GEN_FCN1 (icode) (op[0]);
>        break;
>      case 2:
>        if (target)
> -       pat = GEN_FCN (icode) (target, op[0], op[1]);
> +       pat = GEN_FCN3 (icode) (target, op[0], op[1]);
>        else
> -       pat = GEN_FCN (icode) (op[0], op[1]);
> +       pat = GEN_FCN2 (icode) (op[0], op[1]);
>        break;
>      case 3:
>        if (target)
> -       pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
> +       pat = GEN_FCN4 (icode) (target, op[0], op[1], op[2]);
>        else
> -       pat = GEN_FCN (icode) (op[0], op[1], op[2]);
> +       pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
>        break;
>      case 4:
>        if (target)
> -       pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
> +       pat = GEN_FCN5 (icode) (target, op[0], op[1], op[2], op[3]);
>        else
> -       pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
> +       pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
>        break;
>      default:
>        gcc_unreachable ();
> Index: gcc/config/tilepro/tilepro.c
> ===================================================================
> --- gcc/config/tilepro/tilepro.c        (revision 200820)
> +++ gcc/config/tilepro/tilepro.c        (working copy)
> @@ -1895,7 +1895,7 @@
>           gcc_assert (shift_count > 0 && shift_count < 32);
>
>           /* Emit the actual instruction.  */
> -         emit_insn (GEN_FCN (opcode)
> +         emit_insn (GEN_FCN3 (opcode)
>                      (out, subexprs[entry->lhs],
>                       gen_rtx_CONST_INT (SImode, shift_count)));
>         }
> @@ -1909,7 +1909,7 @@
>           gcc_assert (entry->rhs < num_subexprs);
>
>           /* Emit the actual instruction.  */
> -         emit_insn (GEN_FCN (opcode)
> +         emit_insn (GEN_FCN3 (opcode)
>                      (out, subexprs[entry->lhs], subexprs[entry->rhs]));
>         }
>
> @@ -3092,7 +3092,6 @@
>    rtx op[MAX_BUILTIN_ARGS + 1], pat;
>    int opnum;
>    bool nonvoid;
> -  insn_gen_fn fn;
>
>    if (fcode >= TILEPRO_BUILTIN_max)
>      internal_error ("bad builtin fcode");
> @@ -3141,26 +3140,25 @@
>        op[0] = target;
>      }
>
> -  fn = GEN_FCN (icode);
>    switch (opnum)
>      {
>      case 0:
> -      pat = fn (NULL_RTX);
> +      pat = GEN_FCN0 (idcode) ();
>        break;
>      case 1:
> -      pat = fn (op[0]);
> +      pat = GEN_FCN1 (icode) (op[0]);
>        break;
>      case 2:
> -      pat = fn (op[0], op[1]);
> +      pat = GEN_FCN2 (icode) (op[0], op[1]);
>        break;
>      case 3:
> -      pat = fn (op[0], op[1], op[2]);
> +      pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
>        break;
>      case 4:
> -      pat = fn (op[0], op[1], op[2], op[3]);
> +      pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
>        break;
>      case 5:
> -      pat = fn (op[0], op[1], op[2], op[3], op[4]);
> +      pat = GEN_FCN5 (icode) (op[0], op[1], op[2], op[3], op[4]);
>        break;
>      default:
>        gcc_unreachable ();
> Index: gcc/config/s390/s390.c
> ===================================================================
> --- gcc/config/s390/s390.c      (revision 200820)
> +++ gcc/config/s390/s390.c      (working copy)
> @@ -9828,19 +9828,19 @@
>    switch (arity)
>      {
>      case 0:
> -      pat = GEN_FCN (icode) (target);
> +      pat = GEN_FCN1 (icode) (target);
>        break;
>      case 1:
>        if (nonvoid)
> -        pat = GEN_FCN (icode) (target, op[0]);
> +        pat = GEN_FCN2 (icode) (target, op[0]);
>        else
> -       pat = GEN_FCN (icode) (op[0]);
> +       pat = GEN_FCN1 (icode) (op[0]);
>        break;
>      case 2:
>        if (nonvoid)
> -       pat = GEN_FCN (icode) (target, op[0], op[1]);
> +       pat = GEN_FCN3 (icode) (target, op[0], op[1]);
>        else
> -       pat = GEN_FCN (icode) (op[0], op[1]);
> +       pat = GEN_FCN2 (icode) (op[0], op[1]);
>        break;
>      default:
>        gcc_unreachable ();
> Index: gcc/config/i386/i386.c
> ===================================================================
> --- gcc/config/i386/i386.c      (revision 200820)
> +++ gcc/config/i386/i386.c      (working copy)
> @@ -22220,8 +22220,8 @@
>        /* We move from memory to memory, so we'll need to do it via
>          a temporary register.  */
>        tempreg = gen_reg_rtx (move_mode);
> -      emit_insn (GEN_FCN (code) (tempreg, src));
> -      emit_insn (GEN_FCN (code) (dst, tempreg));
> +      emit_insn (GEN_FCN2 (code) (tempreg, src));
> +      emit_insn (GEN_FCN2 (code) (dst, tempreg));
>
>        emit_move_insn (destptr,
>                       gen_rtx_PLUS (Pmode, copy_rtx (destptr), adjust));
> @@ -30451,7 +30451,7 @@
>    if (!insn_data[icode].operand[2].predicate (op1, mode1))
>      op1 = copy_to_mode_reg (mode1, op1);
>
> -  pat = GEN_FCN (icode) (target, op0, op1);
> +  pat = GEN_FCN3 (icode) (target, op0, op1);
>    if (! pat)
>      return 0;
>
> @@ -30656,31 +30656,31 @@
>    switch (nargs)
>      {
>      case 1:
> -      pat = GEN_FCN (icode) (target, args[0].op);
> +      pat = GEN_FCN2 (icode) (target, args[0].op);
>        break;
>
>      case 2:
>        if (tf_p)
> -       pat = GEN_FCN (icode) (target, args[0].op, args[1].op,
> +       pat = GEN_FCN4 (icode) (target, args[0].op, args[1].op,
>                                GEN_INT ((int)sub_code));
>        else if (! comparison_p)
> -       pat = GEN_FCN (icode) (target, args[0].op, args[1].op);
> +       pat = GEN_FCN3 (icode) (target, args[0].op, args[1].op);
>        else
>         {
>           rtx cmp_op = gen_rtx_fmt_ee (sub_code, GET_MODE (target),
>                                        args[0].op,
>                                        args[1].op);
>
> -         pat = GEN_FCN (icode) (target, cmp_op, args[0].op, args[1].op);
> +         pat = GEN_FCN4 (icode) (target, cmp_op, args[0].op, args[1].op);
>         }
>        break;
>
>      case 3:
> -      pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op);
> +      pat = GEN_FCN4 (icode) (target, args[0].op, args[1].op, args[2].op);
>        break;
>
>      case 4:
> -      pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op, args[3].op);
> +      pat = GEN_FCN5 (icode) (target, args[0].op, args[1].op, args[2].op, args[3].op);
>        break;
>
>      default:
> @@ -30723,7 +30723,7 @@
>    if (!insn_data[icode].operand[2].predicate (op1, mode0))
>      op1 = copy_to_mode_reg (mode0, op1);
>
> -  pat = GEN_FCN (icode) (target, op0, op1);
> +  pat = GEN_FCN3 (icode) (target, op0, op1);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -30775,7 +30775,7 @@
>      op1 = copy_to_mode_reg (mode1, op1);
>
>    op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
> -  pat = GEN_FCN (d->icode) (target, op0, op1, op2);
> +  pat = GEN_FCN4 (d->icode) (target, op0, op1, op2);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -30822,7 +30822,7 @@
>        || !insn_data[d->icode].operand[1].predicate (op1, mode1))
>      op1 = copy_to_mode_reg (mode1, op1);
>
> -  pat = GEN_FCN (d->icode) (op0, op1);
> +  pat = GEN_FCN2 (d->icode) (op0, op1);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -30861,7 +30861,7 @@
>
>    op1 = GEN_INT (d->comparison);
>
> -  pat = GEN_FCN (d->icode) (target, op0, op1);
> +  pat = GEN_FCN3 (d->icode) (target, op0, op1);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -30899,7 +30899,7 @@
>
>    op2 = GEN_INT (d->comparison);
>
> -  pat = GEN_FCN (d->icode) (target, op0, op1, op2);
> +  pat = GEN_FCN4 (d->icode) (target, op0, op1, op2);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -30937,7 +30937,7 @@
>        || !insn_data[d->icode].operand[1].predicate (op1, mode1))
>      op1 = copy_to_mode_reg (mode1, op1);
>
> -  pat = GEN_FCN (d->icode) (op0, op1);
> +  pat = GEN_FCN2 (d->icode) (op0, op1);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -31008,7 +31008,7 @@
>
>        scratch1 = gen_reg_rtx (tmode1);
>
> -      pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2, op3, op4);
> +      pat = GEN_FCN7 (d->icode) (target, scratch1, op0, op1, op2, op3, op4);
>      }
>    else if (d->code == IX86_BUILTIN_PCMPESTRM128)
>      {
> @@ -31019,7 +31019,7 @@
>
>        scratch0 = gen_reg_rtx (tmode0);
>
> -      pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2, op3, op4);
> +      pat = GEN_FCN7 (d->icode) (scratch0, target, op0, op1, op2, op3, op4);
>      }
>    else
>      {
> @@ -31028,7 +31028,7 @@
>        scratch0 = gen_reg_rtx (tmode0);
>        scratch1 = gen_reg_rtx (tmode1);
>
> -      pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2, op3, op4);
> +      pat = GEN_FCN7 (d->icode) (scratch0, scratch1, op0, op1, op2, op3, op4);
>      }
>
>    if (! pat)
> @@ -31103,7 +31103,7 @@
>
>        scratch1 = gen_reg_rtx (tmode1);
>
> -      pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2);
> +      pat = GEN_FCN5 (d->icode) (target, scratch1, op0, op1, op2);
>      }
>    else if (d->code == IX86_BUILTIN_PCMPISTRM128)
>      {
> @@ -31114,7 +31114,7 @@
>
>        scratch0 = gen_reg_rtx (tmode0);
>
> -      pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2);
> +      pat = GEN_FCN5 (d->icode) (scratch0, target, op0, op1, op2);
>      }
>    else
>      {
> @@ -31123,7 +31123,7 @@
>        scratch0 = gen_reg_rtx (tmode0);
>        scratch1 = gen_reg_rtx (tmode1);
>
> -      pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2);
> +      pat = GEN_FCN5 (d->icode) (scratch0, scratch1, op0, op1, op2);
>      }
>
>    if (! pat)
> @@ -31600,17 +31600,17 @@
>    switch (nargs)
>      {
>      case 1:
> -      pat = GEN_FCN (icode) (real_target, args[0].op);
> +      pat = GEN_FCN2 (icode) (real_target, args[0].op);
>        break;
>      case 2:
> -      pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op);
> +      pat = GEN_FCN3 (icode) (real_target, args[0].op, args[1].op);
>        break;
>      case 3:
> -      pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op,
> +      pat = GEN_FCN4 (icode) (real_target, args[0].op, args[1].op,
>                              args[2].op);
>        break;
>      case 4:
> -      pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op,
> +      pat = GEN_FCN5 (icode) (real_target, args[0].op, args[1].op,
>                              args[2].op, args[3].op);
>        break;
>      default:
> @@ -31648,7 +31648,7 @@
>    switch ((enum ix86_builtin_func_type) d->flag)
>      {
>      case VOID_FTYPE_VOID:
> -      emit_insn (GEN_FCN (icode) (target));
> +      emit_insn (GEN_FCN1 (icode) (target));
>        return 0;
>      case VOID_FTYPE_UINT64:
>      case VOID_FTYPE_UNSIGNED:
> @@ -31819,16 +31819,16 @@
>    switch (nargs)
>      {
>      case 0:
> -      pat = GEN_FCN (icode) (target);
> +      pat = GEN_FCN1 (icode) (target);
>        break;
>      case 1:
> -      pat = GEN_FCN (icode) (target, args[0].op);
> +      pat = GEN_FCN2 (icode) (target, args[0].op);
>        break;
>      case 2:
> -      pat = GEN_FCN (icode) (target, args[0].op, args[1].op);
> +      pat = GEN_FCN3 (icode) (target, args[0].op, args[1].op);
>        break;
>      case 3:
> -      pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op);
> +      pat = GEN_FCN4 (icode) (target, args[0].op, args[1].op, args[2].op);
>        break;
>      default:
>        gcc_unreachable ();
> @@ -32053,7 +32053,7 @@
>         op1 = copy_to_mode_reg (mode1, op1);
>        if (!insn_data[icode].operand[2].predicate (op2, mode2))
>         op2 = copy_to_mode_reg (mode2, op2);
> -      pat = GEN_FCN (icode) (op0, op1, op2);
> +      pat = GEN_FCN3 (icode) (op0, op1, op2);
>        if (! pat)
>         return 0;
>        emit_insn (pat);
> @@ -32247,7 +32247,7 @@
>         }
>        op0 = gen_rtx_MEM (BLKmode, op0);
>
> -      pat = GEN_FCN (icode) (op0);
> +      pat = GEN_FCN1 (icode) (op0);
>        if (pat)
>         emit_insn (pat);
>        return 0;
> @@ -32302,7 +32302,7 @@
>
>           op2 = gen_lowpart (SImode, op2);
>           op1 = gen_lowpart (SImode, op1);
> -         pat = GEN_FCN (icode) (op0, op1, op2);
> +         pat = GEN_FCN3 (icode) (op0, op1, op2);
>         }
>        else
>         {
> @@ -32320,7 +32320,7 @@
>             default:
>               gcc_unreachable ();
>             }
> -         pat = GEN_FCN (icode) (op0, op1);
> +         pat = GEN_FCN2 (icode) (op0, op1);
>         }
>
>        if (pat)
> @@ -32364,7 +32364,7 @@
>            unsigned char lsb_index = INTVAL (op1) & 0xFF;
>            op1 = GEN_INT (length);
>            op2 = GEN_INT (lsb_index);
> -          pat = GEN_FCN (icode) (target, op0, op1, op2);
> +          pat = GEN_FCN4 (icode) (target, op0, op1, op2);
>            if (pat)
>              emit_insn (pat);
>            return target;
> @@ -32386,7 +32386,7 @@
>
>  rdrand_step:
>        op0 = gen_reg_rtx (mode0);
> -      emit_insn (GEN_FCN (icode) (op0));
> +      emit_insn (GEN_FCN1 (icode) (op0));
>
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        op1 = expand_normal (arg0);
> @@ -32436,7 +32436,7 @@
>
>  rdseed_step:
>        op0 = gen_reg_rtx (mode0);
> -      emit_insn (GEN_FCN (icode) (op0));
> +      emit_insn (GEN_FCN1 (icode) (op0));
>
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        op1 = expand_normal (arg0);
> @@ -32494,7 +32494,7 @@
>
>        op4 = gen_rtx_REG (CCCmode, FLAGS_REG);
>        pat = gen_rtx_LTU (VOIDmode, op4, const0_rtx);
> -      emit_insn (GEN_FCN (icode) (op0, op2, op3, op4, pat));
> +      emit_insn (GEN_FCN5 (icode) (op0, op2, op3, op4, pat));
>
>        /* Store the result.  */
>        op4 = expand_normal (arg3);
> @@ -32706,7 +32706,7 @@
>             }
>         }
>
> -      pat = GEN_FCN (icode) (subtarget, op0, op1, op2, op3, op4);
> +      pat = GEN_FCN6 (icode) (subtarget, op0, op1, op2, op3, op4);
>        if (! pat)
>         return const0_rtx;
>        emit_insn (pat);
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> --- gcc/config/rs6000/rs6000.c  (revision 200820)
> +++ gcc/config/rs6000/rs6000.c  (working copy)
> @@ -10446,7 +10446,7 @@
>        || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
>      target = gen_reg_rtx (tmode);
>
> -  pat = GEN_FCN (icode) (target);
> +  pat = GEN_FCN1 (icode) (target);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -10496,7 +10496,7 @@
>    if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
>      op0 = copy_to_mode_reg (mode0, op0);
>
> -  pat = GEN_FCN (icode) (target, op0);
> +  pat = GEN_FCN2 (icode) (target, op0);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -10528,7 +10528,7 @@
>    scratch1 = gen_reg_rtx (mode0);
>    scratch2 = gen_reg_rtx (mode0);
>
> -  pat = GEN_FCN (icode) (target, op0, scratch1, scratch2);
> +  pat = GEN_FCN4 (icode) (target, op0, scratch1, scratch2);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -10601,7 +10601,7 @@
>    if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
>      op1 = copy_to_mode_reg (mode1, op1);
>
> -  pat = GEN_FCN (icode) (target, op0, op1);
> +  pat = GEN_FCN3 (icode) (target, op0, op1);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -10649,7 +10649,7 @@
>
>    scratch = gen_reg_rtx (mode0);
>
> -  pat = GEN_FCN (icode) (scratch, op0, op1);
> +  pat = GEN_FCN3 (icode) (scratch, op0, op1);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -10721,7 +10721,7 @@
>        addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op0, op1));
>      }
>
> -  pat = GEN_FCN (icode) (target, addr);
> +  pat = GEN_FCN2 (icode) (target, addr);
>
>    if (! pat)
>      return 0;
> @@ -10767,7 +10767,7 @@
>        addr = gen_rtx_MEM (blk ? BLKmode : tmode, gen_rtx_PLUS (Pmode, op0, op1));
>      }
>
> -  pat = GEN_FCN (icode) (target, addr);
> +  pat = GEN_FCN2 (icode) (target, addr);
>
>    if (! pat)
>      return 0;
> @@ -10803,7 +10803,7 @@
>    if (! (*insn_data[icode].operand[1].predicate) (op2, mode1))
>      op2 = copy_to_mode_reg (mode1, op2);
>
> -  pat = GEN_FCN (icode) (op1, op2, op0);
> +  pat = GEN_FCN3 (icode) (op1, op2, op0);
>    if (pat)
>      emit_insn (pat);
>    return NULL_RTX;
> @@ -10844,7 +10844,7 @@
>        addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op1, op2));
>      }
>
> -  pat = GEN_FCN (icode) (addr, op0);
> +  pat = GEN_FCN2 (icode) (addr, op0);
>    if (pat)
>      emit_insn (pat);
>    return NULL_RTX;
> @@ -10886,7 +10886,7 @@
>        addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op1, op2));
>      }
>
> -  pat = GEN_FCN (icode) (addr, op0);
> +  pat = GEN_FCN2 (icode) (addr, op0);
>    if (pat)
>      emit_insn (pat);
>    return NULL_RTX;
> @@ -11003,9 +11003,9 @@
>      op2 = copy_to_mode_reg (mode2, op2);
>
>    if (TARGET_PAIRED_FLOAT && icode == CODE_FOR_selv2sf4)
> -    pat = GEN_FCN (icode) (target, op0, op1, op2, CONST0_RTX (SFmode));
> +    pat = GEN_FCN5 (icode) (target, op0, op1, op2, CONST0_RTX (SFmode));
>    else
> -    pat = GEN_FCN (icode) (target, op0, op1, op2);
> +    pat = GEN_FCN4 (icode) (target, op0, op1, op2);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -11064,7 +11064,7 @@
>    if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
>      op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
>
> -  pat = GEN_FCN (icode) (target, op0);
> +  pat = GEN_FCN2 (icode) (target, op0);
>    if (! pat)
>      return 0;
>    emit_insn (pat);
> @@ -11120,7 +11120,7 @@
>    if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
>      op1 = copy_to_mode_reg (mode1, op1);
>
> -  pat = GEN_FCN (icode) (op0, op1);
> +  pat = GEN_FCN2 (icode) (op0, op1);
>    if (pat)
>      emit_insn (pat);
>
> @@ -11177,7 +11177,7 @@
>         if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1))
>           op1 = copy_to_mode_reg (mode1, op1);
>
> -       pat = GEN_FCN (d->icode) (op0, op1, op2);
> +       pat = GEN_FCN3 (d->icode) (op0, op1, op2);
>         if (pat != 0)
>           emit_insn (pat);
>
> @@ -11373,7 +11373,7 @@
>           || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
>         target = gen_reg_rtx (tmode);
>
> -      pat = GEN_FCN (icode) (target);
> +      pat = GEN_FCN1 (icode) (target);
>        if (! pat)
>         return 0;
>        emit_insn (pat);
> @@ -11392,7 +11392,7 @@
>        if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
>         op0 = copy_to_mode_reg (mode0, op0);
>
> -      pat = GEN_FCN (icode) (op0);
> +      pat = GEN_FCN1 (icode) (op0);
>        if (pat)
>         emit_insn (pat);
>        return NULL_RTX;
> @@ -11699,7 +11699,7 @@
>           || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
>         target = gen_reg_rtx (tmode);
>
> -      pat = GEN_FCN (icode) (target);
> +      pat = GEN_FCN1 (icode) (target);
>        if (! pat)
>         return 0;
>        emit_insn (pat);
> @@ -11716,7 +11716,7 @@
>        if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
>         op0 = copy_to_mode_reg (mode0, op0);
>
> -      pat = GEN_FCN (icode) (op0);
> +      pat = GEN_FCN1 (icode) (op0);
>        if (pat)
>         emit_insn (pat);
>        return NULL_RTX;
> @@ -11766,7 +11766,7 @@
>
>    scratch = gen_reg_rtx (CCFPmode);
>
> -  pat = GEN_FCN (icode) (scratch, op0, op1);
> +  pat = GEN_FCN3 (icode) (scratch, op0, op1);
>    if (!pat)
>      return const0_rtx;
>
> @@ -11839,7 +11839,7 @@
>
>    scratch = gen_reg_rtx (CCmode);
>
> -  pat = GEN_FCN (icode) (scratch, op0, op1);
> +  pat = GEN_FCN3 (icode) (scratch, op0, op1);
>    if (! pat)
>      return const0_rtx;
>    emit_insn (pat);
> @@ -11945,7 +11945,7 @@
>
>    /* Generate the compare.  */
>    scratch = gen_reg_rtx (CCmode);
> -  pat = GEN_FCN (icode) (scratch, op0, op1);
> +  pat = GEN_FCN3 (icode) (scratch, op0, op1);
>    if (! pat)
>      return const0_rtx;
>    emit_insn (pat);
> @@ -12106,7 +12106,7 @@
>           target = gen_reg_rtx (tmode);
>
>         /*pat = gen_altivec_lvsr (target, op);*/
> -       pat = GEN_FCN (icode) (target, op);
> +       pat = GEN_FCN2 (icode) (target, op);
>         if (!pat)
>           return 0;
>         emit_insn (pat);
> @@ -17328,7 +17328,7 @@
>           return NULL_RTX;
>
>         mask = gen_reg_rtx (dmode);
> -       emit_insn (GEN_FCN (nor_code) (mask, mask2));
> +       emit_insn (GEN_FCN2 (nor_code) (mask, mask2));
>         return mask;
>        }
>        break;
> @@ -17377,7 +17377,7 @@
>           return NULL_RTX;
>
>         mask = gen_reg_rtx (dmode);
> -       emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
> +       emit_insn (GEN_FCN3 (ior_code) (mask, c_rtx, eq_rtx));
>         return mask;
>        }
>        break;
> @@ -27769,7 +27769,7 @@
>      passes++;
>
>    enum insn_code code = optab_handler (smul_optab, mode);
> -  gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN (code);
> +  gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN3 (code);
>
>    gcc_assert (code != CODE_FOR_nothing);
>
> @@ -27847,7 +27847,7 @@
>    int i;
>    rtx halfthree;
>    enum insn_code code = optab_handler (smul_optab, mode);
> -  gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN (code);
> +  gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN3 (code);
>
>    gcc_assert (code != CODE_FOR_nothing);
>
> @@ -28172,7 +28172,7 @@
>             x = target;
>           else
>             x = gen_reg_rtx (omode);
> -         emit_insn (GEN_FCN (icode) (x, op0, op1));
> +         emit_insn (GEN_FCN3 (icode) (x, op0, op1));
>           if (omode != V16QImode)
>             emit_move_insn (target, gen_lowpart (V16QImode, x));
>           return true;
> Index: gcc/genoutput.c
> ===================================================================
> --- gcc/genoutput.c     (revision 200820)
> +++ gcc/genoutput.c     (working copy)
> @@ -404,9 +404,25 @@
>         }
>
>        if (d->name && d->name[0] != '*')
> -       printf ("    (insn_gen_fn) gen_%s,\n", d->name);
> +       {
> +         int i;
> +
> +         printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
> +         printf ("    { .argc%d = gen_%s },\n", d->n_generator_args, d->name);
> +         printf ("#else\n");
> +         printf ("    { ");
> +         for (i = 0; i < d->n_generator_args; i++)
> +           printf ("0, ");
> +         printf ("gen_%s, ", d->name);
> +         for (i = d->n_generator_args + 1; i <= 11; i++)
> +           printf ("0, ");
> +         printf ("},\n");
> +         printf ("#endif\n");
> +       }
>        else
> -       printf ("    0,\n");
> +       {
> +         printf ("    { 0 },\n");
> +       }
>
>        printf ("    &operand_data[%d],\n", d->operand_number);
>        printf ("    %d,\n", d->n_generator_args);
> Index: gcc/expr.c
> ===================================================================
> --- gcc/expr.c  (revision 200820)
> +++ gcc/expr.c  (working copy)
> @@ -119,7 +119,7 @@
>    int reverse;
>  };
>
> -static void move_by_pieces_1 (rtx (*) (rtx, ...), enum machine_mode,
> +static void move_by_pieces_1 (rtx (*) (rtx, rtx), enum machine_mode,
>                               struct move_by_pieces_d *);
>  static bool block_move_libcall_safe_for_call_parm (void);
>  static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT);
> @@ -128,7 +128,7 @@
>  static rtx clear_by_pieces_1 (void *, HOST_WIDE_INT, enum machine_mode);
>  static void clear_by_pieces (rtx, unsigned HOST_WIDE_INT, unsigned int);
>  static void store_by_pieces_1 (struct store_by_pieces_d *, unsigned int);
> -static void store_by_pieces_2 (rtx (*) (rtx, ...), enum machine_mode,
> +static void store_by_pieces_2 (rtx (*) (rtx, rtx), enum machine_mode,
>                                struct store_by_pieces_d *);
>  static tree clear_storage_libcall_fn (int);
>  static rtx compress_float_constant (rtx, rtx);
> @@ -966,7 +966,7 @@
>
>        icode = optab_handler (mov_optab, mode);
>        if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
> -       move_by_pieces_1 (GEN_FCN (icode), mode, &data);
> +       move_by_pieces_1 (GEN_FCN2 (icode), mode, &data);
>
>        max_size = GET_MODE_SIZE (mode);
>      }
> @@ -1043,7 +1043,7 @@
>     to make a move insn for that mode.  DATA has all the other info.  */
>
>  static void
> -move_by_pieces_1 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
> +move_by_pieces_1 (rtx (*genfun) (rtx, rtx), enum machine_mode mode,
>                   struct move_by_pieces_d *data)
>  {
>    unsigned int size = GET_MODE_SIZE (mode);
> @@ -2643,7 +2643,7 @@
>
>        icode = optab_handler (mov_optab, mode);
>        if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
> -       store_by_pieces_2 (GEN_FCN (icode), mode, data);
> +       store_by_pieces_2 (GEN_FCN2 (icode), mode, data);
>
>        max_size = GET_MODE_SIZE (mode);
>      }
> @@ -2657,7 +2657,7 @@
>     to make a move insn for that mode.  DATA has all the other info.  */
>
>  static void
> -store_by_pieces_2 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
> +store_by_pieces_2 (rtx (*genfun) (rtx, rtx), enum machine_mode mode,
>                    struct store_by_pieces_d *data)
>  {
>    unsigned int size = GET_MODE_SIZE (mode);
> @@ -3096,7 +3096,7 @@
>    y = emit_move_change_mode (imode, mode, y, force);
>    if (y == NULL_RTX)
>      return NULL_RTX;
> -  return emit_insn (GEN_FCN (code) (x, y));
> +  return emit_insn (GEN_FCN2 (code) (x, y));
>  }
>
>  /* A subroutine of emit_move_insn_1.  X is a push_operand in MODE.
> @@ -3292,7 +3292,7 @@
>         {
>           x = emit_move_change_mode (CCmode, mode, x, true);
>           y = emit_move_change_mode (CCmode, mode, y, true);
> -         return emit_insn (GEN_FCN (code) (x, y));
> +         return emit_insn (GEN_FCN2 (code) (x, y));
>         }
>      }
>
> @@ -3429,7 +3429,7 @@
>
>    code = optab_handler (mov_optab, mode);
>    if (code != CODE_FOR_nothing)
> -    return emit_insn (GEN_FCN (code) (x, y));
> +    return emit_insn (GEN_FCN2 (code) (x, y));
>
>    /* Expand complex moves by moving real part and imag part.  */
>    if (COMPLEX_MODE_P (mode))
> @@ -6322,7 +6322,7 @@
>           }
>
>         if (vector)
> -         emit_insn (GEN_FCN (icode)
> +         emit_insn (GEN_FCN2 (icode)
>                      (target,
>                       gen_rtx_PARALLEL (GET_MODE (target), vector)));
>         break;
> @@ -10374,7 +10374,7 @@
>               reg = gen_reg_rtx (mode);
>
>               /* Nor can the insn generator.  */
> -             insn = GEN_FCN (icode) (reg, op0);
> +             insn = GEN_FCN2 (icode) (reg, op0);
>               emit_insn (insn);
>               return reg;
>             }
> Index: gcc/lra-constraints.c
> ===================================================================
> --- gcc/lra-constraints.c       (revision 200820)
> +++ gcc/lra-constraints.c       (working copy)
> @@ -1009,7 +1009,7 @@
>        scratch_reg = (lra_create_new_reg_with_unique_value
>                      (insn_data[sri.icode].operand[2].mode, NULL_RTX,
>                       scratch_class, "scratch"));
> -      emit_insn (GEN_FCN (sri.icode) (new_reg != NULL_RTX ? new_reg : dest,
> +      emit_insn (GEN_FCN3 (sri.icode) (new_reg != NULL_RTX ? new_reg : dest,
>                                       sreg, scratch_reg));
>      }
>    before = get_insns ();
> Index: gcc/optabs.c
> ===================================================================
> --- gcc/optabs.c        (revision 200820)
> +++ gcc/optabs.c        (working copy)
> @@ -792,7 +792,7 @@
>      return NULL;
>
>    ret = gen_reg_rtx (vmode);
> -  emit_insn (GEN_FCN (icode) (ret, gen_rtx_PARALLEL (vmode, vec)));
> +  emit_insn (GEN_FCN2 (icode) (ret, gen_rtx_PARALLEL (vmode, vec)));
>
>    return ret;
>  }
> @@ -4098,7 +4098,7 @@
>           result_mode = insn_data[cmp_code].operand[0].mode;
>           result = gen_reg_rtx (result_mode);
>           size = convert_to_mode (cmp_mode, size, 1);
> -         emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
> +         emit_insn (GEN_FCN5 (cmp_code) (result, x, y, size, opalign));
>
>            *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
>            *pmode = result_mode;
> @@ -4275,7 +4275,7 @@
>
>    gcc_assert (icode != CODE_FOR_nothing);
>    gcc_assert (insn_operand_matches (icode, 0, test));
> -  insn = emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0),
> +  insn = emit_jump_insn (GEN_FCN4 (icode) (test, XEXP (test, 0),
>                                            XEXP (test, 1), label));
>    if (prob != -1
>        && profile_status != PROFILE_ABSENT
> @@ -4704,7 +4704,7 @@
>    gcc_assert (insn_operand_matches (icode, 1, x));
>    gcc_assert (insn_operand_matches (icode, 2, y));
>
> -  return GEN_FCN (icode) (x, x, y);
> +  return GEN_FCN3 (icode) (x, x, y);
>  }
>
>  /* Generate and return an insn body to add r1 and c,
> @@ -4721,7 +4721,7 @@
>        || !insn_operand_matches (icode, 2, c))
>      return NULL_RTX;
>
> -  return GEN_FCN (icode) (r0, r1, c);
> +  return GEN_FCN3 (icode) (r0, r1, c);
>  }
>
>  int
> @@ -4755,7 +4755,7 @@
>    gcc_assert (insn_operand_matches (icode, 1, x));
>    gcc_assert (insn_operand_matches (icode, 2, y));
>
> -  return GEN_FCN (icode) (x, x, y);
> +  return GEN_FCN3 (icode) (x, x, y);
>  }
>
>  /* Generate and return an insn body to subtract r1 and c,
> @@ -4772,7 +4772,7 @@
>        || !insn_operand_matches (icode, 2, c))
>      return NULL_RTX;
>
> -  return GEN_FCN (icode) (r0, r1, c);
> +  return GEN_FCN3 (icode) (r0, r1, c);
>  }
>
>  int
> @@ -4836,7 +4836,7 @@
>                  enum machine_mode mfrom, int unsignedp)
>  {
>    enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
> -  return GEN_FCN (icode) (x, y);
> +  return GEN_FCN2 (icode) (x, y);
>  }
>
>  /* can_fix_p and can_float_p say whether the target machine
> @@ -6367,7 +6367,7 @@
>    if (!trap_rtx)
>      insn = NULL_RTX;
>    else
> -    insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
> +    insn = GEN_FCN4 (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
>                             tcode);
>
>    /* If that failed, then give up.  */
> @@ -8206,28 +8206,28 @@
>    switch (nops)
>      {
>      case 1:
> -      return GEN_FCN (icode) (ops[0].value);
> +      return GEN_FCN1 (icode) (ops[0].value);
>      case 2:
> -      return GEN_FCN (icode) (ops[0].value, ops[1].value);
> +      return GEN_FCN2 (icode) (ops[0].value, ops[1].value);
>      case 3:
> -      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value);
> +      return GEN_FCN3 (icode) (ops[0].value, ops[1].value, ops[2].value);
>      case 4:
> -      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
> -                             ops[3].value);
> +      return GEN_FCN4 (icode) (ops[0].value, ops[1].value, ops[2].value,
> +                              ops[3].value);
>      case 5:
> -      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
> -                             ops[3].value, ops[4].value);
> +      return GEN_FCN5 (icode) (ops[0].value, ops[1].value, ops[2].value,
> +                              ops[3].value, ops[4].value);
>      case 6:
> -      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
> -                             ops[3].value, ops[4].value, ops[5].value);
> +      return GEN_FCN6 (icode) (ops[0].value, ops[1].value, ops[2].value,
> +                              ops[3].value, ops[4].value, ops[5].value);
>      case 7:
> -      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
> -                             ops[3].value, ops[4].value, ops[5].value,
> -                             ops[6].value);
> +      return GEN_FCN7 (icode) (ops[0].value, ops[1].value, ops[2].value,
> +                              ops[3].value, ops[4].value, ops[5].value,
> +                              ops[6].value);
>      case 8:
> -      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
> -                             ops[3].value, ops[4].value, ops[5].value,
> -                             ops[6].value, ops[7].value);
> +      return GEN_FCN8 (icode) (ops[0].value, ops[1].value, ops[2].value,
> +                              ops[3].value, ops[4].value, ops[5].value,
> +                              ops[6].value, ops[7].value);
>      }
>    gcc_unreachable ();
>  }
> Index: gcc/optabs.h
> ===================================================================
> --- gcc/optabs.h        (revision 200820)
> +++ gcc/optabs.h        (working copy)
> @@ -44,7 +44,18 @@
>
>  /* Given an enum insn_code, access the function to construct
>     the body of that kind of insn.  */
> -#define GEN_FCN(CODE) (insn_data[CODE].genfun)
> +#define GEN_FCN0(CODE) (insn_data[CODE].genfun.argc0)
> +#define GEN_FCN1(CODE) (insn_data[CODE].genfun.argc1)
> +#define GEN_FCN2(CODE) (insn_data[CODE].genfun.argc2)
> +#define GEN_FCN3(CODE) (insn_data[CODE].genfun.argc3)
> +#define GEN_FCN4(CODE) (insn_data[CODE].genfun.argc4)
> +#define GEN_FCN5(CODE) (insn_data[CODE].genfun.argc5)
> +#define GEN_FCN6(CODE) (insn_data[CODE].genfun.argc6)
> +#define GEN_FCN7(CODE) (insn_data[CODE].genfun.argc7)
> +#define GEN_FCN8(CODE) (insn_data[CODE].genfun.argc8)
> +#define GEN_FCN9(CODE) (insn_data[CODE].genfun.argc9)
> +#define GEN_FCN10(CODE)        (insn_data[CODE].genfun.argc10)
> +#define GEN_FCN11(CODE)        (insn_data[CODE].genfun.argc11)
>
>  /* Contains the optab used for each rtx code, and vice-versa.  */
>  extern const optab code_to_optab_[NUM_RTX_CODE];
> Index: gcc/reload1.c
> ===================================================================
> --- gcc/reload1.c       (revision 200820)
> +++ gcc/reload1.c       (working copy)
> @@ -7538,7 +7538,7 @@
>               /* We'd have to add extra code to handle this case.  */
>               gcc_assert (!third_reload_reg);
>
> -             emit_insn (GEN_FCN (icode) (reloadreg, real_oldequiv,
> +             emit_insn (GEN_FCN3 (icode) (reloadreg, real_oldequiv,
>                                           second_reload_reg));
>               special = 1;
>             }
> @@ -7548,7 +7548,7 @@
>                  intermediate register (a tertiary reload).  */
>               if (tertiary_icode != CODE_FOR_nothing)
>                 {
> -                 emit_insn ((GEN_FCN (tertiary_icode)
> +                 emit_insn ((GEN_FCN3 (tertiary_icode)
>                               (second_reload_reg, real_oldequiv,
>                                third_reload_reg)));
>                 }
> @@ -7657,7 +7657,7 @@
>               /* We'd have to add extra code to handle this case.  */
>               gcc_assert (tertiary_reload < 0);
>
> -             emit_insn ((GEN_FCN (rl->secondary_out_icode)
> +             emit_insn ((GEN_FCN3 (rl->secondary_out_icode)
>                           (real_old, second_reloadreg, reloadreg)));
>               special = 1;
>             }
> @@ -7691,7 +7691,7 @@
>
>                   gen_reload (reloadreg, second_reloadreg,
>                               rl->opnum, rl->when_needed);
> -                 emit_insn ((GEN_FCN (tertiary_icode)
> +                 emit_insn ((GEN_FCN3 (tertiary_icode)
>                               (real_old, reloadreg, third_reloadreg)));
>                   special = 1;
>                 }
Stefan Kristiansson - Aug. 27, 2013, 9:54 a.m.
On Tue, Aug 27, 2013 at 11:03:32AM +0200, Richard Biener wrote:
> On Wed, Jul 10, 2013 at 3:14 AM, Stefan Kristiansson
> <stefan.kristiansson@saunalahti.fi> wrote:
> > The (static arg) generator functions are casted to a var arg
> > function pointer, making the assumption that the ABI for passing
> > the arguments will be the same as for static arguments.
> > This isn't a valid assumption on all architectures, var args might for
> > example be passed on the stack, even if there would be function argument
> > registers still available.
> >
> > There exists a bugreport for the problem here:
> > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12081
> >
> > This patch is taken from the suggestion by Rask Ingemann Lambertsen
> > and updated to the current svn tip of trunk.
> >
> > gcc/Changelog:
> >
> > 2013-07-10  Stefan Kristiansson  <stefan.kristiansson@saunalahti.fi>
> >
> >             PR target/12081
> >             * recog.h (rtx (*insn_gen_fn) (rtx, ...)): Remove typedef.
> >             (genfun): Replace var arg function pointer with static argument
> >             function pointers.
> >             * optabs.h (GEN_FCN): Replace single define with ones of the
> >             form GEN_FCN?, where ? is the number of arguments.
> >             * reload1.c: Use GEN_FCN? instead of GEN_FCN
> 
> Can't we use a template for all this to avoid the union and *[12345] mess?
> 

Oleg Endo proposed a cleaner approach using functors here:
http://gcc.gnu.org/ml/gcc-patches/2013-07/msg01315.html
and AFAIK that (or something close to it) is already applied.

Stefan

Patch

Index: gcc/recog.h
===================================================================
--- gcc/recog.h	(revision 200820)
+++ gcc/recog.h	(working copy)
@@ -256,7 +256,6 @@ 
 
 typedef int (*insn_operand_predicate_fn) (rtx, enum machine_mode);
 typedef const char * (*insn_output_fn) (rtx *, rtx);
-typedef rtx (*insn_gen_fn) (rtx, ...);
 
 struct insn_operand_data
 {
@@ -291,14 +290,41 @@ 
     const char *const *multi;
     insn_output_fn function;
   } output;
+  union {
+    rtx (*argc0)	(void);
+    rtx (*argc1)	(rtx);
+    rtx (*argc2)	(rtx, rtx);
+    rtx (*argc3)	(rtx, rtx, rtx);
+    rtx (*argc4)	(rtx, rtx, rtx, rtx);
+    rtx (*argc5)	(rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc6)	(rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc7)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc8)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc9)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc10)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc11)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  } genfun;
 #else
   struct {
     const char *single;
     const char *const *multi;
     insn_output_fn function;
   } output;
+  struct {
+    rtx (*argc0)	(void);
+    rtx (*argc1)	(rtx);
+    rtx (*argc2)	(rtx, rtx);
+    rtx (*argc3)	(rtx, rtx, rtx);
+    rtx (*argc4)	(rtx, rtx, rtx, rtx);
+    rtx (*argc5)	(rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc6)	(rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc7)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc8)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc9)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc10)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+    rtx (*argc11)	(rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  } genfun;
 #endif
-  const insn_gen_fn genfun;
   const struct insn_operand_data *const operand;
 
   const char n_generator_args;
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	(revision 200820)
+++ gcc/config/frv/frv.c	(working copy)
@@ -8860,7 +8860,7 @@ 
     return NULL_RTX;
 
   target = frv_legitimize_target (icode, target);
-  pat = GEN_FCN (icode) (target, op0);
+  pat = GEN_FCN2 (icode) (target, op0);
   if (! pat)
     return NULL_RTX;
 
@@ -8878,7 +8878,7 @@ 
 
   target = frv_legitimize_target (icode, target);
   op0 = frv_legitimize_argument (icode, 1, op0);
-  pat = GEN_FCN (icode) (target, op0);
+  pat = GEN_FCN2 (icode) (target, op0);
   if (! pat)
     return NULL_RTX;
 
@@ -8898,7 +8898,7 @@ 
   target = frv_legitimize_target (icode, target);
   op0 = frv_legitimize_argument (icode, 1, op0);
   op1 = frv_legitimize_argument (icode, 2, op1);
-  pat = GEN_FCN (icode) (target, op0, op1);
+  pat = GEN_FCN3 (icode) (target, op0, op1);
   if (! pat)
     return NULL_RTX;
 
@@ -8931,7 +8931,7 @@ 
     op1 = frv_legitimize_argument (icode, 2, op1);
 
   op2 = frv_matching_accg_for_acc (op0);
-  pat = GEN_FCN (icode) (target, op0, op1, op2);
+  pat = GEN_FCN4 (icode) (target, op0, op1, op2);
   if (! pat)
     return NULL_RTX;
 
@@ -8953,7 +8953,7 @@ 
 
   target = frv_legitimize_target (icode, target);
   op0 = frv_legitimize_argument (icode, 1, op0);
-  pat = GEN_FCN (icode) (target, op0, op1);
+  pat = GEN_FCN3 (icode) (target, op0, op1);
   if (! pat)
     return NULL_RTX;
 
@@ -8992,7 +8992,7 @@ 
 
   op0 = change_address (op0, V4SImode, addr);
   op1 = frv_legitimize_argument (icode, 1, op1);
-  pat = GEN_FCN (icode) (op0, op1);
+  pat = GEN_FCN2 (icode) (op0, op1);
   if (! pat)
     return 0;
 
@@ -9011,7 +9011,7 @@ 
 
   op0 = frv_legitimize_argument (icode, 1, op0);
   op1 = frv_legitimize_argument (icode, 1, op1);
-  pat = GEN_FCN (icode) (op0, op1);
+  pat = GEN_FCN2 (icode) (op0, op1);
   if (! pat)
     return NULL_RTX;
 
@@ -9027,7 +9027,7 @@ 
   rtx pat;
   rtx op0 = frv_read_argument (call, 0);
 
-  pat = GEN_FCN (icode) (force_reg (Pmode, op0));
+  pat = GEN_FCN1 (icode) (force_reg (Pmode, op0));
   if (! pat)
     return 0;
 
@@ -9056,7 +9056,7 @@ 
   op1 = frv_legitimize_argument (icode, 1, op1);
   op2 = frv_legitimize_argument (icode, 2, op2);
   op3 = frv_matching_accg_for_acc (op0);
-  pat = GEN_FCN (icode) (op0, op1, op2, op3);
+  pat = GEN_FCN4 (icode) (op0, op1, op2, op3);
   if (! pat)
     return NULL_RTX;
 
@@ -9087,7 +9087,7 @@ 
 
   op2 = frv_matching_accg_for_acc (op0);
   op3 = frv_matching_accg_for_acc (op1);
-  pat = GEN_FCN (icode) (op0, op1, op2, op3);
+  pat = GEN_FCN4 (icode) (op0, op1, op2, op3);
   if (! pat)
     return NULL_RTX;
 
@@ -9109,7 +9109,7 @@ 
     target = gen_reg_rtx (target_mode);
   op0 = frv_volatile_memref (insn_data[icode].operand[0].mode, op0);
   convert_move (target, op0, 1);
-  emit_insn (GEN_FCN (icode) (copy_rtx (op0), cookie, GEN_INT (FRV_IO_READ)));
+  emit_insn (GEN_FCN3 (icode) (copy_rtx (op0), cookie, GEN_INT (FRV_IO_READ)));
   cfun->machine->has_membar_p = 1;
   return target;
 }
@@ -9125,7 +9125,7 @@ 
 
   op0 = frv_volatile_memref (insn_data[icode].operand[0].mode, op0);
   convert_move (op0, force_reg (insn_data[icode].operand[0].mode, op1), 1);
-  emit_insn (GEN_FCN (icode) (copy_rtx (op0), cookie, GEN_INT (FRV_IO_WRITE)));
+  emit_insn (GEN_FCN3 (icode) (copy_rtx (op0), cookie, GEN_INT (FRV_IO_WRITE)));
   cfun->machine->has_membar_p = 1;
   return NULL_RTX;
 }
@@ -9160,7 +9160,7 @@ 
   emit_move_insn (simplify_gen_subreg (HImode, op1, DImode, 2), arg3);
   emit_move_insn (simplify_gen_subreg (HImode, op1, DImode, 6), arg4);
 
-  pat = GEN_FCN (icode) (target, op0, op1);
+  pat = GEN_FCN3 (icode) (target, op0, op1);
   if (! pat)
     return NULL_RTX;
 
@@ -9182,7 +9182,7 @@ 
   if (! op0)
     return NULL_RTX;
 
-  pat = GEN_FCN (icode) (op0);
+  pat = GEN_FCN1 (icode) (op0);
   if (pat)
     emit_insn (pat);
 
@@ -9194,7 +9194,7 @@ 
 static rtx
 frv_expand_noargs_builtin (enum insn_code icode)
 {
-  rtx pat = GEN_FCN (icode) (const0_rtx);
+  rtx pat = GEN_FCN0 (icode) ();
   if (pat)
     emit_insn (pat);
 
@@ -9215,7 +9215,7 @@ 
   if (! op0)
     return NULL_RTX;
 
-  pat = GEN_FCN (icode) (target, op0);
+  pat = GEN_FCN2 (icode) (target, op0);
   if (! pat)
     return NULL_RTX;
 
@@ -9239,7 +9239,7 @@ 
     return NULL_RTX;
 
   op1 = frv_legitimize_argument (icode, 1, op1);
-  pat = GEN_FCN (icode) (op0, op1);
+  pat = GEN_FCN2 (icode) (op0, op1);
   if (pat)
     emit_insn (pat);
 
Index: gcc/config/mep/mep.c
===================================================================
--- gcc/config/mep/mep.c	(revision 200820)
+++ gcc/config/mep/mep.c	(working copy)
@@ -6308,8 +6308,8 @@ 
     }
 
   /* Emit the instruction.  */
-  pat = idata->genfun (op[0], op[1], op[2], op[3], op[4],
-		       op[5], op[6], op[7], op[8], op[9]);
+  pat = idata->genfun.argc10 (op[0], op[1], op[2], op[3], op[4],
+			      op[5], op[6], op[7], op[8], op[9]);
 
   if (GET_CODE (pat) == SET
       && GET_CODE (SET_DEST (pat)) == PC
@@ -7079,9 +7079,9 @@ 
 	return false;
     }
 
-  emit_insn (idata->genfun (newop[0], newop[1], newop[2],
-			    newop[3], newop[4], newop[5],
-			    newop[6], newop[7], newop[8]));
+  emit_insn (idata->genfun.argc9 (newop[0], newop[1], newop[2],
+				  newop[3], newop[4], newop[5],
+				  newop[6], newop[7], newop[8]));
 
   return true;
 }
Index: gcc/config/picochip/picochip.c
===================================================================
--- gcc/config/picochip/picochip.c	(revision 200820)
+++ gcc/config/picochip/picochip.c	(working copy)
@@ -55,7 +55,7 @@ 
 #include "insn-attr.h"		/* For DFA state_t. */
 #include "insn-config.h"	/* Required by recog.h */
 #include "insn-codes.h"		/* For CODE_FOR_? */
-#include "optabs.h"		/* For GEN_FCN */
+#include "optabs.h"		/* For GEN_FCN? */
 #include "basic-block.h"	/* UPDATE_LIFE_GLOBAL* for picochip_reorg. */
 #include "timevar.h"		/* For TV_SCHED2, in picochip_reorg. */
 #include "libfuncs.h"		/* For memcpy_libfuncs, etc. */
@@ -3941,7 +3941,7 @@ 
     target = gen_reg_rtx (tmode);
 
   /* Emit and return the new instruction. */
-  pat = GEN_FCN (icode) (target, op0);
+  pat = GEN_FCN2 (icode) (target, op0);
   if (!pat)
     return 0;
   emit_insn (pat);
@@ -3986,7 +3986,7 @@ 
     target = gen_reg_rtx (tmode);
 
   /* Emit and return the new instruction. */
-  pat = GEN_FCN (icode) (target, op0, op1);
+  pat = GEN_FCN3 (icode) (target, op0, op1);
   if (!pat)
     return 0;
   emit_insn (pat);
@@ -4023,7 +4023,7 @@ 
     op1 = copy_to_mode_reg (mode1, op1);
 
   /* Emit and return the new instruction. */
-  pat = GEN_FCN (icode) (op0, op1);
+  pat = GEN_FCN2 (icode) (op0, op1);
   if (!pat)
     return 0;
   emit_insn (pat);
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	(revision 200820)
+++ gcc/config/alpha/alpha.c	(working copy)
@@ -6615,16 +6615,16 @@ 
   switch (arity)
     {
     case 0:
-      pat = GEN_FCN (icode) (target);
+      pat = GEN_FCN1 (icode) (target);
       break;
     case 1:
       if (nonvoid)
-        pat = GEN_FCN (icode) (target, op[0]);
+        pat = GEN_FCN2 (icode) (target, op[0]);
       else
-	pat = GEN_FCN (icode) (op[0]);
+	pat = GEN_FCN1 (icode) (op[0]);
       break;
     case 2:
-      pat = GEN_FCN (icode) (target, op[0], op[1]);
+      pat = GEN_FCN3 (icode) (target, op[0], op[1]);
       break;
     default:
       gcc_unreachable ();
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	(revision 200820)
+++ gcc/config/sparc/sparc.c	(working copy)
@@ -10295,19 +10295,19 @@ 
   switch (arg_count)
     {
     case 0:
-      pat = GEN_FCN (icode) (op[0]);
+      pat = GEN_FCN1 (icode) (op[0]);
       break;
     case 1:
       if (nonvoid)
-	pat = GEN_FCN (icode) (op[0], op[1]);
+	pat = GEN_FCN2 (icode) (op[0], op[1]);
       else
-	pat = GEN_FCN (icode) (op[1]);
+	pat = GEN_FCN1 (icode) (op[1]);
       break;
     case 2:
-      pat = GEN_FCN (icode) (op[0], op[1], op[2]);
+      pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
       break;
     case 3:
-      pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
+      pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
       break;
     default:
       gcc_unreachable ();
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	(revision 200820)
+++ gcc/config/aarch64/aarch64.c	(working copy)
@@ -6914,7 +6914,7 @@ 
       x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, one_var));
       icode = optab_handler (vec_set_optab, mode);
       gcc_assert (icode != CODE_FOR_nothing);
-      emit_insn (GEN_FCN (icode) (target, x, index));
+      emit_insn (GEN_FCN3 (icode) (target, x, index));
       return;
     }
 
Index: gcc/config/aarch64/aarch64-builtins.c
===================================================================
--- gcc/config/aarch64/aarch64-builtins.c	(revision 200820)
+++ gcc/config/aarch64/aarch64-builtins.c	(working copy)
@@ -1016,23 +1016,23 @@ 
     switch (argc)
       {
       case 1:
-	pat = GEN_FCN (icode) (target, op[0]);
+	pat = GEN_FCN2 (icode) (target, op[0]);
 	break;
 
       case 2:
-	pat = GEN_FCN (icode) (target, op[0], op[1]);
+	pat = GEN_FCN3 (icode) (target, op[0], op[1]);
 	break;
 
       case 3:
-	pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
+	pat = GEN_FCN4 (icode) (target, op[0], op[1], op[2]);
 	break;
 
       case 4:
-	pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
+	pat = GEN_FCN5 (icode) (target, op[0], op[1], op[2], op[3]);
 	break;
 
       case 5:
-	pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]);
+	pat = GEN_FCN6 (icode) (target, op[0], op[1], op[2], op[3], op[4]);
 	break;
 
       default:
@@ -1042,23 +1042,23 @@ 
     switch (argc)
       {
       case 1:
-	pat = GEN_FCN (icode) (op[0]);
+	pat = GEN_FCN1 (icode) (op[0]);
 	break;
 
       case 2:
-	pat = GEN_FCN (icode) (op[0], op[1]);
+	pat = GEN_FCN2 (icode) (op[0], op[1]);
 	break;
 
       case 3:
-	pat = GEN_FCN (icode) (op[0], op[1], op[2]);
+	pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
 	break;
 
       case 4:
-	pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
+	pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
 	break;
 
       case 5:
-	pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
+	pat = GEN_FCN5 (icode) (op[0], op[1], op[2], op[3], op[4]);
 	break;
 
       default:
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	(revision 200820)
+++ gcc/config/bfin/bfin.c	(working copy)
@@ -5366,9 +5366,9 @@ 
     op1 = copy_to_mode_reg (mode1, op1);
 
   if (macflag == -1)
-    pat = GEN_FCN (icode) (target, op0, op1);
+    pat = GEN_FCN3 (icode) (target, op0, op1);
   else
-    pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
+    pat = GEN_FCN4 (icode) (target, op0, op1, GEN_INT (macflag));
   if (! pat)
     return 0;
 
@@ -5407,7 +5407,7 @@ 
   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
     op0 = copy_to_mode_reg (mode0, op0);
 
-  pat = GEN_FCN (icode) (target, op0);
+  pat = GEN_FCN2 (icode) (target, op0);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -5466,7 +5466,7 @@ 
       if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
 	op0 = copy_to_mode_reg (mode0, op0);
 
-      pat = GEN_FCN (icode) (target, op0, op0);
+      pat = GEN_FCN3 (icode) (target, op0, op0);
       if (! pat)
 	return 0;
       emit_insn (pat);
Index: gcc/config/bfin/bfin.md
===================================================================
--- gcc/config/bfin/bfin.md	(revision 200820)
+++ gcc/config/bfin/bfin.md	(working copy)
@@ -984,10 +984,10 @@ 
   split_di (operands, 3, lo_half, hi_half);
   if (!(*insn_data[icode].operand[2].predicate) (lo_half[2], SImode))
     lo_half[2] = force_reg (SImode, lo_half[2]);
-  emit_insn (GEN_FCN (icode) (lo_half[0], lo_half[1], lo_half[2]));
+  emit_insn (GEN_FCN3 (icode) (lo_half[0], lo_half[1], lo_half[2]));
   if (!(*insn_data[icode].operand[2].predicate) (hi_half[2], SImode))
     hi_half[2] = force_reg (SImode, hi_half[2]);
-  emit_insn (GEN_FCN (icode) (hi_half[0], hi_half[1], hi_half[2]));
+  emit_insn (GEN_FCN3 (icode) (hi_half[0], hi_half[1], hi_half[2]));
   DONE;
 })
 
Index: gcc/config/arm/arm.md
===================================================================
--- gcc/config/arm/arm.md	(revision 200820)
+++ gcc/config/arm/arm.md	(working copy)
@@ -9904,8 +9904,8 @@ 
     if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
       operands[2] = force_reg (SImode, operands[2]);
 
-    emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
-					  operands[3], operands[4]));
+    emit_jump_insn (GEN_FCN4 ((int) code) (operands[0], operands[2],
+					   operands[3], operands[4]));
     DONE;
   }"
 )
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(revision 200820)
+++ gcc/config/arm/arm.c	(working copy)
@@ -21850,7 +21850,7 @@ 
   if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
     op1 = copy_to_mode_reg (mode1, op1);
 
-  pat = GEN_FCN (icode) (target, op0, op1);
+  pat = GEN_FCN3 (icode) (target, op0, op1);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -21884,7 +21884,7 @@ 
 	op0 = copy_to_mode_reg (mode0, op0);
     }
 
-  pat = GEN_FCN (icode) (target, op0);
+  pat = GEN_FCN2 (icode) (target, op0);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -22043,23 +22043,23 @@ 
     switch (argc)
       {
       case 1:
-	pat = GEN_FCN (icode) (target, op[0]);
+	pat = GEN_FCN2 (icode) (target, op[0]);
 	break;
 
       case 2:
-	pat = GEN_FCN (icode) (target, op[0], op[1]);
+	pat = GEN_FCN3 (icode) (target, op[0], op[1]);
 	break;
 
       case 3:
-	pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
+	pat = GEN_FCN4 (icode) (target, op[0], op[1], op[2]);
 	break;
 
       case 4:
-	pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
+	pat = GEN_FCN5 (icode) (target, op[0], op[1], op[2], op[3]);
 	break;
 
       case 5:
-	pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]);
+	pat = GEN_FCN6 (icode) (target, op[0], op[1], op[2], op[3], op[4]);
 	break;
 
       default:
@@ -22069,23 +22069,23 @@ 
     switch (argc)
       {
       case 1:
-	pat = GEN_FCN (icode) (op[0]);
+	pat = GEN_FCN1 (icode) (op[0]);
 	break;
 
       case 2:
-	pat = GEN_FCN (icode) (op[0], op[1]);
+	pat = GEN_FCN2 (icode) (op[0], op[1]);
 	break;
 
       case 3:
-	pat = GEN_FCN (icode) (op[0], op[1], op[2]);
+	pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
 	break;
 
       case 4:
-	pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
+	pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
 	break;
 
       case 5:
-	pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
+	pat = GEN_FCN5 (icode) (op[0], op[1], op[2], op[3], op[4]);
         break;
 
       default:
@@ -22414,7 +22414,7 @@ 
 	  || GET_MODE (target) != tmode
 	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
 	target = gen_reg_rtx (tmode);
-      pat = GEN_FCN (icode) (target, op0, op1);
+      pat = GEN_FCN3 (icode) (target, op0, op1);
       if (! pat)
 	return 0;
       emit_insn (pat);
@@ -22462,7 +22462,7 @@ 
 	  || GET_MODE (target) != tmode
 	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
 	target = gen_reg_rtx (tmode);
-      pat = GEN_FCN (icode) (target, op0, op1, op2);
+      pat = GEN_FCN4 (icode) (target, op0, op1, op2);
       if (!pat)
 	return 0;
       emit_insn (pat);
@@ -22521,7 +22521,7 @@ 
 	  || GET_MODE (target) != tmode
 	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
 	target = gen_reg_rtx (tmode);
-      pat = GEN_FCN (icode) (target, op0, op1, op2);
+      pat = GEN_FCN4 (icode) (target, op0, op1, op2);
       if (! pat)
 	return 0;
       emit_insn (pat);
@@ -22540,7 +22540,7 @@ 
       mode0 = insn_data[icode].operand[0].mode;
       if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
         op0 = copy_to_mode_reg (mode0, op0);
-      pat = GEN_FCN (icode) (op0);
+      pat = GEN_FCN1 (icode) (op0);
       if (!pat)
 	return 0;
       emit_insn (pat);
@@ -22559,7 +22559,7 @@ 
 	  || GET_MODE (target) != tmode
 	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
         target = gen_reg_rtx (tmode);
-      pat = GEN_FCN (icode) (target);
+      pat = GEN_FCN1 (icode) (target);
       if (!pat)
         return 0;
       emit_insn (pat);
@@ -22589,7 +22589,7 @@ 
 	  || GET_MODE (target) != tmode
 	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
 	target = gen_reg_rtx (tmode);
-      pat = GEN_FCN (icode) (target, op0, op1);
+      pat = GEN_FCN3 (icode) (target, op0, op1);
       if (! pat)
 	return 0;
       emit_insn (pat);
@@ -22702,7 +22702,7 @@ 
 	  || GET_MODE (target) != tmode
 	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
 	target = gen_reg_rtx (tmode);
-      pat = GEN_FCN (icode) (target, op0, op1, op2);
+      pat = GEN_FCN4 (icode) (target, op0, op1, op2);
       if (! pat)
 	return 0;
       emit_insn (pat);
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c	(revision 200820)
+++ gcc/config/stormy16/stormy16.c	(working copy)
@@ -2354,8 +2354,8 @@ 
 	retval = op[o];
     }
 
-  pat = GEN_FCN (code) (op[0], op[1], op[2], op[3], op[4],
-			op[5], op[6], op[7], op[8], op[9]);
+  pat = GEN_FCN10 (code) (op[0], op[1], op[2], op[3], op[4],
+			  op[5], op[6], op[7], op[8], op[9]);
   emit_insn (pat);
 
   for (o = 0; s16builtins[i].arg_ops[o]; o++)
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	(revision 200820)
+++ gcc/config/spu/spu.c	(working copy)
@@ -878,7 +878,7 @@ 
       if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate)
 	  (op1, op_mode))
 	op1 = force_reg (op_mode, op1);
-      comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result,
+      comp_rtx = GEN_FCN3 (spu_comp_icode[index][scode]) (compare_result,
 							 op0, op1);
       if (comp_rtx == 0)
 	abort ();
@@ -887,14 +887,14 @@ 
       if (eq_test)
         {
           eq_result = gen_reg_rtx (comp_mode);
-          eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result,
+          eq_rtx = GEN_FCN3 (spu_comp_icode[index][eq_code]) (eq_result,
 							     op0, op1);
           if (eq_rtx == 0)
 	    abort ();
           emit_insn (eq_rtx);
           ior_code = optab_handler (ior_optab, comp_mode);
           gcc_assert (ior_code != CODE_FOR_nothing);
-          emit_insn (GEN_FCN (ior_code)
+          emit_insn (GEN_FCN3 (ior_code)
 		     (compare_result, compare_result, eq_result));
         }
     }
@@ -4450,7 +4450,7 @@ 
 	{
 	  enum insn_code icode = convert_optab_handler (trunc_optab,
 							mode, imode);
-	  emit_insn (GEN_FCN (icode) (ops[0], from));
+	  emit_insn (GEN_FCN2 (icode) (ops[0], from));
 	}
       else
 	emit_insn (gen_extend_insn (ops[0], from, mode, imode, 1));
@@ -6150,7 +6150,7 @@ 
 
             nor_code = optab_handler (one_cmpl_optab, dest_mode);
             gcc_assert (nor_code != CODE_FOR_nothing);
-            emit_insn (GEN_FCN (nor_code) (mask, rev_mask));
+            emit_insn (GEN_FCN2 (nor_code) (mask, rev_mask));
             if (dmode != dest_mode)
               {
                 rtx temp = gen_reg_rtx (dest_mode);
@@ -6185,7 +6185,7 @@ 
 
             ior_code = optab_handler (ior_optab, dest_mode);
             gcc_assert (ior_code != CODE_FOR_nothing);
-            emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
+            emit_insn (GEN_FCN3 (ior_code) (mask, c_rtx, eq_rtx));
             if (dmode != dest_mode)
               {
                 rtx temp = gen_reg_rtx (dest_mode);
@@ -6206,7 +6206,7 @@ 
 
             ior_code = optab_handler (ior_optab, dest_mode);
             gcc_assert (ior_code != CODE_FOR_nothing);
-            emit_insn (GEN_FCN (ior_code) (mask, lt_rtx, gt_rtx));
+            emit_insn (GEN_FCN3 (ior_code) (mask, lt_rtx, gt_rtx));
             if (dmode != dest_mode)
               {
                 rtx temp = gen_reg_rtx (dest_mode);
@@ -6227,7 +6227,7 @@ 
 
             and_code = optab_handler (and_optab, dest_mode);
             gcc_assert (and_code != CODE_FOR_nothing);
-            emit_insn (GEN_FCN (and_code) (mask, a_rtx, b_rtx));
+            emit_insn (GEN_FCN3 (and_code) (mask, a_rtx, b_rtx));
             if (dmode != dest_mode)
               {
                 rtx temp = gen_reg_rtx (dest_mode);
@@ -6256,7 +6256,7 @@ 
         }
     }
 
-  emit_insn (GEN_FCN (vec_cmp_insn) (mask, op0, op1));
+  emit_insn (GEN_FCN3 (vec_cmp_insn) (mask, op0, op1));
   if (dmode != dest_mode)
     {
       rtx temp = gen_reg_rtx (dest_mode);
@@ -6460,7 +6460,7 @@ 
                  gen_rtx_NEG (GET_MODE (addr), addr)));
       op = gen_rtx_MEM (mode, op);
 
-      pat = GEN_FCN (icode) (target, op);
+      pat = GEN_FCN2 (icode) (target, op);
       if (!pat) 
         return 0;
       emit_insn (pat);
@@ -6516,25 +6516,25 @@ 
   switch (n_operands)
     {
     case 0:
-      pat = GEN_FCN (icode) (0);
+      pat = GEN_FCN0 (icode) ();
       break;
     case 1:
-      pat = GEN_FCN (icode) (ops[0]);
+      pat = GEN_FCN1 (icode) (ops[0]);
       break;
     case 2:
-      pat = GEN_FCN (icode) (ops[0], ops[1]);
+      pat = GEN_FCN2 (icode) (ops[0], ops[1]);
       break;
     case 3:
-      pat = GEN_FCN (icode) (ops[0], ops[1], ops[2]);
+      pat = GEN_FCN3 (icode) (ops[0], ops[1], ops[2]);
       break;
     case 4:
-      pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]);
+      pat = GEN_FCN4 (icode) (ops[0], ops[1], ops[2], ops[3]);
       break;
     case 5:
-      pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3], ops[4]);
+      pat = GEN_FCN5 (icode) (ops[0], ops[1], ops[2], ops[3], ops[4]);
       break;
     case 6:
-      pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3], ops[4], ops[5]);
+      pat = GEN_FCN6 (icode) (ops[0], ops[1], ops[2], ops[3], ops[4], ops[5]);
       break;
     default:
       abort ();
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c	(revision 200820)
+++ gcc/config/avr/avr.c	(working copy)
@@ -11727,9 +11727,9 @@ 
 
   switch (n_args)
     {
-    case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
-    case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
-    case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
+    case 1: pat = GEN_FCN2 (icode) (target, xop[0]); break;
+    case 2: pat = GEN_FCN3 (icode) (target, xop[0], xop[1]); break;
+    case 3: pat = GEN_FCN4 (icode) (target, xop[0], xop[1], xop[2]); break;
 
     default:
       gcc_unreachable();
@@ -11857,7 +11857,7 @@ 
 
   if (d->n_args == 0)
     {
-      emit_insn ((GEN_FCN (d->icode)) (target));
+      emit_insn ((GEN_FCN1 (d->icode)) (target));
       return NULL_RTX;
     }
 
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(revision 200820)
+++ gcc/config/ia64/ia64.c	(working copy)
@@ -2335,7 +2335,7 @@ 
 	  gcc_unreachable ();
 	}
 
-      emit_insn (GEN_FCN (icode) (old_dst, mem, val));
+      emit_insn (GEN_FCN3 (icode) (old_dst, mem, val));
 
       if (new_dst)
 	{
@@ -2426,7 +2426,7 @@ 
       gcc_unreachable ();
     }
 
-  emit_insn (GEN_FCN (icode) (cmp_reg, mem, ar_ccv, new_reg));
+  emit_insn (GEN_FCN4 (icode) (cmp_reg, mem, ar_ccv, new_reg));
 
   emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, NULL, DImode, true, label);
 }
Index: gcc/config/tilegx/tilegx.c
===================================================================
--- gcc/config/tilegx/tilegx.c	(revision 200820)
+++ gcc/config/tilegx/tilegx.c	(working copy)
@@ -2064,7 +2064,7 @@ 
 	  gcc_assert (shift_count > 0 && shift_count < 64);
 
 	  /* Emit the actual instruction.  */
-	  emit_insn (GEN_FCN (opcode)
+	  emit_insn (GEN_FCN3 (opcode)
 		     (out, subexprs[entry->lhs],
 		      gen_rtx_CONST_INT (DImode, shift_count)));
 	}
@@ -2078,7 +2078,7 @@ 
 	  gcc_assert (entry->rhs < num_subexprs);
 
 	  /* Emit the actual instruction.  */
-	  emit_insn (GEN_FCN (opcode)
+	  emit_insn (GEN_FCN3 (opcode)
 		     (out, subexprs[entry->lhs], subexprs[entry->rhs]));
 	}
 
@@ -3446,7 +3446,6 @@ 
   rtx op[MAX_BUILTIN_ARGS + 1], pat;
   int opnum;
   bool nonvoid;
-  insn_gen_fn fn;
 
   if (fcode >= TILEGX_BUILTIN_max)
     internal_error ("bad builtin fcode");
@@ -3517,26 +3516,25 @@ 
       op[0] = target;
     }
 
-  fn = GEN_FCN (icode);
   switch (opnum)
     {
     case 0:
-      pat = fn (NULL_RTX);
+      pat = GEN_FCN0 (icode) ();
       break;
     case 1:
-      pat = fn (op[0]);
+      pat = GEN_FCN1 (icode) (op[0]);
       break;
     case 2:
-      pat = fn (op[0], op[1]);
+      pat = GEN_FCN2 (icode) (op[0], op[1]);
       break;
     case 3:
-      pat = fn (op[0], op[1], op[2]);
+      pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
       break;
     case 4:
-      pat = fn (op[0], op[1], op[2], op[3]);
+      pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
       break;
     case 5:
-      pat = fn (op[0], op[1], op[2], op[3], op[4]);
+      pat = GEN_FCN5 (icode) (op[0], op[1], op[2], op[3], op[4]);
       break;
     default:
       gcc_unreachable ();
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	(revision 200820)
+++ gcc/config/sh/sh.c	(working copy)
@@ -12005,16 +12005,16 @@ 
   switch (nop)
     {
     case 1:
-      pat = (*insn_data[d->icode].genfun) (op[0]);
+      pat = GEN_FCN1 (d->icode) (op[0]);
       break;
     case 2:
-      pat = (*insn_data[d->icode].genfun) (op[0], op[1]);
+      pat = GEN_FCN2 (d->icode) (op[0], op[1]);
       break;
     case 3:
-      pat = (*insn_data[d->icode].genfun) (op[0], op[1], op[2]);
+      pat = GEN_FCN3 (d->icode) (op[0], op[1], op[2]);
       break;
     case 4:
-      pat = (*insn_data[d->icode].genfun) (op[0], op[1], op[2], op[3]);
+      pat = GEN_FCN4 (d->icode) (op[0], op[1], op[2], op[3]);
       break;
     default:
       gcc_unreachable ();
Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	(revision 200820)
+++ gcc/config/c6x/c6x.c	(working copy)
@@ -1770,7 +1770,7 @@ 
 	{
 	  enum insn_code icode = (srcmode == SImode ? CODE_FOR_movmisalignsi
 				  : CODE_FOR_movmisaligndi);
-	  emit_insn (GEN_FCN (icode) (reg_lowpart, srcmem));
+	  emit_insn (GEN_FCN2 (icode) (reg_lowpart, srcmem));
 	}
       else
 	emit_move_insn (reg_lowpart, srcmem);
@@ -1804,7 +1804,7 @@ 
 	    {
 	      enum insn_code icode = (dstmode == SImode ? CODE_FOR_movmisalignsi
 				      : CODE_FOR_movmisaligndi);
-	      emit_insn (GEN_FCN (icode) (dstmem, dstreg));
+	      emit_insn (GEN_FCN2 (icode) (dstmem, dstreg));
 	    }
 	  else
 	    emit_move_insn (dstmem, dstreg);
@@ -6583,9 +6583,9 @@ 
     op1 = copy_to_mode_reg (mode1, op1);
 
   if (match_op)
-    pat = GEN_FCN (icode) (target, target, op0, op1);
+    pat = GEN_FCN4 (icode) (target, target, op0, op1);
   else
-    pat = GEN_FCN (icode) (target, op0, op1);
+    pat = GEN_FCN3 (icode) (target, op0, op1);
 
   if (! pat)
     return 0;
@@ -6626,7 +6626,7 @@ 
   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
     op0 = copy_to_mode_reg (mode0, op0);
 
-  pat = GEN_FCN (icode) (target, op0);
+  pat = GEN_FCN2 (icode) (target, op0);
   if (! pat)
     return 0;
   emit_insn (pat);
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	(revision 200820)
+++ gcc/config/iq2000/iq2000.c	(working copy)
@@ -2611,30 +2611,30 @@ 
   switch (argcount)
     {
     case 0:
-	pat = GEN_FCN (icode) (target);
+	pat = GEN_FCN1 (icode) (target);
     case 1:
       if (target)
-	pat = GEN_FCN (icode) (target, op[0]);
+	pat = GEN_FCN2 (icode) (target, op[0]);
       else
-	pat = GEN_FCN (icode) (op[0]);
+	pat = GEN_FCN1 (icode) (op[0]);
       break;
     case 2:
       if (target)
-	pat = GEN_FCN (icode) (target, op[0], op[1]);
+	pat = GEN_FCN3 (icode) (target, op[0], op[1]);
       else
-	pat = GEN_FCN (icode) (op[0], op[1]);
+	pat = GEN_FCN2 (icode) (op[0], op[1]);
       break;
     case 3:
       if (target)
-	pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
+	pat = GEN_FCN4 (icode) (target, op[0], op[1], op[2]);
       else
-	pat = GEN_FCN (icode) (op[0], op[1], op[2]);
+	pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
       break;
     case 4:
       if (target)
-	pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
+	pat = GEN_FCN5 (icode) (target, op[0], op[1], op[2], op[3]);
       else
-	pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
+	pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
       break;
     default:
       gcc_unreachable ();
Index: gcc/config/tilepro/tilepro.c
===================================================================
--- gcc/config/tilepro/tilepro.c	(revision 200820)
+++ gcc/config/tilepro/tilepro.c	(working copy)
@@ -1895,7 +1895,7 @@ 
 	  gcc_assert (shift_count > 0 && shift_count < 32);
 
 	  /* Emit the actual instruction.  */
-	  emit_insn (GEN_FCN (opcode)
+	  emit_insn (GEN_FCN3 (opcode)
 		     (out, subexprs[entry->lhs],
 		      gen_rtx_CONST_INT (SImode, shift_count)));
 	}
@@ -1909,7 +1909,7 @@ 
 	  gcc_assert (entry->rhs < num_subexprs);
 
 	  /* Emit the actual instruction.  */
-	  emit_insn (GEN_FCN (opcode)
+	  emit_insn (GEN_FCN3 (opcode)
 		     (out, subexprs[entry->lhs], subexprs[entry->rhs]));
 	}
 
@@ -3092,7 +3092,6 @@ 
   rtx op[MAX_BUILTIN_ARGS + 1], pat;
   int opnum;
   bool nonvoid;
-  insn_gen_fn fn;
 
   if (fcode >= TILEPRO_BUILTIN_max)
     internal_error ("bad builtin fcode");
@@ -3141,26 +3140,25 @@ 
       op[0] = target;
     }
 
-  fn = GEN_FCN (icode);
   switch (opnum)
     {
     case 0:
-      pat = fn (NULL_RTX);
+      pat = GEN_FCN0 (idcode) ();
       break;
     case 1:
-      pat = fn (op[0]);
+      pat = GEN_FCN1 (icode) (op[0]);
       break;
     case 2:
-      pat = fn (op[0], op[1]);
+      pat = GEN_FCN2 (icode) (op[0], op[1]);
       break;
     case 3:
-      pat = fn (op[0], op[1], op[2]);
+      pat = GEN_FCN3 (icode) (op[0], op[1], op[2]);
       break;
     case 4:
-      pat = fn (op[0], op[1], op[2], op[3]);
+      pat = GEN_FCN4 (icode) (op[0], op[1], op[2], op[3]);
       break;
     case 5:
-      pat = fn (op[0], op[1], op[2], op[3], op[4]);
+      pat = GEN_FCN5 (icode) (op[0], op[1], op[2], op[3], op[4]);
       break;
     default:
       gcc_unreachable ();
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	(revision 200820)
+++ gcc/config/s390/s390.c	(working copy)
@@ -9828,19 +9828,19 @@ 
   switch (arity)
     {
     case 0:
-      pat = GEN_FCN (icode) (target);
+      pat = GEN_FCN1 (icode) (target);
       break;
     case 1:
       if (nonvoid)
-        pat = GEN_FCN (icode) (target, op[0]);
+        pat = GEN_FCN2 (icode) (target, op[0]);
       else
-	pat = GEN_FCN (icode) (op[0]);
+	pat = GEN_FCN1 (icode) (op[0]);
       break;
     case 2:
       if (nonvoid)
-	pat = GEN_FCN (icode) (target, op[0], op[1]);
+	pat = GEN_FCN3 (icode) (target, op[0], op[1]);
       else
-	pat = GEN_FCN (icode) (op[0], op[1]);
+	pat = GEN_FCN2 (icode) (op[0], op[1]);
       break;
     default:
       gcc_unreachable ();
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 200820)
+++ gcc/config/i386/i386.c	(working copy)
@@ -22220,8 +22220,8 @@ 
       /* We move from memory to memory, so we'll need to do it via
 	 a temporary register.  */
       tempreg = gen_reg_rtx (move_mode);
-      emit_insn (GEN_FCN (code) (tempreg, src));
-      emit_insn (GEN_FCN (code) (dst, tempreg));
+      emit_insn (GEN_FCN2 (code) (tempreg, src));
+      emit_insn (GEN_FCN2 (code) (dst, tempreg));
 
       emit_move_insn (destptr,
 		      gen_rtx_PLUS (Pmode, copy_rtx (destptr), adjust));
@@ -30451,7 +30451,7 @@ 
   if (!insn_data[icode].operand[2].predicate (op1, mode1))
     op1 = copy_to_mode_reg (mode1, op1);
 
-  pat = GEN_FCN (icode) (target, op0, op1);
+  pat = GEN_FCN3 (icode) (target, op0, op1);
   if (! pat)
     return 0;
 
@@ -30656,31 +30656,31 @@ 
   switch (nargs)
     {
     case 1:
-      pat = GEN_FCN (icode) (target, args[0].op);
+      pat = GEN_FCN2 (icode) (target, args[0].op);
       break;
 
     case 2:
       if (tf_p)
-	pat = GEN_FCN (icode) (target, args[0].op, args[1].op,
+	pat = GEN_FCN4 (icode) (target, args[0].op, args[1].op,
 			       GEN_INT ((int)sub_code));
       else if (! comparison_p)
-	pat = GEN_FCN (icode) (target, args[0].op, args[1].op);
+	pat = GEN_FCN3 (icode) (target, args[0].op, args[1].op);
       else
 	{
 	  rtx cmp_op = gen_rtx_fmt_ee (sub_code, GET_MODE (target),
 				       args[0].op,
 				       args[1].op);
 
-	  pat = GEN_FCN (icode) (target, cmp_op, args[0].op, args[1].op);
+	  pat = GEN_FCN4 (icode) (target, cmp_op, args[0].op, args[1].op);
 	}
       break;
 
     case 3:
-      pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op);
+      pat = GEN_FCN4 (icode) (target, args[0].op, args[1].op, args[2].op);
       break;
 
     case 4:
-      pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op, args[3].op);
+      pat = GEN_FCN5 (icode) (target, args[0].op, args[1].op, args[2].op, args[3].op);
       break;
 
     default:
@@ -30723,7 +30723,7 @@ 
   if (!insn_data[icode].operand[2].predicate (op1, mode0))
     op1 = copy_to_mode_reg (mode0, op1);
 
-  pat = GEN_FCN (icode) (target, op0, op1);
+  pat = GEN_FCN3 (icode) (target, op0, op1);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -30775,7 +30775,7 @@ 
     op1 = copy_to_mode_reg (mode1, op1);
 
   op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
-  pat = GEN_FCN (d->icode) (target, op0, op1, op2);
+  pat = GEN_FCN4 (d->icode) (target, op0, op1, op2);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -30822,7 +30822,7 @@ 
       || !insn_data[d->icode].operand[1].predicate (op1, mode1))
     op1 = copy_to_mode_reg (mode1, op1);
 
-  pat = GEN_FCN (d->icode) (op0, op1);
+  pat = GEN_FCN2 (d->icode) (op0, op1);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -30861,7 +30861,7 @@ 
 
   op1 = GEN_INT (d->comparison);
 
-  pat = GEN_FCN (d->icode) (target, op0, op1);
+  pat = GEN_FCN3 (d->icode) (target, op0, op1);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -30899,7 +30899,7 @@ 
 
   op2 = GEN_INT (d->comparison);
 
-  pat = GEN_FCN (d->icode) (target, op0, op1, op2);
+  pat = GEN_FCN4 (d->icode) (target, op0, op1, op2);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -30937,7 +30937,7 @@ 
       || !insn_data[d->icode].operand[1].predicate (op1, mode1))
     op1 = copy_to_mode_reg (mode1, op1);
 
-  pat = GEN_FCN (d->icode) (op0, op1);
+  pat = GEN_FCN2 (d->icode) (op0, op1);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -31008,7 +31008,7 @@ 
 
       scratch1 = gen_reg_rtx (tmode1);
 
-      pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2, op3, op4);
+      pat = GEN_FCN7 (d->icode) (target, scratch1, op0, op1, op2, op3, op4);
     }
   else if (d->code == IX86_BUILTIN_PCMPESTRM128)
     {
@@ -31019,7 +31019,7 @@ 
 
       scratch0 = gen_reg_rtx (tmode0);
 
-      pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2, op3, op4);
+      pat = GEN_FCN7 (d->icode) (scratch0, target, op0, op1, op2, op3, op4);
     }
   else
     {
@@ -31028,7 +31028,7 @@ 
       scratch0 = gen_reg_rtx (tmode0);
       scratch1 = gen_reg_rtx (tmode1);
 
-      pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2, op3, op4);
+      pat = GEN_FCN7 (d->icode) (scratch0, scratch1, op0, op1, op2, op3, op4);
     }
 
   if (! pat)
@@ -31103,7 +31103,7 @@ 
 
       scratch1 = gen_reg_rtx (tmode1);
 
-      pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2);
+      pat = GEN_FCN5 (d->icode) (target, scratch1, op0, op1, op2);
     }
   else if (d->code == IX86_BUILTIN_PCMPISTRM128)
     {
@@ -31114,7 +31114,7 @@ 
 
       scratch0 = gen_reg_rtx (tmode0);
 
-      pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2);
+      pat = GEN_FCN5 (d->icode) (scratch0, target, op0, op1, op2);
     }
   else
     {
@@ -31123,7 +31123,7 @@ 
       scratch0 = gen_reg_rtx (tmode0);
       scratch1 = gen_reg_rtx (tmode1);
 
-      pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2);
+      pat = GEN_FCN5 (d->icode) (scratch0, scratch1, op0, op1, op2);
     }
 
   if (! pat)
@@ -31600,17 +31600,17 @@ 
   switch (nargs)
     {
     case 1:
-      pat = GEN_FCN (icode) (real_target, args[0].op);
+      pat = GEN_FCN2 (icode) (real_target, args[0].op);
       break;
     case 2:
-      pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op);
+      pat = GEN_FCN3 (icode) (real_target, args[0].op, args[1].op);
       break;
     case 3:
-      pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op,
+      pat = GEN_FCN4 (icode) (real_target, args[0].op, args[1].op,
 			     args[2].op);
       break;
     case 4:
-      pat = GEN_FCN (icode) (real_target, args[0].op, args[1].op,
+      pat = GEN_FCN5 (icode) (real_target, args[0].op, args[1].op,
 			     args[2].op, args[3].op);
       break;
     default:
@@ -31648,7 +31648,7 @@ 
   switch ((enum ix86_builtin_func_type) d->flag)
     {
     case VOID_FTYPE_VOID:
-      emit_insn (GEN_FCN (icode) (target));
+      emit_insn (GEN_FCN1 (icode) (target));
       return 0;
     case VOID_FTYPE_UINT64:
     case VOID_FTYPE_UNSIGNED:
@@ -31819,16 +31819,16 @@ 
   switch (nargs)
     {
     case 0:
-      pat = GEN_FCN (icode) (target);
+      pat = GEN_FCN1 (icode) (target);
       break;
     case 1:
-      pat = GEN_FCN (icode) (target, args[0].op);
+      pat = GEN_FCN2 (icode) (target, args[0].op);
       break;
     case 2:
-      pat = GEN_FCN (icode) (target, args[0].op, args[1].op);
+      pat = GEN_FCN3 (icode) (target, args[0].op, args[1].op);
       break;
     case 3:
-      pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op);
+      pat = GEN_FCN4 (icode) (target, args[0].op, args[1].op, args[2].op);
       break;
     default:
       gcc_unreachable ();
@@ -32053,7 +32053,7 @@ 
 	op1 = copy_to_mode_reg (mode1, op1);
       if (!insn_data[icode].operand[2].predicate (op2, mode2))
 	op2 = copy_to_mode_reg (mode2, op2);
-      pat = GEN_FCN (icode) (op0, op1, op2);
+      pat = GEN_FCN3 (icode) (op0, op1, op2);
       if (! pat)
 	return 0;
       emit_insn (pat);
@@ -32247,7 +32247,7 @@ 
 	}
       op0 = gen_rtx_MEM (BLKmode, op0);
 
-      pat = GEN_FCN (icode) (op0);
+      pat = GEN_FCN1 (icode) (op0);
       if (pat)
 	emit_insn (pat);
       return 0;
@@ -32302,7 +32302,7 @@ 
 
 	  op2 = gen_lowpart (SImode, op2);
 	  op1 = gen_lowpart (SImode, op1);
-	  pat = GEN_FCN (icode) (op0, op1, op2);
+	  pat = GEN_FCN3 (icode) (op0, op1, op2);
 	}
       else
 	{
@@ -32320,7 +32320,7 @@ 
 	    default:
 	      gcc_unreachable ();
 	    }
-	  pat = GEN_FCN (icode) (op0, op1);
+	  pat = GEN_FCN2 (icode) (op0, op1);
 	}
 
       if (pat)
@@ -32364,7 +32364,7 @@ 
           unsigned char lsb_index = INTVAL (op1) & 0xFF;
           op1 = GEN_INT (length);
           op2 = GEN_INT (lsb_index);
-          pat = GEN_FCN (icode) (target, op0, op1, op2);
+          pat = GEN_FCN4 (icode) (target, op0, op1, op2);
           if (pat)
             emit_insn (pat);
           return target;
@@ -32386,7 +32386,7 @@ 
 
 rdrand_step:
       op0 = gen_reg_rtx (mode0);
-      emit_insn (GEN_FCN (icode) (op0));
+      emit_insn (GEN_FCN1 (icode) (op0));
 
       arg0 = CALL_EXPR_ARG (exp, 0);
       op1 = expand_normal (arg0);
@@ -32436,7 +32436,7 @@ 
 
 rdseed_step:
       op0 = gen_reg_rtx (mode0);
-      emit_insn (GEN_FCN (icode) (op0));
+      emit_insn (GEN_FCN1 (icode) (op0));
 
       arg0 = CALL_EXPR_ARG (exp, 0);
       op1 = expand_normal (arg0);
@@ -32494,7 +32494,7 @@ 
 
       op4 = gen_rtx_REG (CCCmode, FLAGS_REG);
       pat = gen_rtx_LTU (VOIDmode, op4, const0_rtx);
-      emit_insn (GEN_FCN (icode) (op0, op2, op3, op4, pat));
+      emit_insn (GEN_FCN5 (icode) (op0, op2, op3, op4, pat));
 
       /* Store the result.  */
       op4 = expand_normal (arg3);
@@ -32706,7 +32706,7 @@ 
 	    }
 	}
 
-      pat = GEN_FCN (icode) (subtarget, op0, op1, op2, op3, op4);
+      pat = GEN_FCN6 (icode) (subtarget, op0, op1, op2, op3, op4);
       if (! pat)
 	return const0_rtx;
       emit_insn (pat);
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 200820)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -10446,7 +10446,7 @@ 
       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
     target = gen_reg_rtx (tmode);
 
-  pat = GEN_FCN (icode) (target);
+  pat = GEN_FCN1 (icode) (target);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -10496,7 +10496,7 @@ 
   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
     op0 = copy_to_mode_reg (mode0, op0);
 
-  pat = GEN_FCN (icode) (target, op0);
+  pat = GEN_FCN2 (icode) (target, op0);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -10528,7 +10528,7 @@ 
   scratch1 = gen_reg_rtx (mode0);
   scratch2 = gen_reg_rtx (mode0);
 
-  pat = GEN_FCN (icode) (target, op0, scratch1, scratch2);
+  pat = GEN_FCN4 (icode) (target, op0, scratch1, scratch2);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -10601,7 +10601,7 @@ 
   if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
     op1 = copy_to_mode_reg (mode1, op1);
 
-  pat = GEN_FCN (icode) (target, op0, op1);
+  pat = GEN_FCN3 (icode) (target, op0, op1);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -10649,7 +10649,7 @@ 
 
   scratch = gen_reg_rtx (mode0);
 
-  pat = GEN_FCN (icode) (scratch, op0, op1);
+  pat = GEN_FCN3 (icode) (scratch, op0, op1);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -10721,7 +10721,7 @@ 
       addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op0, op1));
     }
 
-  pat = GEN_FCN (icode) (target, addr);
+  pat = GEN_FCN2 (icode) (target, addr);
 
   if (! pat)
     return 0;
@@ -10767,7 +10767,7 @@ 
       addr = gen_rtx_MEM (blk ? BLKmode : tmode, gen_rtx_PLUS (Pmode, op0, op1));
     }
 
-  pat = GEN_FCN (icode) (target, addr);
+  pat = GEN_FCN2 (icode) (target, addr);
 
   if (! pat)
     return 0;
@@ -10803,7 +10803,7 @@ 
   if (! (*insn_data[icode].operand[1].predicate) (op2, mode1))
     op2 = copy_to_mode_reg (mode1, op2);
 
-  pat = GEN_FCN (icode) (op1, op2, op0);
+  pat = GEN_FCN3 (icode) (op1, op2, op0);
   if (pat)
     emit_insn (pat);
   return NULL_RTX;
@@ -10844,7 +10844,7 @@ 
       addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op1, op2));
     }
 
-  pat = GEN_FCN (icode) (addr, op0);
+  pat = GEN_FCN2 (icode) (addr, op0);
   if (pat)
     emit_insn (pat);
   return NULL_RTX;
@@ -10886,7 +10886,7 @@ 
       addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op1, op2));
     }
 
-  pat = GEN_FCN (icode) (addr, op0);
+  pat = GEN_FCN2 (icode) (addr, op0);
   if (pat)
     emit_insn (pat);
   return NULL_RTX;
@@ -11003,9 +11003,9 @@ 
     op2 = copy_to_mode_reg (mode2, op2);
 
   if (TARGET_PAIRED_FLOAT && icode == CODE_FOR_selv2sf4)
-    pat = GEN_FCN (icode) (target, op0, op1, op2, CONST0_RTX (SFmode));
+    pat = GEN_FCN5 (icode) (target, op0, op1, op2, CONST0_RTX (SFmode));
   else 
-    pat = GEN_FCN (icode) (target, op0, op1, op2);
+    pat = GEN_FCN4 (icode) (target, op0, op1, op2);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -11064,7 +11064,7 @@ 
   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
     op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
 
-  pat = GEN_FCN (icode) (target, op0);
+  pat = GEN_FCN2 (icode) (target, op0);
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -11120,7 +11120,7 @@ 
   if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
     op1 = copy_to_mode_reg (mode1, op1);
 
-  pat = GEN_FCN (icode) (op0, op1);
+  pat = GEN_FCN2 (icode) (op0, op1);
   if (pat)
     emit_insn (pat);
 
@@ -11177,7 +11177,7 @@ 
 	if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1))
 	  op1 = copy_to_mode_reg (mode1, op1);
 
-	pat = GEN_FCN (d->icode) (op0, op1, op2);
+	pat = GEN_FCN3 (d->icode) (op0, op1, op2);
 	if (pat != 0)
 	  emit_insn (pat);
 
@@ -11373,7 +11373,7 @@ 
 	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
 	target = gen_reg_rtx (tmode);
 
-      pat = GEN_FCN (icode) (target);
+      pat = GEN_FCN1 (icode) (target);
       if (! pat)
 	return 0;
       emit_insn (pat);
@@ -11392,7 +11392,7 @@ 
       if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
 	op0 = copy_to_mode_reg (mode0, op0);
 
-      pat = GEN_FCN (icode) (op0);
+      pat = GEN_FCN1 (icode) (op0);
       if (pat)
 	emit_insn (pat);
       return NULL_RTX;
@@ -11699,7 +11699,7 @@ 
 	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
 	target = gen_reg_rtx (tmode);
 
-      pat = GEN_FCN (icode) (target);
+      pat = GEN_FCN1 (icode) (target);
       if (! pat)
 	return 0;
       emit_insn (pat);
@@ -11716,7 +11716,7 @@ 
       if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
 	op0 = copy_to_mode_reg (mode0, op0);
 
-      pat = GEN_FCN (icode) (op0);
+      pat = GEN_FCN1 (icode) (op0);
       if (pat)
 	emit_insn (pat);
       return NULL_RTX;
@@ -11766,7 +11766,7 @@ 
 
   scratch = gen_reg_rtx (CCFPmode);
 
-  pat = GEN_FCN (icode) (scratch, op0, op1);
+  pat = GEN_FCN3 (icode) (scratch, op0, op1);
   if (!pat)
     return const0_rtx;
 
@@ -11839,7 +11839,7 @@ 
 
   scratch = gen_reg_rtx (CCmode);
 
-  pat = GEN_FCN (icode) (scratch, op0, op1);
+  pat = GEN_FCN3 (icode) (scratch, op0, op1);
   if (! pat)
     return const0_rtx;
   emit_insn (pat);
@@ -11945,7 +11945,7 @@ 
 
   /* Generate the compare.  */
   scratch = gen_reg_rtx (CCmode);
-  pat = GEN_FCN (icode) (scratch, op0, op1);
+  pat = GEN_FCN3 (icode) (scratch, op0, op1);
   if (! pat)
     return const0_rtx;
   emit_insn (pat);
@@ -12106,7 +12106,7 @@ 
 	  target = gen_reg_rtx (tmode);
 
 	/*pat = gen_altivec_lvsr (target, op);*/
-	pat = GEN_FCN (icode) (target, op);
+	pat = GEN_FCN2 (icode) (target, op);
 	if (!pat)
 	  return 0;
 	emit_insn (pat);
@@ -17328,7 +17328,7 @@ 
 	  return NULL_RTX;
 
 	mask = gen_reg_rtx (dmode);
-	emit_insn (GEN_FCN (nor_code) (mask, mask2));
+	emit_insn (GEN_FCN2 (nor_code) (mask, mask2));
 	return mask;
       }
       break;
@@ -17377,7 +17377,7 @@ 
 	  return NULL_RTX;
 
 	mask = gen_reg_rtx (dmode);
-	emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
+	emit_insn (GEN_FCN3 (ior_code) (mask, c_rtx, eq_rtx));
 	return mask;
       }
       break;
@@ -27769,7 +27769,7 @@ 
     passes++;
 
   enum insn_code code = optab_handler (smul_optab, mode);
-  gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN (code);
+  gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN3 (code);
 
   gcc_assert (code != CODE_FOR_nothing);
 
@@ -27847,7 +27847,7 @@ 
   int i;
   rtx halfthree;
   enum insn_code code = optab_handler (smul_optab, mode);
-  gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN (code);
+  gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN3 (code);
 
   gcc_assert (code != CODE_FOR_nothing);
 
@@ -28172,7 +28172,7 @@ 
 	    x = target;
 	  else
 	    x = gen_reg_rtx (omode);
-	  emit_insn (GEN_FCN (icode) (x, op0, op1));
+	  emit_insn (GEN_FCN3 (icode) (x, op0, op1));
 	  if (omode != V16QImode)
 	    emit_move_insn (target, gen_lowpart (V16QImode, x));
 	  return true;
Index: gcc/genoutput.c
===================================================================
--- gcc/genoutput.c	(revision 200820)
+++ gcc/genoutput.c	(working copy)
@@ -404,9 +404,25 @@ 
 	}
 
       if (d->name && d->name[0] != '*')
-	printf ("    (insn_gen_fn) gen_%s,\n", d->name);
+	{
+	  int i;
+
+	  printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
+	  printf ("    { .argc%d = gen_%s },\n", d->n_generator_args, d->name);
+	  printf ("#else\n");
+	  printf ("    { ");
+	  for (i = 0; i < d->n_generator_args; i++)
+	    printf ("0, ");
+	  printf ("gen_%s, ", d->name);
+	  for (i = d->n_generator_args + 1; i <= 11; i++)
+	    printf ("0, ");
+	  printf ("},\n");
+	  printf ("#endif\n");
+	}
       else
-	printf ("    0,\n");
+	{
+	  printf ("    { 0 },\n");
+	}
 
       printf ("    &operand_data[%d],\n", d->operand_number);
       printf ("    %d,\n", d->n_generator_args);
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 200820)
+++ gcc/expr.c	(working copy)
@@ -119,7 +119,7 @@ 
   int reverse;
 };
 
-static void move_by_pieces_1 (rtx (*) (rtx, ...), enum machine_mode,
+static void move_by_pieces_1 (rtx (*) (rtx, rtx), enum machine_mode,
 			      struct move_by_pieces_d *);
 static bool block_move_libcall_safe_for_call_parm (void);
 static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT);
@@ -128,7 +128,7 @@ 
 static rtx clear_by_pieces_1 (void *, HOST_WIDE_INT, enum machine_mode);
 static void clear_by_pieces (rtx, unsigned HOST_WIDE_INT, unsigned int);
 static void store_by_pieces_1 (struct store_by_pieces_d *, unsigned int);
-static void store_by_pieces_2 (rtx (*) (rtx, ...), enum machine_mode,
+static void store_by_pieces_2 (rtx (*) (rtx, rtx), enum machine_mode,
 			       struct store_by_pieces_d *);
 static tree clear_storage_libcall_fn (int);
 static rtx compress_float_constant (rtx, rtx);
@@ -966,7 +966,7 @@ 
 
       icode = optab_handler (mov_optab, mode);
       if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
-	move_by_pieces_1 (GEN_FCN (icode), mode, &data);
+	move_by_pieces_1 (GEN_FCN2 (icode), mode, &data);
 
       max_size = GET_MODE_SIZE (mode);
     }
@@ -1043,7 +1043,7 @@ 
    to make a move insn for that mode.  DATA has all the other info.  */
 
 static void
-move_by_pieces_1 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
+move_by_pieces_1 (rtx (*genfun) (rtx, rtx), enum machine_mode mode,
 		  struct move_by_pieces_d *data)
 {
   unsigned int size = GET_MODE_SIZE (mode);
@@ -2643,7 +2643,7 @@ 
 
       icode = optab_handler (mov_optab, mode);
       if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
-	store_by_pieces_2 (GEN_FCN (icode), mode, data);
+	store_by_pieces_2 (GEN_FCN2 (icode), mode, data);
 
       max_size = GET_MODE_SIZE (mode);
     }
@@ -2657,7 +2657,7 @@ 
    to make a move insn for that mode.  DATA has all the other info.  */
 
 static void
-store_by_pieces_2 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
+store_by_pieces_2 (rtx (*genfun) (rtx, rtx), enum machine_mode mode,
 		   struct store_by_pieces_d *data)
 {
   unsigned int size = GET_MODE_SIZE (mode);
@@ -3096,7 +3096,7 @@ 
   y = emit_move_change_mode (imode, mode, y, force);
   if (y == NULL_RTX)
     return NULL_RTX;
-  return emit_insn (GEN_FCN (code) (x, y));
+  return emit_insn (GEN_FCN2 (code) (x, y));
 }
 
 /* A subroutine of emit_move_insn_1.  X is a push_operand in MODE.
@@ -3292,7 +3292,7 @@ 
 	{
 	  x = emit_move_change_mode (CCmode, mode, x, true);
 	  y = emit_move_change_mode (CCmode, mode, y, true);
-	  return emit_insn (GEN_FCN (code) (x, y));
+	  return emit_insn (GEN_FCN2 (code) (x, y));
 	}
     }
 
@@ -3429,7 +3429,7 @@ 
 
   code = optab_handler (mov_optab, mode);
   if (code != CODE_FOR_nothing)
-    return emit_insn (GEN_FCN (code) (x, y));
+    return emit_insn (GEN_FCN2 (code) (x, y));
 
   /* Expand complex moves by moving real part and imag part.  */
   if (COMPLEX_MODE_P (mode))
@@ -6322,7 +6322,7 @@ 
 	  }
 
 	if (vector)
-	  emit_insn (GEN_FCN (icode)
+	  emit_insn (GEN_FCN2 (icode)
 		     (target,
 		      gen_rtx_PARALLEL (GET_MODE (target), vector)));
 	break;
@@ -10374,7 +10374,7 @@ 
 	      reg = gen_reg_rtx (mode);
 
 	      /* Nor can the insn generator.  */
-	      insn = GEN_FCN (icode) (reg, op0);
+	      insn = GEN_FCN2 (icode) (reg, op0);
 	      emit_insn (insn);
 	      return reg;
 	    }
Index: gcc/lra-constraints.c
===================================================================
--- gcc/lra-constraints.c	(revision 200820)
+++ gcc/lra-constraints.c	(working copy)
@@ -1009,7 +1009,7 @@ 
       scratch_reg = (lra_create_new_reg_with_unique_value
 		     (insn_data[sri.icode].operand[2].mode, NULL_RTX,
 		      scratch_class, "scratch"));
-      emit_insn (GEN_FCN (sri.icode) (new_reg != NULL_RTX ? new_reg : dest,
+      emit_insn (GEN_FCN3 (sri.icode) (new_reg != NULL_RTX ? new_reg : dest,
 				      sreg, scratch_reg));
     }
   before = get_insns ();
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	(revision 200820)
+++ gcc/optabs.c	(working copy)
@@ -792,7 +792,7 @@ 
     return NULL;
 
   ret = gen_reg_rtx (vmode);
-  emit_insn (GEN_FCN (icode) (ret, gen_rtx_PARALLEL (vmode, vec)));
+  emit_insn (GEN_FCN2 (icode) (ret, gen_rtx_PARALLEL (vmode, vec)));
 
   return ret;
 }
@@ -4098,7 +4098,7 @@ 
 	  result_mode = insn_data[cmp_code].operand[0].mode;
 	  result = gen_reg_rtx (result_mode);
 	  size = convert_to_mode (cmp_mode, size, 1);
-	  emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
+	  emit_insn (GEN_FCN5 (cmp_code) (result, x, y, size, opalign));
 
           *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
           *pmode = result_mode;
@@ -4275,7 +4275,7 @@ 
 
   gcc_assert (icode != CODE_FOR_nothing);
   gcc_assert (insn_operand_matches (icode, 0, test));
-  insn = emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0),
+  insn = emit_jump_insn (GEN_FCN4 (icode) (test, XEXP (test, 0),
                                           XEXP (test, 1), label));
   if (prob != -1
       && profile_status != PROFILE_ABSENT
@@ -4704,7 +4704,7 @@ 
   gcc_assert (insn_operand_matches (icode, 1, x));
   gcc_assert (insn_operand_matches (icode, 2, y));
 
-  return GEN_FCN (icode) (x, x, y);
+  return GEN_FCN3 (icode) (x, x, y);
 }
 
 /* Generate and return an insn body to add r1 and c,
@@ -4721,7 +4721,7 @@ 
       || !insn_operand_matches (icode, 2, c))
     return NULL_RTX;
 
-  return GEN_FCN (icode) (r0, r1, c);
+  return GEN_FCN3 (icode) (r0, r1, c);
 }
 
 int
@@ -4755,7 +4755,7 @@ 
   gcc_assert (insn_operand_matches (icode, 1, x));
   gcc_assert (insn_operand_matches (icode, 2, y));
 
-  return GEN_FCN (icode) (x, x, y);
+  return GEN_FCN3 (icode) (x, x, y);
 }
 
 /* Generate and return an insn body to subtract r1 and c,
@@ -4772,7 +4772,7 @@ 
       || !insn_operand_matches (icode, 2, c))
     return NULL_RTX;
 
-  return GEN_FCN (icode) (r0, r1, c);
+  return GEN_FCN3 (icode) (r0, r1, c);
 }
 
 int
@@ -4836,7 +4836,7 @@ 
 		 enum machine_mode mfrom, int unsignedp)
 {
   enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
-  return GEN_FCN (icode) (x, y);
+  return GEN_FCN2 (icode) (x, y);
 }
 
 /* can_fix_p and can_float_p say whether the target machine
@@ -6367,7 +6367,7 @@ 
   if (!trap_rtx)
     insn = NULL_RTX;
   else
-    insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
+    insn = GEN_FCN4 (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
 			    tcode);
 
   /* If that failed, then give up.  */
@@ -8206,28 +8206,28 @@ 
   switch (nops)
     {
     case 1:
-      return GEN_FCN (icode) (ops[0].value);
+      return GEN_FCN1 (icode) (ops[0].value);
     case 2:
-      return GEN_FCN (icode) (ops[0].value, ops[1].value);
+      return GEN_FCN2 (icode) (ops[0].value, ops[1].value);
     case 3:
-      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value);
+      return GEN_FCN3 (icode) (ops[0].value, ops[1].value, ops[2].value);
     case 4:
-      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
-			      ops[3].value);
+      return GEN_FCN4 (icode) (ops[0].value, ops[1].value, ops[2].value,
+			       ops[3].value);
     case 5:
-      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
-			      ops[3].value, ops[4].value);
+      return GEN_FCN5 (icode) (ops[0].value, ops[1].value, ops[2].value,
+			       ops[3].value, ops[4].value);
     case 6:
-      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
-			      ops[3].value, ops[4].value, ops[5].value);
+      return GEN_FCN6 (icode) (ops[0].value, ops[1].value, ops[2].value,
+			       ops[3].value, ops[4].value, ops[5].value);
     case 7:
-      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
-			      ops[3].value, ops[4].value, ops[5].value,
-			      ops[6].value);
+      return GEN_FCN7 (icode) (ops[0].value, ops[1].value, ops[2].value,
+			       ops[3].value, ops[4].value, ops[5].value,
+			       ops[6].value);
     case 8:
-      return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
-			      ops[3].value, ops[4].value, ops[5].value,
-			      ops[6].value, ops[7].value);
+      return GEN_FCN8 (icode) (ops[0].value, ops[1].value, ops[2].value,
+			       ops[3].value, ops[4].value, ops[5].value,
+			       ops[6].value, ops[7].value);
     }
   gcc_unreachable ();
 }
Index: gcc/optabs.h
===================================================================
--- gcc/optabs.h	(revision 200820)
+++ gcc/optabs.h	(working copy)
@@ -44,7 +44,18 @@ 
 
 /* Given an enum insn_code, access the function to construct
    the body of that kind of insn.  */
-#define GEN_FCN(CODE) (insn_data[CODE].genfun)
+#define GEN_FCN0(CODE)	(insn_data[CODE].genfun.argc0)
+#define GEN_FCN1(CODE)	(insn_data[CODE].genfun.argc1)
+#define GEN_FCN2(CODE)	(insn_data[CODE].genfun.argc2)
+#define GEN_FCN3(CODE)	(insn_data[CODE].genfun.argc3)
+#define GEN_FCN4(CODE)	(insn_data[CODE].genfun.argc4)
+#define GEN_FCN5(CODE)	(insn_data[CODE].genfun.argc5)
+#define GEN_FCN6(CODE)	(insn_data[CODE].genfun.argc6)
+#define GEN_FCN7(CODE)	(insn_data[CODE].genfun.argc7)
+#define GEN_FCN8(CODE)	(insn_data[CODE].genfun.argc8)
+#define GEN_FCN9(CODE)	(insn_data[CODE].genfun.argc9)
+#define GEN_FCN10(CODE)	(insn_data[CODE].genfun.argc10)
+#define GEN_FCN11(CODE)	(insn_data[CODE].genfun.argc11)
 
 /* Contains the optab used for each rtx code, and vice-versa.  */
 extern const optab code_to_optab_[NUM_RTX_CODE];
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c	(revision 200820)
+++ gcc/reload1.c	(working copy)
@@ -7538,7 +7538,7 @@ 
 	      /* We'd have to add extra code to handle this case.  */
 	      gcc_assert (!third_reload_reg);
 
-	      emit_insn (GEN_FCN (icode) (reloadreg, real_oldequiv,
+	      emit_insn (GEN_FCN3 (icode) (reloadreg, real_oldequiv,
 					  second_reload_reg));
 	      special = 1;
 	    }
@@ -7548,7 +7548,7 @@ 
 		 intermediate register (a tertiary reload).  */
 	      if (tertiary_icode != CODE_FOR_nothing)
 		{
-		  emit_insn ((GEN_FCN (tertiary_icode)
+		  emit_insn ((GEN_FCN3 (tertiary_icode)
 			      (second_reload_reg, real_oldequiv,
 			       third_reload_reg)));
 		}
@@ -7657,7 +7657,7 @@ 
 	      /* We'd have to add extra code to handle this case.  */
 	      gcc_assert (tertiary_reload < 0);
 
-	      emit_insn ((GEN_FCN (rl->secondary_out_icode)
+	      emit_insn ((GEN_FCN3 (rl->secondary_out_icode)
 			  (real_old, second_reloadreg, reloadreg)));
 	      special = 1;
 	    }
@@ -7691,7 +7691,7 @@ 
 
 		  gen_reload (reloadreg, second_reloadreg,
 			      rl->opnum, rl->when_needed);
-		  emit_insn ((GEN_FCN (tertiary_icode)
+		  emit_insn ((GEN_FCN3 (tertiary_icode)
 			      (real_old, reloadreg, third_reloadreg)));
 		  special = 1;
 		}