diff options
author | Richard Henderson <rth@cygnus.com> | 1999-08-31 13:37:09 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 1999-08-31 13:37:09 -0700 |
commit | ede7cd44999a94c3eeb6708db37d6939045b554e (patch) | |
tree | afdcdc35501714ae0479a8139d1ee32d313b0176 /gcc/genemit.c | |
parent | 4dfeccf9d064821bede6f09da2949499f19c68c4 (diff) | |
download | gcc-ede7cd44999a94c3eeb6708db37d6939045b554e.tar.gz |
backport: Makefile.in (STAGESTUFF): Add *.peephole2.
Merge peephole2 from new_ia32_branch:
* Makefile.in (STAGESTUFF): Add *.peephole2.
(mostlyclean): Likewise.
(recog.o): Depend on resource.h.
* final.c (peephole): Conditionalize decl on HAVE_peephole.
(final_scan_insn): Likewise for the invocation of peephole.
* genconfig.c (main): Look for peephole and peephole2 patterns.
Emit HAVE_peephole* accordingly.
* genpeep.c (main): Conditionalize entire output on HAVE_peephole.
* flags.h (flag_peephole2): Declare.
* toplev.c: New pass peephole2. New flag -fpeephole2.
* genattrtab.c (main): Count DEFINE_PEEPHOLE2.
* gencodes.c (main): Likewise.
* genextract.c (main): Likewise.
* genoutput.c (main): Likewise.
* genemit.c (max_operand_1): Look for the max scratch operand.
(gen_rtx_scratch): New.
(gen_exp): Use it, and pass on new arg subroutine_type.
(gen_expand): Take max scratch into account.
(gen_split): Emit peephole2 functions.
(output_peephole2_scratch): New.
(main): Include hard-reg-set.h and resource.h. Handle peephole2.
* genrecog.c (routine_type): Add PEEPHOLE2.
(IS_SPLIT): New.
(make_insn_sequence): Match outer parallel for peep2. Discard
top level scratches and dups.
(add_to_sequence): New args insn_type and top. Update all callers.
Handle toplevel peep2 matching insns.
(write_subroutine): Handle peep2.
(write_tree_1): Likewise.
(write_tree): Likewise.
(main): Likewise.
(change_state): New arg afterward. Update all callers.
Handle matching separate insns.
* recog.c (recog_next_insn): New.
(peephole2_optimize): New.
* rtl.def (DEFINE_PEEPHOLE2): New.
* resource.c (find_free_register): New argument last_insn. Use it
to find a register available through the entire span.
* resource.h (find_free_register): Update prototype.
From-SVN: r29015
Diffstat (limited to 'gcc/genemit.c')
-rw-r--r-- | gcc/genemit.c | 152 |
1 files changed, 129 insertions, 23 deletions
diff --git a/gcc/genemit.c b/gcc/genemit.c index dc9a49af9d6..68188e6c2ea 100644 --- a/gcc/genemit.c +++ b/gcc/genemit.c @@ -36,6 +36,7 @@ char **insn_name_ptr = 0; static int max_opno; static int max_dup_opno; +static int max_scratch_opno; static int register_constraints; static int insn_code_number; static int insn_index_number; @@ -63,12 +64,13 @@ struct clobber_ent static void max_operand_1 PROTO((rtx)); static int max_operand_vec PROTO((rtx, int)); static void print_code PROTO((RTX_CODE)); -static void gen_exp PROTO((rtx)); +static void gen_exp PROTO((rtx, enum rtx_code)); static void gen_insn PROTO((rtx)); static void gen_expand PROTO((rtx)); static void gen_split PROTO((rtx)); static void output_add_clobbers PROTO((void)); -static void output_init_mov_optab PROTO((void)); +static void gen_rtx_scratch PROTO((rtx, enum rtx_code)); +static void output_peephole2_scratches PROTO((rtx)); static void @@ -94,6 +96,8 @@ max_operand_1 (x) max_opno = MAX (max_opno, XINT (x, 0)); if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP) max_dup_opno = MAX (max_dup_opno, XINT (x, 0)); + if (code == MATCH_SCRATCH) + max_scratch_opno = MAX (max_scratch_opno, XINT (x, 0)); fmt = GET_RTX_FORMAT (code); len = GET_RTX_LENGTH (code); @@ -120,6 +124,7 @@ max_operand_vec (insn, arg) max_opno = -1; max_dup_opno = -1; + max_scratch_opno = -1; for (i = 0; i < len; i++) max_operand_1 (XVECEXP (insn, arg, i)); @@ -141,12 +146,28 @@ print_code (code) } } +static void +gen_rtx_scratch (x, subroutine_type) + rtx x; + enum rtx_code subroutine_type; +{ + if (subroutine_type == DEFINE_PEEPHOLE2) + { + printf ("operand%d", XINT (x, 0)); + } + else + { + printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); + } +} + /* Print a C expression to construct an RTX just like X, substituting any operand references appearing within. */ static void -gen_exp (x) +gen_exp (x, subroutine_type) rtx x; + enum rtx_code subroutine_type; { register RTX_CODE code; register int i; @@ -177,7 +198,7 @@ gen_exp (x) for (i = 0; i < XVECLEN (x, 1); i++) { printf (",\n\t\t"); - gen_exp (XVECEXP (x, 1, i)); + gen_exp (XVECEXP (x, 1, i), subroutine_type); } printf (")"); return; @@ -188,7 +209,7 @@ gen_exp (x) for (i = 0; i < XVECLEN (x, 2); i++) { printf (",\n\t\t"); - gen_exp (XVECEXP (x, 2, i)); + gen_exp (XVECEXP (x, 2, i), subroutine_type); } printf (")"); return; @@ -199,7 +220,7 @@ gen_exp (x) return; case MATCH_SCRATCH: - printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); + gen_rtx_scratch (x, subroutine_type); return; case ADDRESS: @@ -251,7 +272,7 @@ gen_exp (x) break; printf (",\n\t"); if (fmt[i] == 'e' || fmt[i] == 'u') - gen_exp (XEXP (x, i)); + gen_exp (XEXP (x, i), subroutine_type); else if (fmt[i] == 'i') printf ("%u", XINT (x, i)); else if (fmt[i] == 's') @@ -263,7 +284,7 @@ gen_exp (x) for (j = 0; j < XVECLEN (x, i); j++) { printf (",\n\t\t"); - gen_exp (XVECEXP (x, i, j)); + gen_exp (XVECEXP (x, i, j), subroutine_type); } printf (")"); } @@ -375,7 +396,7 @@ gen_insn (insn) if (XVECLEN (insn, 1) == 1) { printf (" return "); - gen_exp (XVECEXP (insn, 1, 0)); + gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN); printf (";\n}\n\n"); } else @@ -384,7 +405,7 @@ gen_insn (insn) for (i = 0; i < XVECLEN (insn, 1); i++) { printf (",\n\t\t"); - gen_exp (XVECEXP (insn, 1, i)); + gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN); } printf ("));\n}\n\n"); } @@ -427,7 +448,7 @@ gen_expand (expand) && XVECLEN (expand, 1) == 1) { printf (" return "); - gen_exp (XVECEXP (expand, 1, 0)); + gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND); printf (";\n}\n\n"); return; } @@ -436,8 +457,11 @@ gen_expand (expand) make a local variable. */ for (i = operands; i <= max_dup_opno; i++) printf (" rtx operand%d;\n", i); - if (operands > 0 || max_dup_opno >= 0) - printf (" rtx operands[%d];\n", MAX (operands, max_dup_opno + 1)); + for (; i <= max_scratch_opno; i++) + printf (" rtx operand%d;\n", i); + if (operands > 0 || max_dup_opno >= 0 || max_scratch_opno >= 0) + printf (" rtx operands[%d];\n", + MAX (operands, MAX (max_scratch_opno, max_dup_opno) + 1)); printf (" rtx _val = 0;\n"); printf (" start_sequence ();\n"); @@ -465,6 +489,8 @@ gen_expand (expand) printf (" operand%d = operands[%d];\n", i, i); for (; i <= max_dup_opno; i++) printf (" operand%d = operands[%d];\n", i, i); + for (; i <= max_scratch_opno; i++) + printf (" operand%d = operands[%d];\n", i, i); } } @@ -501,7 +527,7 @@ gen_expand (expand) printf (" emit ("); else printf (" emit_insn ("); - gen_exp (next); + gen_exp (next, DEFINE_EXPAND); printf (");\n"); if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC && GET_CODE (SET_SRC (next)) == LABEL_REF) @@ -524,28 +550,49 @@ gen_split (split) { register int i; int operands; + char *name = "split"; + + if (GET_CODE (split) == DEFINE_PEEPHOLE2) + name = "peephole2"; if (XVEC (split, 0) == 0) - fatal ("define_split (definition %d) lacks a pattern", insn_index_number); + fatal ("define_%s (definition %d) lacks a pattern", name, + insn_index_number); else if (XVEC (split, 2) == 0) - fatal ("define_split (definition %d) lacks a replacement pattern", + fatal ("define_%s (definition %d) lacks a replacement pattern", name, insn_index_number); /* Find out how many operands this function has. */ max_operand_vec (split, 2); - operands = MAX (max_opno, max_dup_opno) + 1; + operands = MAX (max_opno, MAX (max_dup_opno, max_scratch_opno)) + 1; - /* Output the prototype, the function name and argument declarations. */ - printf ("extern rtx gen_split_%d PROTO ((rtx *));\n", insn_code_number); - printf ("rtx\ngen_split_%d (operands)\n rtx *operands;\n", - insn_code_number); + /* Output the prototype, function name and argument declarations. */ + if (GET_CODE (split) == DEFINE_PEEPHOLE2) + { + printf ("extern rtx gen_%s_%d PROTO ((rtx, rtx *));\n", + name, insn_code_number); + printf ("rtx\ngen_%s_%d (curr_insn, operands)\n\ + rtx curr_insn ATTRIBUTE_UNUSED;\n\ + rtx *operands;\n", + name, insn_code_number); + } + else + { + printf ("extern rtx gen_split_%d PROTO ((rtx *));\n", insn_code_number); + printf ("rtx\ngen_%s_%d (operands)\n rtx *operands;\n", name, + insn_code_number); + } printf ("{\n"); /* Declare all local variables. */ for (i = 0; i < operands; i++) printf (" rtx operand%d;\n", i); printf (" rtx _val = 0;\n"); + + if (GET_CODE (split) == DEFINE_PEEPHOLE2) + output_peephole2_scratches (split); + printf (" start_sequence ();\n"); /* The fourth operand of DEFINE_SPLIT is some code to be executed @@ -590,7 +637,7 @@ gen_split (split) printf (" emit ("); else printf (" emit_insn ("); - gen_exp (next); + gen_exp (next, GET_CODE (split)); printf (");\n"); if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC && GET_CODE (SET_SRC (next)) == LABEL_REF) @@ -630,7 +677,8 @@ output_add_clobbers () for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) { printf (" XVECEXP (pattern, 0, %d) = ", i); - gen_exp (XVECEXP (clobber->pattern, 1, i)); + gen_exp (XVECEXP (clobber->pattern, 1, i), + GET_CODE (clobber->pattern)); printf (";\n"); } @@ -643,6 +691,56 @@ output_add_clobbers () printf ("}\n"); } +/* Generate code to invoke find_free_register () as needed for the + scratch registers used by the peephole2 pattern in SPLIT. */ + +static void +output_peephole2_scratches (split) + rtx split; +{ + int i; + int insn_nr = 0; + + printf (" rtx first_insn ATTRIBUTE_UNUSED;\n"); + printf (" rtx last_insn ATTRIBUTE_UNUSED;\n"); + printf (" HARD_REG_SET _regs_allocated;\n"); + + printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n"); + + for (i = 0; i < XVECLEN (split, 0); i++) + { + rtx elt = XVECEXP (split, 0, i); + if (GET_CODE (elt) == MATCH_SCRATCH) + { + int last_insn_nr = insn_nr; + int cur_insn_nr = insn_nr; + int j; + for (j = i + 1; j < XVECLEN (split, 0); j++) + if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP) + { + if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0)) + last_insn_nr = cur_insn_nr; + } + else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH) + cur_insn_nr++; + printf (" first_insn = recog_next_insn (curr_insn, %d);\n", insn_nr); + if (last_insn_nr > insn_nr) + printf (" last_insn = recog_next_insn (curr_insn, %d);\n", + last_insn_nr - 1); + else + printf (" last_insn = 0;\n"); + printf (" if ((operands[%d] = find_free_register (first_insn, last_insn, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\ + return NULL;\n", + XINT (elt, 0), + XSTR (elt, 1), + GET_MODE_NAME (GET_MODE (elt))); + + } + else if (GET_CODE (elt) != MATCH_DUP) + insn_nr++; + } +} + PTR xmalloc (size) size_t size; @@ -713,6 +811,8 @@ from the machine description file `md'. */\n\n"); printf ("#include \"insn-flags.h\"\n"); printf ("#include \"insn-codes.h\"\n"); printf ("#include \"recog.h\"\n"); + printf ("#include \"hard-reg-set.h\"\n"); + printf ("#include \"resource.h\"\n"); printf ("#include \"reload.h\"\n\n"); printf ("extern rtx recog_operand[];\n"); printf ("#define operands emit_operand\n\n"); @@ -729,6 +829,7 @@ from the machine description file `md'. */\n\n"); ungetc (c, infile); desc = read_rtx (infile); + if (GET_CODE (desc) == DEFINE_INSN) { gen_insn (desc); @@ -744,6 +845,11 @@ from the machine description file `md'. */\n\n"); gen_split (desc); ++insn_code_number; } + if (GET_CODE (desc) == DEFINE_PEEPHOLE2) + { + gen_split (desc); + ++insn_code_number; + } if (GET_CODE (desc) == DEFINE_PEEPHOLE) { ++insn_code_number; |