Annotation of cci/usr/src/usr.bin/f77/f77pass1/optim.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)optim.c    5.2 (Berkeley) 6/9/85";
                      9: #endif not lint
                     10: 
                     11: /*
                     12:  * optim.c
                     13:  *
                     14:  * Miscellaneous optimizer routines, f77 compiler pass 1.
                     15:  *
                     16:  * UCSD Chemistry modification history:
                     17:  *
                     18:  * $Log:       optim.c,v $
                     19:  * Revision 1.2  86/02/12  15:28:39  rcs
                     20:  * 4.3 F77. C. Keating.
                     21:  * 
                     22:  * Revision 2.12  85/06/08  22:57:01  donn
                     23:  * Prevent core dumps -- bug in optinsert was causing lastslot to be wrong
                     24:  * when a slot was inserted at the end of the buffer.
                     25:  * 
                     26:  * Revision 2.11  85/03/18  08:05:05  donn
                     27:  * Prevent warnings about implicit conversions.
                     28:  * 
                     29:  * Revision 2.10  85/02/12  20:13:00  donn
                     30:  * Resurrected the hack in 2.6.1.1 to avoid creating a temporary when
                     31:  * there is a concatenation on the rhs of an assignment, and threw out
                     32:  * all the code dealing with starcat().  It seems that we can't use a
                     33:  * temporary because the lhs as well as the rhs may have nonconstant length.
                     34:  * 
                     35:  * Revision 2.9  85/01/18  00:53:52  donn
                     36:  * Missed a call to free() in the last change...
                     37:  * 
                     38:  * Revision 2.8  85/01/18  00:50:03  donn
                     39:  * Fixed goof made when modifying buffmnmx() to explicitly call expand().
                     40:  * 
                     41:  * Revision 2.7  85/01/15  18:47:35  donn
                     42:  * Changes to allow character*(*) variables to appear in concatenations in
                     43:  * the rhs of an assignment statement.
                     44:  * 
                     45:  * Revision 2.6  84/12/16  21:46:27  donn
                     46:  * Fixed bug that prevented concatenations from being run together.  Changed
                     47:  * buffpower() to not touch exponents greater than 64 -- let putpower do them.
                     48:  * 
                     49:  * Revision 2.5  84/10/29  08:41:45  donn
                     50:  * Added hack to flushopt() to prevent the compiler from trying to generate
                     51:  * intermediate code after an error.
                     52:  * 
                     53:  * Revision 2.4  84/08/07  21:28:00  donn
                     54:  * Removed call to p2flush() in putopt() -- this allows us to make better use
                     55:  * of the buffering on the intermediate code file.
                     56:  * 
                     57:  * Revision 2.3  84/08/01  16:06:24  donn
                     58:  * Forced expand() to expand subscripts.
                     59:  * 
                     60:  * Revision 2.2  84/07/19  20:21:55  donn
                     61:  * Decided I liked the expression tree algorithm after all.  The algorithm
                     62:  * which repeatedly squares temporaries is now checked in as rev. 2.1.
                     63:  * 
                     64:  * Revision 1.3.1.1  84/07/10  14:18:18  donn
                     65:  * I'm taking this branch off the trunk -- it works but it's not as good as
                     66:  * the old version would be if it worked right.
                     67:  * 
                     68:  * Revision 1.5  84/07/09  22:28:50  donn
                     69:  * Added fix to buffpower() to prevent it chasing after huge exponents.
                     70:  * 
                     71:  * Revision 1.4  84/07/09  20:13:59  donn
                     72:  * Replaced buffpower() routine with a new one that generates trees which can
                     73:  * be handled by CSE later on.  
                     74:  * 
                     75:  * Revision 1.3  84/05/04  21:02:07  donn
                     76:  * Added fix for a bug in buffpower() that caused func(x)**2 to turn into
                     77:  * func(x) * func(x).  This bug had already been fixed in putpower()...
                     78:  * 
                     79:  * Revision 1.2  84/03/23  22:47:21  donn
                     80:  * The subroutine argument temporary fixes from Bob Corbett didn't take into
                     81:  * account the fact that the code generator collects all the assignments to
                     82:  * temporaries at the start of a statement -- hence the temporaries need to
                     83:  * be initialized once per statement instead of once per call.
                     84:  * 
                     85:  */
                     86: 
                     87: #include "defs.h"
                     88: #include "optim.h"
                     89: 
                     90: 
                     91: 
                     92: /*
                     93:  *             Information buffered for each slot type
                     94:  *
                     95:  *  slot type         expptr          integer          pointer
                     96:  *
                     97:  *  IFN                        expr            label           -
                     98:  *  GOTO               -               label           -
                     99:  *  LABEL              -               label           -
                    100:  *  EQ                 expr            -               -
                    101:  *  CALL               expr            -               -
                    102:  *  CMGOTO             expr            num             labellist*
                    103:  *  STOP               expr            -               -
                    104:  *  DOHEAD             [1]             -               ctlframe*
                    105:  *  ENDDO              [1]             -               ctlframe*
                    106:  *  ARIF               expr            -               labellist*
                    107:  *  RETURN             expr            label           -
                    108:  *  ASGOTO             expr            -               labellist*
                    109:  *  PAUSE              expr            -               -
                    110:  *  ASSIGN             expr            label           -
                    111:  *  SKIOIFN            expr            label           -
                    112:  *  SKFRTEMP           expr            -               -
                    113:  *
                    114:  *     Note [1]:  the nullslot field is a pointer to a fake slot which is
                    115:  *     at the end of the slots which may be replaced by this slot.  In
                    116:  *     other words, it looks like this:
                    117:  *             DOHEAD slot
                    118:  *             slot   \
                    119:  *             slot    > ordinary IF, GOTO, LABEL slots which implement the DO
                    120:  *             slot   /
                    121:  *             NULL slot
                    122:  */
                    123: 
                    124: 
                    125: expptr expand();
                    126: 
                    127: Slotp  firstslot = NULL;
                    128: Slotp  lastslot = NULL;
                    129: int    numslots = 0;
                    130: 
                    131: 
                    132: /*
                    133:  *  turns off optimization option
                    134:  */
                    135: 
                    136: optoff()
                    137: 
                    138: {
                    139: flushopt();
                    140: optimflag = 0;
                    141: }
                    142: 
                    143: 
                    144: 
                    145: /*
                    146:  *  initializes the code buffer for optimization
                    147:  */
                    148: 
                    149: setopt()
                    150: 
                    151: {
                    152: register Slotp sp;
                    153: 
                    154: for (sp = firstslot; sp; sp = sp->next)
                    155:        free ( (charptr) sp);
                    156: firstslot = lastslot = NULL;
                    157: numslots = 0;
                    158: }
                    159: 
                    160: 
                    161: 
                    162: /*
                    163:  *  flushes the code buffer
                    164:  */
                    165: 
                    166: LOCAL int alreadycalled = 0;
                    167: 
                    168: flushopt()
                    169: {
                    170: register Slotp sp;
                    171: int savelineno;
                    172: 
                    173: if (alreadycalled) return;     /* to prevent recursive call during errors */
                    174: alreadycalled = 1;
                    175: 
                    176: if (debugflag[1])
                    177:        showbuffer ();
                    178: 
                    179: frtempbuff ();
                    180: 
                    181: savelineno = lineno;
                    182: for (sp = firstslot; sp; sp = sp->next)
                    183:        {
                    184:        if (nerr == 0)
                    185:                putopt (sp);
                    186:        else
                    187:                frexpr (sp->expr);
                    188:         if(sp->ctlinfo) free ( (charptr) sp->ctlinfo);
                    189:         free ( (charptr) sp);
                    190:         numslots--;
                    191:        }
                    192: firstslot = lastslot = NULL;
                    193: numslots = 0;
                    194: clearbb();
                    195: lineno = savelineno;
                    196: 
                    197: alreadycalled = 0;
                    198: }
                    199: 
                    200: 
                    201: 
                    202: /*
                    203:  *  puts out code for the given slot (from the code buffer)
                    204:  */
                    205: 
                    206: LOCAL putopt (sp)
                    207: register Slotp sp;
                    208: {
                    209:        lineno = sp->lineno;
                    210:        switch (sp->type) {
                    211:            case SKNULL:
                    212:                break;
                    213:            case SKIFN:
                    214:            case SKIOIFN:
                    215:                putif(sp->expr, sp->label);
                    216:                break;
                    217:            case SKGOTO:
                    218:                putgoto(sp->label);
                    219:                break;
                    220:            case SKCMGOTO:
                    221:                putcmgo(sp->expr, sp->label, sp->ctlinfo);
                    222:                break;
                    223:            case SKCALL:
                    224:                putexpr(sp->expr);
                    225:                break;
                    226:            case SKSTOP:
                    227:                putexpr (call1 (TYSUBR, "s_stop", sp->expr));
                    228:                break;
                    229:            case SKPAUSE:
                    230:                putexpr (call1 (TYSUBR, "s_paus", sp->expr));
                    231:                break;
                    232:            case SKASSIGN:
                    233:                puteq (sp->expr,
                    234:                    intrconv(sp->expr->headblock.vtype, mkaddcon(sp->label)));
                    235:                break;
                    236:            case SKDOHEAD:
                    237:            case SKENDDO:
                    238:                break;
                    239:            case SKEQ:
                    240:                putexpr(sp->expr);
                    241:                break;
                    242:            case SKARIF:
                    243: #define LM   ((struct Labelblock * *)sp->ctlinfo)[0]->labelno 
                    244: #define LZ   ((struct Labelblock * *)sp->ctlinfo)[1]->labelno 
                    245: #define LP   ((struct Labelblock * *)sp->ctlinfo)[2]->labelno 
                    246:                        prarif(sp->expr, LM, LZ, LP);
                    247:                break;
                    248:            case SKASGOTO:
                    249:                putbranch((Addrp) sp->expr);
                    250:                break;
                    251:            case SKLABEL:
                    252:                putlabel(sp->label);
                    253:                break;
                    254:            case SKRETURN:
                    255:                if (sp->expr)
                    256:                        {
                    257:                        putforce(TYINT, sp->expr);
                    258:                        putgoto(sp->label);
                    259:                        }
                    260:                else
                    261:                        putgoto(sp->label);
                    262:                break;
                    263:            case SKFRTEMP:
                    264:                templist = mkchain (sp->expr,templist);
                    265:                break;
                    266:            default:
                    267:                badthing("SKtype", "putopt", sp->type);
                    268:                break;
                    269:        }
                    270: 
                    271:        /*
                    272:         * Recycle argument temporaries here.  This must get done on a
                    273:         *      statement-by-statement basis because the code generator
                    274:         *      makes side effects happen at the start of a statement.
                    275:         */
                    276:        argtemplist = hookup(argtemplist, activearglist);
                    277:        activearglist = CHNULL;
                    278: }
                    279: 
                    280: 
                    281: 
                    282: /*
                    283:  *  copies one element of the control stack
                    284:  */
                    285: 
                    286: LOCAL struct Ctlframe *cpframe(p)
                    287: register char *p;
                    288: {
                    289: static int size =  sizeof (struct Ctlframe);
                    290: register int n;
                    291: register char *q;
                    292: struct Ctlframe *q0;
                    293: 
                    294: q0 = ALLOC(Ctlframe);
                    295: q = (char *) q0;
                    296: n = size;
                    297: while(n-- > 0)
                    298:        *q++ = *p++;
                    299: return( q0);
                    300: }
                    301: 
                    302: 
                    303: 
                    304: /*
                    305:  *  copies an array of labelblock pointers
                    306:  */
                    307: 
                    308: LOCAL struct Labelblock **cplabarr(n,arr)
                    309: struct Labelblock *arr[];
                    310: int n;
                    311: {
                    312: struct Labelblock **newarr;
                    313: register char *in, *out;
                    314: register int i,j;
                    315: 
                    316: newarr = (struct Labelblock **) ckalloc (n * sizeof (char *));
                    317: for (i = 0; i < n; i++)
                    318:        {
                    319:        newarr[i] = ALLOC (Labelblock);
                    320:        out = (char *) newarr[i];
                    321:        in = (char *) arr[i];
                    322:        j = sizeof (struct Labelblock);
                    323:        while (j-- > 0)
                    324:                *out++ = *in++;
                    325:        }
                    326: return (newarr);
                    327: }
                    328: 
                    329: 
                    330: 
                    331: /*
                    332:  *  creates a new slot in the code buffer
                    333:  */
                    334: 
                    335: LOCAL Slotp newslot()
                    336: {
                    337: register Slotp sp;
                    338: 
                    339: ++numslots;
                    340: sp = ALLOC( slt );
                    341: sp->next = NULL ;
                    342: if (lastslot)
                    343:        {
                    344:        sp->prev = lastslot;
                    345:        lastslot = lastslot->next = sp;
                    346:        }
                    347: else
                    348:        {
                    349:        firstslot = lastslot = sp;
                    350:        sp->prev = NULL;
                    351:        }
                    352: sp->lineno = lineno;
                    353: return (sp);
                    354: }
                    355: 
                    356: 
                    357: 
                    358: /*
                    359:  *  removes (but not deletes) the specified slot from the code buffer
                    360:  */
                    361: 
                    362: removeslot (sl)
                    363: Slotp  sl;
                    364: 
                    365: {
                    366: if (sl->next)
                    367:        sl->next->prev = sl->prev;
                    368: else
                    369:        lastslot = sl->prev;
                    370: if (sl->prev)
                    371:        sl->prev->next = sl->next;
                    372: else
                    373:        firstslot = sl->next;
                    374: sl->next = sl->prev = NULL;
                    375: 
                    376: --numslots;
                    377: }
                    378: 
                    379: 
                    380: 
                    381: /*
                    382:  *  inserts slot s1 before existing slot s2 in the code buffer;
                    383:  *  appends to end of list if s2 is NULL.
                    384:  */
                    385: 
                    386: insertslot (s1,s2)
                    387: Slotp  s1,s2;
                    388: 
                    389: {
                    390: if (s2)
                    391:        {
                    392:        if (s2->prev)
                    393:                s2->prev->next = s1;
                    394:        else
                    395:                firstslot = s1;
                    396:        s1->prev = s2->prev;
                    397:        s2->prev = s1;
                    398:        }
                    399: else
                    400:        {
                    401:        s1->prev = lastslot;
                    402:        lastslot->next = s1;
                    403:        lastslot = s1;
                    404:        }
                    405: s1->next = s2;
                    406: 
                    407: ++numslots;
                    408: }
                    409: 
                    410: 
                    411: 
                    412: /*
                    413:  *  deletes the specified slot from the code buffer
                    414:  */
                    415: 
                    416: delslot (sl)
                    417: Slotp  sl;
                    418: 
                    419: {
                    420: removeslot (sl);
                    421: 
                    422: if (sl->ctlinfo)
                    423:        free ((charptr) sl->ctlinfo);
                    424: frexpr (sl->expr);
                    425: free ((charptr) sl);
                    426: numslots--;
                    427: }
                    428: 
                    429: 
                    430: 
                    431: /*
                    432:  *  inserts a slot before the specified slot; if given NULL, it is
                    433:  *  inserted at the end of the buffer
                    434:  */
                    435: 
                    436: Slotp optinsert (type,p,l,c,currslot)
                    437: int    type;
                    438: expptr p;
                    439: int    l;
                    440: int    *c;
                    441: Slotp  currslot;
                    442: 
                    443: {
                    444: Slotp  savelast,new;
                    445: 
                    446: savelast = lastslot;
                    447: if (currslot)
                    448:        lastslot = currslot->prev;
                    449: new = optbuff (type,p,l,c);
                    450: new->next = currslot;
                    451: if (currslot)
                    452:        currslot->prev = new;
                    453: new->lineno = -1;      /* who knows what the line number should be ??!! */
                    454: if (currslot)
                    455:        lastslot = savelast;
                    456: return (new);
                    457: }
                    458: 
                    459: 
                    460: 
                    461: /*
                    462:  *  buffers the FRTEMP slots which have been waiting
                    463:  */
                    464: 
                    465: frtempbuff ()
                    466: 
                    467: {
                    468: chainp ht;
                    469: register Slotp sp;
                    470: 
                    471: for (ht = holdtemps; ht; ht = ht->nextp)
                    472:        {
                    473:        sp = newslot();
                    474:                /* this slot actually belongs to some previous source line */
                    475:        sp->lineno = sp->lineno - 1;
                    476:        sp->type = SKFRTEMP;
                    477:        sp->expr = (expptr) ht->datap;
                    478:        sp->label = 0;
                    479:        sp->ctlinfo = NULL;
                    480:        }
                    481: holdtemps = NULL;
                    482: }
                    483: 
                    484: 
                    485: 
                    486: /*
                    487:  *  puts the given information into a slot at the end of the code buffer
                    488:  */
                    489: 
                    490: Slotp optbuff (type,p,l,c)
                    491: int    type;
                    492: expptr p;
                    493: int    l;
                    494: int    *c;
                    495: 
                    496: {
                    497: register Slotp sp;
                    498: 
                    499: if (debugflag[1])
                    500:        {
                    501:        fprintf (diagfile,"-----optbuff-----"); showslottype (type);
                    502:        showexpr (p,0); fprintf (diagfile,"\n");
                    503:        }
                    504: 
                    505: p = expand (p);
                    506: sp = newslot();
                    507: sp->type = type;
                    508: sp->expr = p;
                    509: sp->label = l;
                    510: sp->ctlinfo = NULL;
                    511: switch (type)
                    512:        {
                    513:        case SKCMGOTO:
                    514:                sp->ctlinfo = (int*) cplabarr (l, (struct Labelblock**) c);
                    515:                break;
                    516:        case SKARIF:
                    517:                sp->ctlinfo = (int*) cplabarr (3, (struct Labelblock**) c);
                    518:                break;
                    519:        case SKDOHEAD:
                    520:        case SKENDDO:
                    521:                sp->ctlinfo = (int*) cpframe ((struct Ctlframe*) c);
                    522:                break;
                    523:        default:
                    524:                break;
                    525:        }
                    526: 
                    527: frtempbuff ();
                    528: 
                    529: return (sp);
                    530: }
                    531: 
                    532: 
                    533: 
                    534: /*
                    535:  *  expands the given expression, if possible (e.g., concat, min, max, etc.);
                    536:  *  also frees temporaries when they are indicated as being the last use
                    537:  */
                    538: 
                    539: #define APPEND(z)      \
                    540:        res = res->exprblock.rightp = mkexpr (OPCOMMA, z, newtemp)
                    541: 
                    542: LOCAL expptr expand (p)
                    543: tagptr p;
                    544: 
                    545: {
                    546: Addrp t;
                    547: expptr q;
                    548: expptr buffmnmx(), buffpower();
                    549: 
                    550: if (!p)
                    551:        return (ENULL);
                    552: switch (p->tag)
                    553:        {
                    554:        case TEXPR:
                    555:                switch (p->exprblock.opcode)
                    556:                        {
                    557:                        case OPASSIGN: /* handle a = b // c */
                    558:                                if (p->exprblock.vtype != TYCHAR)
                    559:                                        goto standard;
                    560:                                q = p->exprblock.rightp;
                    561:                                if (!(q->tag == TEXPR &&
                    562:                                      q->exprblock.opcode == OPCONCAT))
                    563:                                        goto standard;
                    564:                                t = (Addrp) expand(p->exprblock.leftp);
                    565:                                frexpr(p->exprblock.vleng);
                    566:                                free( (charptr) p );
                    567:                                p = (tagptr) q;
                    568:                                goto cat;
                    569:                        case OPCONCAT:
                    570:                                t = mktemp (TYCHAR, ICON(lencat(p)));
                    571:                        cat:
                    572:                                q = (expptr) cpexpr (p->exprblock.vleng);
                    573:                                buffcat (cpexpr(t),p);
                    574:                                frexpr (t->vleng);
                    575:                                t->vleng = q;
                    576:                                p = (tagptr) t;
                    577:                                break;
                    578:                        case OPMIN:
                    579:                        case OPMAX:
                    580:                                p = (tagptr) buffmnmx (p);
                    581:                                break;
                    582:                        case OPPOWER:
                    583:                                p = (tagptr) buffpower (p);
                    584:                                break;
                    585:                        default:
                    586:                        standard:
                    587:                                p->exprblock.leftp =
                    588:                                        expand (p->exprblock.leftp);
                    589:                                if (p->exprblock.rightp)
                    590:                                        p->exprblock.rightp =
                    591:                                                expand (p->exprblock.rightp);
                    592:                                break;
                    593:                        }
                    594:                break;
                    595: 
                    596:        case TLIST:
                    597:                {
                    598:                chainp t;
                    599:                for (t = p->listblock.listp; t; t = t->nextp)
                    600:                        t->datap = (tagptr) expand (t->datap);
                    601:                }
                    602:                break;
                    603: 
                    604:        case TTEMP:
                    605:                if (p->tempblock.istemp)
                    606:                        frtemp(p);
                    607:                break;
                    608: 
                    609:        case TADDR:
                    610:                p->addrblock.memoffset = expand( p->addrblock.memoffset );
                    611:                break;
                    612: 
                    613:        default:
                    614:                break;
                    615:        }
                    616: return ((expptr) p);
                    617: }
                    618: 
                    619: 
                    620: 
                    621: /*
                    622:  *  local version of routine putcat in putpcc.c, called by expand
                    623:  */
                    624: 
                    625: LOCAL buffcat(lhs, rhs)
                    626: register Addrp lhs;
                    627: register expptr rhs;
                    628: {
                    629: int n;
                    630: Addrp lp, cp;
                    631: 
                    632: n = ncat(rhs);
                    633: lp = (Addrp) mkaltmpn(n, TYLENG, PNULL);
                    634: cp = (Addrp) mkaltmpn(n, TYADDR, PNULL);
                    635: 
                    636: n = 0;
                    637: buffct1(rhs, lp, cp, &n);
                    638: 
                    639: optbuff (SKCALL, call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n))),
                    640:        0, 0);
                    641: }
                    642: 
                    643: 
                    644: 
                    645: /*
                    646:  *  local version of routine putct1 in putpcc.c, called by expand
                    647:  */
                    648: 
                    649: LOCAL buffct1(q, lp, cp, ip)
                    650: register expptr q;
                    651: register Addrp lp, cp;
                    652: int *ip;
                    653: {
                    654: int i;
                    655: Addrp lp1, cp1;
                    656: 
                    657: if(q->tag==TEXPR && q->exprblock.opcode==OPCONCAT)
                    658:        {
                    659:        buffct1(q->exprblock.leftp, lp, cp, ip);
                    660:        buffct1(q->exprblock.rightp, lp, cp, ip);
                    661:        frexpr(q->exprblock.vleng);
                    662:        free( (charptr) q );
                    663:        }
                    664: else
                    665:        {
                    666:        i = (*ip)++;
                    667:        lp1 = (Addrp) cpexpr(lp);
                    668:        lp1->memoffset = mkexpr(OPPLUS,lp1->memoffset, ICON(i*SZLENG));
                    669:        cp1 = (Addrp) cpexpr(cp);
                    670:        cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR));
                    671:        optbuff (SKEQ, (mkexpr(OPASSIGN, lp1, cpexpr(q->headblock.vleng))),
                    672:                0,0);
                    673:        optbuff (SKEQ, (mkexpr(OPASSIGN, cp1, addrof(expand (q)))), 0, 0);
                    674:        }
                    675: }
                    676: 
                    677: 
                    678: 
                    679: /*
                    680:  *  local version of routine putmnmx in putpcc.c, called by expand
                    681:  */
                    682: 
                    683: LOCAL expptr buffmnmx(p)
                    684: register expptr p;
                    685: {
                    686: int op, type;
                    687: expptr qp;
                    688: chainp p0, p1;
                    689: Addrp sp, tp;
                    690: Addrp newtemp;
                    691: expptr result, res;
                    692: 
                    693: if(p->tag != TEXPR)
                    694:        badtag("buffmnmx", p->tag);
                    695: 
                    696: type = p->exprblock.vtype;
                    697: op = (p->exprblock.opcode==OPMIN ? OPLT : OPGT );
                    698: qp = expand(p->exprblock.leftp);
                    699: if(qp->tag != TLIST)
                    700:        badtag("buffmnmx list", qp->tag);
                    701: p0 = qp->listblock.listp;
                    702: free( (charptr) qp );
                    703: free( (charptr) p );
                    704: 
                    705: sp = mktemp(type, PNULL);
                    706: tp = mktemp(type, PNULL);
                    707: qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp));
                    708: qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp);
                    709: qp = fixexpr(qp);
                    710: 
                    711: newtemp = mktemp (type,PNULL);
                    712: 
                    713: result = res = mkexpr (OPCOMMA,
                    714:        mkexpr( OPASSIGN, cpexpr(sp), p0->datap ), cpexpr(newtemp));
                    715: 
                    716: for(p1 = p0->nextp ; p1 ; p1 = p1->nextp)
                    717:        {
                    718:        APPEND (mkexpr( OPASSIGN, cpexpr(tp), p1->datap ));
                    719:        if(p1->nextp)
                    720:                APPEND (mkexpr (OPASSIGN, cpexpr(sp), cpexpr(qp)) );
                    721:        else
                    722:                APPEND (mkexpr (OPASSIGN, cpexpr(newtemp), qp));
                    723:        }
                    724: 
                    725: frtemp(sp);
                    726: frtemp(tp);
                    727: frtemp(newtemp);
                    728: frchain( &p0 );
                    729: 
                    730: return (result);
                    731: }
                    732: 
                    733: 
                    734: 
                    735: /*
                    736:  * Called by expand() to eliminate exponentiations to integer constants.
                    737:  */
                    738: LOCAL expptr buffpower( p )
                    739:        expptr p;
                    740: {
                    741:        expptr base;
                    742:        Addrp newtemp;
                    743:        expptr storetemp = ENULL;
                    744:        expptr powtree();
                    745:        expptr result;
                    746:        ftnint exp;
                    747: 
                    748:        if ( ! ISICON( p->exprblock.rightp ) )
                    749:                fatal( "buffpower: bad non-integer exponent" );
                    750: 
                    751:        base = expand(p->exprblock.leftp);
                    752:        exp = p->exprblock.rightp->constblock.const.ci;
                    753:        if ( exp < 2 )
                    754:                fatal( "buffpower: bad exponent less than 2" );
                    755: 
                    756:        if ( exp > 64 ) {
                    757:                /*
                    758:                 * Let's be reasonable, here...  Let putpower() do the job.
                    759:                 */
                    760:                p->exprblock.leftp = base;
                    761:                return ( p );
                    762:        }
                    763: 
                    764:        /*
                    765:         * If the base is not a simple variable, evaluate it and copy the
                    766:         *      result into a temporary.
                    767:         */
                    768:        if ( ! (base->tag == TADDR && ISCONST( base->addrblock.memoffset )) ) {
                    769:                newtemp = mktemp( base->headblock.vtype, PNULL );
                    770:                storetemp = mkexpr( OPASSIGN,
                    771:                              cpexpr( (expptr) newtemp ),
                    772:                              cpexpr( base ) );
                    773:                base = (expptr) newtemp;
                    774:        }
                    775: 
                    776:        result = powtree( base, exp );
                    777: 
                    778:        if ( storetemp != ENULL )
                    779:                result = mkexpr( OPCOMMA, storetemp, result );
                    780:        frexpr( p );
                    781: 
                    782:        return ( result );
                    783: }
                    784: 
                    785: 
                    786: 
                    787: /*
                    788:  * powtree( base, exp ) -- Create a tree of multiplications which computes
                    789:  *     base ** exp.  The tree is built so that CSE will compact it if
                    790:  *     possible.  The routine works by creating subtrees that compute
                    791:  *     exponents which are powers of two, then multiplying these
                    792:  *     together to get the result; this gives a log2( exp ) tree depth
                    793:  *     and lots of subexpressions which can be eliminated.
                    794:  */
                    795: LOCAL expptr powtree( base, exp )
                    796:        expptr base;
                    797:        register ftnint exp;
                    798: {
                    799:        register expptr r = ENULL, r1;
                    800:        register int i;
                    801: 
                    802:        for ( i = 0; exp; ++i, exp >>= 1 )
                    803:                if ( exp & 1 )
                    804:                        if ( i == 0 )
                    805:                                r = (expptr) cpexpr( base );
                    806:                        else {
                    807:                                r1 = powtree( base, 1 << (i - 1) );
                    808:                                r1 = mkexpr( OPSTAR, r1, cpexpr( r1 ) );
                    809:                                r = (r ? mkexpr( OPSTAR, r1, r ) : r1);
                    810:                        }
                    811: 
                    812:        return ( r );
                    813: }

unix.superglobalmegacorp.com

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