Annotation of gcc/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 "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: }

unix.superglobalmegacorp.com

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