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