122851Smckusick /* 222851Smckusick * Copyright (c) 1980 Regents of the University of California. 322851Smckusick * All rights reserved. The Berkeley software License Agreement 422851Smckusick * specifies the terms and conditions for redistribution. 522851Smckusick */ 622851Smckusick 722851Smckusick #ifndef lint 8*33257Sbostic static char sccsid[] = "@(#)optim.c 5.4 (Berkeley) 01/03/88"; 922851Smckusick #endif not lint 1022851Smckusick 1122851Smckusick /* 1222851Smckusick * optim.c 1322851Smckusick * 1422851Smckusick * Miscellaneous optimizer routines, f77 compiler pass 1. 1522851Smckusick * 1622851Smckusick * UCSD Chemistry modification history: 1722851Smckusick * 1822851Smckusick * $Log: optim.c,v $ 1926512Sdonn * Revision 5.2 86/03/04 17:47:08 donn 2026512Sdonn * Change buffcat() and buffct1() analogously to putcat and putct1() -- 2126512Sdonn * ensure that memoffset is evaluated before vleng. Take care not to 2226512Sdonn * screw up and return something other than an expression. 2326512Sdonn * 2426512Sdonn * Revision 5.1 85/08/10 03:48:42 donn 2526512Sdonn * 4.3 alpha 2626512Sdonn * 2723478Smckusick * Revision 2.12 85/06/08 22:57:01 donn 2823478Smckusick * Prevent core dumps -- bug in optinsert was causing lastslot to be wrong 2923478Smckusick * when a slot was inserted at the end of the buffer. 3023478Smckusick * 3122851Smckusick * Revision 2.11 85/03/18 08:05:05 donn 3222851Smckusick * Prevent warnings about implicit conversions. 3322851Smckusick * 3422851Smckusick * Revision 2.10 85/02/12 20:13:00 donn 3522851Smckusick * Resurrected the hack in 2.6.1.1 to avoid creating a temporary when 3622851Smckusick * there is a concatenation on the rhs of an assignment, and threw out 3722851Smckusick * all the code dealing with starcat(). It seems that we can't use a 3822851Smckusick * temporary because the lhs as well as the rhs may have nonconstant length. 3922851Smckusick * 4022851Smckusick * Revision 2.9 85/01/18 00:53:52 donn 4122851Smckusick * Missed a call to free() in the last change... 4222851Smckusick * 4322851Smckusick * Revision 2.8 85/01/18 00:50:03 donn 4422851Smckusick * Fixed goof made when modifying buffmnmx() to explicitly call expand(). 4522851Smckusick * 4622851Smckusick * Revision 2.7 85/01/15 18:47:35 donn 4722851Smckusick * Changes to allow character*(*) variables to appear in concatenations in 4822851Smckusick * the rhs of an assignment statement. 4922851Smckusick * 5022851Smckusick * Revision 2.6 84/12/16 21:46:27 donn 5122851Smckusick * Fixed bug that prevented concatenations from being run together. Changed 5222851Smckusick * buffpower() to not touch exponents greater than 64 -- let putpower do them. 5322851Smckusick * 5422851Smckusick * Revision 2.5 84/10/29 08:41:45 donn 5522851Smckusick * Added hack to flushopt() to prevent the compiler from trying to generate 5622851Smckusick * intermediate code after an error. 5722851Smckusick * 5822851Smckusick * Revision 2.4 84/08/07 21:28:00 donn 5922851Smckusick * Removed call to p2flush() in putopt() -- this allows us to make better use 6022851Smckusick * of the buffering on the intermediate code file. 6122851Smckusick * 6222851Smckusick * Revision 2.3 84/08/01 16:06:24 donn 6322851Smckusick * Forced expand() to expand subscripts. 6422851Smckusick * 6522851Smckusick * Revision 2.2 84/07/19 20:21:55 donn 6622851Smckusick * Decided I liked the expression tree algorithm after all. The algorithm 6722851Smckusick * which repeatedly squares temporaries is now checked in as rev. 2.1. 6822851Smckusick * 6922851Smckusick * Revision 1.3.1.1 84/07/10 14:18:18 donn 7022851Smckusick * I'm taking this branch off the trunk -- it works but it's not as good as 7122851Smckusick * the old version would be if it worked right. 7222851Smckusick * 7322851Smckusick * Revision 1.5 84/07/09 22:28:50 donn 7422851Smckusick * Added fix to buffpower() to prevent it chasing after huge exponents. 7522851Smckusick * 7622851Smckusick * Revision 1.4 84/07/09 20:13:59 donn 7722851Smckusick * Replaced buffpower() routine with a new one that generates trees which can 7822851Smckusick * be handled by CSE later on. 7922851Smckusick * 8022851Smckusick * Revision 1.3 84/05/04 21:02:07 donn 8122851Smckusick * Added fix for a bug in buffpower() that caused func(x)**2 to turn into 8222851Smckusick * func(x) * func(x). This bug had already been fixed in putpower()... 8322851Smckusick * 8422851Smckusick * Revision 1.2 84/03/23 22:47:21 donn 8522851Smckusick * The subroutine argument temporary fixes from Bob Corbett didn't take into 8622851Smckusick * account the fact that the code generator collects all the assignments to 8722851Smckusick * temporaries at the start of a statement -- hence the temporaries need to 8822851Smckusick * be initialized once per statement instead of once per call. 8922851Smckusick * 9022851Smckusick */ 9122851Smckusick 9222851Smckusick #include "defs.h" 9322851Smckusick #include "optim.h" 9422851Smckusick 9522851Smckusick 9622851Smckusick 9722851Smckusick /* 9822851Smckusick * Information buffered for each slot type 9922851Smckusick * 10022851Smckusick * slot type expptr integer pointer 10122851Smckusick * 10222851Smckusick * IFN expr label - 10322851Smckusick * GOTO - label - 10422851Smckusick * LABEL - label - 10522851Smckusick * EQ expr - - 10622851Smckusick * CALL expr - - 10722851Smckusick * CMGOTO expr num labellist* 10822851Smckusick * STOP expr - - 10922851Smckusick * DOHEAD [1] - ctlframe* 11022851Smckusick * ENDDO [1] - ctlframe* 11122851Smckusick * ARIF expr - labellist* 11222851Smckusick * RETURN expr label - 11322851Smckusick * ASGOTO expr - labellist* 11422851Smckusick * PAUSE expr - - 11522851Smckusick * ASSIGN expr label - 11622851Smckusick * SKIOIFN expr label - 11722851Smckusick * SKFRTEMP expr - - 11822851Smckusick * 11922851Smckusick * Note [1]: the nullslot field is a pointer to a fake slot which is 12022851Smckusick * at the end of the slots which may be replaced by this slot. In 12122851Smckusick * other words, it looks like this: 12222851Smckusick * DOHEAD slot 12322851Smckusick * slot \ 12422851Smckusick * slot > ordinary IF, GOTO, LABEL slots which implement the DO 12522851Smckusick * slot / 12622851Smckusick * NULL slot 12722851Smckusick */ 12822851Smckusick 12922851Smckusick 13022851Smckusick expptr expand(); 13122851Smckusick 13222851Smckusick Slotp firstslot = NULL; 13322851Smckusick Slotp lastslot = NULL; 13422851Smckusick int numslots = 0; 13522851Smckusick 13622851Smckusick 13722851Smckusick /* 13822851Smckusick * turns off optimization option 13922851Smckusick */ 14022851Smckusick 14122851Smckusick optoff() 14222851Smckusick 14322851Smckusick { 14422851Smckusick flushopt(); 14522851Smckusick optimflag = 0; 14622851Smckusick } 14722851Smckusick 14822851Smckusick 14922851Smckusick 15022851Smckusick /* 15122851Smckusick * initializes the code buffer for optimization 15222851Smckusick */ 15322851Smckusick 15422851Smckusick setopt() 15522851Smckusick 15622851Smckusick { 15722851Smckusick register Slotp sp; 15822851Smckusick 15922851Smckusick for (sp = firstslot; sp; sp = sp->next) 16022851Smckusick free ( (charptr) sp); 16122851Smckusick firstslot = lastslot = NULL; 16222851Smckusick numslots = 0; 16322851Smckusick } 16422851Smckusick 16522851Smckusick 16622851Smckusick 16722851Smckusick /* 16822851Smckusick * flushes the code buffer 16922851Smckusick */ 17022851Smckusick 17122851Smckusick LOCAL int alreadycalled = 0; 17222851Smckusick 17322851Smckusick flushopt() 17422851Smckusick { 17522851Smckusick register Slotp sp; 17622851Smckusick int savelineno; 17722851Smckusick 17822851Smckusick if (alreadycalled) return; /* to prevent recursive call during errors */ 17922851Smckusick alreadycalled = 1; 18022851Smckusick 18122851Smckusick if (debugflag[1]) 18222851Smckusick showbuffer (); 18322851Smckusick 18422851Smckusick frtempbuff (); 18522851Smckusick 18622851Smckusick savelineno = lineno; 18722851Smckusick for (sp = firstslot; sp; sp = sp->next) 18822851Smckusick { 18922851Smckusick if (nerr == 0) 19022851Smckusick putopt (sp); 19122851Smckusick else 19222851Smckusick frexpr (sp->expr); 19322851Smckusick if(sp->ctlinfo) free ( (charptr) sp->ctlinfo); 19422851Smckusick free ( (charptr) sp); 19522851Smckusick numslots--; 19622851Smckusick } 19722851Smckusick firstslot = lastslot = NULL; 19822851Smckusick numslots = 0; 19922851Smckusick clearbb(); 20022851Smckusick lineno = savelineno; 20122851Smckusick 20222851Smckusick alreadycalled = 0; 20322851Smckusick } 20422851Smckusick 20522851Smckusick 20622851Smckusick 20722851Smckusick /* 20822851Smckusick * puts out code for the given slot (from the code buffer) 20922851Smckusick */ 21022851Smckusick 21122851Smckusick LOCAL putopt (sp) 21222851Smckusick register Slotp sp; 21322851Smckusick { 21422851Smckusick lineno = sp->lineno; 21522851Smckusick switch (sp->type) { 21622851Smckusick case SKNULL: 21722851Smckusick break; 21822851Smckusick case SKIFN: 21922851Smckusick case SKIOIFN: 22022851Smckusick putif(sp->expr, sp->label); 22122851Smckusick break; 22222851Smckusick case SKGOTO: 22322851Smckusick putgoto(sp->label); 22422851Smckusick break; 22522851Smckusick case SKCMGOTO: 22622851Smckusick putcmgo(sp->expr, sp->label, sp->ctlinfo); 22722851Smckusick break; 22822851Smckusick case SKCALL: 22922851Smckusick putexpr(sp->expr); 23022851Smckusick break; 23122851Smckusick case SKSTOP: 23222851Smckusick putexpr (call1 (TYSUBR, "s_stop", sp->expr)); 23322851Smckusick break; 23422851Smckusick case SKPAUSE: 23522851Smckusick putexpr (call1 (TYSUBR, "s_paus", sp->expr)); 23622851Smckusick break; 23722851Smckusick case SKASSIGN: 23822851Smckusick puteq (sp->expr, 23922851Smckusick intrconv(sp->expr->headblock.vtype, mkaddcon(sp->label))); 24022851Smckusick break; 24122851Smckusick case SKDOHEAD: 24222851Smckusick case SKENDDO: 24322851Smckusick break; 24422851Smckusick case SKEQ: 24522851Smckusick putexpr(sp->expr); 24622851Smckusick break; 24722851Smckusick case SKARIF: 24822851Smckusick #define LM ((struct Labelblock * *)sp->ctlinfo)[0]->labelno 24922851Smckusick #define LZ ((struct Labelblock * *)sp->ctlinfo)[1]->labelno 25022851Smckusick #define LP ((struct Labelblock * *)sp->ctlinfo)[2]->labelno 25122851Smckusick prarif(sp->expr, LM, LZ, LP); 25222851Smckusick break; 25322851Smckusick case SKASGOTO: 25422851Smckusick putbranch((Addrp) sp->expr); 25522851Smckusick break; 25622851Smckusick case SKLABEL: 25722851Smckusick putlabel(sp->label); 25822851Smckusick break; 25922851Smckusick case SKRETURN: 26022851Smckusick if (sp->expr) 26122851Smckusick { 26222851Smckusick putforce(TYINT, sp->expr); 26322851Smckusick putgoto(sp->label); 26422851Smckusick } 26522851Smckusick else 26622851Smckusick putgoto(sp->label); 26722851Smckusick break; 26822851Smckusick case SKFRTEMP: 26922851Smckusick templist = mkchain (sp->expr,templist); 27022851Smckusick break; 27122851Smckusick default: 27222851Smckusick badthing("SKtype", "putopt", sp->type); 27322851Smckusick break; 27422851Smckusick } 27522851Smckusick 27622851Smckusick /* 27722851Smckusick * Recycle argument temporaries here. This must get done on a 27822851Smckusick * statement-by-statement basis because the code generator 27922851Smckusick * makes side effects happen at the start of a statement. 28022851Smckusick */ 28122851Smckusick argtemplist = hookup(argtemplist, activearglist); 28222851Smckusick activearglist = CHNULL; 28322851Smckusick } 28422851Smckusick 28522851Smckusick 28622851Smckusick 28722851Smckusick /* 28822851Smckusick * copies one element of the control stack 28922851Smckusick */ 29022851Smckusick 29122851Smckusick LOCAL struct Ctlframe *cpframe(p) 29222851Smckusick register char *p; 29322851Smckusick { 29422851Smckusick static int size = sizeof (struct Ctlframe); 29522851Smckusick register int n; 29622851Smckusick register char *q; 29722851Smckusick struct Ctlframe *q0; 29822851Smckusick 29922851Smckusick q0 = ALLOC(Ctlframe); 30022851Smckusick q = (char *) q0; 30122851Smckusick n = size; 30222851Smckusick while(n-- > 0) 30322851Smckusick *q++ = *p++; 30422851Smckusick return( q0); 30522851Smckusick } 30622851Smckusick 30722851Smckusick 30822851Smckusick 30922851Smckusick /* 31022851Smckusick * copies an array of labelblock pointers 31122851Smckusick */ 31222851Smckusick 31322851Smckusick LOCAL struct Labelblock **cplabarr(n,arr) 31422851Smckusick struct Labelblock *arr[]; 31522851Smckusick int n; 31622851Smckusick { 31722851Smckusick struct Labelblock **newarr; 31822851Smckusick register char *in, *out; 31922851Smckusick register int i,j; 32022851Smckusick 32122851Smckusick newarr = (struct Labelblock **) ckalloc (n * sizeof (char *)); 32222851Smckusick for (i = 0; i < n; i++) 32322851Smckusick { 32422851Smckusick newarr[i] = ALLOC (Labelblock); 32522851Smckusick out = (char *) newarr[i]; 32622851Smckusick in = (char *) arr[i]; 32722851Smckusick j = sizeof (struct Labelblock); 32822851Smckusick while (j-- > 0) 32922851Smckusick *out++ = *in++; 33022851Smckusick } 33122851Smckusick return (newarr); 33222851Smckusick } 33322851Smckusick 33422851Smckusick 33522851Smckusick 33622851Smckusick /* 33722851Smckusick * creates a new slot in the code buffer 33822851Smckusick */ 33922851Smckusick 34022851Smckusick LOCAL Slotp newslot() 34122851Smckusick { 34222851Smckusick register Slotp sp; 34322851Smckusick 34422851Smckusick ++numslots; 34522851Smckusick sp = ALLOC( slt ); 34622851Smckusick sp->next = NULL ; 34722851Smckusick if (lastslot) 34822851Smckusick { 34922851Smckusick sp->prev = lastslot; 35022851Smckusick lastslot = lastslot->next = sp; 35122851Smckusick } 35222851Smckusick else 35322851Smckusick { 35422851Smckusick firstslot = lastslot = sp; 35522851Smckusick sp->prev = NULL; 35622851Smckusick } 35722851Smckusick sp->lineno = lineno; 35822851Smckusick return (sp); 35922851Smckusick } 36022851Smckusick 36122851Smckusick 36222851Smckusick 36322851Smckusick /* 36422851Smckusick * removes (but not deletes) the specified slot from the code buffer 36522851Smckusick */ 36622851Smckusick 36722851Smckusick removeslot (sl) 36822851Smckusick Slotp sl; 36922851Smckusick 37022851Smckusick { 37122851Smckusick if (sl->next) 37222851Smckusick sl->next->prev = sl->prev; 37322851Smckusick else 37422851Smckusick lastslot = sl->prev; 37522851Smckusick if (sl->prev) 37622851Smckusick sl->prev->next = sl->next; 37722851Smckusick else 37822851Smckusick firstslot = sl->next; 37922851Smckusick sl->next = sl->prev = NULL; 38022851Smckusick 38122851Smckusick --numslots; 38222851Smckusick } 38322851Smckusick 38422851Smckusick 38522851Smckusick 38622851Smckusick /* 38722851Smckusick * inserts slot s1 before existing slot s2 in the code buffer; 38822851Smckusick * appends to end of list if s2 is NULL. 38922851Smckusick */ 39022851Smckusick 39122851Smckusick insertslot (s1,s2) 39222851Smckusick Slotp s1,s2; 39322851Smckusick 39422851Smckusick { 39522851Smckusick if (s2) 39622851Smckusick { 39722851Smckusick if (s2->prev) 39822851Smckusick s2->prev->next = s1; 39922851Smckusick else 40022851Smckusick firstslot = s1; 40122851Smckusick s1->prev = s2->prev; 40222851Smckusick s2->prev = s1; 40322851Smckusick } 40422851Smckusick else 40522851Smckusick { 40622851Smckusick s1->prev = lastslot; 40722851Smckusick lastslot->next = s1; 40822851Smckusick lastslot = s1; 40922851Smckusick } 41022851Smckusick s1->next = s2; 41122851Smckusick 41222851Smckusick ++numslots; 41322851Smckusick } 41422851Smckusick 41522851Smckusick 41622851Smckusick 41722851Smckusick /* 41822851Smckusick * deletes the specified slot from the code buffer 41922851Smckusick */ 42022851Smckusick 42122851Smckusick delslot (sl) 42222851Smckusick Slotp sl; 42322851Smckusick 42422851Smckusick { 42522851Smckusick removeslot (sl); 42622851Smckusick 42722851Smckusick if (sl->ctlinfo) 42822851Smckusick free ((charptr) sl->ctlinfo); 42922851Smckusick frexpr (sl->expr); 43022851Smckusick free ((charptr) sl); 43122851Smckusick numslots--; 43222851Smckusick } 43322851Smckusick 43422851Smckusick 43522851Smckusick 43622851Smckusick /* 43722851Smckusick * inserts a slot before the specified slot; if given NULL, it is 43822851Smckusick * inserted at the end of the buffer 43922851Smckusick */ 44022851Smckusick 44122851Smckusick Slotp optinsert (type,p,l,c,currslot) 44222851Smckusick int type; 44322851Smckusick expptr p; 44422851Smckusick int l; 44522851Smckusick int *c; 44622851Smckusick Slotp currslot; 44722851Smckusick 44822851Smckusick { 44922851Smckusick Slotp savelast,new; 45022851Smckusick 45122851Smckusick savelast = lastslot; 45222851Smckusick if (currslot) 45322851Smckusick lastslot = currslot->prev; 45422851Smckusick new = optbuff (type,p,l,c); 45522851Smckusick new->next = currslot; 45622851Smckusick if (currslot) 45722851Smckusick currslot->prev = new; 45822851Smckusick new->lineno = -1; /* who knows what the line number should be ??!! */ 45923478Smckusick if (currslot) 46023478Smckusick lastslot = savelast; 46122851Smckusick return (new); 46222851Smckusick } 46322851Smckusick 46422851Smckusick 46522851Smckusick 46622851Smckusick /* 46722851Smckusick * buffers the FRTEMP slots which have been waiting 46822851Smckusick */ 46922851Smckusick 47022851Smckusick frtempbuff () 47122851Smckusick 47222851Smckusick { 47322851Smckusick chainp ht; 47422851Smckusick register Slotp sp; 47522851Smckusick 47622851Smckusick for (ht = holdtemps; ht; ht = ht->nextp) 47722851Smckusick { 47822851Smckusick sp = newslot(); 47922851Smckusick /* this slot actually belongs to some previous source line */ 48022851Smckusick sp->lineno = sp->lineno - 1; 48122851Smckusick sp->type = SKFRTEMP; 48222851Smckusick sp->expr = (expptr) ht->datap; 48322851Smckusick sp->label = 0; 48422851Smckusick sp->ctlinfo = NULL; 48522851Smckusick } 48622851Smckusick holdtemps = NULL; 48722851Smckusick } 48822851Smckusick 48922851Smckusick 49022851Smckusick 49122851Smckusick /* 49222851Smckusick * puts the given information into a slot at the end of the code buffer 49322851Smckusick */ 49422851Smckusick 49522851Smckusick Slotp optbuff (type,p,l,c) 49622851Smckusick int type; 49722851Smckusick expptr p; 49822851Smckusick int l; 49922851Smckusick int *c; 50022851Smckusick 50122851Smckusick { 50222851Smckusick register Slotp sp; 50322851Smckusick 50422851Smckusick if (debugflag[1]) 50522851Smckusick { 50622851Smckusick fprintf (diagfile,"-----optbuff-----"); showslottype (type); 50722851Smckusick showexpr (p,0); fprintf (diagfile,"\n"); 50822851Smckusick } 50922851Smckusick 51022851Smckusick p = expand (p); 51122851Smckusick sp = newslot(); 51222851Smckusick sp->type = type; 51322851Smckusick sp->expr = p; 51422851Smckusick sp->label = l; 51522851Smckusick sp->ctlinfo = NULL; 51622851Smckusick switch (type) 51722851Smckusick { 51822851Smckusick case SKCMGOTO: 51922851Smckusick sp->ctlinfo = (int*) cplabarr (l, (struct Labelblock**) c); 52022851Smckusick break; 52122851Smckusick case SKARIF: 52222851Smckusick sp->ctlinfo = (int*) cplabarr (3, (struct Labelblock**) c); 52322851Smckusick break; 52422851Smckusick case SKDOHEAD: 52522851Smckusick case SKENDDO: 52622851Smckusick sp->ctlinfo = (int*) cpframe ((struct Ctlframe*) c); 52722851Smckusick break; 52822851Smckusick default: 52922851Smckusick break; 53022851Smckusick } 53122851Smckusick 53222851Smckusick frtempbuff (); 53322851Smckusick 53422851Smckusick return (sp); 53522851Smckusick } 53622851Smckusick 53722851Smckusick 53822851Smckusick 53922851Smckusick /* 54022851Smckusick * expands the given expression, if possible (e.g., concat, min, max, etc.); 54122851Smckusick * also frees temporaries when they are indicated as being the last use 54222851Smckusick */ 54322851Smckusick 54422851Smckusick #define APPEND(z) \ 54522851Smckusick res = res->exprblock.rightp = mkexpr (OPCOMMA, z, newtemp) 54622851Smckusick 54722851Smckusick LOCAL expptr expand (p) 54822851Smckusick tagptr p; 54922851Smckusick 55022851Smckusick { 55122851Smckusick Addrp t; 55222851Smckusick expptr q; 55326512Sdonn expptr buffmnmx(), buffpower(), buffcat(); 55422851Smckusick 55522851Smckusick if (!p) 55622851Smckusick return (ENULL); 55722851Smckusick switch (p->tag) 55822851Smckusick { 55922851Smckusick case TEXPR: 56022851Smckusick switch (p->exprblock.opcode) 56122851Smckusick { 56222851Smckusick case OPASSIGN: /* handle a = b // c */ 56322851Smckusick if (p->exprblock.vtype != TYCHAR) 56422851Smckusick goto standard; 56522851Smckusick q = p->exprblock.rightp; 56622851Smckusick if (!(q->tag == TEXPR && 56722851Smckusick q->exprblock.opcode == OPCONCAT)) 56822851Smckusick goto standard; 56922851Smckusick t = (Addrp) expand(p->exprblock.leftp); 57022851Smckusick frexpr(p->exprblock.vleng); 57122851Smckusick free( (charptr) p ); 57222851Smckusick p = (tagptr) q; 57322851Smckusick goto cat; 57422851Smckusick case OPCONCAT: 57522851Smckusick t = mktemp (TYCHAR, ICON(lencat(p))); 57622851Smckusick cat: 57722851Smckusick q = (expptr) cpexpr (p->exprblock.vleng); 57826512Sdonn p = (tagptr) buffcat (t, p); 57926512Sdonn frexpr (p->headblock.vleng); 58026512Sdonn p->headblock.vleng = q; 58122851Smckusick break; 58222851Smckusick case OPMIN: 58322851Smckusick case OPMAX: 58422851Smckusick p = (tagptr) buffmnmx (p); 58522851Smckusick break; 58622851Smckusick case OPPOWER: 58722851Smckusick p = (tagptr) buffpower (p); 58822851Smckusick break; 58922851Smckusick default: 59022851Smckusick standard: 59122851Smckusick p->exprblock.leftp = 59222851Smckusick expand (p->exprblock.leftp); 59322851Smckusick if (p->exprblock.rightp) 59422851Smckusick p->exprblock.rightp = 59522851Smckusick expand (p->exprblock.rightp); 59622851Smckusick break; 59722851Smckusick } 59822851Smckusick break; 59922851Smckusick 60022851Smckusick case TLIST: 60122851Smckusick { 60222851Smckusick chainp t; 60322851Smckusick for (t = p->listblock.listp; t; t = t->nextp) 60422851Smckusick t->datap = (tagptr) expand (t->datap); 60522851Smckusick } 60622851Smckusick break; 60722851Smckusick 60822851Smckusick case TTEMP: 60922851Smckusick if (p->tempblock.istemp) 61022851Smckusick frtemp(p); 61122851Smckusick break; 61222851Smckusick 61322851Smckusick case TADDR: 61422851Smckusick p->addrblock.memoffset = expand( p->addrblock.memoffset ); 61522851Smckusick break; 61622851Smckusick 61722851Smckusick default: 61822851Smckusick break; 61922851Smckusick } 62022851Smckusick return ((expptr) p); 62122851Smckusick } 62222851Smckusick 62322851Smckusick 62422851Smckusick 62522851Smckusick /* 62622851Smckusick * local version of routine putcat in putpcc.c, called by expand 62722851Smckusick */ 62822851Smckusick 62926512Sdonn LOCAL expptr buffcat(lhs, rhs) 63022851Smckusick register Addrp lhs; 63122851Smckusick register expptr rhs; 63222851Smckusick { 63322851Smckusick int n; 63422851Smckusick Addrp lp, cp; 63526512Sdonn expptr ep, buffct1(); 63622851Smckusick 63722851Smckusick n = ncat(rhs); 63822851Smckusick lp = (Addrp) mkaltmpn(n, TYLENG, PNULL); 63922851Smckusick cp = (Addrp) mkaltmpn(n, TYADDR, PNULL); 64022851Smckusick 64122851Smckusick n = 0; 64226512Sdonn ep = buffct1(rhs, lp, cp, &n); 64322851Smckusick 64426512Sdonn ep = mkexpr(OPCOMMA, ep, 64526512Sdonn call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n)))); 64626512Sdonn 64726512Sdonn return (ep); 64822851Smckusick } 64922851Smckusick 65022851Smckusick 65122851Smckusick 65222851Smckusick /* 65322851Smckusick * local version of routine putct1 in putpcc.c, called by expand 65422851Smckusick */ 65522851Smckusick 65626512Sdonn LOCAL expptr buffct1(q, lp, cp, ip) 65722851Smckusick register expptr q; 65822851Smckusick register Addrp lp, cp; 65922851Smckusick int *ip; 66022851Smckusick { 66122851Smckusick int i; 66222851Smckusick Addrp lp1, cp1; 66326512Sdonn expptr eleft, eright; 66422851Smckusick 66522851Smckusick if(q->tag==TEXPR && q->exprblock.opcode==OPCONCAT) 66622851Smckusick { 66726512Sdonn eleft = buffct1(q->exprblock.leftp, lp, cp, ip); 66826512Sdonn eright = buffct1(q->exprblock.rightp, lp, cp, ip); 66922851Smckusick frexpr(q->exprblock.vleng); 67022851Smckusick free( (charptr) q ); 67122851Smckusick } 67222851Smckusick else 67322851Smckusick { 67422851Smckusick i = (*ip)++; 67522851Smckusick cp1 = (Addrp) cpexpr(cp); 67622851Smckusick cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR)); 67726512Sdonn lp1 = (Addrp) cpexpr(lp); 67826512Sdonn lp1->memoffset = mkexpr(OPPLUS, lp1->memoffset, ICON(i*SZLENG)); 67926512Sdonn eleft = mkexpr(OPASSIGN, cp1, addrof(expand(cpexpr(q)))); 68026512Sdonn eright = mkexpr(OPASSIGN, lp1, cpexpr(q->headblock.vleng)); 68126512Sdonn frexpr(q); 68222851Smckusick } 68326512Sdonn return (mkexpr(OPCOMMA, eleft, eright)); 68422851Smckusick } 68522851Smckusick 68622851Smckusick 68722851Smckusick 68822851Smckusick /* 68922851Smckusick * local version of routine putmnmx in putpcc.c, called by expand 69022851Smckusick */ 69122851Smckusick 69222851Smckusick LOCAL expptr buffmnmx(p) 69322851Smckusick register expptr p; 69422851Smckusick { 69522851Smckusick int op, type; 69622851Smckusick expptr qp; 69722851Smckusick chainp p0, p1; 69822851Smckusick Addrp sp, tp; 69922851Smckusick Addrp newtemp; 70022851Smckusick expptr result, res; 70122851Smckusick 70222851Smckusick if(p->tag != TEXPR) 70322851Smckusick badtag("buffmnmx", p->tag); 70422851Smckusick 70522851Smckusick type = p->exprblock.vtype; 70622851Smckusick op = (p->exprblock.opcode==OPMIN ? OPLT : OPGT ); 70722851Smckusick qp = expand(p->exprblock.leftp); 70822851Smckusick if(qp->tag != TLIST) 70922851Smckusick badtag("buffmnmx list", qp->tag); 71022851Smckusick p0 = qp->listblock.listp; 71122851Smckusick free( (charptr) qp ); 71222851Smckusick free( (charptr) p ); 71322851Smckusick 71422851Smckusick sp = mktemp(type, PNULL); 71522851Smckusick tp = mktemp(type, PNULL); 71622851Smckusick qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp)); 71722851Smckusick qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp); 71822851Smckusick qp = fixexpr(qp); 71922851Smckusick 72022851Smckusick newtemp = mktemp (type,PNULL); 72122851Smckusick 72222851Smckusick result = res = mkexpr (OPCOMMA, 72322851Smckusick mkexpr( OPASSIGN, cpexpr(sp), p0->datap ), cpexpr(newtemp)); 72422851Smckusick 72522851Smckusick for(p1 = p0->nextp ; p1 ; p1 = p1->nextp) 72622851Smckusick { 72722851Smckusick APPEND (mkexpr( OPASSIGN, cpexpr(tp), p1->datap )); 72822851Smckusick if(p1->nextp) 72922851Smckusick APPEND (mkexpr (OPASSIGN, cpexpr(sp), cpexpr(qp)) ); 73022851Smckusick else 73122851Smckusick APPEND (mkexpr (OPASSIGN, cpexpr(newtemp), qp)); 73222851Smckusick } 73322851Smckusick 73422851Smckusick frtemp(sp); 73522851Smckusick frtemp(tp); 73622851Smckusick frtemp(newtemp); 73722851Smckusick frchain( &p0 ); 73822851Smckusick 73922851Smckusick return (result); 74022851Smckusick } 74122851Smckusick 74222851Smckusick 74322851Smckusick 74422851Smckusick /* 74522851Smckusick * Called by expand() to eliminate exponentiations to integer constants. 74622851Smckusick */ 74722851Smckusick LOCAL expptr buffpower( p ) 74822851Smckusick expptr p; 74922851Smckusick { 75022851Smckusick expptr base; 75122851Smckusick Addrp newtemp; 75222851Smckusick expptr storetemp = ENULL; 75322851Smckusick expptr powtree(); 75422851Smckusick expptr result; 75522851Smckusick ftnint exp; 75622851Smckusick 75722851Smckusick if ( ! ISICON( p->exprblock.rightp ) ) 75822851Smckusick fatal( "buffpower: bad non-integer exponent" ); 75922851Smckusick 76022851Smckusick base = expand(p->exprblock.leftp); 761*33257Sbostic exp = p->exprblock.rightp->constblock.constant.ci; 76222851Smckusick if ( exp < 2 ) 76322851Smckusick fatal( "buffpower: bad exponent less than 2" ); 76422851Smckusick 76522851Smckusick if ( exp > 64 ) { 76622851Smckusick /* 76722851Smckusick * Let's be reasonable, here... Let putpower() do the job. 76822851Smckusick */ 76922851Smckusick p->exprblock.leftp = base; 77022851Smckusick return ( p ); 77122851Smckusick } 77222851Smckusick 77322851Smckusick /* 77422851Smckusick * If the base is not a simple variable, evaluate it and copy the 77522851Smckusick * result into a temporary. 77622851Smckusick */ 77722851Smckusick if ( ! (base->tag == TADDR && ISCONST( base->addrblock.memoffset )) ) { 77822851Smckusick newtemp = mktemp( base->headblock.vtype, PNULL ); 77922851Smckusick storetemp = mkexpr( OPASSIGN, 78022851Smckusick cpexpr( (expptr) newtemp ), 78122851Smckusick cpexpr( base ) ); 78222851Smckusick base = (expptr) newtemp; 78322851Smckusick } 78422851Smckusick 78522851Smckusick result = powtree( base, exp ); 78622851Smckusick 78722851Smckusick if ( storetemp != ENULL ) 78822851Smckusick result = mkexpr( OPCOMMA, storetemp, result ); 78922851Smckusick frexpr( p ); 79022851Smckusick 79122851Smckusick return ( result ); 79222851Smckusick } 79322851Smckusick 79422851Smckusick 79522851Smckusick 79622851Smckusick /* 79722851Smckusick * powtree( base, exp ) -- Create a tree of multiplications which computes 79822851Smckusick * base ** exp. The tree is built so that CSE will compact it if 79922851Smckusick * possible. The routine works by creating subtrees that compute 80022851Smckusick * exponents which are powers of two, then multiplying these 80122851Smckusick * together to get the result; this gives a log2( exp ) tree depth 80222851Smckusick * and lots of subexpressions which can be eliminated. 80322851Smckusick */ 80422851Smckusick LOCAL expptr powtree( base, exp ) 80522851Smckusick expptr base; 80622851Smckusick register ftnint exp; 80722851Smckusick { 80822851Smckusick register expptr r = ENULL, r1; 80922851Smckusick register int i; 81022851Smckusick 81122851Smckusick for ( i = 0; exp; ++i, exp >>= 1 ) 81222851Smckusick if ( exp & 1 ) 81322851Smckusick if ( i == 0 ) 81422851Smckusick r = (expptr) cpexpr( base ); 81522851Smckusick else { 81622851Smckusick r1 = powtree( base, 1 << (i - 1) ); 81722851Smckusick r1 = mkexpr( OPSTAR, r1, cpexpr( r1 ) ); 81822851Smckusick r = (r ? mkexpr( OPSTAR, r1, r ) : r1); 81922851Smckusick } 82022851Smckusick 82122851Smckusick return ( r ); 82222851Smckusick } 823