public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
@ 2013-07-26  8:09 Uros Bizjak
  2013-07-26  8:12 ` Stefan Kristiansson
  2013-07-27 13:03 ` Oleg Endo
  0 siblings, 2 replies; 14+ messages in thread
From: Uros Bizjak @ 2013-07-26  8:09 UTC (permalink / raw)
  To: gcc-patches; +Cc: Stefan Kristiansson, Andreas Schwab

Hello!

> 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.

Stefan, can you resubmit an updated patch (with proposed update from [1])?

I would really like to see this patch in the mainline.

BTW: I am not c++ expert, but doesn't c++ offer some sort of
abstraction to get rid of

+  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;

[1] http://gcc.gnu.org/ml/gcc-patches/2013-07/msg00448.html

Thanks,
Uros.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-07-26  8:09 [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...) Uros Bizjak
@ 2013-07-26  8:12 ` Stefan Kristiansson
  2013-07-27 13:03 ` Oleg Endo
  1 sibling, 0 replies; 14+ messages in thread
From: Stefan Kristiansson @ 2013-07-26  8:12 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches, Andreas Schwab

[-- Attachment #1: Type: text/plain, Size: 244 bytes --]

On Fri, Jul 26, 2013 at 08:51:41AM +0200, Uros Bizjak wrote:
> 
> Stefan, can you resubmit an updated patch (with proposed update from [1])?
> 
> I would really like to see this patch in the mainline.
> 

Attached is the updated patch.

Stefan

[-- Attachment #2: gen_fcn.patch --]
[-- Type: text/x-diff, Size: 60628 bytes --]

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;
 		}
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/genoutput.c
===================================================================
--- gcc/genoutput.c	(revision 200820)
+++ gcc/genoutput.c	(working copy)
@@ -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);
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/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/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/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/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/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/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/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/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/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/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/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/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-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/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/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/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/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/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/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
 {
@@ -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;
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);
 }
 \f
 /* 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];

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-07-26  8:09 [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...) Uros Bizjak
  2013-07-26  8:12 ` Stefan Kristiansson
@ 2013-07-27 13:03 ` Oleg Endo
  2013-07-27 13:16   ` Oleg Endo
                     ` (2 more replies)
  1 sibling, 3 replies; 14+ messages in thread
From: Oleg Endo @ 2013-07-27 13:03 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches, Stefan Kristiansson, Andreas Schwab

[-- Attachment #1: Type: text/plain, Size: 3130 bytes --]

Hi,

On Fri, 2013-07-26 at 08:51 +0200, Uros Bizjak wrote:

> BTW: I am not c++ expert, but doesn't c++ offer some sort of
> abstraction to get rid of
> 
> +  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;
> 

Variadic templates maybe, but we can't use them since that requires C
++11.

Anyway, I think it's better to turn the insn_gen_fn typedef in recog.h
into a functor.  The change is quite transparent to the users, as the
attached patch shows.  There really is no need for things like GEN_FCN?,
nor do we need to fixup all the backends etc.

I've tested the attached patch on my SH cross setup with 'make all-gcc'
and it can still produce a valid 'hello world'.  Not sure whether it's
sufficient.

Some notes regarding the patch:

* The whole arg list thing could probably be folded with x-macros or
something like that, but I don't think it's worth doing it for this
single case.  If we can use C++11 in GCC at some point in time in the
future, the insn_gen_fn implementation can be folded with variadic
templates without touching all the code that uses it.

* I had to extend the number of max. args to 16, otherwise the SH
backend's sync.md code wouldn't compile.

* I don't know whether it's really needed to properly format the code of
class insn_gen_fn.  After reading the first two or three overloads
(which do fit into 80 columns) one gets the idea and so I guess nobody
is going to read that stuff completely anyway.

* The class insn_gen_fn is a POD, so it can be passed by value without
any overhead, just like a normal function pointer.  Same goes for the
function call through the wrapper class.

* Initially I had overloaded constructors in class insn_gen_fn which
worked and didn't require the cast in genoutput.c.  However, it
introduced static initializer functions and defeated the purpose of the
generated const struct insn_data_d insn_data[].  This is worked around
by casting the function pointer to insn_gen_fn::stored_funcptr. (Since
it's C++ and not C it won't implicitly cast to void*).

* The whole thing will fall apart if the stored pointer to a function
'rtx (*)(void)' is different from a stored pointer to e.g. 'rtx
(*)(rtx)'.  But I guess this is not likely to happen.

Cheers,
Oleg

gcc/ChangeLog:
	* recog.h (rtx (*insn_gen_fn) (rtx, ...)): Replace typedef with
	new class insn_gen_fn.
	* expr.c (move_by_pieces_1, store_by_pieces_2): Replace
	argument rtx (*) (rtx, ...) with insn_gen_fn.
	* genoutput.c (output_insn_data): Cast gen_? function pointers
	to insn_gen_fn::stored_funcptr.  Add initializer braces.

[-- Attachment #2: rtx_dotdotdot.patch --]
[-- Type: text/x-patch, Size: 6755 bytes --]

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 201282)
+++ 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 (insn_gen_fn, 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 (insn_gen_fn, machine_mode,
 			       struct store_by_pieces_d *);
 static tree clear_storage_libcall_fn (int);
 static rtx compress_float_constant (rtx, rtx);
@@ -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 (insn_gen_fn genfun, machine_mode mode,
 		  struct move_by_pieces_d *data)
 {
   unsigned int 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 (insn_gen_fn genfun, machine_mode mode,
 		   struct store_by_pieces_d *data)
 {
   unsigned int size = GET_MODE_SIZE (mode);
Index: gcc/genoutput.c
===================================================================
--- gcc/genoutput.c	(revision 201282)
+++ gcc/genoutput.c	(working copy)
@@ -404,9 +404,9 @@
 	}
 
       if (d->name && d->name[0] != '*')
-	printf ("    (insn_gen_fn) gen_%s,\n", d->name);
+	printf ("    { (insn_gen_fn::stored_funcptr) 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);
Index: gcc/recog.h
===================================================================
--- gcc/recog.h	(revision 201282)
+++ gcc/recog.h	(working copy)
@@ -256,8 +256,58 @@
 
 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_gen_fn
+{
+  typedef rtx (*f0) (void);
+  typedef rtx (*f1) (rtx);
+  typedef rtx (*f2) (rtx, rtx);
+  typedef rtx (*f3) (rtx, rtx, rtx);
+  typedef rtx (*f4) (rtx, rtx, rtx, rtx);
+  typedef rtx (*f5) (rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f6) (rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f7) (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f8) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f9) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f10) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f11) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f12) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f13) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f14) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f15) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f16) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+
+  typedef f0 stored_funcptr;
+
+  rtx operator () (void) const { return ((f0)func) (); }
+  rtx operator () (rtx a0) const { return ((f1)func) (a0); }
+  rtx operator () (rtx a0, rtx a1) const { return ((f2)func) (a0, a1); }
+  rtx operator () (rtx a0, rtx a1, rtx a2) const { return ((f3)func) (a0, a1, a2); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3) const { return ((f4)func) (a0, a1, a2, a3); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4) const { return ((f5)func) (a0, a1, a2, a3, a4); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5) const { return ((f6)func) (a0, a1, a2, a3, a4, a5); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6) const { return ((f7)func) (a0, a1, a2, a3, a4, a5, a6); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7) const { return ((f8)func) (a0, a1, a2, a3, a4, a5, a6, a7); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8) const { return ((f9)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9) const { return ((f10)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10) const { return ((f11)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11) const { return ((f12)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12) const { return ((f13)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13) const { return ((f14)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14) const { return ((f15)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14, rtx a15) const { return ((f16)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+
+  // This is for compatibility of code that invokes functions like
+  //   (*funcptr) (arg)
+  insn_gen_fn operator * (void) const { return *this; }
+
+  // The wrapped function pointer must be public and there must not be any
+  // constructors.  Otherwise the insn_data_d struct initializers generated
+  // by genoutput.c will result in static initializer functions, which defeats
+  // the purpose of the generated insn_data_d array.
+  stored_funcptr func;
+};
+
 struct insn_operand_data
 {
   const insn_operand_predicate_fn predicate;

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-07-27 13:03 ` Oleg Endo
@ 2013-07-27 13:16   ` Oleg Endo
  2013-08-05 21:31   ` [PING] " Oleg Endo
  2013-08-05 21:43   ` Richard Henderson
  2 siblings, 0 replies; 14+ messages in thread
From: Oleg Endo @ 2013-07-27 13:16 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches, Stefan Kristiansson, Andreas Schwab

On Sat, 2013-07-27 at 14:52 +0200, Oleg Endo wrote:

> * I had to extend the number of max. args to 16, otherwise the SH
> backend's sync.md code wouldn't compile.

The error message was misleading.  It wasn't sync.md but some other SH
insn gen func that takes 16 args.  Anyway, doesn't change the original
fact that 11 args are not enough for all :)

Cheers,
Oleg

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PING] Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-07-27 13:03 ` Oleg Endo
  2013-07-27 13:16   ` Oleg Endo
@ 2013-08-05 21:31   ` Oleg Endo
  2013-08-05 21:43   ` Richard Henderson
  2 siblings, 0 replies; 14+ messages in thread
From: Oleg Endo @ 2013-08-05 21:31 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches, Stefan Kristiansson, Andreas Schwab

Hello,

Any comments?
(patch is here: http://gcc.gnu.org/ml/gcc-patches/2013-07/msg01315.html)

Cheers,
Oleg

On Sat, 2013-07-27 at 14:52 +0200, Oleg Endo wrote:
> Hi,
> 
> On Fri, 2013-07-26 at 08:51 +0200, Uros Bizjak wrote:
> 
> > BTW: I am not c++ expert, but doesn't c++ offer some sort of
> > abstraction to get rid of
> > 
> > +  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;
> > 
> 
> Variadic templates maybe, but we can't use them since that requires C
> ++11.
> 
> Anyway, I think it's better to turn the insn_gen_fn typedef in recog.h
> into a functor.  The change is quite transparent to the users, as the
> attached patch shows.  There really is no need for things like GEN_FCN?,
> nor do we need to fixup all the backends etc.
> 
> I've tested the attached patch on my SH cross setup with 'make all-gcc'
> and it can still produce a valid 'hello world'.  Not sure whether it's
> sufficient.
> 
> Some notes regarding the patch:
> 
> * The whole arg list thing could probably be folded with x-macros or
> something like that, but I don't think it's worth doing it for this
> single case.  If we can use C++11 in GCC at some point in time in the
> future, the insn_gen_fn implementation can be folded with variadic
> templates without touching all the code that uses it.
> 
> * I had to extend the number of max. args to 16, otherwise the SH
> backend's sync.md code wouldn't compile.
> 
> * I don't know whether it's really needed to properly format the code of
> class insn_gen_fn.  After reading the first two or three overloads
> (which do fit into 80 columns) one gets the idea and so I guess nobody
> is going to read that stuff completely anyway.
> 
> * The class insn_gen_fn is a POD, so it can be passed by value without
> any overhead, just like a normal function pointer.  Same goes for the
> function call through the wrapper class.
> 
> * Initially I had overloaded constructors in class insn_gen_fn which
> worked and didn't require the cast in genoutput.c.  However, it
> introduced static initializer functions and defeated the purpose of the
> generated const struct insn_data_d insn_data[].  This is worked around
> by casting the function pointer to insn_gen_fn::stored_funcptr. (Since
> it's C++ and not C it won't implicitly cast to void*).
> 
> * The whole thing will fall apart if the stored pointer to a function
> 'rtx (*)(void)' is different from a stored pointer to e.g. 'rtx
> (*)(rtx)'.  But I guess this is not likely to happen.
> 
> Cheers,
> Oleg
> 
> gcc/ChangeLog:
> 	* recog.h (rtx (*insn_gen_fn) (rtx, ...)): Replace typedef with
> 	new class insn_gen_fn.
> 	* expr.c (move_by_pieces_1, store_by_pieces_2): Replace
> 	argument rtx (*) (rtx, ...) with insn_gen_fn.
> 	* genoutput.c (output_insn_data): Cast gen_? function pointers
> 	to insn_gen_fn::stored_funcptr.  Add initializer braces.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-07-27 13:03 ` Oleg Endo
  2013-07-27 13:16   ` Oleg Endo
  2013-08-05 21:31   ` [PING] " Oleg Endo
@ 2013-08-05 21:43   ` Richard Henderson
  2013-08-05 22:32     ` Oleg Endo
  2 siblings, 1 reply; 14+ messages in thread
From: Richard Henderson @ 2013-08-05 21:43 UTC (permalink / raw)
  To: Oleg Endo; +Cc: Uros Bizjak, gcc-patches, Stefan Kristiansson, Andreas Schwab

On 07/27/2013 02:52 AM, Oleg Endo wrote:
> gcc/ChangeLog:
> 	* recog.h (rtx (*insn_gen_fn) (rtx, ...)): Replace typedef with
> 	new class insn_gen_fn.
> 	* expr.c (move_by_pieces_1, store_by_pieces_2): Replace
> 	argument rtx (*) (rtx, ...) with insn_gen_fn.
> 	* genoutput.c (output_insn_data): Cast gen_? function pointers
> 	to insn_gen_fn::stored_funcptr.  Add initializer braces.

Ok.


r~

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-08-05 21:43   ` Richard Henderson
@ 2013-08-05 22:32     ` Oleg Endo
  2013-08-05 23:25       ` Richard Henderson
  0 siblings, 1 reply; 14+ messages in thread
From: Oleg Endo @ 2013-08-05 22:32 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Uros Bizjak, gcc-patches, Stefan Kristiansson, Andreas Schwab

On Mon, 2013-08-05 at 11:42 -1000, Richard Henderson wrote:
> On 07/27/2013 02:52 AM, Oleg Endo wrote:
> > gcc/ChangeLog:
> > 	* recog.h (rtx (*insn_gen_fn) (rtx, ...)): Replace typedef with
> > 	new class insn_gen_fn.
> > 	* expr.c (move_by_pieces_1, store_by_pieces_2): Replace
> > 	argument rtx (*) (rtx, ...) with insn_gen_fn.
> > 	* genoutput.c (output_insn_data): Cast gen_? function pointers
> > 	to insn_gen_fn::stored_funcptr.  Add initializer braces.
> 
> Ok.
> 

Thanks, committed as rev 201513.
4.8 also has the same problem.  The patch applies on 4.8 branch without
problems and make all-gcc works.
OK for 4.8, too?

Cheers,
Oleg

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-08-05 22:32     ` Oleg Endo
@ 2013-08-05 23:25       ` Richard Henderson
  2013-08-06 21:46         ` Oleg Endo
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Henderson @ 2013-08-05 23:25 UTC (permalink / raw)
  To: Oleg Endo; +Cc: Uros Bizjak, gcc-patches, Stefan Kristiansson, Andreas Schwab

On 08/05/2013 12:32 PM, Oleg Endo wrote:
> Thanks, committed as rev 201513.
> 4.8 also has the same problem.  The patch applies on 4.8 branch without
> problems and make all-gcc works.
> OK for 4.8, too?

Hum.  I suppose so, since it's relatively self-contained.  I suppose the
out-of-tree openrisc port will thank us...


r~

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-08-05 23:25       ` Richard Henderson
@ 2013-08-06 21:46         ` Oleg Endo
  2013-08-07 19:08           ` Michael Meissner
  0 siblings, 1 reply; 14+ messages in thread
From: Oleg Endo @ 2013-08-06 21:46 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Uros Bizjak, gcc-patches, Stefan Kristiansson, Andreas Schwab

On Mon, 2013-08-05 at 13:25 -1000, Richard Henderson wrote:
> On 08/05/2013 12:32 PM, Oleg Endo wrote:
> > Thanks, committed as rev 201513.
> > 4.8 also has the same problem.  The patch applies on 4.8 branch without
> > problems and make all-gcc works.
> > OK for 4.8, too?
> 
> Hum.  I suppose so, since it's relatively self-contained.  I suppose the
> out-of-tree openrisc port will thank us...

Maybe it's better to wait for a while and collect follow up patches such
as the rs6000 one.

Cheers,
Oleg

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-08-06 21:46         ` Oleg Endo
@ 2013-08-07 19:08           ` Michael Meissner
  2013-08-07 19:25             ` Oleg Endo
  0 siblings, 1 reply; 14+ messages in thread
From: Michael Meissner @ 2013-08-07 19:08 UTC (permalink / raw)
  To: Oleg Endo
  Cc: Richard Henderson, Uros Bizjak, gcc-patches, Stefan Kristiansson,
	Andreas Schwab

On Tue, Aug 06, 2013 at 11:45:40PM +0200, Oleg Endo wrote:
> On Mon, 2013-08-05 at 13:25 -1000, Richard Henderson wrote:
> > On 08/05/2013 12:32 PM, Oleg Endo wrote:
> > > Thanks, committed as rev 201513.
> > > 4.8 also has the same problem.  The patch applies on 4.8 branch without
> > > problems and make all-gcc works.
> > > OK for 4.8, too?
> > 
> > Hum.  I suppose so, since it's relatively self-contained.  I suppose the
> > out-of-tree openrisc port will thank us...
> 
> Maybe it's better to wait for a while and collect follow up patches such
> as the rs6000 one.

The tree right now is broken for the powerpc.  I would prefer to get patches
installed ASAP rather than waiting for additional ports.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-08-07 19:08           ` Michael Meissner
@ 2013-08-07 19:25             ` Oleg Endo
  2013-08-29 18:51               ` Oleg Endo
  0 siblings, 1 reply; 14+ messages in thread
From: Oleg Endo @ 2013-08-07 19:25 UTC (permalink / raw)
  To: Michael Meissner
  Cc: Richard Henderson, Uros Bizjak, gcc-patches, Stefan Kristiansson,
	Andreas Schwab

On Wed, 2013-08-07 at 15:08 -0400, Michael Meissner wrote:
> On Tue, Aug 06, 2013 at 11:45:40PM +0200, Oleg Endo wrote:
> > On Mon, 2013-08-05 at 13:25 -1000, Richard Henderson wrote:
> > > On 08/05/2013 12:32 PM, Oleg Endo wrote:
> > > > Thanks, committed as rev 201513.
> > > > 4.8 also has the same problem.  The patch applies on 4.8 branch without
> > > > problems and make all-gcc works.
> > > > OK for 4.8, too?
> > > 
> > > Hum.  I suppose so, since it's relatively self-contained.  I suppose the
> > > out-of-tree openrisc port will thank us...
> > 
> > Maybe it's better to wait for a while and collect follow up patches such
> > as the rs6000 one.
> 
> The tree right now is broken for the powerpc.  I would prefer to get patches
> installed ASAP rather than waiting for additional ports.

I've just committed the PPC fix for trunk.  Sorry for the delay.
I haven't committed anything related to this issue on the 4.8 branch
yet.  I'll do that next week if nothing else comes up.

Cheers,
Oleg

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-08-07 19:25             ` Oleg Endo
@ 2013-08-29 18:51               ` Oleg Endo
  2013-08-29 19:00                 ` Jakub Jelinek
  0 siblings, 1 reply; 14+ messages in thread
From: Oleg Endo @ 2013-08-29 18:51 UTC (permalink / raw)
  To: Michael Meissner
  Cc: Richard Henderson, Uros Bizjak, gcc-patches, Stefan Kristiansson,
	Andreas Schwab

[-- Attachment #1: Type: text/plain, Size: 1247 bytes --]

On Wed, 2013-08-07 at 21:24 +0200, Oleg Endo wrote:
> On Wed, 2013-08-07 at 15:08 -0400, Michael Meissner wrote:
> > On Tue, Aug 06, 2013 at 11:45:40PM +0200, Oleg Endo wrote:
> > > On Mon, 2013-08-05 at 13:25 -1000, Richard Henderson wrote:
> > > > On 08/05/2013 12:32 PM, Oleg Endo wrote:
> > > > > Thanks, committed as rev 201513.
> > > > > 4.8 also has the same problem.  The patch applies on 4.8 branch without
> > > > > problems and make all-gcc works.
> > > > > OK for 4.8, too?
> > > > 
> > > > Hum.  I suppose so, since it's relatively self-contained.  I suppose the
> > > > out-of-tree openrisc port will thank us...
> > > 
> > > Maybe it's better to wait for a while and collect follow up patches such
> > > as the rs6000 one.
> > 
> > The tree right now is broken for the powerpc.  I would prefer to get patches
> > installed ASAP rather than waiting for additional ports.
> 
> I've just committed the PPC fix for trunk.  Sorry for the delay.
> I haven't committed anything related to this issue on the 4.8 branch
> yet.  I'll do that next week if nothing else comes up.

Sorry for the delay.  I've just backported the 2 patches to 4.8.
Tested with 'make all-gcc' for SH and PPC cross compilers.
Committed as rev 202083.

Cheers,
Oleg

[-- Attachment #2: rtx_dotdotdot_4_8.patch --]
[-- Type: text/x-patch, Size: 8280 bytes --]

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 202080)
+++ 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 (insn_gen_fn, 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 (insn_gen_fn, machine_mode,
 			       struct store_by_pieces_d *);
 static tree clear_storage_libcall_fn (int);
 static rtx compress_float_constant (rtx, rtx);
@@ -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 (insn_gen_fn genfun, machine_mode mode,
 		  struct move_by_pieces_d *data)
 {
   unsigned int 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 (insn_gen_fn genfun, machine_mode mode,
 		   struct store_by_pieces_d *data)
 {
   unsigned int size = GET_MODE_SIZE (mode);
Index: gcc/recog.h
===================================================================
--- gcc/recog.h	(revision 202080)
+++ gcc/recog.h	(working copy)
@@ -256,8 +256,58 @@
 
 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_gen_fn
+{
+  typedef rtx (*f0) (void);
+  typedef rtx (*f1) (rtx);
+  typedef rtx (*f2) (rtx, rtx);
+  typedef rtx (*f3) (rtx, rtx, rtx);
+  typedef rtx (*f4) (rtx, rtx, rtx, rtx);
+  typedef rtx (*f5) (rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f6) (rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f7) (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f8) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f9) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f10) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f11) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f12) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f13) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f14) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f15) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+  typedef rtx (*f16) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+
+  typedef f0 stored_funcptr;
+
+  rtx operator () (void) const { return ((f0)func) (); }
+  rtx operator () (rtx a0) const { return ((f1)func) (a0); }
+  rtx operator () (rtx a0, rtx a1) const { return ((f2)func) (a0, a1); }
+  rtx operator () (rtx a0, rtx a1, rtx a2) const { return ((f3)func) (a0, a1, a2); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3) const { return ((f4)func) (a0, a1, a2, a3); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4) const { return ((f5)func) (a0, a1, a2, a3, a4); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5) const { return ((f6)func) (a0, a1, a2, a3, a4, a5); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6) const { return ((f7)func) (a0, a1, a2, a3, a4, a5, a6); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7) const { return ((f8)func) (a0, a1, a2, a3, a4, a5, a6, a7); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8) const { return ((f9)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9) const { return ((f10)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10) const { return ((f11)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11) const { return ((f12)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12) const { return ((f13)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13) const { return ((f14)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14) const { return ((f15)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14, rtx a15) const { return ((f16)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+
+  // This is for compatibility of code that invokes functions like
+  //   (*funcptr) (arg)
+  insn_gen_fn operator * (void) const { return *this; }
+
+  // The wrapped function pointer must be public and there must not be any
+  // constructors.  Otherwise the insn_data_d struct initializers generated
+  // by genoutput.c will result in static initializer functions, which defeats
+  // the purpose of the generated insn_data_d array.
+  stored_funcptr func;
+};
+
 struct insn_operand_data
 {
   const insn_operand_predicate_fn predicate;
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 202080)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -284,9 +284,6 @@
   { "rsqrtd",	 (RECIP_DF_RSQRT | RECIP_V2DF_RSQRT) },
 };
 
-/* 2 argument gen function typedef.  */
-typedef rtx (*gen_2arg_fn_t) (rtx, rtx, rtx);
-
 /* Pointer to function (in rs6000-c.c) that can define or undefine target
    macros that have changed.  Languages that don't support the preprocessor
    don't link in rs6000-c.c, so we can't call it directly.  */
