Commit ede7cd44 by Richard Henderson Committed by Richard Henderson

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
parent 4dfeccf9
Tue Aug 31 13:35:42 1999 Richard Henderson <rth@cygnus.com>
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.
Tue Aug 31 11:51:06 1999 Jim Kingdon <http://developer.redhat.com>
* i386.c (output_strlen_unroll): Don't write xops[7]
......
......@@ -697,7 +697,7 @@ STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
specs collect2$(exeext) $(USE_COLLECT2) underscore.c \
gcov$(exeext) *.bp \
*.greg *.lreg *.combine *.flow *.cse *.jump *.rtl *.tree *.loop \
*.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.gcse *.flow2 \
*.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.gcse *.flow2 *.peephole2 \
*.[si] libcpp.a \
$(LANG_STAGESTUFF)
......@@ -1577,10 +1577,10 @@ final.o : final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h intl.h \
dbxout.h
recog.o : recog.c $(CONFIG_H) system.h $(RTL_H) function.h \
$(REGS_H) $(RECOG_H) hard-reg-set.h flags.h insn-config.h insn-attr.h \
insn-flags.h insn-codes.h real.h toplev.h
insn-flags.h insn-codes.h real.h toplev.h output.h resource.h
reg-stack.o : reg-stack.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) recog.h \
$(REGS_H) hard-reg-set.h flags.h insn-config.h insn-flags.h toplev.h \
function.h
varray.h function.h
dyn-string.o: dyn-string.c dyn-string.h $(CONFIG_H) system.h
lists.o: lists.c $(CONFIG_H) system.h toplev.h $(RTL_H)
......@@ -2311,10 +2311,11 @@ mostlyclean: intl.mostlyclean lang.mostlyclean
# Delete debugging dump files.
-rm -f *.greg *.lreg *.combine *.flow *.cse *.jump *.rtl *.tree *.loop
-rm -f *.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.addressof
-rm -f *.regmove *.mach *.bp *.gcse *.flow2
-rm -f *.regmove *.mach *.bp *.gcse *.flow2 *.peephole2
-rm -f */*.greg */*.lreg */*.combine */*.flow */*.cse */*.jump */*.rtl
-rm -f */*.tree */*.loop */*.dbr */*.jump2 */*.sched */*.cse2
-rm -f */*.sched2 */*.stack */*.regmove */*.gcse */*.flow2
-rm -f */*.peephole2
# Delete some files made during installation.
-rm -f specs float.h-* enquire SYSCALLS.c.X SYSCALLS.c
-rm -f collect collect2 mips-tfile mips-tdump alloca.s
......
......@@ -284,7 +284,9 @@ struct bb_str {
int length; /* string length */
};
#ifdef HAVE_peephole
extern rtx peephole PROTO((rtx));
#endif
static struct bb_str *sbb_head = 0; /* Head of string list. */
static struct bb_str **sbb_tail = &sbb_head; /* Ptr to store next bb str */
......@@ -2825,6 +2827,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
#endif
#ifdef HAVE_peephole
/* Do machine-specific peephole optimizations if desired. */
if (optimize && !flag_no_peephole && !nopeepholes)
......@@ -2855,6 +2858,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
/* PEEPHOLE might have changed this. */
body = PATTERN (insn);
}
#endif
/* Try to recognize the instruction.
If successful, verify that the operands satisfy the
......
......@@ -474,6 +474,9 @@ extern int flag_regmove;
/* Instrument functions with calls at entry and exit, for profiling. */
extern int flag_instrument_function_entry_exit;
/* Perform a peephole pass before sched2. */
extern int flag_peephole2;
/* Other basic status info about current function. */
/* Nonzero means current function must be given a frame pointer.
......
......@@ -6018,6 +6018,9 @@ from the machine description file `md'. */\n\n");
else if (GET_CODE (desc) == DEFINE_SPLIT)
insn_code_number++, insn_index_number++;
else if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
insn_code_number++, insn_index_number++;
else if (GET_CODE (desc) == DEFINE_ATTR)
{
gen_attr (desc);
......
......@@ -125,6 +125,7 @@ from the machine description file `md'. */\n\n");
insn_code_number++;
}
if (GET_CODE (desc) == DEFINE_PEEPHOLE
|| GET_CODE (desc) == DEFINE_PEEPHOLE2
|| GET_CODE (desc) == DEFINE_SPLIT)
{
insn_code_number++;
......
......@@ -43,6 +43,8 @@ static int register_constraint_flag;
static int have_cc0_flag;
static int have_cmove_flag;
static int have_lo_sum_flag;
static int have_peephole_flag;
static int have_peephole2_flag;
/* Maximum number of insns seen in a split. */
static int max_insns_per_split = 1;
......@@ -313,9 +315,17 @@ from the machine description file `md'. */\n\n");
gen_expand (desc);
if (GET_CODE (desc) == DEFINE_SPLIT)
gen_split (desc);
if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
{
have_peephole2_flag = 1;
gen_split (desc);
}
if (GET_CODE (desc) == DEFINE_PEEPHOLE)
{
have_peephole_flag = 1;
gen_peephole (desc);
}
}
printf ("\n#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
......@@ -338,6 +348,12 @@ from the machine description file `md'. */\n\n");
if (have_lo_sum_flag)
printf ("#define HAVE_lo_sum\n");
if (have_peephole_flag)
printf ("#define HAVE_peephole\n");
if (have_peephole2_flag)
printf ("#define HAVE_peephole2\n");
fflush (stdout);
exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
/* NOTREACHED */
......
......@@ -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. */
/* 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_split_%d (operands)\n rtx *operands;\n",
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;
......
......@@ -463,6 +463,7 @@ from the machine description file `md'. */\n\n");
}
else if (GET_CODE (desc) == DEFINE_EXPAND
|| GET_CODE (desc) == DEFINE_PEEPHOLE2
|| GET_CODE (desc) == DEFINE_SPLIT)
++insn_code_number;
}
......
......@@ -968,7 +968,8 @@ main (argc, argv)
gen_peephole (desc);
if (GET_CODE (desc) == DEFINE_EXPAND)
gen_expand (desc);
if (GET_CODE (desc) == DEFINE_SPLIT)
if (GET_CODE (desc) == DEFINE_SPLIT
|| GET_CODE (desc) == DEFINE_PEEPHOLE2)
gen_split (desc);
next_index_number++;
}
......
......@@ -445,6 +445,7 @@ from the machine description file `md'. */\n\n");
printf ("#include \"except.h\"\n\n");
printf ("#include \"function.h\"\n\n");
printf ("#ifdef HAVE_peephole\n");
printf ("extern rtx peep_operand[];\n\n");
printf ("#define operands peep_operand\n\n");
......@@ -485,6 +486,7 @@ from the machine description file `md'. */\n\n");
max_opno = 1;
printf ("rtx peep_operand[%d];\n", max_opno + 1);
printf ("#endif\n");
fflush (stdout);
exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
......
......@@ -34,6 +34,8 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "toplev.h"
#include "basic-block.h"
#include "output.h"
#include "resource.h"
#ifndef STACK_PUSH_CODE
#ifdef STACK_GROWS_DOWNWARD
......@@ -2688,3 +2690,69 @@ split_block_insns (b, do_split)
break;
}
}
#ifdef HAVE_peephole2
/* Return the Nth non-note insn after INSN, or return NULL_RTX if it does
not exist. Used by the recognizer to find the next insn to match in a
multi-insn pattern. */
rtx
recog_next_insn (insn, n)
rtx insn;
int n;
{
while (insn != NULL_RTX && n > 0)
{
insn = next_nonnote_insn (insn);
if (insn == NULL_RTX)
return insn;
if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
return NULL_RTX;
n--;
}
return insn;
}
/* Perform the peephole2 optimization pass. */
void
peephole2_optimize (dump_file)
FILE *dump_file ATTRIBUTE_UNUSED;
{
rtx insn;
rtx epilogue_insn = 0;
for (insn = get_last_insn (); insn != NULL_RTX; insn = PREV_INSN (insn))
{
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
{
epilogue_insn = insn;
break;
}
}
init_resource_info (epilogue_insn);
for (insn = get_insns (); insn != NULL;
insn = next_nonnote_insn (insn))
{
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
{
rtx last_insn;
rtx before = PREV_INSN (insn);
rtx try = peephole2_insns (PATTERN (insn), insn, &last_insn);
if (try != NULL)
{
replace_insns (insn, last_insn, try, NULL_RTX);
insn = NEXT_INSN (before);
}
}
}
free_resource_info ();
}
#endif
......@@ -114,6 +114,9 @@ extern void add_clobbers PROTO((rtx, int));
extern void insn_extract PROTO((rtx));
extern void extract_insn PROTO((rtx));
extern void preprocess_constraints PROTO((void));
extern rtx recog_next_insn PROTO((rtx, int));
extern void peephole2_optimize PROTO((FILE *));
extern rtx peephole2_insns PROTO((rtx, rtx, rtx *));
/* Nonzero means volatile operands are recognized. */
extern int volatile_ok;
......
......@@ -1239,17 +1239,20 @@ mark_end_of_function_resources (trial, include_delayed_effects)
include_delayed_effects);
}
/* Try to find an available hard register of mode MODE at
CURRENT_INSN, matching the register class in CLASS_STR. Registers
that already have bits set in REG_SET will not be considered.
/* Try to find a hard register of mode MODE, matching the register class in
CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX,
in which case the only condition is that the register must be available
before CURRENT_INSN.
Registers that already have bits set in REG_SET will not be considered.
If an appropriate register is available, it will be returned and the
corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
returned. */
rtx
find_free_register (current_insn, class_str, mode, reg_set)
rtx current_insn;
find_free_register (current_insn, last_insn, class_str, mode, reg_set)
rtx current_insn, last_insn;
char *class_str;
int mode;
HARD_REG_SET *reg_set;
......@@ -1261,6 +1264,14 @@ find_free_register (current_insn, class_str, mode, reg_set)
= (clet == 'r' ? GENERAL_REGS : REG_CLASS_FROM_LETTER (clet));
mark_target_live_regs (get_insns (), current_insn, &used);
if (last_insn)
while (current_insn != last_insn)
{
/* Exclude anything set in this insn. */
mark_set_resources (PATTERN (current_insn), &used, 0, 1);
current_insn = next_nonnote_insn (current_insn);
}
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
......
......@@ -42,5 +42,5 @@ extern void incr_ticks_for_insn PROTO((rtx));
extern void mark_end_of_function_resources PROTO ((rtx, int));
extern void init_resource_info PROTO((rtx));
extern void free_resource_info PROTO((void));
extern rtx find_free_register PROTO((rtx, char *, int,
extern rtx find_free_register PROTO((rtx, rtx, char *, int,
HARD_REG_SET *));
......@@ -207,6 +207,10 @@ DEF_RTL_EXPR(DEFINE_PEEPHOLE, "define_peephole", "EssV", 'x')
(`operands' is an alias here for `recog_operand'). */
DEF_RTL_EXPR(DEFINE_SPLIT, "define_split", "EsES", 'x')
/* Definition of an RTL peephole operation.
Follows the same arguments as define_split. */
DEF_RTL_EXPR(DEFINE_PEEPHOLE2, "define_peephole2", "EsES", 'x')
/* Definition of a combiner pattern.
Operands not defined yet. */
DEF_RTL_EXPR(DEFINE_COMBINE, "define_combine", "Ess", 'x')
......
......@@ -290,6 +290,7 @@ int sched_dump = 0;
int local_reg_dump = 0;
int global_reg_dump = 0;
int flow2_dump = 0;
int peephole2_dump = 0;
int sched2_dump = 0;
int jump2_opt_dump = 0;
#ifdef DELAY_SLOTS
......@@ -761,6 +762,9 @@ int flag_instrument_function_entry_exit = 0;
int flag_no_ident = 0;
/* This will perform a peephole pass before sched2. */
int flag_peephole2 = 0;
/* Table of supported debugging formats. */
static struct
{
......@@ -966,7 +970,9 @@ lang_independent_options f_options[] =
{"leading-underscore", &flag_leading_underscore, 1,
"External symbols have a leading underscore" },
{"ident", &flag_no_ident, 0,
"Process #ident directives"}
"Process #ident directives"},
{ "peephole2", &flag_peephole2, 1,
"Enables an rtl peephole pass run before sched2" }
};
#define NUM_ELEM(a) (sizeof (a) / sizeof ((a)[0]))
......@@ -3004,6 +3010,12 @@ compile_file (name)
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".flow2");
}
if (peephole2_dump)
{
clean_dump_file (".peephole2");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".peephole2");
}
if (sched2_dump)
{
clean_dump_file (".sched2");
......@@ -4226,6 +4238,23 @@ rest_of_compilation (decl)
print_rtl_graph_with_bb (dump_base_name, ".flow2", insns);
}
#ifdef HAVE_peephole2
if (optimize > 0 && flag_peephole2)
{
if (peephole2_dump)
open_dump_file (".peephole2", decl_printable_name (decl, 2));
peephole2_optimize (rtl_dump_file);
if (peephole2_dump)
{
close_dump_file (print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".peephole2", insns);
}
}
#endif
if (optimize > 0 && flag_schedule_insns_after_reload)
{
if (sched2_dump)
......@@ -4822,6 +4851,7 @@ main (argc, argv)
flag_rerun_loop_opt = 1;
flag_caller_saves = 1;
flag_force_mem = 1;
flag_peephole2 = 1;
#ifdef INSN_SCHEDULING
flag_schedule_insns = 1;
flag_schedule_insns_after_reload = 1;
......@@ -4917,6 +4947,7 @@ main (argc, argv)
#ifdef MACHINE_DEPENDENT_REORG
mach_dep_reorg_dump = 1;
#endif
peephole2_dump = 1;
break;
case 'A':
flag_debug_asm = 1;
......@@ -4996,11 +5027,14 @@ main (argc, argv)
case 'w':
flow2_dump = 1;
break;
case 'x':
rtl_dump_and_exit = 1;
break;
case 'y':
set_yydebug (1);
break;
case 'x':
rtl_dump_and_exit = 1;
case 'z':
peephole2_dump = 1;
break;
case 'D': /* these are handled by the preprocessor */
case 'I':
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment