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
......
......@@ -473,6 +473,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. */
......
......@@ -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,8 +315,16 @@ 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)
gen_peephole (desc);
{
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. */
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;
......
......@@ -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);
......
......@@ -111,10 +111,13 @@ struct decision
static int next_subroutine_number;
/* We can write two types of subroutines: One for insn recognition and
one to split insns. This defines which type is being written. */
/* We can write three types of subroutines: One for insn recognition,
one to split insns, and one for peephole-type optimizations. This
defines which type is being written. */
enum routine_type {RECOG, SPLIT};
enum routine_type {RECOG, SPLIT, PEEPHOLE2};
#define IS_SPLIT(X) ((X) == SPLIT || (X)==PEEPHOLE2)
/* Next available node number for tree nodes. */
......@@ -173,7 +176,8 @@ static struct pred_table
static struct decision_head make_insn_sequence PROTO((rtx, enum routine_type));
static struct decision *add_to_sequence PROTO((rtx, struct decision_head *,
const char *));
const char *,
enum routine_type, int));
static int not_both_true PROTO((struct decision *, struct decision *,
int));
static int position_merit PROTO((struct decision *, enum machine_mode,
......@@ -193,8 +197,9 @@ static void clear_modes PROTO((struct decision *));
static void write_tree PROTO((struct decision *, const char *,
struct decision *, int,
enum routine_type));
static void change_state PROTO((const char *, const char *, int));
static void change_state PROTO((const char *, const char *, int,
struct decision *));
/* Construct and return a sequence of decisions
that will recognize INSN.
......@@ -219,9 +224,8 @@ make_insn_sequence (insn, type)
{
int new_size;
new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
insn_name_ptr =
(char **) xrealloc (insn_name_ptr, sizeof(char *) * new_size);
bzero ((PTR)(insn_name_ptr + insn_name_ptr_size),
insn_name_ptr = xrealloc (insn_name_ptr, sizeof(char *) * new_size);
bzero (insn_name_ptr + insn_name_ptr_size,
sizeof(char *) * (new_size - insn_name_ptr_size));
insn_name_ptr_size = new_size;
}
......@@ -243,7 +247,29 @@ make_insn_sequence (insn, type)
insn_name_ptr[next_insn_code] = name;
}
if (XVECLEN (insn, type == RECOG) == 1)
if (type == PEEPHOLE2)
{
int i, j;
/* peephole2 gets special treatment:
- X always gets an outer parallel even if it's only one entry
- we remove all traces of outer-level match_scratch and match_dup
expressions here. */
x = rtx_alloc (PARALLEL);
PUT_MODE (x, VOIDmode);
XVEC (x, 0) = rtvec_alloc (XVECLEN (insn, 0));
for (i = j = 0; i < XVECLEN (insn, 0); i++)
{
rtx tmp = XVECEXP (insn, 0, i);
if (GET_CODE (tmp) != MATCH_SCRATCH && GET_CODE (tmp) != MATCH_DUP)
{
XVECEXP (x, 0, j) = tmp;
j++;
}
}
XVECLEN (x, 0) = j;
}
else if (XVECLEN (insn, type == RECOG) == 1)
x = XVECEXP (insn, type == RECOG, 0);
else
{
......@@ -252,7 +278,7 @@ make_insn_sequence (insn, type)
PUT_MODE (x, VOIDmode);
}
last = add_to_sequence (x, &head, "");
last = add_to_sequence (x, &head, "", type, 1);
if (c_test[0])
last->c_test = c_test;
......@@ -290,7 +316,7 @@ make_insn_sequence (insn, type)
XVECEXP (new, 0, j) = XVECEXP (x, 0, j);
}
last = add_to_sequence (new, &clobber_head, "");
last = add_to_sequence (new, &clobber_head, "", type, 1);
if (c_test[0])
last->c_test = c_test;
......@@ -305,7 +331,13 @@ make_insn_sequence (insn, type)
if (type == SPLIT)
/* Define the subroutine we will call below and emit in genemit. */
printf ("extern rtx gen_split_%d PROTO ((rtx *));\n", last->insn_code_number);
printf ("extern rtx gen_split_%d PROTO ((rtx *));\n",
last->insn_code_number);
else if (type == PEEPHOLE2)
/* Define the subroutine we will call below and emit in genemit. */
printf ("extern rtx gen_peephole2_%d PROTO ((rtx, rtx *));\n",
last->insn_code_number);
return head;
}
......@@ -318,13 +350,17 @@ make_insn_sequence (insn, type)
POSITION is the string representing the current position in the insn.
INSN_TYPE is the type of insn for which we are emitting code.
A pointer to the final node in the chain is returned. */
static struct decision *
add_to_sequence (pattern, last, position)
add_to_sequence (pattern, last, position, insn_type, top)
rtx pattern;
struct decision_head *last;
const char *position;
enum routine_type insn_type;
int top;
{
register RTX_CODE code;
register struct decision *new
......@@ -381,6 +417,27 @@ add_to_sequence (pattern, last, position)
switch (code)
{
case PARALLEL:
/* Toplevel peephole pattern. */
if (insn_type == PEEPHOLE2 && top)
{
struct decision_head *place = last;
for (i = 0; i < (size_t) XVECLEN (pattern, 0); i++)
{
/* Which insn we're looking at is represented by A-Z. We don't
ever use 'A', however; it is always implied. */
if (i > 0)
newpos[depth] = 'A' + i;
else
newpos[depth] = 0;
new = add_to_sequence (XVECEXP (pattern, 0, i),
place, newpos, insn_type, 0);
place = &new->success;
}
return new;
}
break;
case MATCH_OPERAND:
case MATCH_SCRATCH:
case MATCH_OPERATOR:
......@@ -452,7 +509,7 @@ add_to_sequence (pattern, last, position)
{
newpos[depth] = i + (code == MATCH_OPERATOR ? '0': 'a');
new = add_to_sequence (XVECEXP (pattern, 2, i),
&new->success, newpos);
&new->success, newpos, insn_type, 0);
}
}
......@@ -467,7 +524,7 @@ add_to_sequence (pattern, last, position)
{
newpos[depth] = i + '0';
new = add_to_sequence (XVECEXP (pattern, 1, i),
&new->success, newpos);
&new->success, newpos, insn_type, 0);
}
return new;
......@@ -497,10 +554,12 @@ add_to_sequence (pattern, last, position)
fatal ("mode mismatch in SET");
}
newpos[depth] = '0';
new = add_to_sequence (SET_DEST (pattern), &new->success, newpos);
new = add_to_sequence (SET_DEST (pattern), &new->success, newpos,
insn_type, 0);
this->success.first->enforce_mode = 1;
newpos[depth] = '1';
new = add_to_sequence (SET_SRC (pattern), &new->success, newpos);
new = add_to_sequence (SET_SRC (pattern), &new->success, newpos,
insn_type, 0);
/* If set are setting CC0 from anything other than a COMPARE, we
must enforce the mode so that we do not produce ambiguous insns. */
......@@ -513,7 +572,8 @@ add_to_sequence (pattern, last, position)
case ZERO_EXTEND:
case STRICT_LOW_PART:
newpos[depth] = '0';
new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos);
new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos,
insn_type, 0);
this->success.first->enforce_mode = 1;
return new;
......@@ -521,19 +581,23 @@ add_to_sequence (pattern, last, position)
this->test_elt_one_int = 1;
this->elt_one_int = XINT (pattern, 1);
newpos[depth] = '0';
new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos);
new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos,
insn_type, 0);
this->success.first->enforce_mode = 1;
return new;
case ZERO_EXTRACT:
case SIGN_EXTRACT:
newpos[depth] = '0';
new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos);
new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos,
insn_type, 0);
this->success.first->enforce_mode = 1;
newpos[depth] = '1';
new = add_to_sequence (XEXP (pattern, 1), &new->success, newpos);
new = add_to_sequence (XEXP (pattern, 1), &new->success, newpos,
insn_type, 0);
newpos[depth] = '2';
new = add_to_sequence (XEXP (pattern, 2), &new->success, newpos);
new = add_to_sequence (XEXP (pattern, 2), &new->success, newpos,
insn_type, 0);
return new;
case EQ: case NE: case LE: case LT: case GE: case GT:
......@@ -548,10 +612,12 @@ add_to_sequence (pattern, last, position)
case COMPARE:
/* Enforce the mode on the first operand to avoid ambiguous insns. */
newpos[depth] = '0';
new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos);
new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos,
insn_type, 0);
this->success.first->enforce_mode = 1;
newpos[depth] = '1';
new = add_to_sequence (XEXP (pattern, 1), &new->success, newpos);
new = add_to_sequence (XEXP (pattern, 1), &new->success, newpos,
insn_type, 0);
return new;
default:
......@@ -564,7 +630,8 @@ add_to_sequence (pattern, last, position)
{
newpos[depth] = '0' + i;
if (fmt[i] == 'e' || fmt[i] == 'u')
new = add_to_sequence (XEXP (pattern, i), &new->success, newpos);
new = add_to_sequence (XEXP (pattern, i), &new->success, newpos,
insn_type, 0);
else if (fmt[i] == 'i' && i == 0)
{
this->test_elt_zero_int = 1;
......@@ -596,7 +663,7 @@ add_to_sequence (pattern, last, position)
{
newpos[depth] = 'a' + j;
new = add_to_sequence (XVECEXP (pattern, i, j),
&new->success, newpos);
&new->success, newpos, insn_type, 0);
}
}
else if (fmt[i] != '0')
......@@ -1030,7 +1097,9 @@ write_subroutine (tree, type)
{
int i;
if (type == SPLIT)
if (type == PEEPHOLE2)
printf ("extern rtx peephole2");
else if (type == SPLIT)
printf ("extern rtx split");
else
printf ("extern int recog");
......@@ -1041,26 +1110,36 @@ write_subroutine (tree, type)
printf (" PROTO ((rtx, rtx");
if (type == RECOG)
printf (", int *");
else if (type == PEEPHOLE2)
printf (", rtx *");
printf ("));\n");
if (type == SPLIT)
if (type == PEEPHOLE2)
printf ("rtx\npeephole2");
else if (type == SPLIT)
printf ("rtx\nsplit");
else
printf ("int\nrecog");
if (tree != 0 && tree->subroutine_number > 0)
printf ("_%d", tree->subroutine_number);
else if (type == SPLIT)
else if (IS_SPLIT (type))
printf ("_insns");
printf (" (x0, insn");
if (type == RECOG)
printf (", pnum_clobbers");
else if (type == PEEPHOLE2)
printf (", _plast_insn");
printf (")\n");
/* The peephole2 pass uses the insn argument to determine which
hard registers are available at that point. */
printf (" register rtx x0;\n rtx insn ATTRIBUTE_UNUSED;\n");
if (type == RECOG)
printf (" int *pnum_clobbers ATTRIBUTE_UNUSED;\n");
else if (type == PEEPHOLE2)
printf (" rtx *_plast_insn ATTRIBUTE_UNUSED;\n");
printf ("{\n");
printf (" register rtx *ro = &recog_operand[0];\n");
......@@ -1070,9 +1149,13 @@ write_subroutine (tree, type)
printf ("x%d ATTRIBUTE_UNUSED, ", i);
printf ("x%d ATTRIBUTE_UNUSED;\n", max_depth);
printf (" %s tem ATTRIBUTE_UNUSED;\n", type == SPLIT ? "rtx" : "int");
if (type == PEEPHOLE2)
printf (" register rtx _last_insn = insn;\n");
printf (" %s tem ATTRIBUTE_UNUSED;\n", IS_SPLIT (type) ? "rtx" : "int");
write_tree (tree, "", NULL_PTR, 1, type);
printf (" ret0: return %d;\n}\n\n", type == SPLIT ? 0 : -1);
if (type == PEEPHOLE2)
printf (" ret1:\n *_plast_insn = _last_insn;\n return tem;\n");
printf (" ret0:\n return %d;\n}\n\n", IS_SPLIT (type) ? 0 : -1);
}
/* This table is used to indent the recog_* functions when we are inside
......@@ -1157,7 +1240,7 @@ write_tree_1 (tree, prevpos, afterward, type)
if (tree)
{
change_state (prevpos, tree->position, 2);
change_state (prevpos, tree->position, 2, afterward);
prevpos = tree->position;
}
......@@ -1308,7 +1391,8 @@ write_tree_1 (tree, prevpos, afterward, type)
if (afterward)
{
printf (" {\n");
change_state (p->position, afterward->position, 6);
change_state (p->position, afterward->position, 6,
afterward);
printf (" goto L%d;\n }\n", afterward->number);
}
else
......@@ -1328,7 +1412,8 @@ write_tree_1 (tree, prevpos, afterward, type)
if (afterward)
{
printf (" {\n");
change_state (p->position, afterward->position, indent + 4);
change_state (p->position, afterward->position, indent + 4,
afterward);
printf (" goto L%d;\n }\n", afterward->number);
}
else
......@@ -1466,9 +1551,22 @@ write_tree_1 (tree, prevpos, afterward, type)
if (p->insn_code_number >= 0)
{
if (type == SPLIT)
printf ("%sreturn gen_split_%d (operands);\n",
indents[inner_indent], p->insn_code_number);
else
{
printf ("%sreturn gen_split_%d (operands);\n",
indents[inner_indent], p->insn_code_number);
}
else if (type == PEEPHOLE2)
{
printf ("%s{\n", indents[inner_indent]);
inner_indent += 2;
printf ("%stem = gen_peephole2_%d (insn, operands);\n",
indents[inner_indent], p->insn_code_number);
printf ("%sif (tem != 0) goto ret1;\n", indents[inner_indent]);
inner_indent -= 2;
printf ("%s}\n", indents[inner_indent]);
}
else
{
if (p->num_clobbers_to_add)
{
......@@ -1528,7 +1626,7 @@ write_tree_1 (tree, prevpos, afterward, type)
if (afterward)
{
change_state (prevpos, afterward->position, 2);
change_state (prevpos, afterward->position, 2, afterward);
printf (" goto L%d;\n", afterward->number);
}
else
......@@ -1606,9 +1704,24 @@ write_tree (tree, prevpos, afterward, initial, type)
enum routine_type type;
{
register struct decision *p;
const char *name_prefix = (type == SPLIT ? "split" : "recog");
const char *call_suffix = (type == SPLIT ? "" : ", pnum_clobbers");
const char *name_prefix;
const char *call_suffix;
switch (type)
{
case SPLIT:
name_prefix = "split";
call_suffix = "";
break;
case PEEPHOLE2:
name_prefix = "peephole2";
call_suffix = ", _plast_insn";
break;
case RECOG:
name_prefix = "recog";
call_suffix = ", pnum_clobbers";
break;
}
if (! initial && tree->subroutine_number > 0)
{
OUTPUT_LABEL (" ", tree->number);
......@@ -1617,11 +1730,11 @@ write_tree (tree, prevpos, afterward, initial, type)
{
printf (" tem = %s_%d (x0, insn%s);\n",
name_prefix, tree->subroutine_number, call_suffix);
if (type == SPLIT)
if (IS_SPLIT (type))
printf (" if (tem != 0) return tem;\n");
else
printf (" if (tem >= 0) return tem;\n");
change_state (tree->position, afterward->position, 2);
change_state (tree->position, afterward->position, 2, afterward);
printf (" goto L%d;\n", afterward->number);
}
else
......@@ -1640,30 +1753,76 @@ write_tree (tree, prevpos, afterward, initial, type)
/* Assuming that the state of argument is denoted by OLDPOS, take whatever
actions are necessary to move to NEWPOS.
actions are necessary to move to NEWPOS. If we fail to move to the
new state, branch to node AFTERWARD if non-zero, otherwise return.
INDENT says how many blanks to place at the front of lines.
INDENT says how many blanks to place at the front of lines. */
Failure to move to the new state can only occur if we are trying to
match multiple insns and we try to step past the end of the
stream. */
static void
change_state (oldpos, newpos, indent)
change_state (oldpos, newpos, indent, afterward)
const char *oldpos;
const char *newpos;
int indent;
struct decision *afterward;
{
int odepth = strlen (oldpos);
int depth = odepth;
int ndepth = strlen (newpos);
int basedepth;
int old_has_insn, new_has_insn;
/* Pop up as many levels as necessary. */
while (strncmp (oldpos, newpos, depth))
--depth;
basedepth = depth;
/* Make sure to reset the _last_insn pointer when popping back up. */
for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
if (oldpos[old_has_insn] >= 'A' && oldpos[old_has_insn] <= 'Z')
break;
for (new_has_insn = odepth - 1; new_has_insn >= 0; --new_has_insn)
if (newpos[new_has_insn] >= 'A' && newpos[new_has_insn] <= 'Z')
break;
if (old_has_insn >= 0 && new_has_insn < 0)
printf ("%s_last_insn = insn;\n", indents[indent]);
/* Go down to desired level. */
while (depth < ndepth)
{
if (newpos[depth] >= 'a' && newpos[depth] <= 'z')
/* It's a different insn from the first one. */
if (newpos[depth] >= 'A' && newpos[depth] <= 'Z')
{
/* We can only fail if we're moving down the tree. */
if (old_has_insn >= 0 && oldpos[old_has_insn] >= newpos[depth])
{
printf ("%s_last_insn = recog_next_insn (insn, %d);\n",
indents[indent], newpos[depth] - 'A');
}
else
{
printf ("%stem = recog_next_insn (insn, %d);\n",
indents[indent], newpos[depth] - 'A');
printf ("%sif (tem == NULL_RTX)\n", indents[indent]);
if (afterward)
printf ("%sgoto L%d;\n", indents[indent + 2],
afterward->number);
else
printf ("%sgoto ret0;\n", indents[indent + 2]);
printf ("%s_last_insn = tem;\n", indents[indent]);
}
printf ("%sx%d = PATTERN (_last_insn);\n",
indents[indent], depth + 1);
}
else if (newpos[depth] >= 'a' && newpos[depth] <= 'z')
printf ("%sx%d = XVECEXP (x%d, 0, %d);\n",
indents[indent], depth + 1, depth, newpos[depth] - 'a');
else
......@@ -1717,12 +1876,14 @@ main (argc, argv)
rtx desc;
struct decision_head recog_tree;
struct decision_head split_tree;
struct decision_head peephole2_tree;
FILE *infile;
register int c;
progname = "genrecog";
obstack_init (rtl_obstack);
recog_tree.first = recog_tree.last = split_tree.first = split_tree.last = 0;
peephole2_tree.first = peephole2_tree.last = 0;
if (argc <= 1)
fatal ("No input file name.");
......@@ -1767,6 +1928,10 @@ from the machine description file `md'. */\n\n");
else if (GET_CODE (desc) == DEFINE_SPLIT)
split_tree = merge_trees (split_tree,
make_insn_sequence (desc, SPLIT));
else if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
peephole2_tree = merge_trees (peephole2_tree,
make_insn_sequence (desc, PEEPHOLE2));
if (GET_CODE (desc) == DEFINE_PEEPHOLE
|| GET_CODE (desc) == DEFINE_EXPAND)
next_insn_code++;
......@@ -1797,6 +1962,11 @@ from the machine description file `md'. */\n\n");
printf ("\n\n The function split_insns returns 0 if the rtl could not\n\
be split or the split rtl in a SEQUENCE if it can be.");
if (peephole2_tree.first)
printf ("\n\n The function peephole2_insns returns 0 if the rtl could not\n\
be matched. If there was a match, the new rtl is returned in a SEQUENCE,\n\
and LAST_INSN will point to the last recognized insn in the old sequence.");
printf ("*/\n\n");
printf ("#define operands recog_operand\n\n");
......@@ -1809,6 +1979,10 @@ from the machine description file `md'. */\n\n");
break_out_subroutines (split_tree, SPLIT, 1);
write_subroutine (split_tree.first, SPLIT);
next_subroutine_number = 0;
break_out_subroutines (peephole2_tree, PEEPHOLE2, 1);
write_subroutine (peephole2_tree.first, PEEPHOLE2);
fflush (stdout);
exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
/* NOTREACHED */
......
......@@ -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