This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

define_insn_and_split patch


Based on the discussion that started with:

	http://gcc.gnu.org/ml/gcc/2000-03/msg00283.html

I implemented the "define_insn_and_split" feature.  An example of how this
might be used is from i386.md, to turn:

(define_insn "zero_extendhisi2_and"
  [(set (match_operand:SI 0 "register_operand" "=r")
     (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))
   (clobber (reg:CC 17))]
  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
  "#"
  [(set_attr "type" "alu1")])

(define_split
  [(set (match_operand:SI 0 "register_operand" "")
	(zero_extend:SI (match_operand:HI 1 "register_operand" "")))
   (clobber (reg:CC 17))]
  "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535)))
	      (clobber (reg:CC 17))])]
  "")


into 

(define_insn_and_split "zero_extendhisi2_and"
  [(set (match_operand:SI 0 "register_operand" "=r")
     (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))
   (clobber (reg:CC 17))]
  "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
  "#"
  "&& reload_completed"
  [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535)))
	      (clobber (reg:CC 17))])]
  ""
  [(set_attr "type" "alu1")])


I'm working on a perl script to find eligible pattens for this conversion, but
it's not yet done, and I wanted to get these changes in first.

				-Clint


Wed Apr 26 11:24:04 CDT 2000  Clinton Popetz  <cpopetz@cygnus.com>

	* genattrtab.c (gen_insn, main): Handle DEFINE_INSN_AND_SPLIT.
	* gencodes.c (main): Ditto.
	* genconfig.c (gen_split, main): Ditto.
	* genemit.c (gen_split, main):  Ditto.
	* genextract.c (main): Ditto.
	* genflags.c (main): Ditto.
	* genopinit.c (main): Ditto.
	* genoutput.c (gen_split, main): Ditto.
	* genpeep.c (main): Ditto.
	* genrecog.c (current_type): New variable.
	(get_test): New function.
	(validate_pattern): Use get_test, and handle DEFINE_INSN_AND_SPLIT.
	(make_insn_sequence): Remove type parameter, and use current_type.
	(main): Set current_type, and handle DEFINE_INSN_AND_SPLIT.
	* rtl.def (define_insn_and_split): New DEF_RTL_EXPR.
	* md.texi (Insn Splitting): Document define_insn_and_split.

Index: genattrtab.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genattrtab.c,v
retrieving revision 1.74
diff -c -2 -p -r1.74 genattrtab.c
*** genattrtab.c	2000/04/24 06:45:30	1.74
--- genattrtab.c	2000/04/26 18:42:51
*************** gen_insn (exp)
*** 4305,4308 ****
--- 4305,4309 ----
      {
      case DEFINE_INSN:
+     case DEFINE_INSN_AND_SPLIT:
        id->insn_code = insn_code_number++;
        id->insn_index = insn_index_number++;
*************** gen_insn (exp)
*** 4310,4314 ****
        if (id->num_alternatives == 0)
  	id->num_alternatives = 1;
!       id->vec_idx = 4;
        break;
  
--- 4311,4315 ----
        if (id->num_alternatives == 0)
  	id->num_alternatives = 1;
!       id->vec_idx = (GET_CODE (exp) == DEFINE_INSN) ? 4 : 7;
        break;
  
*************** from the machine description file `md'. 
*** 6032,6036 ****
  	  || GET_CODE (desc) == DEFINE_ASM_ATTRIBUTES)
  	gen_insn (desc);
! 
        else if (GET_CODE (desc) == DEFINE_EXPAND)
  	insn_code_number++, insn_index_number++;
--- 6033,6041 ----
  	  || GET_CODE (desc) == DEFINE_ASM_ATTRIBUTES)
  	gen_insn (desc);
!       else if (GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
! 	{
! 	  gen_insn (desc);
! 	  insn_code_number++, insn_index_number++;
! 	}
        else if (GET_CODE (desc) == DEFINE_EXPAND)
  	insn_code_number++, insn_index_number++;
Index: gencodes.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/gencodes.c,v
retrieving revision 1.28
diff -c -2 -p -r1.28 gencodes.c
*** gencodes.c	2000/02/26 13:50:42	1.28
--- gencodes.c	2000/04/26 18:42:51
*************** from the machine description file `md'. 
*** 125,128 ****
--- 125,133 ----
  	  insn_code_number++;
  	}
