This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
define_insn_and_split patch
- To: gcc-patches at gcc dot gnu dot org
- Subject: define_insn_and_split patch
- From: Clinton Popetz <cpopetz at cygnus dot com>
- Date: Wed, 26 Apr 2000 13:51:00 -0500
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