118334Speter/* Generate code from machine description to perform peephole optimizations. 290075Sobrien Copyright (C) 1987, 1989, 1992, 1997, 1998, 3169689Skan 1999, 2000, 2003, 2004 Free Software Foundation, Inc. 418334Speter 590075SobrienThis file is part of GCC. 618334Speter 790075SobrienGCC is free software; you can redistribute it and/or modify it under 890075Sobrienthe terms of the GNU General Public License as published by the Free 990075SobrienSoftware Foundation; either version 2, or (at your option) any later 1090075Sobrienversion. 1118334Speter 1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1490075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1590075Sobrienfor more details. 1618334Speter 1718334SpeterYou should have received a copy of the GNU General Public License 1890075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20169689Skan02110-1301, USA. */ 2118334Speter 2218334Speter 23132718Skan#include "bconfig.h" 2450397Sobrien#include "system.h" 25132718Skan#include "coretypes.h" 26132718Skan#include "tm.h" 2718334Speter#include "rtl.h" 2890075Sobrien#include "errors.h" 2990075Sobrien#include "gensupport.h" 3018334Speter 3118334Speter 3218334Speter/* While tree-walking an instruction pattern, we keep a chain 3318334Speter of these `struct link's to record how to get down to the 3418334Speter current position. In each one, POS is the operand number, 3518334Speter and if the operand is a vector VEC is the element number. 3618334Speter VEC is -1 if the operand is not a vector. */ 3718334Speter 3818334Speterstruct link 3918334Speter{ 4018334Speter struct link *next; 4118334Speter int pos; 4218334Speter int vecelt; 4318334Speter}; 4418334Speter 4518334Speterstatic int max_opno; 4618334Speter 4718334Speter/* Number of operands used in current peephole definition. */ 4818334Speter 4918334Speterstatic int n_operands; 5018334Speter 5118334Speter/* Peephole optimizations get insn codes just like insn patterns. 5218334Speter Count them so we know the code of the define_peephole we are handling. */ 5318334Speter 5418334Speterstatic int insn_code_number = 0; 5518334Speter 56132718Skanstatic void gen_peephole (rtx); 57132718Skanstatic void match_rtx (rtx, struct link *, int); 58132718Skanstatic void print_path (struct link *); 59132718Skanstatic void print_code (RTX_CODE); 6018334Speter 6118334Speterstatic void 62132718Skangen_peephole (rtx peep) 6318334Speter{ 6418334Speter int ninsns = XVECLEN (peep, 0); 6518334Speter int i; 6618334Speter 6718334Speter n_operands = 0; 6818334Speter 6918334Speter printf (" insn = ins1;\n"); 7018334Speter 7118334Speter for (i = 0; i < ninsns; i++) 7218334Speter { 7318334Speter if (i > 0) 7418334Speter { 7518334Speter printf (" do { insn = NEXT_INSN (insn);\n"); 7618334Speter printf (" if (insn == 0) goto L%d; }\n", 7718334Speter insn_code_number); 78169689Skan printf (" while (NOTE_P (insn)\n"); 79169689Skan printf ("\t || (NONJUMP_INSN_P (insn)\n"); 8018334Speter printf ("\t && (GET_CODE (PATTERN (insn)) == USE\n"); 8118334Speter printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n"); 8218334Speter 83169689Skan printf (" if (LABEL_P (insn)\n\ 84169689Skan || BARRIER_P (insn))\n goto L%d;\n", 85132718Skan insn_code_number); 8618334Speter } 8718334Speter 8818334Speter printf (" pat = PATTERN (insn);\n"); 8918334Speter 9018334Speter /* Walk the insn's pattern, remembering at all times the path 9118334Speter down to the walking point. */ 9218334Speter 9390075Sobrien match_rtx (XVECEXP (peep, 0, i), NULL, insn_code_number); 9418334Speter } 9518334Speter 9618334Speter /* We get this far if the pattern matches. 9718334Speter Now test the extra condition. */ 9818334Speter 9918334Speter if (XSTR (peep, 1) && XSTR (peep, 1)[0]) 10018334Speter printf (" if (! (%s)) goto L%d;\n", 10118334Speter XSTR (peep, 1), insn_code_number); 10218334Speter 10318334Speter /* If that matches, construct new pattern and put it in the first insn. 10418334Speter This new pattern will never be matched. 10518334Speter It exists only so that insn-extract can get the operands back. 10618334Speter So use a simple regular form: a PARALLEL containing a vector 10718334Speter of all the operands. */ 10818334Speter 10950397Sobrien printf (" PATTERN (ins1) = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands); 11018334Speter 11118334Speter /* Record this define_peephole's insn code in the insn, 11218334Speter as if it had been recognized to match this. */ 11318334Speter printf (" INSN_CODE (ins1) = %d;\n", 11418334Speter insn_code_number); 11518334Speter 11618334Speter /* Delete the remaining insns. */ 11718334Speter if (ninsns > 1) 11818334Speter printf (" delete_for_peephole (NEXT_INSN (ins1), insn);\n"); 11918334Speter 12018334Speter /* See reload1.c for insertion of NOTE which guarantees that this 12118334Speter cannot be zero. */ 12218334Speter printf (" return NEXT_INSN (insn);\n"); 12318334Speter 12418334Speter printf (" L%d:\n\n", insn_code_number); 12518334Speter} 12618334Speter 12718334Speterstatic void 128132718Skanmatch_rtx (rtx x, struct link *path, int fail_label) 12918334Speter{ 13090075Sobrien RTX_CODE code; 13190075Sobrien int i; 13290075Sobrien int len; 13390075Sobrien const char *fmt; 13418334Speter struct link link; 13518334Speter 13618334Speter if (x == 0) 13718334Speter return; 13818334Speter 13918334Speter 14018334Speter code = GET_CODE (x); 14118334Speter 14218334Speter switch (code) 14318334Speter { 14418334Speter case MATCH_OPERAND: 14518334Speter if (XINT (x, 0) > max_opno) 14618334Speter max_opno = XINT (x, 0); 14718334Speter if (XINT (x, 0) >= n_operands) 14818334Speter n_operands = 1 + XINT (x, 0); 14918334Speter 15018334Speter printf (" x = "); 15118334Speter print_path (path); 15218334Speter printf (";\n"); 15318334Speter 15418334Speter printf (" operands[%d] = x;\n", XINT (x, 0)); 15518334Speter if (XSTR (x, 1) && XSTR (x, 1)[0]) 15618334Speter printf (" if (! %s (x, %smode)) goto L%d;\n", 15718334Speter XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label); 15818334Speter return; 15918334Speter 16018334Speter case MATCH_DUP: 16118334Speter case MATCH_PAR_DUP: 16218334Speter printf (" x = "); 16318334Speter print_path (path); 16418334Speter printf (";\n"); 16518334Speter 16618334Speter printf (" if (!rtx_equal_p (operands[%d], x)) goto L%d;\n", 16718334Speter XINT (x, 0), fail_label); 16818334Speter return; 16918334Speter 17018334Speter case MATCH_OP_DUP: 17118334Speter printf (" x = "); 17218334Speter print_path (path); 17318334Speter printf (";\n"); 17418334Speter 17518334Speter printf (" if (GET_CODE (operands[%d]) != GET_CODE (x)\n", XINT (x, 0)); 17618334Speter printf (" || GET_MODE (operands[%d]) != GET_MODE (x)) goto L%d;\n", 17718334Speter XINT (x, 0), fail_label); 17818334Speter printf (" operands[%d] = x;\n", XINT (x, 0)); 17918334Speter link.next = path; 18018334Speter link.vecelt = -1; 18118334Speter for (i = 0; i < XVECLEN (x, 1); i++) 18218334Speter { 18318334Speter link.pos = i; 18418334Speter match_rtx (XVECEXP (x, 1, i), &link, fail_label); 18518334Speter } 18618334Speter return; 18718334Speter 18818334Speter case MATCH_OPERATOR: 18918334Speter if (XINT (x, 0) > max_opno) 19018334Speter max_opno = XINT (x, 0); 19118334Speter if (XINT (x, 0) >= n_operands) 19218334Speter n_operands = 1 + XINT (x, 0); 19318334Speter 19418334Speter printf (" x = "); 19518334Speter print_path (path); 19618334Speter printf (";\n"); 19718334Speter 19818334Speter printf (" operands[%d] = x;\n", XINT (x, 0)); 19918334Speter if (XSTR (x, 1) && XSTR (x, 1)[0]) 20018334Speter printf (" if (! %s (x, %smode)) goto L%d;\n", 20118334Speter XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label); 20218334Speter link.next = path; 20318334Speter link.vecelt = -1; 20418334Speter for (i = 0; i < XVECLEN (x, 2); i++) 20518334Speter { 20618334Speter link.pos = i; 20718334Speter match_rtx (XVECEXP (x, 2, i), &link, fail_label); 20818334Speter } 20918334Speter return; 21018334Speter 21118334Speter case MATCH_PARALLEL: 21218334Speter if (XINT (x, 0) > max_opno) 21318334Speter max_opno = XINT (x, 0); 21418334Speter if (XINT (x, 0) >= n_operands) 21518334Speter n_operands = 1 + XINT (x, 0); 21618334Speter 21718334Speter printf (" x = "); 21818334Speter print_path (path); 21918334Speter printf (";\n"); 22018334Speter 22118334Speter printf (" if (GET_CODE (x) != PARALLEL) goto L%d;\n", fail_label); 22218334Speter printf (" operands[%d] = x;\n", XINT (x, 0)); 22318334Speter if (XSTR (x, 1) && XSTR (x, 1)[0]) 22418334Speter printf (" if (! %s (x, %smode)) goto L%d;\n", 22518334Speter XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label); 22618334Speter link.next = path; 22718334Speter link.pos = 0; 22818334Speter for (i = 0; i < XVECLEN (x, 2); i++) 22918334Speter { 23018334Speter link.vecelt = i; 23118334Speter match_rtx (XVECEXP (x, 2, i), &link, fail_label); 23218334Speter } 23318334Speter return; 23418334Speter 23518334Speter case ADDRESS: 23618334Speter match_rtx (XEXP (x, 0), path, fail_label); 23718334Speter return; 238132718Skan 23950397Sobrien default: 24050397Sobrien break; 24118334Speter } 24218334Speter 24318334Speter printf (" x = "); 24418334Speter print_path (path); 24518334Speter printf (";\n"); 24618334Speter 24718334Speter printf (" if (GET_CODE (x) != "); 24818334Speter print_code (code); 24918334Speter printf (") goto L%d;\n", fail_label); 25018334Speter 25118334Speter if (GET_MODE (x) != VOIDmode) 25218334Speter { 25318334Speter printf (" if (GET_MODE (x) != %smode) goto L%d;\n", 25418334Speter GET_MODE_NAME (GET_MODE (x)), fail_label); 25518334Speter } 25618334Speter 25718334Speter link.next = path; 25818334Speter link.vecelt = -1; 25918334Speter fmt = GET_RTX_FORMAT (code); 26018334Speter len = GET_RTX_LENGTH (code); 26118334Speter for (i = 0; i < len; i++) 26218334Speter { 26318334Speter link.pos = i; 26418334Speter if (fmt[i] == 'e' || fmt[i] == 'u') 26518334Speter match_rtx (XEXP (x, i), &link, fail_label); 26618334Speter else if (fmt[i] == 'E') 26718334Speter { 26818334Speter int j; 26918334Speter printf (" if (XVECLEN (x, %d) != %d) goto L%d;\n", 27018334Speter i, XVECLEN (x, i), fail_label); 27118334Speter for (j = 0; j < XVECLEN (x, i); j++) 27218334Speter { 27318334Speter link.vecelt = j; 27418334Speter match_rtx (XVECEXP (x, i, j), &link, fail_label); 27518334Speter } 27618334Speter } 27718334Speter else if (fmt[i] == 'i') 27818334Speter { 27918334Speter /* Make sure that at run time `x' is the RTX we want to test. */ 28018334Speter if (i != 0) 28118334Speter { 28218334Speter printf (" x = "); 28318334Speter print_path (path); 28418334Speter printf (";\n"); 28518334Speter } 28618334Speter 28718334Speter printf (" if (XINT (x, %d) != %d) goto L%d;\n", 28818334Speter i, XINT (x, i), fail_label); 28918334Speter } 29018334Speter else if (fmt[i] == 'w') 29118334Speter { 29218334Speter /* Make sure that at run time `x' is the RTX we want to test. */ 29318334Speter if (i != 0) 29418334Speter { 29518334Speter printf (" x = "); 29618334Speter print_path (path); 29718334Speter printf (";\n"); 29818334Speter } 29918334Speter 30050397Sobrien printf (" if (XWINT (x, %d) != ", i); 30150397Sobrien printf (HOST_WIDE_INT_PRINT_DEC, XWINT (x, i)); 30250397Sobrien printf (") goto L%d;\n", fail_label); 30318334Speter } 30418334Speter else if (fmt[i] == 's') 30518334Speter { 30618334Speter /* Make sure that at run time `x' is the RTX we want to test. */ 30718334Speter if (i != 0) 30818334Speter { 30918334Speter printf (" x = "); 31018334Speter print_path (path); 31118334Speter printf (";\n"); 31218334Speter } 31318334Speter 31418334Speter printf (" if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n", 31518334Speter i, XSTR (x, i), fail_label); 31618334Speter } 31718334Speter } 31818334Speter} 31918334Speter 32018334Speter/* Given a PATH, representing a path down the instruction's 32118334Speter pattern from the root to a certain point, output code to 32218334Speter evaluate to the rtx at that point. */ 32318334Speter 32418334Speterstatic void 325132718Skanprint_path (struct link *path) 32618334Speter{ 32718334Speter if (path == 0) 32818334Speter printf ("pat"); 32918334Speter else if (path->vecelt >= 0) 33018334Speter { 33118334Speter printf ("XVECEXP ("); 33218334Speter print_path (path->next); 33318334Speter printf (", %d, %d)", path->pos, path->vecelt); 33418334Speter } 33518334Speter else 33618334Speter { 33718334Speter printf ("XEXP ("); 33818334Speter print_path (path->next); 33918334Speter printf (", %d)", path->pos); 34018334Speter } 34118334Speter} 34218334Speter 34318334Speterstatic void 344132718Skanprint_code (RTX_CODE code) 34518334Speter{ 34690075Sobrien const char *p1; 34718334Speter for (p1 = GET_RTX_NAME (code); *p1; p1++) 34890075Sobrien putchar (TOUPPER(*p1)); 34918334Speter} 35018334Speter 351132718Skanextern int main (int, char **); 35218334Speter 35318334Speterint 354132718Skanmain (int argc, char **argv) 35518334Speter{ 35618334Speter rtx desc; 35718334Speter 35818334Speter max_opno = -1; 35918334Speter 36090075Sobrien progname = "genpeep"; 36118334Speter 36290075Sobrien if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 36390075Sobrien return (FATAL_EXIT_CODE); 36418334Speter 36518334Speter printf ("/* Generated automatically by the program `genpeep'\n\ 36618334Speterfrom the machine description file `md'. */\n\n"); 36718334Speter 36818334Speter printf ("#include \"config.h\"\n"); 36950397Sobrien printf ("#include \"system.h\"\n"); 370132718Skan printf ("#include \"coretypes.h\"\n"); 371132718Skan printf ("#include \"tm.h\"\n"); 37252284Sobrien printf ("#include \"insn-config.h\"\n"); 37318334Speter printf ("#include \"rtl.h\"\n"); 37490075Sobrien printf ("#include \"tm_p.h\"\n"); 37518334Speter printf ("#include \"regs.h\"\n"); 37618334Speter printf ("#include \"output.h\"\n"); 37750397Sobrien printf ("#include \"real.h\"\n"); 37852284Sobrien printf ("#include \"recog.h\"\n"); 379169689Skan printf ("#include \"except.h\"\n"); 380169689Skan printf ("#include \"function.h\"\n"); 381169689Skan printf ("#include \"toplev.h\"\n"); 382169689Skan printf ("#include \"flags.h\"\n"); 383169689Skan printf ("#include \"tm-constrs.h\"\n\n"); 38418334Speter 38590075Sobrien printf ("#ifdef HAVE_peephole\n"); 38618334Speter printf ("extern rtx peep_operand[];\n\n"); 38718334Speter printf ("#define operands peep_operand\n\n"); 38818334Speter 389132718Skan printf ("rtx\npeephole (rtx ins1)\n{\n"); 39050397Sobrien printf (" rtx insn ATTRIBUTE_UNUSED, x ATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;\n\n"); 39118334Speter 39218334Speter /* Early out: no peepholes for insns followed by barriers. */ 39318334Speter printf (" if (NEXT_INSN (ins1)\n"); 394169689Skan printf (" && BARRIER_P (NEXT_INSN (ins1)))\n"); 39518334Speter printf (" return 0;\n\n"); 39618334Speter 39718334Speter /* Read the machine description. */ 39818334Speter 39918334Speter while (1) 40018334Speter { 40190075Sobrien int line_no, rtx_number = 0; 40290075Sobrien 40390075Sobrien desc = read_md_rtx (&line_no, &rtx_number); 40490075Sobrien if (desc == NULL) 40518334Speter break; 40618334Speter 40790075Sobrien if (GET_CODE (desc) == DEFINE_PEEPHOLE) 40818334Speter { 40918334Speter gen_peephole (desc); 41018334Speter insn_code_number++; 41118334Speter } 41218334Speter if (GET_CODE (desc) == DEFINE_INSN 41318334Speter || GET_CODE (desc) == DEFINE_EXPAND 41490075Sobrien || GET_CODE (desc) == DEFINE_SPLIT 41590075Sobrien || GET_CODE (desc) == DEFINE_PEEPHOLE2) 41618334Speter { 41718334Speter insn_code_number++; 41818334Speter } 41918334Speter } 42018334Speter 42118334Speter printf (" return 0;\n}\n\n"); 42218334Speter 42318334Speter if (max_opno == -1) 42418334Speter max_opno = 1; 42518334Speter 42618334Speter printf ("rtx peep_operand[%d];\n", max_opno + 1); 42790075Sobrien printf ("#endif\n"); 42818334Speter 42918334Speter fflush (stdout); 43090075Sobrien return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 43118334Speter} 432