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