@@ -26657,7 +26654,7 @@
   enum machine_mode mode = GET_MODE (dst);
   rtx x0, e0, e1, y1, u0, v0;
   enum insn_code code = optab_handler (smul_optab, mode);
-  gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN (code);
+  insn_gen_fn gen_mul = GEN_FCN (code);
   rtx one = rs6000_load_constant_and_splat (mode, dconst1);
 
   gcc_assert (code != CODE_FOR_nothing);
@@ -26695,7 +26692,7 @@
   enum machine_mode mode = GET_MODE (dst);
   rtx x0, e0, e1, e2, y1, y2, y3, u0, v0, one;
   enum insn_code code = optab_handler (smul_optab, mode);
-  gen_2arg_fn_t gen_mul = (gen_2arg_fn_t) GEN_FCN (code);
+  insn_gen_fn gen_mul = GEN_FCN (code);
 
   gcc_assert (code != CODE_FOR_nothing);
 
@@ -26766,7 +26763,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);
+  insn_gen_fn gen_mul = GEN_FCN (code);
 
   gcc_assert (code != CODE_FOR_nothing);
 
Index: gcc/genoutput.c
===================================================================
--- gcc/genoutput.c	(revision 202080)
+++ gcc/genoutput.c	(working copy)
@@ -404,9 +404,9 @@
 	}
 
       if (d->name && d->name[0] != '*')
