Annotation of gcc/genpeep.c, revision 1.1.1.4

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

unix.superglobalmegacorp.com

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