Annotation of gcc/genpeep.c, revision 1.1.1.2

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 ();
1.1.1.2 ! root       33: extern rtx read_rtx ();
1.1       root       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), 0, 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:       printf ("  x = ");
                    190:       print_path (path);
                    191:       printf (";\n");
                    192: 
                    193:       printf ("  if (!rtx_equal_p (operands[%d], x)) goto L%d;\n",
                    194:              XINT (x, 0), fail_label);
                    195:       return;
                    196: 
                    197:     case MATCH_OP_DUP:
                    198:       printf ("  x = ");
                    199:       print_path (path);
                    200:       printf (";\n");
                    201: 
                    202:       printf ("  if (GET_CODE (operands[%d]) != GET_CODE (x)\n", XINT (x, 0));
                    203:       printf ("      || GET_MODE (operands[%d]) != GET_MODE (x)) goto L%d;\n",
                    204:              XINT (x, 0), fail_label);
                    205:       printf ("  operands[%d] = x;\n", XINT (x, 0));
                    206:       link.next = path;
                    207:       link.vecelt = -1;
                    208:       for (i = 0; i < XVECLEN (x, 1); i++)
                    209:        {
                    210:          link.pos = i;
                    211:          match_rtx (XVECEXP (x, 1, i), &link, fail_label);
                    212:        }
                    213:       return;
                    214: 
                    215:     case MATCH_OPERATOR:
                    216:       if (XINT (x, 0) > max_opno)
                    217:        max_opno = XINT (x, 0);
                    218:       if (XINT (x, 0) >= n_operands)
                    219:        n_operands = 1 + XINT (x, 0);
                    220: 
                    221:       printf ("  x = ");
                    222:       print_path (path);
                    223:       printf (";\n");
                    224: 
                    225:       printf ("  operands[%d] = x;\n", XINT (x, 0));
                    226:       if (XSTR (x, 1) && XSTR (x, 1)[0])
                    227:        printf ("  if (! %s (x, %smode)) goto L%d;\n",
                    228:                XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
                    229:       link.next = path;
                    230:       link.vecelt = -1;
                    231:       for (i = 0; i < XVECLEN (x, 2); i++)
                    232:        {
                    233:          link.pos = i;
                    234:          match_rtx (XVECEXP (x, 2, i), &link, fail_label);
                    235:        }
                    236:       return;
                    237: 
                    238:     case MATCH_PARALLEL:
                    239:       if (XINT (x, 0) > max_opno)
                    240:        max_opno = XINT (x, 0);
                    241:       if (XINT (x, 0) >= n_operands)
                    242:        n_operands = 1 + XINT (x, 0);
                    243: 
                    244:       printf ("  x = ");
                    245:       print_path (path);
                    246:       printf (";\n");
                    247: 
                    248:       printf ("  if (GET_CODE (x) != PARALLEL) goto L%d;\n", fail_label);
                    249:       printf ("  operands[%d] = x;\n", XINT (x, 0));
                    250:       if (XSTR (x, 1) && XSTR (x, 1)[0])
                    251:        printf ("  if (! %s (x, %smode)) goto L%d;\n",
                    252:                XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label);
                    253:       link.next = path;
                    254:       link.pos = 0;
                    255:       for (i = 0; i < XVECLEN (x, 2); i++)
                    256:        {
                    257:          link.vecelt = i;
                    258:          match_rtx (XVECEXP (x, 2, i), &link, fail_label);
                    259:        }
                    260:       return;
                    261: 
                    262:     case ADDRESS:
                    263:       match_rtx (XEXP (x, 0), path, fail_label);
                    264:       return;
                    265:     }
                    266: 
                    267:   printf ("  x = ");
                    268:   print_path (path);
                    269:   printf (";\n");
                    270: 
                    271:   printf ("  if (GET_CODE (x) != ");
                    272:   print_code (code);
                    273:   printf (") goto L%d;\n", fail_label);
                    274: 
                    275:   if (GET_MODE (x) != VOIDmode)
                    276:     {
                    277:       printf ("  if (GET_MODE (x) != %smode) goto L%d;\n",
                    278:              GET_MODE_NAME (GET_MODE (x)), fail_label);
                    279:     }
                    280: 
                    281:   link.next = path;
                    282:   link.vecelt = -1;
                    283:   fmt = GET_RTX_FORMAT (code);
                    284:   len = GET_RTX_LENGTH (code);
                    285:   for (i = 0; i < len; i++)
                    286:     {
                    287:       link.pos = i;
                    288:       if (fmt[i] == 'e' || fmt[i] == 'u')
                    289:        match_rtx (XEXP (x, i), &link, fail_label);
                    290:       else if (fmt[i] == 'E')
                    291:        {
                    292:          int j;
                    293:          printf ("  if (XVECLEN (x, %d) != %d) goto L%d;\n",
                    294:                  i, XVECLEN (x, i), fail_label);
                    295:          for (j = 0; j < XVECLEN (x, i); j++)
                    296:            {
                    297:              link.vecelt = j;
                    298:              match_rtx (XVECEXP (x, i, j), &link, fail_label);
                    299:            }
                    300:        }
                    301:       else if (fmt[i] == 'i')
                    302:        {
                    303:          /* Make sure that at run time `x' is the RTX we want to test.  */
                    304:          if (i != 0)
                    305:            {
                    306:              printf ("  x = ");
                    307:              print_path (path);
                    308:              printf (";\n");
                    309:            }
                    310: 
                    311:          printf ("  if (XINT (x, %d) != %d) goto L%d;\n",
                    312:                  i, XINT (x, i), fail_label);
                    313:        }
                    314:       else if (fmt[i] == 's')
                    315:        {
                    316:          /* Make sure that at run time `x' is the RTX we want to test.  */
                    317:          if (i != 0)
                    318:            {
                    319:              printf ("  x = ");
                    320:              print_path (path);
                    321:              printf (";\n");
                    322:            }
                    323: 
                    324:          printf ("  if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n",
                    325:                  i, XSTR (x, i), fail_label);
                    326:        }
                    327:     }
                    328: }
                    329: 
                    330: /* Given a PATH, representing a path down the instruction's
                    331:    pattern from the root to a certain point, output code to
                    332:    evaluate to the rtx at that point.  */
                    333: 
                    334: static void
                    335: print_path (path)
                    336:      struct link *path;
                    337: {
                    338:   if (path == 0)
                    339:     printf ("pat");
                    340:   else if (path->vecelt >= 0)
                    341:     {
                    342:       printf ("XVECEXP (");
                    343:       print_path (path->next);
                    344:       printf (", %d, %d)", path->pos, path->vecelt);
                    345:     }
                    346:   else
                    347:     {
                    348:       printf ("XEXP (");
                    349:       print_path (path->next);
                    350:       printf (", %d)", path->pos);
                    351:     }
                    352: }
                    353: 
                    354: static void
                    355: print_code (code)
                    356:      RTX_CODE code;
                    357: {
                    358:   register char *p1;
                    359:   for (p1 = GET_RTX_NAME (code); *p1; p1++)
                    360:     {
                    361:       if (*p1 >= 'a' && *p1 <= 'z')
                    362:        putchar (*p1 + 'A' - 'a');
                    363:       else
                    364:        putchar (*p1);
                    365:     }
                    366: }
                    367: 
                    368: char *
                    369: xmalloc (size)
                    370:      unsigned size;
                    371: {
                    372:   register char *val = (char *) malloc (size);
                    373: 
                    374:   if (val == 0)
                    375:     fatal ("virtual memory exhausted");
                    376:   return val;
                    377: }
                    378: 
                    379: char *
                    380: xrealloc (ptr, size)
                    381:      char *ptr;
                    382:      unsigned size;
                    383: {
                    384:   char *result = (char *) realloc (ptr, size);
                    385:   if (!result)
                    386:     fatal ("virtual memory exhausted");
                    387:   return result;
                    388: }
                    389: 
                    390: static void
                    391: fatal (s, a1, a2)
                    392:      char *s;
                    393: {
                    394:   fprintf (stderr, "genpeep: ");
                    395:   fprintf (stderr, s, a1, a2);
                    396:   fprintf (stderr, "\n");
                    397:   exit (FATAL_EXIT_CODE);
                    398: }
                    399: 
                    400: /* More 'friendly' abort that prints the line and file.
                    401:    config.h can #define abort fancy_abort if you like that sort of thing.  */
                    402: 
                    403: void
                    404: fancy_abort ()
                    405: {
                    406:   fatal ("Internal gcc abort.");
                    407: }
                    408: 
                    409: int
                    410: main (argc, argv)
                    411:      int argc;
                    412:      char **argv;
                    413: {
                    414:   rtx desc;
                    415:   FILE *infile;
                    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: }

unix.superglobalmegacorp.com

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