-	printf ("    (insn_gen_fn) gen_%s,\n", d->name);
+	printf ("    { (insn_gen_fn::stored_funcptr) 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);

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-08-29 18:51               ` Oleg Endo
@ 2013-08-29 19:00                 ` Jakub Jelinek
  2013-08-29 19:07                   ` Oleg Endo
  0 siblings, 1 reply; 14+ messages in thread
From: Jakub Jelinek @ 2013-08-29 19:00 UTC (permalink / raw)
  To: Oleg Endo
  Cc: Michael Meissner, Richard Henderson, Uros Bizjak, gcc-patches,
	Stefan Kristiansson, Andreas Schwab

On Thu, Aug 29, 2013 at 08:45:33PM +0200, Oleg Endo wrote:
> Sorry for the delay.  I've just backported the 2 patches to 4.8.
> Tested with 'make all-gcc' for SH and PPC cross compilers.
> Committed as rev 202083.

Please fix the overly long lines as a follow-up.

> +struct insn_gen_fn
> +{
> +  typedef rtx (*f0) (void);
> +  typedef rtx (*f1) (rtx);
> +  typedef rtx (*f2) (rtx, rtx);
> +  typedef rtx (*f3) (rtx, rtx, rtx);
> +  typedef rtx (*f4) (rtx, rtx, rtx, rtx);
> +  typedef rtx (*f5) (rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f6) (rtx, rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f7) (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f8) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f9) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f10) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f11) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f12) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f13) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f14) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f15) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +  typedef rtx (*f16) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> +
> +  typedef f0 stored_funcptr;
> +
> +  rtx operator () (void) const { return ((f0)func) (); }
> +  rtx operator () (rtx a0) const { return ((f1)func) (a0); }
> +  rtx operator () (rtx a0, rtx a1) const { return ((f2)func) (a0, a1); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2) const { return ((f3)func) (a0, a1, a2); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3) const { return ((f4)func) (a0, a1, a2, a3); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4) const { return ((f5)func) (a0, a1, a2, a3, a4); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5) const { return ((f6)func) (a0, a1, a2, a3, a4, a5); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6) const { return ((f7)func) (a0, a1, a2, a3, a4, a5, a6); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7) const { return ((f8)func) (a0, a1, a2, a3, a4, a5, a6, a7); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8) const { return ((f9)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9) const { return ((f10)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10) const { return ((f11)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11) const { return ((f12)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12) const { return ((f13)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13) const { return ((f14)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14) const { return ((f15)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
> +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14, rtx a15) const { return ((f16)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
> +
> +  // This is for compatibility of code that invokes functions like
> +  //   (*funcptr) (arg)
> +  insn_gen_fn operator * (void) const { return *this; }
> +
> +  // The wrapped function pointer must be public and there must not be any
> +  // constructors.  Otherwise the insn_data_d struct initializers generated
> +  // by genoutput.c will result in static initializer functions, which defeats
> +  // the purpose of the generated insn_data_d array.
> +  stored_funcptr func;
> +};

	Jakub

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...)
  2013-08-29 19:00                 ` Jakub Jelinek
@ 2013-08-29 19:07                   ` Oleg Endo
  0 siblings, 0 replies; 14+ messages in thread
From: Oleg Endo @ 2013-08-29 19:07 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Michael Meissner, Richard Henderson, Uros Bizjak, gcc-patches,
	Stefan Kristiansson, Andreas Schwab

On Thu, 2013-08-29 at 20:51 +0200, Jakub Jelinek wrote:
> On Thu, Aug 29, 2013 at 08:45:33PM +0200, Oleg Endo wrote:
> > Sorry for the delay.  I've just backported the 2 patches to 4.8.
> > Tested with 'make all-gcc' for SH and PPC cross compilers.
> > Committed as rev 202083.
> 
> Please fix the overly long lines as a follow-up.
> 

In m original mail
http://gcc.gnu.org/ml/gcc-patches/2013-07/msg01315.html
I wrote:

* I don't know whether it's really needed to properly format the code of
class insn_gen_fn.  After reading the first two or three overloads
(which do fit into 80 columns) one gets the idea and so I guess nobody
is going to read that stuff completely anyway.

Nobody commented on it and after Richard's OK to the patch I assumed
it's fine that way as an exception.

Of course I'll do it if you insist :)

Cheers,
Oleg


> > +struct insn_gen_fn
> > +{
> > +  typedef rtx (*f0) (void);
> > +  typedef rtx (*f1) (rtx);
> > +  typedef rtx (*f2) (rtx, rtx);
> > +  typedef rtx (*f3) (rtx, rtx, rtx);
> > +  typedef rtx (*f4) (rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f5) (rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f6) (rtx, rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f7) (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f8) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f9) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f10) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f11) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f12) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f13) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f14) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f15) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> > +  typedef rtx (*f16) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> > +
> > +  typedef f0 stored_funcptr;
> > +
> > +  rtx operator () (void) const { return ((f0)func) (); }
> > +  rtx operator () (rtx a0) const { return ((f1)func) (a0); }
> > +  rtx operator () (rtx a0, rtx a1) const { return ((f2)func) (a0, a1); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2) const { return ((f3)func) (a0, a1, a2); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3) const { return ((f4)func) (a0, a1, a2, a3); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4) const { return ((f5)func) (a0, a1, a2, a3, a4); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5) const { return ((f6)func) (a0, a1, a2, a3, a4, a5); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6) const { return ((f7)func) (a0, a1, a2, a3, a4, a5, a6); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7) const { return ((f8)func) (a0, a1, a2, a3, a4, a5, a6, a7); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8) const { return ((f9)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9) const { return ((f10)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10) const { return ((f11)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11) const { return ((f12)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12) const { return ((f13)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13) const { return ((f14)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14) const { return ((f15)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
> > +  rtx operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14, rtx a15) const { return ((f16)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
> > +
> > +  // This is for compatibility of code that invokes functions like
> > +  //   (*funcptr) (arg)
> > +  insn_gen_fn operator * (void) const { return *this; }
> > +
> > +  // The wrapped function pointer must be public and there must not be any
> > +  // constructors.  Otherwise the insn_data_d struct initializers generated
> > +  // by genoutput.c will result in static initializer functions, which defeats
> > +  // the purpose of the generated insn_data_d array.
> > +  stored_funcptr func;
> > +};
> 



^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-08-29 19:00 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-26  8:09 [PATCH] Fix illegal cast to rtx (*insn_gen_fn) (rtx, ...) Uros Bizjak
2013-07-26  8:12 ` Stefan Kristiansson
2013-07-27 13:03 ` Oleg Endo
2013-07-27 13:16   ` Oleg Endo
2013-08-05 21:31   ` [PING] " Oleg Endo
2013-08-05 21:43   ` Richard Henderson
2013-08-05 22:32     ` Oleg Endo
2013-08-05 23:25       ` Richard Henderson
2013-08-06 21:46         ` Oleg Endo
2013-08-07 19:08           ` Michael Meissner
2013-08-07 19:25             ` Oleg Endo
2013-08-29 18:51               ` Oleg Endo
2013-08-29 19:00                 ` Jakub Jelinek
2013-08-29 19:07                   ` Oleg Endo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).