+       if (GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
+ 	{
+ 	  gen_insn (desc);
+ 	  insn_code_number += 2;
+ 	}
        if (GET_CODE (desc) == DEFINE_PEEPHOLE
  	  || GET_CODE (desc) == DEFINE_PEEPHOLE2
Index: genconfig.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genconfig.c,v
retrieving revision 1.33
diff -c -2 -p -r1.33 genconfig.c
*** genconfig.c	2000/04/07 09:24:44	1.33
--- genconfig.c	2000/04/26 18:42:52
*************** gen_split (split)
*** 222,234 ****
       rtx split;
  {
!   int i;
  
    /* Look through the patterns that are matched
       to compute the maximum operand number.  */
!   for (i = 0; i < XVECLEN (split, 0); i++)
!     walk_insn_part (XVECEXP (split, 0, i), 1, 0);
    /* Look at the number of insns this insn could split into.  */
!   if (XVECLEN (split, 2) > max_insns_per_split)
!     max_insns_per_split = XVECLEN (split, 2);
  }
  
--- 222,236 ----
       rtx split;
  {
!   int i; 
!   int split_pattern_op = (GET_CODE (split) == DEFINE_INSN_AND_SPLIT) ? 5 : 2; 
!   int split_match_op = (GET_CODE (split) == DEFINE_INSN_AND_SPLIT) ? 1 : 0;
  
    /* Look through the patterns that are matched
       to compute the maximum operand number.  */
!   for (i = 0; i < XVECLEN (split, split_match_op); i++)
!     walk_insn_part (XVECEXP (split, split_match_op, i), 1, 0);
    /* Look at the number of insns this insn could split into.  */
!   if (XVECLEN (split, split_pattern_op) > max_insns_per_split)
!     max_insns_per_split = XVECLEN (split, split_pattern_op);
  }
  
*************** from the machine description file `md'. 
*** 314,322 ****
  
        desc = read_rtx (infile);
!       if (GET_CODE (desc) == DEFINE_INSN)
  	gen_insn (desc);
        if (GET_CODE (desc) == DEFINE_EXPAND)
  	gen_expand (desc);
!       if (GET_CODE (desc) == DEFINE_SPLIT)
  	gen_split (desc);
        if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
--- 316,326 ----
  
        desc = read_rtx (infile);
!       if (GET_CODE (desc) == DEFINE_INSN ||
! 	  GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
  	gen_insn (desc);
        if (GET_CODE (desc) == DEFINE_EXPAND)
  	gen_expand (desc);
!       if (GET_CODE (desc) == DEFINE_SPLIT ||
! 	  GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
  	gen_split (desc);
        if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
Index: genemit.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genemit.c,v
retrieving revision 1.53
diff -c -2 -p -r1.53 genemit.c
*** genemit.c	2000/02/26 13:50:42	1.53
--- genemit.c	2000/04/26 18:42:52
*************** gen_split (split)
*** 556,559 ****
--- 556,562 ----
    const char *name = "split";
  
+   int split_pattern_op = (GET_CODE (split) == DEFINE_INSN_AND_SPLIT) ? 5 : 2; 
+   int split_code_op    = (GET_CODE (split) == DEFINE_INSN_AND_SPLIT) ? 6 : 3; 
+ 
    if (GET_CODE (split) == DEFINE_PEEPHOLE2)
      name = "peephole2";
*************** gen_split (split)
*** 562,566 ****
      fatal ("define_%s (definition %d) lacks a pattern", name,
  	   insn_index_number);
!   else if (XVEC (split, 2) == 0)
      fatal ("define_%s (definition %d) lacks a replacement pattern", name,
  	   insn_index_number);
--- 565,569 ----
      fatal ("define_%s (definition %d) lacks a pattern", name,
  	   insn_index_number);
!   else if (XVEC (split, split_pattern_op) == 0)
      fatal ("define_%s (definition %d) lacks a replacement pattern", name,
  	   insn_index_number);
*************** gen_split (split)
*** 568,572 ****
    /* Find out how many operands this function has.  */
  
!   max_operand_vec (split, 2);
    operands = MAX (max_opno, MAX (max_dup_opno, max_scratch_opno)) + 1;
  
--- 571,575 ----
    /* Find out how many operands this function has.  */
  
!   max_operand_vec (split, split_pattern_op);
    operands = MAX (max_opno, MAX (max_dup_opno, max_scratch_opno)) + 1;
  
*************** gen_split (split)
*** 602,607 ****
       before the actual construction.  */
  
!   if (XSTR (split, 3))
!     printf ("%s\n", XSTR (split, 3));
  
    /* Output code to copy the arguments back out of `operands'  */
--- 605,610 ----
       before the actual construction.  */
  
!   if (XSTR (split, split_code_op))
!     printf ("%s\n", XSTR (split, split_code_op));
  
    /* Output code to copy the arguments back out of `operands'  */
*************** gen_split (split)
*** 613,619 ****
       But don't do this if the user's code has set `no_more' nonzero.  */
  
!   for (i = 0; i < XVECLEN (split, 2); i++)
      {
!       rtx next = XVECEXP (split, 2, i);
        if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
  	  || (GET_CODE (next) == PARALLEL
--- 616,622 ----
       But don't do this if the user's code has set `no_more' nonzero.  */
  
!   for (i = 0; i < XVECLEN (split, split_pattern_op); i++)
      {
!       rtx next = XVECEXP (split, split_pattern_op, i);
        if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
  	  || (GET_CODE (next) == PARALLEL
*************** from the machine description file `md'. 
*** 836,840 ****
        desc = read_rtx (infile);
  
!       if (GET_CODE (desc) == DEFINE_INSN)
  	{
  	  gen_insn (desc);
--- 839,844 ----
        desc = read_rtx (infile);
  
!       if (GET_CODE (desc) == DEFINE_INSN ||
! 	  GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
  	{
  	  gen_insn (desc);
*************** from the machine description file `md'. 
*** 846,850 ****
  	  ++insn_code_number;
  	}
!       if (GET_CODE (desc) == DEFINE_SPLIT)
  	{
  	  gen_split (desc);
--- 850,855 ----
  	  ++insn_code_number;
  	}
!       if (GET_CODE (desc) == DEFINE_SPLIT ||
! 	  GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
  	{
  	  gen_split (desc);
Index: genextract.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genextract.c,v
retrieving revision 1.40
diff -c -2 -p -r1.40 genextract.c
*** genextract.c	2000/02/26 13:50:42	1.40
--- genextract.c	2000/04/26 18:42:52
*************** from the machine description file `md'. 
*** 453,461 ****
  
        desc = read_rtx (infile);
!       if (GET_CODE (desc) == DEFINE_INSN)
  	{
  	  record_insn_name (insn_code_number, XSTR (desc, 0));
  	  gen_insn (desc);
  	  ++insn_code_number;
  	}
  
--- 453,464 ----
  
        desc = read_rtx (infile);
!       if (GET_CODE (desc) == DEFINE_INSN
! 	  || GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
  	{
  	  record_insn_name (insn_code_number, XSTR (desc, 0));
  	  gen_insn (desc);
  	  ++insn_code_number;
+ 	  if (GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
+ 	    ++insn_code_number;
  	}
  
Index: genflags.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genflags.c,v
retrieving revision 1.31
diff -c -2 -p -r1.31 genflags.c
*** genflags.c	2000/03/17 22:40:44	1.31
--- genflags.c	2000/04/26 18:42:52
*************** from the machine description file `md'. 
*** 260,264 ****
  
        desc = read_rtx (infile);
!       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
  	gen_insn (desc);
      }
--- 260,265 ----
  
        desc = read_rtx (infile);
!       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND
! 	  || GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
  	gen_insn (desc);
      }
Index: genopinit.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genopinit.c,v
retrieving revision 1.37
diff -c -2 -p -r1.37 genopinit.c
*** genopinit.c	2000/03/07 20:39:05	1.37
--- genopinit.c	2000/04/26 18:42:53
*************** from the machine description file `md'. 
*** 357,361 ****
  
        desc = read_rtx (infile);
!       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
  	gen_insn (desc);
      }
--- 357,362 ----
  
        desc = read_rtx (infile);
!       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND
! 	  || GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
  	gen_insn (desc);
      }
Index: genoutput.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genoutput.c,v
retrieving revision 1.50
diff -c -2 -p -r1.50 genoutput.c
*** genoutput.c	2000/03/17 17:31:54	1.50
--- genoutput.c	2000/04/26 18:42:53
*************** gen_split (split)
*** 840,843 ****
--- 840,844 ----
    register struct data *d = (struct data *) xmalloc (sizeof (struct data));
    register int i;
+   int split_match_op = (GET_CODE (split) == DEFINE_INSN_AND_SPLIT) ? 1 : 0;
  
    d->code_number = next_code_number++;
*************** gen_split (split)
*** 858,864 ****
       split patterns.  But ignore all the rest of the information thus
       obtained.  */
!   for (i = 0; i < XVECLEN (split, 0); i++)
!     scan_operands (d, XVECEXP (split, 0, i), 0, 0);
  
    d->n_operands = max_opno + 1;
    d->n_dups = 0;
--- 859,869 ----
       split patterns.  But ignore all the rest of the information thus
       obtained.  */
!   for (i = 0; i < XVECLEN (split, split_match_op); i++)
!     scan_operands (d, XVECEXP (split, split_match_op, i), 0, 0);
  
+   if (GET_CODE (split) == DEFINE_INSN_AND_SPLIT)
+     for (i = 0; i < max_opno + 1; i++)
+       d->operand[i].constraint = "";
+ 
    d->n_operands = max_opno + 1;
    d->n_dups = 0;
*************** main (argc, argv)
*** 937,940 ****
--- 942,951 ----
        if (GET_CODE (desc) == DEFINE_INSN)
  	gen_insn (desc);
+       if (GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
+ 	{
+ 	  gen_insn (desc);
+ 	  next_index_number++;
+ 	  gen_split (desc);
+ 	}
        if (GET_CODE (desc) == DEFINE_PEEPHOLE)
  	gen_peephole (desc);
Index: genpeep.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genpeep.c,v
retrieving revision 1.41
diff -c -2 -p -r1.41 genpeep.c
*** genpeep.c	2000/02/26 13:50:42	1.41
--- genpeep.c	2000/04/26 18:42:53
*************** from the machine description file `md'. 
*** 472,476 ****
        if (GET_CODE (desc) == DEFINE_INSN
  	  || GET_CODE (desc) == DEFINE_EXPAND
! 	  || GET_CODE (desc) == DEFINE_SPLIT)
  	{
  	  insn_code_number++;
--- 472,477 ----
        if (GET_CODE (desc) == DEFINE_INSN
  	  || GET_CODE (desc) == DEFINE_EXPAND
! 	  || GET_CODE (desc) == DEFINE_SPLIT
! 	  || GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
  	{
  	  insn_code_number++;
Index: genrecog.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genrecog.c,v
retrieving revision 1.78
diff -c -2 -p -r1.78 genrecog.c
*** genrecog.c	2000/04/09 20:26:42	1.78
--- genrecog.c	2000/04/26 18:42:54
*************** enum routine_type {
*** 154,157 ****
--- 154,159 ----
  };
  
+ enum routine_type current_type;
+ 
  #define IS_SPLIT(X) ((X) != RECOG)
  
*************** static void write_header
*** 299,303 ****
  
  static struct decision_head make_insn_sequence
!   PARAMS ((rtx, enum routine_type));
  static void process_tree
    PARAMS ((struct decision_head *, enum routine_type));
--- 301,305 ----
  
  static struct decision_head make_insn_sequence
!   PARAMS ((rtx));
  static void process_tree
    PARAMS ((struct decision_head *, enum routine_type));
*************** validate_pattern (pattern, insn, set)
*** 456,465 ****
  	int allows_non_lvalue = 1, allows_non_const = 1;
  	int special_mode_pred = 0;
! 	const char *c_test;
! 
! 	if (GET_CODE (insn) == DEFINE_INSN)
! 	  c_test = XSTR (insn, 2);
! 	else
! 	  c_test = XSTR (insn, 1);
  
  	if (pred_name[0] != 0)
--- 458,462 ----
  	int allows_non_lvalue = 1, allows_non_const = 1;
  	int special_mode_pred = 0;
! 	const char *c_test = get_test (insn);
  
  	if (pred_name[0] != 0)
*************** validate_pattern (pattern, insn, set)
*** 549,553 ****
  	if (GET_MODE (pattern) == VOIDmode
  	    && code == MATCH_OPERAND
! 	    && GET_CODE (insn) == DEFINE_INSN
  	    && allows_non_const
  	    && ! special_mode_pred
--- 546,551 ----
  	if (GET_MODE (pattern) == VOIDmode
  	    && code == MATCH_OPERAND
! 	    && (GET_CODE (insn) == DEFINE_INSN
! 		|| GET_CODE (insn) == DEFINE_INSN_AND_SPLIT)
  	    && allows_non_const
  	    && ! special_mode_pred
*************** write_header ()
*** 2298,2321 ****
  
  
! /* Construct and return a sequence of decisions
!    that will recognize INSN.
  
!    TYPE says what type of routine we are recognizing (RECOG or SPLIT).  */
  
  static struct decision_head
! make_insn_sequence (insn, type)
       rtx insn;
-      enum routine_type type;
  {
    rtx x;
!   const char *c_test = XSTR (insn, type == RECOG ? 2 : 1);
    struct decision *last;
    struct decision_test *test, **place;
    struct decision_head head;
    char *c_test_pos = "";
  
!   record_insn_name (next_insn_code, (type == RECOG ? XSTR (insn, 0) : NULL));
  
!   if (type == PEEPHOLE2)
      {
        int i, j;
--- 2296,2353 ----
  
  
! 
! /* Return the condition for an insn */
! 
! static char* 
! get_test (insn)
!      rtx insn;
! {
!   const char *c_test;
! 
!   switch (GET_CODE (insn)) 
!     {
!     case DEFINE_INSN_AND_SPLIT:
! 	c_test = XSTR (insn, (current_type == RECOG) ? 2 : 4);
! 	if (c_test[0] == '&' && c_test[1] == '&')
!   	  {
!   	    const char *insn_cond = XSTR (insn, 2);
!   	    const char *combined = 
!   		xmalloc (strlen (insn_cond) + strlen (c_test) + 1);
!  	    strcpy(combined, insn_cond);
!   	    strcat(combined, c_test);
!   	    c_test = combined;
!   	  }
!    	break;
!     case DEFINE_INSN:
!     	c_test = XSTR (insn, 2);
! 	break;
! 
!     default:
!     	c_test = XSTR (insn, 1);
! 	break;
!     }
  
!   return c_test;
! }
  
+ /* Construct and return a sequence of decisions
+    that will recognize INSN.  */
+ 
  static struct decision_head
! make_insn_sequence (insn)
       rtx insn;
  {
    rtx x;
!   const char *c_test = get_test (insn);
    struct decision *last;
    struct decision_test *test, **place;
    struct decision_head head;
+   int pattern_idx = (current_type == RECOG 
+ 	  	     || GET_CODE (insn) == DEFINE_INSN_AND_SPLIT) ? 1 : 0;
    char *c_test_pos = "";
  
!   record_insn_name (next_insn_code, (current_type == RECOG ? XSTR (insn, 0) : NULL));
  
!   if (current_type == PEEPHOLE2)
      {
        int i, j;
*************** make_insn_sequence (insn, type)
*** 2343,2352 ****
        c_test_pos[1] = '\0';
      }
!   else if (XVECLEN (insn, type == RECOG) == 1)
!     x = XVECEXP (insn, type == RECOG, 0);
    else
      {
        x = rtx_alloc (PARALLEL);
!       XVEC (x, 0) = XVEC (insn, type == RECOG);
        PUT_MODE (x, VOIDmode);
      }
--- 2375,2384 ----
        c_test_pos[1] = '\0';
      }
!   else if (XVECLEN (insn, pattern_idx) == 1)
!     x = XVECEXP (insn, pattern_idx, 0);
    else
      {
        x = rtx_alloc (PARALLEL);
!       XVEC (x, 0) = XVEC (insn, pattern_idx);
        PUT_MODE (x, VOIDmode);
      }
*************** make_insn_sequence (insn, type)
*** 2355,2359 ****
  
    memset(&head, 0, sizeof(head));
!   last = add_to_sequence (x, &head, "", type, 1);
  
    /* Find the end of the test chain on the last node.  */
--- 2387,2391 ----
  
    memset(&head, 0, sizeof(head));
!   last = add_to_sequence (x, &head, "", current_type, 1);
  
    /* Find the end of the test chain on the last node.  */
*************** make_insn_sequence (insn, type)
*** 2379,2383 ****
    test->u.insn.num_clobbers_to_add = 0;
  
!   switch (type)
      {
      case RECOG:
--- 2411,2415 ----
    test->u.insn.num_clobbers_to_add = 0;
  
!   switch (current_type)
      {
      case RECOG:
*************** make_insn_sequence (insn, type)
*** 2420,2424 ****
  	      /* Recognize it.  */
  	      memset (&clobber_head, 0, sizeof(clobber_head));
! 	      last = add_to_sequence (new, &clobber_head, "", type, 1);
  
  	      /* Find the end of the test chain on the last node.  */
--- 2452,2456 ----
  	      /* Recognize it.  */
  	      memset (&clobber_head, 0, sizeof(clobber_head));
! 	      last = add_to_sequence (new, &clobber_head, "", current_type, 1);
  
  	      /* Find the end of the test chain on the last node.  */
*************** make_insn_sequence (insn, type)
*** 2449,2453 ****
  	    }
  	}
!       break;
  
      case SPLIT:
--- 2481,2487 ----
  	    }
  	}
!       if (GET_CODE (insn) != DEFINE_INSN_AND_SPLIT)
!       	break;
!       /* fallthrough */
  
      case SPLIT:
*************** main (argc, argv)
*** 2545,2559 ****
        if (GET_CODE (desc) == DEFINE_INSN)
  	{
! 	  h = make_insn_sequence (desc, RECOG);
  	  merge_trees (&recog_tree, &h);
  	}
        else if (GET_CODE (desc) == DEFINE_SPLIT)
  	{
! 	  h = make_insn_sequence (desc, SPLIT);
  	  merge_trees (&split_tree, &h);
  	}
        else if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
  	{
! 	  h = make_insn_sequence (desc, PEEPHOLE2);
  	  merge_trees (&peephole2_tree, &h);
  	}
--- 2579,2606 ----
        if (GET_CODE (desc) == DEFINE_INSN)
  	{
! 	  current_type = RECOG;
! 	  h = make_insn_sequence (desc);
  	  merge_trees (&recog_tree, &h);
  	}
        else if (GET_CODE (desc) == DEFINE_SPLIT)
  	{
! 	  current_type = SPLIT;
! 	  h = make_insn_sequence (desc);
  	  merge_trees (&split_tree, &h);
  	}
+       else if (GET_CODE (desc) == DEFINE_INSN_AND_SPLIT)
+       {
+ 	  current_type = RECOG;
+ 	  h = make_insn_sequence (desc);
+ 	  merge_trees (&recog_tree, &h);
+ 	  next_index++;
+ 	  current_type = SPLIT;
+ 	  h = make_insn_sequence (desc);
+ 	  merge_trees (&split_tree, &h);
+       }
        else if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
  	{
! 	  current_type = PEEPHOLE2;
! 	  h = make_insn_sequence (desc);
  	  merge_trees (&peephole2_tree, &h);
  	}
Index: rtl.def
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.def,v
retrieving revision 1.34
diff -c -2 -p -r1.34 rtl.def
*** rtl.def	2000/04/21 19:32:09	1.34
--- rtl.def	2000/04/26 18:43:01
*************** DEF_RTL_EXPR(DEFINE_PEEPHOLE, "define_pe
*** 204,207 ****
--- 204,234 ----
  DEF_RTL_EXPR(DEFINE_SPLIT, "define_split", "EsES", 'x')
  
+ /* Definition of an insn and associated split.
+    This is the concatenation, with a few modifications, of a define_insn
+    and a define_split which share the same pattern.
+    Operand:
+    0: names this instruction.
+       If the name is the null string, the instruction is in the
+       machine description just to be recognized, and will never be emitted by
+       the tree to rtl expander.
+    1: is the pattern.
+    2: is a string which is a C expression
+       giving an additional condition for recognizing this pattern.
+       A null string means no extra condition.
+    3: is the action to execute if this pattern is matched.
+       If this assembler code template starts with a * then it is a fragment of
+       C code to run to decide on a template to use.  Otherwise, it is the
+       template to use.
+    4: C expression that must be true for split.  This may start with "&&"
+       in which case the split condition is the logical and of the insn 
+       condition and what follows the "&&" of this operand.
+    5: vector of insn patterns to place into a SEQUENCE
+    6: optionally, some C code to execute before generating the
+ 	insns.  This might, for example, create some RTX's and store them in
+ 	elements of `recog_operand' for use by the vector of insn-patterns.
+ 	(`operands' is an alias here for `recog_operand').  
+    7: optionally, a vector of attributes for this insn.  */
+ DEF_RTL_EXPR(DEFINE_INSN_AND_SPLIT, "define_insn_and_split", "sEsssESV", 'x')
+ 
  /* Definition of an RTL peephole operation.
     Follows the same arguments as define_split.  */
Index: md.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/md.texi,v
retrieving revision 1.43
diff -c -2 -p -r1.43 md.texi
*** md.texi	2000/04/05 21:14:53	1.43
--- md.texi	2000/04/26 18:43:03
*************** definitions, one for the insns that are 
*** 3432,3435 ****
--- 3432,3485 ----
  are not valid.
  
+ For the common case where the pattern of a define_split exactly matches the
+ pattern of a define_insn, use @code{define_insn_and_split}.  It looks like
+ this:
+ 
+ @smallexample
+ (define_insn_and_split
+   [@var{insn-pattern}]
+   "@var{condition}"
+   "@var{output-template}"
+   "@var{split-condition}"
+   [@var{new-insn-pattern-1}
+    @var{new-insn-pattern-2}
+    @dots{}]
+   "@var{preparation statements}"
+   [@var{insn-attributes}])
+ 
+ @end smallexample
+ 
+ @var{insn-pattern}, @var{condition}, @var{output-template}, and
+ @var{insn-attributes} are used as in @code{define_insn}.  The
+ @var{new-insn-pattern} vector and the @var{preparation-statements} are used as
+ in a @code{define_split}.  The @var{split-condition} is also used as in
+ @code{define_split}, with the additional behavior that if the condition starts
+ with @samp{&&}, the condition used for the split will be the constructed as a
+ logical "and" of the split condition with the insn condition.  For example,
+ from i386.md:
+ 
+ @smallexample
+ (define_insn_and_split "zero_extendhisi2_and"
+   [(set (match_operand:SI 0 "register_operand" "=r")
+      (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))
+    (clobber (reg:CC 17))]
+   "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
+   "#"
+   "&& reload_completed"
+   [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535)))
+ 	      (clobber (reg:CC 17))])]
+   ""
+   [(set_attr "type" "alu1")])
+ 
+ @end smallexample
+ 
+ In this case, the actual split condition will be 
+ "TARGET_ZERO_EXTEND_WITH_AND && !optimize_size && reload_completed."
+ 
+ The @code{define_insn_and_split} construction provides exactly the same
+ functionality as two separate @code{define_insn} and @code{define_split}
+ patterns.  It exists for compactness, and as a maintenance tool to prevent
+ having to ensure the two patterns' templates match.
+ 
  @node Peephole Definitions
  @section Machine-Specific Peephole Optimizers

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]