Annotation of GNUtools/cc/genpeep.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.