|
|
1.1 ! root 1: /* Generate code from machine description to perform peephole optimizations. ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU CC General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU CC, but only under the conditions described in the ! 15: GNU CC General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU CC so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: #include <stdio.h> ! 23: #include "config.h" ! 24: #include "rtl.h" ! 25: #include "obstack.h" ! 26: ! 27: struct obstack obstack; ! 28: struct obstack *rtl_obstack = &obstack; ! 29: ! 30: #define obstack_chunk_alloc xmalloc ! 31: #define obstack_chunk_free free ! 32: extern int xmalloc (); ! 33: extern void free (); ! 34: ! 35: void match_rtx (); ! 36: void gen_exp (); ! 37: void fatal (); ! 38: ! 39: ! 40: int max_opno; ! 41: ! 42: /* While tree-walking an instruction pattern, we keep a chain ! 43: of these `struct link's to record how to get down to the ! 44: current position. In each one, POS is the operand number, ! 45: and if the operand is a vector VEC is the element number. ! 46: VEC is -1 if the operand is not a vector. */ ! 47: ! 48: struct link ! 49: { ! 50: struct link *next; ! 51: int pos; ! 52: int vecelt; ! 53: }; ! 54: ! 55: /* Number of operands used in current peephole definition. */ ! 56: ! 57: 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: int insn_code_number = 0; ! 63: ! 64: void print_path (); ! 65: void print_code (); ! 66: ! 67: 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: ! 78: for (i = 0; i < ninsns; i++) ! 79: { ! 80: if (i > 0) ! 81: { ! 82: printf (" do { insn = NEXT_INSN (insn);\n"); ! 83: printf (" if (insn == 0) goto L%d; }\n", ! 84: insn_code_number); ! 85: printf (" while (GET_CODE (insn) == NOTE);\n"); ! 86: } ! 87: ! 88: printf (" if (GET_CODE (insn) == CODE_LABEL) goto L%d;\n", ! 89: insn_code_number); ! 90: ! 91: printf (" pat = PATTERN (insn);\n"); ! 92: /* Walk the insn's pattern, remembering at all times the path ! 93: down to the walking point. */ ! 94: ! 95: match_rtx (XVECEXP (peep, 0, i), 0, insn_code_number); ! 96: } ! 97: ! 98: /* We get this far if the pattern matches. ! 99: Now test the extra condition. */ ! 100: ! 101: if (XSTR (peep, 1) && XSTR (peep, 1)[0]) ! 102: printf (" if (! (%s)) goto L%d;\n", ! 103: XSTR (peep, 1), insn_code_number); ! 104: ! 105: /* If that matches, construct new pattern and put it in the first insn. ! 106: This new pattern will never be matched. ! 107: It exists only so that insn-extract can get the operands back. ! 108: So use a simple regular form: a PARALLEL containing a vector ! 109: of all the operands. */ ! 110: ! 111: printf (" PATTERN (ins1) = gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands); ! 112: printf (" insn = ins1;\n"); ! 113: ! 114: /* Make sure that labels referred to by the insns ! 115: don't get deleted because of their counts' going to zero. */ ! 116: printf (" for (i = 0; i < %d; i++)\n", n_operands); ! 117: printf (" if (GET_CODE (operands[i]) == CODE_LABEL)\n"); ! 118: printf (" LABEL_NUSES (operands[i])++;\n"); ! 119: ! 120: /* Record this define_peephole's insn code in the insn, ! 121: as if it had been recognized to match this. */ ! 122: printf (" INSN_CODE (insn) = %d;\n", ! 123: insn_code_number); ! 124: ! 125: /* Delete the remaining insns. */ ! 126: for (i = 1; i < ninsns; i++) ! 127: { ! 128: printf (" do insn = NEXT_INSN (insn);\n"); ! 129: printf (" while (GET_CODE (insn) == NOTE);\n"); ! 130: printf (" delete_insn (insn);\n"); ! 131: } ! 132: ! 133: printf (" return 1;\n"); ! 134: ! 135: printf (" L%d:\n\n", insn_code_number); ! 136: } ! 137: ! 138: void ! 139: match_rtx (x, path, fail_label) ! 140: rtx x; ! 141: struct link *path; ! 142: int fail_label; ! 143: { ! 144: register RTX_CODE code; ! 145: register int i; ! 146: register int len; ! 147: register char *fmt; ! 148: struct link link; ! 149: ! 150: if (x == 0) ! 151: return; ! 152: ! 153: ! 154: code = GET_CODE (x); ! 155: ! 156: switch (code) ! 157: { ! 158: case MATCH_OPERAND: ! 159: if (XINT (x, 0) > max_opno) ! 160: max_opno = XINT (x, 0); ! 161: if (XINT (x, 0) >= n_operands) ! 162: n_operands = 1 + XINT (x, 0); ! 163: ! 164: printf (" x = "); ! 165: print_path (path); ! 166: printf (";\n"); ! 167: ! 168: printf (" operands[%d] = x;\n", XINT (x, 0)); ! 169: if (XSTR (x, 1) && XSTR (x, 1)[0]) ! 170: printf (" if (! %s (x, %smode)) goto L%d;\n", ! 171: XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label); ! 172: return; ! 173: ! 174: case MATCH_DUP: ! 175: printf (" x = "); ! 176: print_path (path); ! 177: printf (";\n"); ! 178: ! 179: printf (" if (!rtx_equal_p (operands[%d], x)) goto L%d;\n", ! 180: XINT (x, 0), fail_label); ! 181: return; ! 182: ! 183: case ADDRESS: ! 184: match_rtx (XEXP (x, 0), path, fail_label); ! 185: return; ! 186: } ! 187: ! 188: printf (" x = "); ! 189: print_path (path); ! 190: printf (";\n"); ! 191: ! 192: printf (" if (GET_CODE (x) != "); ! 193: print_code (code); ! 194: printf (") goto L%d;\n", fail_label); ! 195: ! 196: if (GET_MODE (x) != VOIDmode) ! 197: { ! 198: printf (" if (GET_MODE (x) != %smode) goto L%d;\n", ! 199: GET_MODE_NAME (GET_MODE (x)), fail_label); ! 200: } ! 201: ! 202: link.next = path; ! 203: link.vecelt = -1; ! 204: fmt = GET_RTX_FORMAT (code); ! 205: len = GET_RTX_LENGTH (code); ! 206: for (i = 0; i < len; i++) ! 207: { ! 208: link.pos = i; ! 209: if (fmt[i] == 'e' || fmt[i] == 'u') ! 210: match_rtx (XEXP (x, i), &link, fail_label); ! 211: else if (fmt[i] == 'E') ! 212: { ! 213: int j; ! 214: printf (" if (XVECLEN (x, %d) != %d) goto L%d;\n", ! 215: i, XVECLEN (x, i), fail_label); ! 216: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 217: { ! 218: link.vecelt = j; ! 219: match_rtx (XVECEXP (x, i, j), &link, fail_label); ! 220: } ! 221: } ! 222: else if (fmt[i] == 'i') ! 223: { ! 224: /* Make sure that at run time `x' is the RTX we want to test. */ ! 225: if (i != 0) ! 226: { ! 227: printf (" x = "); ! 228: print_path (path); ! 229: printf (";\n"); ! 230: } ! 231: ! 232: printf (" if (XINT (x, %d) != %d) goto L%d;\n", ! 233: i, XINT (x, i), fail_label); ! 234: } ! 235: else if (fmt[i] == 's') ! 236: { ! 237: /* Make sure that at run time `x' is the RTX we want to test. */ ! 238: if (i != 0) ! 239: { ! 240: printf (" x = "); ! 241: print_path (path); ! 242: printf (";\n"); ! 243: } ! 244: ! 245: printf (" if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n", ! 246: i, XSTR (x, i), fail_label); ! 247: } ! 248: } ! 249: } ! 250: ! 251: /* Given a PATH, representing a path down the instruction's ! 252: pattern from the root to a certain point, output code to ! 253: evaluate to the rtx at that point. */ ! 254: ! 255: void ! 256: print_path (path) ! 257: struct link *path; ! 258: { ! 259: if (path == 0) ! 260: printf ("pat"); ! 261: else if (path->vecelt >= 0) ! 262: { ! 263: printf ("XVECEXP ("); ! 264: print_path (path->next); ! 265: printf (", %d, %d)", path->pos, path->vecelt); ! 266: } ! 267: else ! 268: { ! 269: printf ("XEXP ("); ! 270: print_path (path->next); ! 271: printf (", %d)", path->pos); ! 272: } ! 273: } ! 274: ! 275: void ! 276: print_code (code) ! 277: RTX_CODE code; ! 278: { ! 279: register char *p1; ! 280: for (p1 = GET_RTX_NAME (code); *p1; p1++) ! 281: { ! 282: if (*p1 >= 'a' && *p1 <= 'z') ! 283: putchar (*p1 + 'A' - 'a'); ! 284: else ! 285: putchar (*p1); ! 286: } ! 287: } ! 288: ! 289: int ! 290: xmalloc (size) ! 291: { ! 292: register int val = malloc (size); ! 293: ! 294: if (val == 0) ! 295: fatal ("virtual memory exhausted"); ! 296: return val; ! 297: } ! 298: ! 299: int ! 300: xrealloc (ptr, size) ! 301: char *ptr; ! 302: int size; ! 303: { ! 304: int result = realloc (ptr, size); ! 305: if (!result) ! 306: fatal ("virtual memory exhausted"); ! 307: return result; ! 308: } ! 309: ! 310: void ! 311: fatal (s, a1, a2) ! 312: { ! 313: fprintf (stderr, "genpeep: "); ! 314: fprintf (stderr, s, a1, a2); ! 315: fprintf (stderr, "\n"); ! 316: exit (FATAL_EXIT_CODE); ! 317: } ! 318: ! 319: int ! 320: main (argc, argv) ! 321: int argc; ! 322: char **argv; ! 323: { ! 324: rtx desc; ! 325: FILE *infile; ! 326: extern rtx read_rtx (); ! 327: register int c, i; ! 328: ! 329: max_opno = -1; ! 330: ! 331: obstack_init (rtl_obstack); ! 332: ! 333: if (argc <= 1) ! 334: fatal ("No input file name."); ! 335: ! 336: infile = fopen (argv[1], "r"); ! 337: if (infile == 0) ! 338: { ! 339: perror (argv[1]); ! 340: exit (FATAL_EXIT_CODE); ! 341: } ! 342: ! 343: init_rtl (); ! 344: ! 345: printf ("/* Generated automatically by the program `genpeep'\n\ ! 346: from the machine description file `md'. */\n\n"); ! 347: ! 348: printf ("#include \"rtl.h\"\n\n"); ! 349: printf ("#include \"config.h\"\n\n"); ! 350: printf ("#include \"regs.h\"\n\n"); ! 351: ! 352: printf ("rtx peep_operand[];\n\n"); ! 353: printf ("#define operands peep_operand\n\n"); ! 354: ! 355: printf ("int\npeephole (ins1)\n rtx ins1;\n{\n"); ! 356: printf (" rtx insn, x, pat;\n"); ! 357: printf (" int i;\n"); ! 358: ! 359: /* Read the machine description. */ ! 360: ! 361: while (1) ! 362: { ! 363: c = read_skip_spaces (infile); ! 364: if (c == EOF) ! 365: break; ! 366: ungetc (c, infile); ! 367: ! 368: desc = read_rtx (infile); ! 369: if (GET_CODE (desc) == DEFINE_PEEPHOLE) ! 370: { ! 371: gen_peephole (desc); ! 372: insn_code_number++; ! 373: } ! 374: if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) ! 375: { ! 376: insn_code_number++; ! 377: } ! 378: } ! 379: ! 380: printf (" return 0;\n}\n\n"); ! 381: ! 382: if (max_opno == -1) ! 383: max_opno = 1; ! 384: ! 385: printf ("rtx peep_operand[%d];\n", max_opno + 1); ! 386: ! 387: fflush (stdout); ! 388: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 389: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.