|
|
1.1 ! root 1: /* Generate code from machine description to perform peephole optimizations. ! 2: Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: #include <stdio.h> ! 22: #include "config.h" ! 23: #include "rtl.h" ! 24: #include "obstack.h" ! 25: ! 26: static struct obstack obstack; ! 27: struct obstack *rtl_obstack = &obstack; ! 28: ! 29: #define obstack_chunk_alloc xmalloc ! 30: #define obstack_chunk_free free ! 31: ! 32: extern void free (); ! 33: ! 34: /* While tree-walking an instruction pattern, we keep a chain ! 35: of these `struct link's to record how to get down to the ! 36: current position. In each one, POS is the operand number, ! 37: and if the operand is a vector VEC is the element number. ! 38: VEC is -1 if the operand is not a vector. */ ! 39: ! 40: struct link ! 41: { ! 42: struct link *next; ! 43: int pos; ! 44: int vecelt; ! 45: }; ! 46: ! 47: char *xmalloc (); ! 48: static void match_rtx (); ! 49: static void gen_exp (); ! 50: static void fatal (); ! 51: void fancy_abort (); ! 52: ! 53: static int max_opno; ! 54: ! 55: /* Number of operands used in current peephole definition. */ ! 56: ! 57: static int n_operands; ! 58: ! 59: /* Peephole optimizations get insn codes just like insn patterns. ! 60: Count them so we know the code of the define_peephole we are handling. */ ! 61: ! 62: static int insn_code_number = 0; ! 63: ! 64: static void print_path (); ! 65: static void print_code (); ! 66: ! 67: static void ! 68: gen_peephole (peep) ! 69: rtx peep; ! 70: { ! 71: int ninsns = XVECLEN (peep, 0); ! 72: int i; ! 73: ! 74: n_operands = 0; ! 75: ! 76: printf (" insn = ins1;\n"); ! 77: #if 0 ! 78: printf (" want_jump = 0;\n"); ! 79: #endif ! 80: ! 81: for (i = 0; i < ninsns; i++) ! 82: { ! 83: if (i > 0) ! 84: { ! 85: printf (" do { insn = NEXT_INSN (insn);\n"); ! 86: printf (" if (insn == 0) goto L%d; }\n", ! 87: insn_code_number); ! 88: printf (" while (GET_CODE (insn) == NOTE\n"); ! 89: printf ("\t || (GET_CODE (insn) == INSN\n"); ! 90: printf ("\t && (GET_CODE (PATTERN (insn)) == USE\n"); ! 91: printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n"); ! 92: ! 93: printf (" if (GET_CODE (insn) == CODE_LABEL\n\ ! 94: || GET_CODE (insn) == BARRIER)\n goto L%d;\n", ! 95: insn_code_number); ! 96: } ! 97: ! 98: #if 0 ! 99: printf (" if (GET_CODE (insn) == JUMP_INSN)\n"); ! 100: printf (" want_jump = JUMP_LABEL (insn);\n"); ! 101: #endif ! 102: ! 103: printf (" pat = PATTERN (insn);\n"); ! 104: ! 105: /* Walk the insn's pattern, remembering at all times the path ! 106: down to the walking point. */ ! 107: ! 108: match_rtx (XVECEXP (peep, 0, i), 0, insn_code_number); ! 109: } ! 110: ! 111: /* We get this far if the pattern matches. ! 112: Now test the extra condition. */ ! 113: ! 114: if (XSTR (peep, 1) && XSTR (peep, 1)[0]) ! 115: printf (" if (! (%s)) goto L%d;\n", ! 116: XSTR (peep, 1), insn_code_number); ! 117: ! 118: /* If that matches, construct new pattern and put it in the first insn. ! 119: This new pattern will never be matched. ! 120: It exists only so that insn-extract can get the operands back. ! 121: So use a simple regular form: a PARALLEL containing a vector ! 122: of all the operands. */ ! 123: ! 124: printf (" PATTERN (ins1) = gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands); ! 125: ! 126: #if 0 ! 127: printf (" if (want_jump && GET_CODE (ins1) != JUMP_INSN)\n"); ! 128: printf (" {\n"); ! 129: printf (" rtx insn2 = emit_jump_insn_before (PATTERN (ins1), ins1);\n"); ! 130: printf (" delete_insn (ins1);\n"); ! 131: printf (" ins1 = ins2;\n"); ! 132: printf (" }\n"); ! 133: #endif ! 134: ! 135: /* Record this define_peephole's insn code in the insn, ! 136: as if it had been recognized to match this. */ ! 137: printf (" INSN_CODE (ins1) = %d;\n", ! 138: insn_code_number); ! 139: ! 140: /* Delete the remaining insns. */ ! 141: if (ninsns > 1) ! 142: printf (" delete_for_peephole (NEXT_INSN (ins1), insn);\n"); ! 143: ! 144: /* See reload1.c for insertion of NOTE which guarantees that this ! 145: cannot be zero. */ ! 146: printf (" return NEXT_INSN (insn);\n"); ! 147: ! 148: printf (" L%d:\n\n", insn_code_number); ! 149: } ! 150: ! 151: static void ! 152: match_rtx (x, path, fail_label) ! 153: rtx x; ! 154: struct link *path; ! 155: int fail_label; ! 156: { ! 157: register RTX_CODE code; ! 158: register int i; ! 159: register int len; ! 160: register char *fmt; ! 161: struct link link; ! 162: ! 163: if (x == 0) ! 164: return; ! 165: ! 166: ! 167: code = GET_CODE (x); ! 168: ! 169: switch (code) ! 170: { ! 171: case MATCH_OPERAND: ! 172: if (XINT (x, 0) > max_opno) ! 173: max_opno = XINT (x, 0); ! 174: if (XINT (x, 0) >= n_operands) ! 175: n_operands = 1 + XINT (x, 0); ! 176: ! 177: printf (" x = "); ! 178: print_path (path); ! 179: printf (";\n"); ! 180: ! 181: printf (" operands[%d] = x;\n", XINT (x, 0)); ! 182: if (XSTR (x, 1) && XSTR (x, 1)[0]) ! 183: printf (" if (! %s (x, %smode)) goto L%d;\n", ! 184: XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label); ! 185: return; ! 186: ! 187: case MATCH_DUP: ! 188: printf (" x = "); ! 189: print_path (path); ! 190: printf (";\n"); ! 191: ! 192: printf (" if (!rtx_equal_p (operands[%d], x)) goto L%d;\n", ! 193: XINT (x, 0), fail_label); ! 194: return; ! 195: ! 196: case MATCH_OP_DUP: ! 197: printf (" x = "); ! 198: print_path (path); ! 199: printf (";\n"); ! 200: ! 201: printf (" if (GET_CODE (operands[%d]) != GET_CODE (x)\n", XINT (x, 0)); ! 202: printf (" || GET_MODE (operands[%d]) != GET_MODE (x)) goto L%d;\n", ! 203: XINT (x, 0), fail_label); ! 204: printf (" operands[%d] = x;\n", XINT (x, 0)); ! 205: link.next = path; ! 206: link.vecelt = -1; ! 207: for (i = 0; i < XVECLEN (x, 1); i++) ! 208: { ! 209: link.pos = i; ! 210: match_rtx (XVECEXP (x, 1, i), &link, fail_label); ! 211: } ! 212: return; ! 213: ! 214: case MATCH_OPERATOR: ! 215: if (XINT (x, 0) > max_opno) ! 216: max_opno = XINT (x, 0); ! 217: if (XINT (x, 0) >= n_operands) ! 218: n_operands = 1 + XINT (x, 0); ! 219: ! 220: printf (" x = "); ! 221: print_path (path); ! 222: printf (";\n"); ! 223: ! 224: printf (" operands[%d] = x;\n", XINT (x, 0)); ! 225: if (XSTR (x, 1) && XSTR (x, 1)[0]) ! 226: printf (" if (! %s (x, %smode)) goto L%d;\n", ! 227: XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label); ! 228: link.next = path; ! 229: link.vecelt = -1; ! 230: for (i = 0; i < XVECLEN (x, 2); i++) ! 231: { ! 232: link.pos = i; ! 233: match_rtx (XVECEXP (x, 2, i), &link, fail_label); ! 234: } ! 235: return; ! 236: ! 237: case MATCH_PARALLEL: ! 238: if (XINT (x, 0) > max_opno) ! 239: max_opno = XINT (x, 0); ! 240: if (XINT (x, 0) >= n_operands) ! 241: n_operands = 1 + XINT (x, 0); ! 242: ! 243: printf (" x = "); ! 244: print_path (path); ! 245: printf (";\n"); ! 246: ! 247: printf (" if (GET_CODE (x) != PARALLEL) goto L%d;\n", fail_label); ! 248: printf (" operands[%d] = x;\n", XINT (x, 0)); ! 249: if (XSTR (x, 1) && XSTR (x, 1)[0]) ! 250: printf (" if (! %s (x, %smode)) goto L%d;\n", ! 251: XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label); ! 252: link.next = path; ! 253: link.pos = 0; ! 254: for (i = 0; i < XVECLEN (x, 2); i++) ! 255: { ! 256: link.vecelt = i; ! 257: match_rtx (XVECEXP (x, 2, i), &link, fail_label); ! 258: } ! 259: return; ! 260: ! 261: case ADDRESS: ! 262: match_rtx (XEXP (x, 0), path, fail_label); ! 263: return; ! 264: } ! 265: ! 266: printf (" x = "); ! 267: print_path (path); ! 268: printf (";\n"); ! 269: ! 270: printf (" if (GET_CODE (x) != "); ! 271: print_code (code); ! 272: printf (") goto L%d;\n", fail_label); ! 273: ! 274: if (GET_MODE (x) != VOIDmode) ! 275: { ! 276: printf (" if (GET_MODE (x) != %smode) goto L%d;\n", ! 277: GET_MODE_NAME (GET_MODE (x)), fail_label); ! 278: } ! 279: ! 280: link.next = path; ! 281: link.vecelt = -1; ! 282: fmt = GET_RTX_FORMAT (code); ! 283: len = GET_RTX_LENGTH (code); ! 284: for (i = 0; i < len; i++) ! 285: { ! 286: link.pos = i; ! 287: if (fmt[i] == 'e' || fmt[i] == 'u') ! 288: match_rtx (XEXP (x, i), &link, fail_label); ! 289: else if (fmt[i] == 'E') ! 290: { ! 291: int j; ! 292: printf (" if (XVECLEN (x, %d) != %d) goto L%d;\n", ! 293: i, XVECLEN (x, i), fail_label); ! 294: for (j = 0; j < XVECLEN (x, i); j++) ! 295: { ! 296: link.vecelt = j; ! 297: match_rtx (XVECEXP (x, i, j), &link, fail_label); ! 298: } ! 299: } ! 300: else if (fmt[i] == 'i') ! 301: { ! 302: /* Make sure that at run time `x' is the RTX we want to test. */ ! 303: if (i != 0) ! 304: { ! 305: printf (" x = "); ! 306: print_path (path); ! 307: printf (";\n"); ! 308: } ! 309: ! 310: printf (" if (XINT (x, %d) != %d) goto L%d;\n", ! 311: i, XINT (x, i), fail_label); ! 312: } ! 313: else if (fmt[i] == 's') ! 314: { ! 315: /* Make sure that at run time `x' is the RTX we want to test. */ ! 316: if (i != 0) ! 317: { ! 318: printf (" x = "); ! 319: print_path (path); ! 320: printf (";\n"); ! 321: } ! 322: ! 323: printf (" if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n", ! 324: i, XSTR (x, i), fail_label); ! 325: } ! 326: } ! 327: } ! 328: ! 329: /* Given a PATH, representing a path down the instruction's ! 330: pattern from the root to a certain point, output code to ! 331: evaluate to the rtx at that point. */ ! 332: ! 333: static void ! 334: print_path (path) ! 335: struct link *path; ! 336: { ! 337: if (path == 0) ! 338: printf ("pat"); ! 339: else if (path->vecelt >= 0) ! 340: { ! 341: printf ("XVECEXP ("); ! 342: print_path (path->next); ! 343: printf (", %d, %d)", path->pos, path->vecelt); ! 344: } ! 345: else ! 346: { ! 347: printf ("XEXP ("); ! 348: print_path (path->next); ! 349: printf (", %d)", path->pos); ! 350: } ! 351: } ! 352: ! 353: static void ! 354: print_code (code) ! 355: RTX_CODE code; ! 356: { ! 357: register char *p1; ! 358: for (p1 = GET_RTX_NAME (code); *p1; p1++) ! 359: { ! 360: if (*p1 >= 'a' && *p1 <= 'z') ! 361: putchar (*p1 + 'A' - 'a'); ! 362: else ! 363: putchar (*p1); ! 364: } ! 365: } ! 366: ! 367: char * ! 368: xmalloc (size) ! 369: unsigned size; ! 370: { ! 371: register char *val = (char *) malloc (size); ! 372: ! 373: if (val == 0) ! 374: fatal ("virtual memory exhausted"); ! 375: return val; ! 376: } ! 377: ! 378: char * ! 379: xrealloc (ptr, size) ! 380: char *ptr; ! 381: unsigned size; ! 382: { ! 383: char *result = (char *) realloc (ptr, size); ! 384: if (!result) ! 385: fatal ("virtual memory exhausted"); ! 386: return result; ! 387: } ! 388: ! 389: static void ! 390: fatal (s, a1, a2) ! 391: char *s; ! 392: { ! 393: fprintf (stderr, "genpeep: "); ! 394: fprintf (stderr, s, a1, a2); ! 395: fprintf (stderr, "\n"); ! 396: exit (FATAL_EXIT_CODE); ! 397: } ! 398: ! 399: /* More 'friendly' abort that prints the line and file. ! 400: config.h can #define abort fancy_abort if you like that sort of thing. */ ! 401: ! 402: void ! 403: fancy_abort () ! 404: { ! 405: fatal ("Internal gcc abort."); ! 406: } ! 407: ! 408: int ! 409: main (argc, argv) ! 410: int argc; ! 411: char **argv; ! 412: { ! 413: rtx desc; ! 414: FILE *infile; ! 415: extern rtx read_rtx (); ! 416: register int c; ! 417: ! 418: max_opno = -1; ! 419: ! 420: obstack_init (rtl_obstack); ! 421: ! 422: if (argc <= 1) ! 423: fatal ("No input file name."); ! 424: ! 425: infile = fopen (argv[1], "r"); ! 426: if (infile == 0) ! 427: { ! 428: perror (argv[1]); ! 429: exit (FATAL_EXIT_CODE); ! 430: } ! 431: ! 432: init_rtl (); ! 433: ! 434: printf ("/* Generated automatically by the program `genpeep'\n\ ! 435: from the machine description file `md'. */\n\n"); ! 436: ! 437: printf ("#include \"config.h\"\n"); ! 438: printf ("#include \"rtl.h\"\n"); ! 439: printf ("#include \"regs.h\"\n"); ! 440: printf ("#include \"output.h\"\n"); ! 441: printf ("#include \"real.h\"\n\n"); ! 442: ! 443: printf ("extern rtx peep_operand[];\n\n"); ! 444: printf ("#define operands peep_operand\n\n"); ! 445: ! 446: printf ("rtx\npeephole (ins1)\n rtx ins1;\n{\n"); ! 447: printf (" rtx insn, x, pat;\n"); ! 448: printf (" int i;\n\n"); ! 449: ! 450: /* Early out: no peepholes for insns followed by barriers. */ ! 451: printf (" if (NEXT_INSN (ins1)\n"); ! 452: printf (" && GET_CODE (NEXT_INSN (ins1)) == BARRIER)\n"); ! 453: printf (" return 0;\n\n"); ! 454: ! 455: /* Read the machine description. */ ! 456: ! 457: while (1) ! 458: { ! 459: c = read_skip_spaces (infile); ! 460: if (c == EOF) ! 461: break; ! 462: ungetc (c, infile); ! 463: ! 464: desc = read_rtx (infile); ! 465: if (GET_CODE (desc) == DEFINE_PEEPHOLE) ! 466: { ! 467: gen_peephole (desc); ! 468: insn_code_number++; ! 469: } ! 470: if (GET_CODE (desc) == DEFINE_INSN ! 471: || GET_CODE (desc) == DEFINE_EXPAND ! 472: || GET_CODE (desc) == DEFINE_SPLIT) ! 473: { ! 474: insn_code_number++; ! 475: } ! 476: } ! 477: ! 478: printf (" return 0;\n}\n\n"); ! 479: ! 480: if (max_opno == -1) ! 481: max_opno = 1; ! 482: ! 483: printf ("rtx peep_operand[%d];\n", max_opno + 1); ! 484: ! 485: fflush (stdout); ! 486: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 487: /* NOTREACHED */ ! 488: return 0; ! 489: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.