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