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

unix.superglobalmegacorp.com

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