home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 7
/
FreshFishVol7.bin
/
bbs
/
gnu
/
gcc-2.3.3-src.lha
/
GNU
/
src
/
amiga
/
gcc-2.3.3
/
genpeep.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-06
|
12KB
|
509 lines
/* Generate code from machine description to perform peephole optimizations.
Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "hconfig.h"
#include "rtl.h"
#include "obstack.h"
static struct obstack obstack;
struct obstack *rtl_obstack = &obstack;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
extern void free ();
extern rtx read_rtx ();
/* While tree-walking an instruction pattern, we keep a chain
of these `struct link's to record how to get down to the
current position. In each one, POS is the operand number,
and if the operand is a vector VEC is the element number.
VEC is -1 if the operand is not a vector. */
struct link
{
struct link *next;
int pos;
int vecelt;
};
char *xmalloc ();
static void match_rtx ();
static void gen_exp ();
static void fatal ();
void fancy_abort ();
static int max_opno;
/* Number of operands used in current peephole definition. */
static int n_operands;
/* Peephole optimizations get insn codes just like insn patterns.
Count them so we know the code of the define_peephole we are handling. */
static int insn_code_number = 0;
static void print_path ();
static void print_code ();
static void
gen_peephole (peep)
rtx peep;
{
int ninsns = XVECLEN (peep, 0);
int i;
n_operands = 0;
printf (" insn = ins1;\n");
#if 0
printf (" want_jump = 0;\n");
#endif
for (i = 0; i < ninsns; i++)
{
if (i > 0)
{
printf (" do { insn = NEXT_INSN (insn);\n");
printf (" if (insn == 0) goto L%d; }\n",
insn_code_number);
printf (" while (GET_CODE (insn) == NOTE\n");
printf ("\t || (GET_CODE (insn) == INSN\n");
printf ("\t && (GET_CODE (PATTERN (insn)) == USE\n");
printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n");
printf (" if (GET_CODE (insn) == CODE_LABEL\n\
|| GET_CODE (insn) == BARRIER)\n goto L%d;\n",
insn_code_number);
}
#if 0
printf (" if (GET_CODE (insn) == JUMP_INSN)\n");
printf (" want_jump = JUMP_LABEL (insn);\n");
#endif
printf (" pat = PATTERN (insn);\n");
/* Walk the insn's pattern, remembering at all times the path
down to the walking point. */
match_rtx (XVECEXP (peep, 0, i), NULL_PTR, insn_code_number);
}
/* We get this far if the pattern matches.
Now test the extra condition. */
if (XSTR (peep, 1) && XSTR (peep, 1)[0])
printf (" if (! (%s)) goto L%d;\n",
XSTR (peep, 1), insn_code_number);
/* If that matches, construct new pattern and put it in the first insn.
This new pattern will never be matched.
It exists only so that insn-extract can get the operands back.
So use a simple regular form: a PARALLEL containing a vector
of all the operands. */
printf (" PATTERN (ins1) = gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands);
#if 0
printf (" if (want_jump && GET_CODE (ins1) != JUMP_INSN)\n");
printf (" {\n");
printf (" rtx insn2 = emit_jump_insn_before (PATTERN (ins1), ins1);\n");
printf (" delete_insn (ins1);\n");
printf (" ins1 = ins2;\n");
printf (" }\n");
#endif
/* Record this define_peephole's insn code in the insn,
as if it had been recognized to match this. */
printf (" INSN_CODE (ins1) = %d;\n",
insn_code_number);
/* Delete the remaining insns. */
if (ninsns > 1)
printf (" delete_for_peephole (NEXT_INSN (ins1), insn);\n");
/* See reload1.c for insertion of NOTE which guarantees that this
cannot be zero. */
printf (" return NEXT_INSN (insn);\n");
printf (" L%d:\n\n", insn_code_number);
}
static void
match_rtx (x, path, fail_label)
rtx x;
struct link *path;
int fail_label;
{
register RTX_CODE code;
register int i;
register int len;
register char *fmt;
struct link link;
if (x == 0)
return;
code = GET_CODE (x);
switch (code)
{
case MATCH_OPERAND:
if (XINT (x, 0) > max_opno)
max_opno = XINT (x, 0);
if (XINT (x, 0) >= n_operands)
n_operands = 1 + XINT (x, 0);
printf (" x = ");
print_path (path);
printf (";\n");
printf (" operands[%d] = x;\n", XINT (x, 0));
if (XSTR (x, 1) && XSTR (x, 1)[0])
printf (" if (! %s (x, %smode)) goto L%d;\n",
XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
return;
case MATCH_DUP:
case MATCH_PAR_DUP:
printf (" x = ");
print_path (path);
printf (";\n");
printf (" if (!rtx_equal_p (operands[%d], x)) goto L%d;\n",
XINT (x, 0), fail_label);
return;
case MATCH_OP_DUP:
printf (" x = ");
print_path (path);
printf (";\n");
printf (" if (GET_CODE (operands[%d]) != GET_CODE (x)\n", XINT (x, 0));
printf (" || GET_MODE (operands[%d]) != GET_MODE (x)) goto L%d;\n",
XINT (x, 0), fail_label);
printf (" operands[%d] = x;\n", XINT (x, 0));
link.next = path;
link.vecelt = -1;
for (i = 0; i < XVECLEN (x, 1); i++)
{
link.pos = i;
match_rtx (XVECEXP (x, 1, i), &link, fail_label);
}
return;
case MATCH_OPERATOR:
if (XINT (x, 0) > max_opno)
max_opno = XINT (x, 0);
if (XINT (x, 0) >= n_operands)
n_operands = 1 + XINT (x, 0);
printf (" x = ");
print_path (path);
printf (";\n");
printf (" operands[%d] = x;\n", XINT (x, 0));
if (XSTR (x, 1) && XSTR (x, 1)[0])
printf (" if (! %s (x, %smode)) goto L%d;\n",
XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
link.next = path;
link.vecelt = -1;
for (i = 0; i < XVECLEN (x, 2); i++)
{
link.pos = i;
match_rtx (XVECEXP (x, 2, i), &link, fail_label);
}
return;
case MATCH_PARALLEL:
if (XINT (x, 0) > max_opno)
max_opno = XINT (x, 0);
if (XINT (x, 0) >= n_operands)
n_operands = 1 + XINT (x, 0);
printf (" x = ");
print_path (path);
printf (";\n");
printf (" if (GET_CODE (x) != PARALLEL) goto L%d;\n", fail_label);
printf (" operands[%d] = x;\n", XINT (x, 0));
if (XSTR (x, 1) && XSTR (x, 1)[0])
printf (" if (! %s (x, %smode)) goto L%d;\n",
XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
link.next = path;
link.pos = 0;
for (i = 0; i < XVECLEN (x, 2); i++)
{
link.vecelt = i;
match_rtx (XVECEXP (x, 2, i), &link, fail_label);
}
return;
case ADDRESS:
match_rtx (XEXP (x, 0), path, fail_label);
return;
}
printf (" x = ");
print_path (path);
printf (";\n");
printf (" if (GET_CODE (x) != ");
print_code (code);
printf (") goto L%d;\n", fail_label);
if (GET_MODE (x) != VOIDmode)
{
printf (" if (GET_MODE (x) != %smode) goto L%d;\n",
GET_MODE_NAME (GET_MODE (x)), fail_label);
}
link.next = path;
link.vecelt = -1;
fmt = GET_RTX_FORMAT (code);
len = GET_RTX_LENGTH (code);
for (i = 0; i < len; i++)
{
link.pos = i;
if (fmt[i] == 'e' || fmt[i] == 'u')
match_rtx (XEXP (x, i), &link, fail_label);
else if (fmt[i] == 'E')
{
int j;
printf (" if (XVECLEN (x, %d) != %d) goto L%d;\n",
i, XVECLEN (x, i), fail_label);
for (j = 0; j < XVECLEN (x, i); j++)
{
link.vecelt = j;
match_rtx (XVECEXP (x, i, j), &link, fail_label);
}
}
else if (fmt[i] == 'i')
{
/* Make sure that at run time `x' is the RTX we want to test. */
if (i != 0)
{
printf (" x = ");
print_pat