1*b8be84b8Sbostic /*-
2*b8be84b8Sbostic  * Copyright (c) 1980 The Regents of the University of California.
3*b8be84b8Sbostic  * All rights reserved.
4*b8be84b8Sbostic  *
5*b8be84b8Sbostic  * %sccs.include.proprietary.c%
684bba364Sbostic  */
784bba364Sbostic 
884bba364Sbostic #ifndef lint
9*b8be84b8Sbostic static char sccsid[] = "@(#)optloop.c	5.3 (Berkeley) 04/12/91";
10*b8be84b8Sbostic #endif /* not lint */
1184bba364Sbostic 
1284bba364Sbostic /*
1384bba364Sbostic  * optloop.c
1484bba364Sbostic  *
1584bba364Sbostic  * Loop optimizations, f77 compiler pass 1, 4.2 BSD.
1684bba364Sbostic  *
1784bba364Sbostic  * University of Utah CS Dept. modification history:
1884bba364Sbostic  *
1984bba364Sbostic  * $Log:	optloop.c,v $
2084bba364Sbostic  * Revision 1.4  84/10/25  01:27:29  donn
2184bba364Sbostic  * Fixed a subtle bug in removesafe().  When the moved code is an assignment
2284bba364Sbostic  * into a temporary, we use the lhs to substitute for the expression inside
2384bba364Sbostic  * the loop.  Previously the data structure for the temporary was not copied,
2484bba364Sbostic  * so later on when the lhs was freed, the substitute was too, turning it
2584bba364Sbostic  * into garbage.
2684bba364Sbostic  *
2784bba364Sbostic  * Revision 1.3  84/08/05  17:04:03  donn
2884bba364Sbostic  * Changed worthcost() so that it skips variable length strings -- we can't
2984bba364Sbostic  * make temporaries for these...
3084bba364Sbostic  *
3184bba364Sbostic  * Revision 1.2  84/07/19  11:50:39  donn
3284bba364Sbostic  * Installed changes to force non-intrinsic subroutines and functions to define
3384bba364Sbostic  * their arguments (make them ineligible for optimization), function setsuses.
3484bba364Sbostic  * Fix from A.F.
3584bba364Sbostic  *
3684bba364Sbostic  */
3784bba364Sbostic 
3884bba364Sbostic #include "defs.h"
3984bba364Sbostic #include "optim.h"
4084bba364Sbostic 
4184bba364Sbostic 
4284bba364Sbostic #define SCFREE   0
4384bba364Sbostic #define SCSAFE   1
4484bba364Sbostic 
4584bba364Sbostic 
4684bba364Sbostic 
4784bba364Sbostic typedef
4884bba364Sbostic   struct varblock
4984bba364Sbostic     {
5084bba364Sbostic       struct varblock *next;
5184bba364Sbostic       field vstg;
5284bba364Sbostic       int memno;	/* holds memalloc for TTEMP */
5384bba364Sbostic       short sets;
5484bba364Sbostic       short uses;
5584bba364Sbostic       field setfirst;
5684bba364Sbostic     } VARBLOCK;
5784bba364Sbostic 
5884bba364Sbostic typedef VARBLOCK *Varp;
5984bba364Sbostic 
6084bba364Sbostic #define TABLESIZE 59
6184bba364Sbostic 
6284bba364Sbostic LOCAL Varp table[TABLESIZE];
6384bba364Sbostic 
6484bba364Sbostic 
6584bba364Sbostic 
mkbucket(vstg,memno)6684bba364Sbostic LOCAL Varp mkbucket(vstg,memno)
6784bba364Sbostic field vstg;
6884bba364Sbostic int memno;
6984bba364Sbostic 
7084bba364Sbostic {
7184bba364Sbostic   Varp q;
7284bba364Sbostic 
7384bba364Sbostic   q = ALLOC(varblock);
7484bba364Sbostic   q->vstg = vstg;
7584bba364Sbostic   q->memno = memno;
7684bba364Sbostic   return q;
7784bba364Sbostic }
7884bba364Sbostic 
7984bba364Sbostic 
8084bba364Sbostic 
lookup(p)8184bba364Sbostic LOCAL Varp lookup(p)
8284bba364Sbostic tagptr p;
8384bba364Sbostic 
8484bba364Sbostic {
8584bba364Sbostic int vstg, memno;
8684bba364Sbostic int key;
8784bba364Sbostic Varp q, r;
8884bba364Sbostic 
8984bba364Sbostic switch (p->tag)
9084bba364Sbostic 	{
9184bba364Sbostic 	case TTEMP:
9284bba364Sbostic 		vstg = 0;
9384bba364Sbostic 		memno = (int) p->tempblock.memalloc;
9484bba364Sbostic 		break;
9584bba364Sbostic 
9684bba364Sbostic 	case TADDR:
9784bba364Sbostic 		vstg = p->addrblock.vstg;
9884bba364Sbostic 		memno = p->addrblock.memno;
9984bba364Sbostic 		break;
10084bba364Sbostic 
10184bba364Sbostic 	default:
10284bba364Sbostic 		badtag ("lookup",p->tag);
10384bba364Sbostic 	}
10484bba364Sbostic key = memno % TABLESIZE;
10584bba364Sbostic q = table[key];
10684bba364Sbostic 
10784bba364Sbostic if (q)
10884bba364Sbostic 	{
10984bba364Sbostic 	for (; q; r = q, q = q->next)
11084bba364Sbostic 		if ((q->vstg == vstg) && (q->memno == memno))
11184bba364Sbostic 			return q;
11284bba364Sbostic 	return r->next = mkbucket(vstg,memno);
11384bba364Sbostic 	}
11484bba364Sbostic else
11584bba364Sbostic 	return table[key] = mkbucket(vstg,memno);
11684bba364Sbostic }
11784bba364Sbostic 
11884bba364Sbostic 
11984bba364Sbostic 
freetable()12084bba364Sbostic LOCAL freetable()
12184bba364Sbostic 
12284bba364Sbostic {
12384bba364Sbostic   int i;
12484bba364Sbostic   Varp p, q;
12584bba364Sbostic 
12684bba364Sbostic   for (i = 0; i < TABLESIZE; i++)
12784bba364Sbostic     if (table[i])
12884bba364Sbostic       {
12984bba364Sbostic 	p = table[i];
13084bba364Sbostic 	table[i] = NULL;
13184bba364Sbostic 
13284bba364Sbostic 	while (p)
13384bba364Sbostic 	  {
13484bba364Sbostic 	    q = p->next;
13584bba364Sbostic 	    free((char *) p);
13684bba364Sbostic 	    p = q;
13784bba364Sbostic 	  }
13884bba364Sbostic       }
13984bba364Sbostic }
14084bba364Sbostic 
14184bba364Sbostic 
14284bba364Sbostic 
14384bba364Sbostic Slotp newcode;
14484bba364Sbostic Slotp dohead, doend;
14584bba364Sbostic LOCAL Slotp first, last;
14684bba364Sbostic LOCAL commonset;
14784bba364Sbostic LOCAL int comocount;	/* count of number of code motions done */
14884bba364Sbostic 
14984bba364Sbostic 
optloops()15084bba364Sbostic optloops()
15184bba364Sbostic 
15284bba364Sbostic {
15384bba364Sbostic int	match;
15484bba364Sbostic Slotp	nextslot;
15584bba364Sbostic Slotp	sl1,sl2;
15684bba364Sbostic Slotp	lastlabslot;
15784bba364Sbostic int	lab;
15884bba364Sbostic 
15984bba364Sbostic if (! optimflag) return;
16084bba364Sbostic if (debugflag[6]) return;
16184bba364Sbostic 
16284bba364Sbostic lastlabslot = NULL;
16384bba364Sbostic comocount = 0;
16484bba364Sbostic for (sl1 = firstslot; sl1; sl1 = nextslot)
16584bba364Sbostic 	{
16684bba364Sbostic 	nextslot = sl1->next;
16784bba364Sbostic 	switch (sl1->type)
16884bba364Sbostic 	    {
16984bba364Sbostic 	    case SKLABEL:
17084bba364Sbostic 		lastlabslot = sl1;
17184bba364Sbostic 		break;
17284bba364Sbostic 
17384bba364Sbostic 	    case SKGOTO:
17484bba364Sbostic 		if (lastlabslot && sl1->label == lastlabslot->label)
17584bba364Sbostic 			{
17684bba364Sbostic 			lab = newlabel ();
17784bba364Sbostic 			first = optinsert (SKLABEL,0,lab,0,lastlabslot->next);
17884bba364Sbostic 			last = sl1;
17984bba364Sbostic 			last->label = lab;
18084bba364Sbostic 			optloop ();
18184bba364Sbostic 			}
18284bba364Sbostic 		break;
18384bba364Sbostic 
18484bba364Sbostic 	    case SKDOHEAD:
18584bba364Sbostic 		match = 0;
18684bba364Sbostic 		for (sl2 = sl1; sl2; sl2 = sl2->next)
18784bba364Sbostic 			{
18884bba364Sbostic 			if (sl2->type == SKDOHEAD) match++;
18984bba364Sbostic 			else if (sl2->type == SKENDDO) match--;
19084bba364Sbostic 			if (match == 0) break;
19184bba364Sbostic 			}
19284bba364Sbostic 		if (sl2)
19384bba364Sbostic 			last = sl2;
19484bba364Sbostic 		else
19584bba364Sbostic 			fatal ("unmatched do in code buffer");
19684bba364Sbostic 		if (sl2->type != SKENDDO)
19784bba364Sbostic 			fatal ("internal error in optloops");
19884bba364Sbostic 
19984bba364Sbostic 		/*  last now points to the SKENDDO slot; the SKNULL slot
20084bba364Sbostic 		 *  is reached through last->nullslot
20184bba364Sbostic 		 */
20284bba364Sbostic 		last = (Slotp) last->nullslot;
20384bba364Sbostic 
20484bba364Sbostic 		first = sl1;
20584bba364Sbostic 
20684bba364Sbostic 		optloop ();
20784bba364Sbostic 		break;
20884bba364Sbostic 
20984bba364Sbostic 	    default:
21084bba364Sbostic 		break;
21184bba364Sbostic 	    }
21284bba364Sbostic 	}
21384bba364Sbostic 
21484bba364Sbostic if (debugflag[0])
21584bba364Sbostic 	fprintf (diagfile,"%d code motion%s performed\n",comocount,
21684bba364Sbostic 		(comocount==1 ? "" : "s") );
21784bba364Sbostic return;
21884bba364Sbostic }
21984bba364Sbostic 
22084bba364Sbostic 
22184bba364Sbostic 
optloop()22284bba364Sbostic optloop()
22384bba364Sbostic 
22484bba364Sbostic {
22584bba364Sbostic newcode = NULL;
22684bba364Sbostic 
22784bba364Sbostic modify();
22884bba364Sbostic 
22984bba364Sbostic return;
23084bba364Sbostic }
23184bba364Sbostic 
23284bba364Sbostic 
modify()23384bba364Sbostic LOCAL modify()
23484bba364Sbostic 
23584bba364Sbostic {
23684bba364Sbostic   Slotp sp;
23784bba364Sbostic   int s;
23884bba364Sbostic 
23984bba364Sbostic   scanvars();
24084bba364Sbostic 
24184bba364Sbostic   for (sp = first; sp != last->next; sp = sp->next)
24284bba364Sbostic     switch (sp->type)
24384bba364Sbostic       {
24484bba364Sbostic       case SKEQ:
24584bba364Sbostic 	s = anex(sp->expr);
24684bba364Sbostic 	if (s == SCSAFE)
24784bba364Sbostic 	  removesafe (&sp->expr);
24884bba364Sbostic 	break;
24984bba364Sbostic 
25084bba364Sbostic       case SKARIF:
25184bba364Sbostic       case SKASGOTO:
25284bba364Sbostic       case SKCALL:
25384bba364Sbostic       case SKCMGOTO:
25484bba364Sbostic       case SKIFN:
25584bba364Sbostic       case SKSTOP:
25684bba364Sbostic       case SKRETURN:
25784bba364Sbostic       case SKPAUSE:
25884bba364Sbostic       case SKIOIFN:
25984bba364Sbostic 	s = anex(sp->expr);
26084bba364Sbostic 	if (s == SCSAFE)
26184bba364Sbostic 	  removesafe(&sp->expr);
26284bba364Sbostic 	break;
26384bba364Sbostic 
26484bba364Sbostic       default:
26584bba364Sbostic 	break;
26684bba364Sbostic       }
26784bba364Sbostic 
26884bba364Sbostic   freetable();
26984bba364Sbostic   return;
27084bba364Sbostic }
27184bba364Sbostic 
27284bba364Sbostic 
scanvars()27384bba364Sbostic LOCAL scanvars()
27484bba364Sbostic 
27584bba364Sbostic {
27684bba364Sbostic   Slotp sp;
27784bba364Sbostic   Varp varinfo;
27884bba364Sbostic   int i;
27984bba364Sbostic   Varp p;
28084bba364Sbostic 
28184bba364Sbostic   commonset = NO;
28284bba364Sbostic 
28384bba364Sbostic   for (sp = first; sp != last->next; sp = sp->next)
28484bba364Sbostic     {
28584bba364Sbostic       switch (sp->type)
28684bba364Sbostic 	{
28784bba364Sbostic 	case SKARIF:
28884bba364Sbostic 	case SKASGOTO:
28984bba364Sbostic 	case SKCALL:
29084bba364Sbostic 	case SKCMGOTO:
29184bba364Sbostic 	case SKIFN:
29284bba364Sbostic 	case SKSTOP:
29384bba364Sbostic 	case SKRETURN:
29484bba364Sbostic 	case SKPAUSE:
29584bba364Sbostic 	case SKIOIFN:
29684bba364Sbostic 	case SKEQ:
29784bba364Sbostic 	  setsuses(sp->expr);
29884bba364Sbostic 	  break;
29984bba364Sbostic 
30084bba364Sbostic 	default:
30184bba364Sbostic 	  break;
30284bba364Sbostic 	}
30384bba364Sbostic     }
30484bba364Sbostic 
30584bba364Sbostic   if (commonset)
30684bba364Sbostic     for (i = 0; i < TABLESIZE; i++)
30784bba364Sbostic       for (p = table[i]; p; p = p->next)
30884bba364Sbostic 	if (p->vstg == STGCOMMON)
30984bba364Sbostic 	  {
31084bba364Sbostic 	    p->sets++;
31184bba364Sbostic 	    p->setfirst = NO;
31284bba364Sbostic 	  }
31384bba364Sbostic }
31484bba364Sbostic 
31584bba364Sbostic 
setsuses(p)31684bba364Sbostic LOCAL setsuses(p)
31784bba364Sbostic expptr p;
31884bba364Sbostic 
31984bba364Sbostic {
32084bba364Sbostic   Addrp lhs;
32184bba364Sbostic   Varp varinfo;
32284bba364Sbostic   chainp args;
32384bba364Sbostic 
32484bba364Sbostic   if (!p) return;
32584bba364Sbostic 
32684bba364Sbostic   switch (p->tag)
32784bba364Sbostic     {
32884bba364Sbostic     case TEXPR:
32984bba364Sbostic       switch (p->exprblock.opcode)
33084bba364Sbostic 	{
33184bba364Sbostic 	default:
33284bba364Sbostic 	  setsuses(p->exprblock.leftp);
33384bba364Sbostic 	  setsuses(p->exprblock.rightp);
33484bba364Sbostic 	  setsuses(p->exprblock.vleng);
33584bba364Sbostic 	  break;
33684bba364Sbostic 
33784bba364Sbostic 	case OPASSIGN:
33884bba364Sbostic 	  switch (p->exprblock.leftp->tag)
33984bba364Sbostic 	    {
34084bba364Sbostic 	    case TTEMP:
34184bba364Sbostic 	      lhs = (Addrp) p->exprblock.leftp;
34284bba364Sbostic 	      goto taddr;
34384bba364Sbostic 
34484bba364Sbostic 	    case TADDR:
34584bba364Sbostic 	      lhs = (Addrp) p->exprblock.leftp;
34684bba364Sbostic 	      setsuses(lhs->memoffset);
34784bba364Sbostic 	      setsuses(lhs->vleng);
34884bba364Sbostic 	    taddr:
34984bba364Sbostic 	      setsuses(p->exprblock.rightp);
35084bba364Sbostic 	      setsuses(p->exprblock.vleng);
35184bba364Sbostic 	      varinfo = lookup(lhs);
35284bba364Sbostic 	      varinfo->sets++;
35384bba364Sbostic               if (varinfo->uses == 0)
35484bba364Sbostic 	        varinfo->setfirst = YES;
35584bba364Sbostic 	      break;
35684bba364Sbostic 
35784bba364Sbostic 	    default:
35884bba364Sbostic 	      fatal("O6:  l-value expected");
35984bba364Sbostic 	    }
36084bba364Sbostic 	  break;
36184bba364Sbostic 
36284bba364Sbostic 	case OPSTAREQ:
36384bba364Sbostic 	case OPPLUSEQ:
36484bba364Sbostic 	  switch (p->exprblock.leftp->tag)
36584bba364Sbostic 	    {
36684bba364Sbostic 	    case TADDR:
36784bba364Sbostic 	      lhs = (Addrp) p->exprblock.leftp;
36884bba364Sbostic 	      break;
36984bba364Sbostic 	    case TTEMP:
37084bba364Sbostic 	      lhs = (Addrp) p->exprblock.leftp;
37184bba364Sbostic 	      break;
37284bba364Sbostic 	    default:
37384bba364Sbostic 	      fatal("O7:  l-value expected");
37484bba364Sbostic 	    }
37584bba364Sbostic 	  setsuses(p->exprblock.leftp);
37684bba364Sbostic 	  setsuses(p->exprblock.rightp);
37784bba364Sbostic 	  setsuses(p->exprblock.vleng);
37884bba364Sbostic 	  varinfo = lookup(lhs);
37984bba364Sbostic 	  varinfo->sets++;
38084bba364Sbostic 	  break;
38184bba364Sbostic 
38284bba364Sbostic 	case OPCALL:
38384bba364Sbostic 	  if (p->exprblock.leftp->tag != TADDR)
38484bba364Sbostic 	    fatal("O8:  subprogram expected");
38584bba364Sbostic 	  setsuses(p->exprblock.rightp);
38684bba364Sbostic 	  setsuses(p->exprblock.vleng);
38784bba364Sbostic 	  if (p->exprblock.leftp->addrblock.vstg == STGINTR) break;
38884bba364Sbostic 	  commonset = YES;
38984bba364Sbostic 	  if (p->exprblock.rightp == NULL) break;
39084bba364Sbostic 	  args = p->exprblock.rightp->listblock.listp;
39184bba364Sbostic 	  for (; args; args = args->nextp)
39284bba364Sbostic 	    if (args->datap->tag == TADDR)
39384bba364Sbostic 	      {
39484bba364Sbostic 		lhs = (Addrp) args->datap;
39584bba364Sbostic 		switch (lhs->vstg)
39684bba364Sbostic 		  {
39784bba364Sbostic 		  case STGARG:
39884bba364Sbostic 		  case STGAUTO:
39984bba364Sbostic 		  case STGBSS:
40084bba364Sbostic 		  case STGINIT:
40184bba364Sbostic 		  case STGCOMMON:
40284bba364Sbostic 		  case STGEQUIV:
40384bba364Sbostic 		  case STGREG:
40484bba364Sbostic 		  case STGPREG:
40584bba364Sbostic 		    varinfo = lookup(lhs);
40684bba364Sbostic 		    varinfo->sets++;
40784bba364Sbostic 		  }
40884bba364Sbostic 	      }
40984bba364Sbostic 	    else if (args->datap->tag == TTEMP)
41084bba364Sbostic 	      {
41184bba364Sbostic 		lhs = (Addrp) args->datap;
41284bba364Sbostic 		varinfo = lookup (lhs);
41384bba364Sbostic 		varinfo->sets++;
41484bba364Sbostic 	      }
41584bba364Sbostic 	  break;
41684bba364Sbostic         }
41784bba364Sbostic 
41884bba364Sbostic       return;
41984bba364Sbostic 
42084bba364Sbostic     case TTEMP:
42184bba364Sbostic       varinfo = lookup((Addrp) p);
42284bba364Sbostic       varinfo->uses++;
42384bba364Sbostic       return;
42484bba364Sbostic 
42584bba364Sbostic     case TADDR:
42684bba364Sbostic       setsuses(p->addrblock.memoffset);
42784bba364Sbostic       setsuses(p->addrblock.vleng);
42884bba364Sbostic       varinfo = lookup((Addrp) p);
42984bba364Sbostic       varinfo->uses++;
43084bba364Sbostic       return;
43184bba364Sbostic 
43284bba364Sbostic     case TLIST:
43384bba364Sbostic       for (args = p->listblock.listp; args; args = args->nextp)
43484bba364Sbostic 	setsuses(args->datap);
43584bba364Sbostic 
43684bba364Sbostic     case TCONST:
43784bba364Sbostic     case TERROR:
43884bba364Sbostic       return;
43984bba364Sbostic 
44084bba364Sbostic     default:
44184bba364Sbostic       fatal("O9:  bad tag value");
44284bba364Sbostic     }
44384bba364Sbostic }
44484bba364Sbostic 
44584bba364Sbostic 
anex(p)44684bba364Sbostic LOCAL int anex(p)
44784bba364Sbostic expptr p;
44884bba364Sbostic 
44984bba364Sbostic {
45084bba364Sbostic   int s1, s2, s3;
45184bba364Sbostic   expptr q;
45284bba364Sbostic   Varp varinfo;
45384bba364Sbostic   chainp ch;
45484bba364Sbostic   int setfirst;
45584bba364Sbostic   expptr expr;
45684bba364Sbostic 
45784bba364Sbostic 
45884bba364Sbostic   if (p == ENULL)
45984bba364Sbostic     return SCSAFE;
46084bba364Sbostic 
46184bba364Sbostic   switch (p->tag)
46284bba364Sbostic     {
46384bba364Sbostic     case TCONST:
46484bba364Sbostic       return SCSAFE;
46584bba364Sbostic 
46684bba364Sbostic     case TLIST:
46784bba364Sbostic       for (ch = p->listblock.listp; ch; ch = ch->nextp)
46884bba364Sbostic 	{
46984bba364Sbostic 	  s1 = anex (ch->datap);
47084bba364Sbostic 	  if (s1 == SCSAFE)
47184bba364Sbostic 	    removesafe (&ch->datap);
47284bba364Sbostic 	}
47384bba364Sbostic       return SCFREE;
47484bba364Sbostic 
47584bba364Sbostic     case TEXPR:
47684bba364Sbostic       s1 = anex(p->exprblock.leftp);
47784bba364Sbostic       s2 = anex(p->exprblock.rightp);
47884bba364Sbostic       s3 = anex(p->exprblock.vleng);
47984bba364Sbostic 
48084bba364Sbostic       switch (p->exprblock.opcode)
48184bba364Sbostic 	{
48284bba364Sbostic 	case OPASSIGN:
48384bba364Sbostic 	  expr = p->exprblock.leftp;
48484bba364Sbostic 	  varinfo = lookup(expr);
48584bba364Sbostic 	  setfirst = varinfo->setfirst && (varinfo->sets == 1);
48684bba364Sbostic 	  if (expr->tag == TTEMP && setfirst &&
48784bba364Sbostic 		s2 == SCSAFE && s3 == SCSAFE)
48884bba364Sbostic 	    {
48984bba364Sbostic 	      movefrtemp (expr);
49084bba364Sbostic 	      return SCSAFE;
49184bba364Sbostic 	    }
49284bba364Sbostic 	  else
49384bba364Sbostic 	    {
49484bba364Sbostic 	      if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);
49584bba364Sbostic 	      if (s3 == SCSAFE) removesafe (&p->exprblock.vleng);
49684bba364Sbostic 	      return SCFREE;
49784bba364Sbostic 	    }
49884bba364Sbostic 
49984bba364Sbostic 	case OPNEG:
50084bba364Sbostic 	case OPNOT:
50184bba364Sbostic 	case OPABS:
50284bba364Sbostic 	case OPADDR:
50384bba364Sbostic 	case OPBITNOT:
50484bba364Sbostic 	  if ((s2 == SCSAFE) && (s3 == SCSAFE))
50584bba364Sbostic 	    return s1;
50684bba364Sbostic 	  else
50784bba364Sbostic 	    return SCFREE;
50884bba364Sbostic 
50984bba364Sbostic 	case OPCONV:
51084bba364Sbostic 	  if ((s2 != SCSAFE) || (s3 != SCSAFE))
51184bba364Sbostic 	    return SCFREE;
51284bba364Sbostic 
51384bba364Sbostic 	  if (ISINT(p->exprblock.vtype))
51484bba364Sbostic 	    return s1;
51584bba364Sbostic 	  if (ISINT(p->exprblock.leftp->headblock.vtype))
51684bba364Sbostic 	    return s1;
51784bba364Sbostic 
51884bba364Sbostic 	  return SCFREE;
51984bba364Sbostic 
52084bba364Sbostic 
52184bba364Sbostic 	case OPSTAR:
52284bba364Sbostic 	  if (ISINT(p->exprblock.vtype))
52384bba364Sbostic 	    goto safeop;
52484bba364Sbostic 
52584bba364Sbostic 	  if (safefactor(p->exprblock.leftp) ||
52684bba364Sbostic 	      safefactor(p->exprblock.rightp))
52784bba364Sbostic 	    goto safeop;
52884bba364Sbostic 
52984bba364Sbostic 	  goto floatop;
53084bba364Sbostic 
53184bba364Sbostic 
53284bba364Sbostic 	case OPPLUS:
53384bba364Sbostic 	case OPMINUS:
53484bba364Sbostic 	  if (ISINT(p->exprblock.vtype))
53584bba364Sbostic 	    goto safeop;
53684bba364Sbostic 
53784bba364Sbostic 	floatop:
53884bba364Sbostic 	  if (!(ISREAL(p->exprblock.vtype) || ISCOMPLEX(p->exprblock.vtype)))
53984bba364Sbostic 	    return SCFREE;
54084bba364Sbostic 
54184bba364Sbostic 	  switch (s1)
54284bba364Sbostic 	    {
54384bba364Sbostic 	    case SCSAFE:
54484bba364Sbostic 	      removesafe(&p->exprblock.leftp);
54584bba364Sbostic 	      if (s2 == SCSAFE)
54684bba364Sbostic 		removesafe(&p->exprblock.leftp);
54784bba364Sbostic 	      return SCFREE;
54884bba364Sbostic 
54984bba364Sbostic 	    case SCFREE:
55084bba364Sbostic 	      if (s2 == SCSAFE)
55184bba364Sbostic 		removesafe(&p->exprblock.rightp);
55284bba364Sbostic 	      return SCFREE;
55384bba364Sbostic 	    }
55484bba364Sbostic 
55584bba364Sbostic 	case OPOR:
55684bba364Sbostic 	case OPAND:
55784bba364Sbostic 	case OPEQV:
55884bba364Sbostic 	case OPNEQV:
55984bba364Sbostic 	case OPLT:
56084bba364Sbostic 	case OPEQ:
56184bba364Sbostic 	case OPGT:
56284bba364Sbostic 	case OPLE:
56384bba364Sbostic 	case OPNE:
56484bba364Sbostic 	case OPGE:
56584bba364Sbostic 	case OPLSHIFT:
56684bba364Sbostic 	case OPMIN:
56784bba364Sbostic 	case OPMAX:
56884bba364Sbostic 	case OPBITOR:
56984bba364Sbostic 	case OPBITAND:
57084bba364Sbostic 	case OPBITXOR:
57184bba364Sbostic 	case OPRSHIFT:
57284bba364Sbostic 	safeop:
57384bba364Sbostic 	  if ((p->exprblock.vleng != ENULL) && ( ! ISCONST(p->exprblock.vleng)))
57484bba364Sbostic 	    return SCFREE;
57584bba364Sbostic 
57684bba364Sbostic 	  switch (s1)
57784bba364Sbostic 	    {
57884bba364Sbostic 	    case SCSAFE:
57984bba364Sbostic 		if (s2 == SCFREE) removesafe (&p->exprblock.leftp);
58084bba364Sbostic 		return s2;
58184bba364Sbostic 
58284bba364Sbostic 	    case SCFREE:
58384bba364Sbostic 		if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);
58484bba364Sbostic 		return SCFREE;
58584bba364Sbostic 	    }
58684bba364Sbostic 
58784bba364Sbostic 	default:
58884bba364Sbostic 	  if (s1 == SCSAFE) removesafe(&p->exprblock.leftp);
58984bba364Sbostic 	  if (s2 == SCSAFE) removesafe(&p->exprblock.rightp);
59084bba364Sbostic 	  if (s3 == SCSAFE) removesafe(&p->exprblock.vleng);
59184bba364Sbostic 	  return SCFREE;
59284bba364Sbostic 	}
59384bba364Sbostic 
59484bba364Sbostic 
59584bba364Sbostic     case TTEMP:
59684bba364Sbostic       varinfo = lookup(p);
59784bba364Sbostic       if (varinfo->sets == 0)
59884bba364Sbostic 	return SCSAFE;
59984bba364Sbostic       else
60084bba364Sbostic 	return SCFREE;
60184bba364Sbostic 
60284bba364Sbostic     case TADDR:
60384bba364Sbostic       s1 = anex(p->addrblock.memoffset);
60484bba364Sbostic       s2 = anex(p->addrblock.vleng);
60584bba364Sbostic 
60684bba364Sbostic       varinfo = lookup(p);
60784bba364Sbostic 
60884bba364Sbostic       if (varinfo->sets == 0)
60984bba364Sbostic 	switch (s1)
61084bba364Sbostic 	  {
61184bba364Sbostic 	  case SCSAFE:
61284bba364Sbostic 		if (s2 == SCFREE) removesafe(&p->addrblock.memoffset);
61384bba364Sbostic 		return s2;
61484bba364Sbostic 
61584bba364Sbostic 	  case SCFREE:
61684bba364Sbostic 		if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);
61784bba364Sbostic 		return SCFREE;
61884bba364Sbostic 	  }
61984bba364Sbostic 
62084bba364Sbostic       if (s1 == SCSAFE) removesafe(&p->addrblock.memoffset);
62184bba364Sbostic       if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);
62284bba364Sbostic       return SCFREE;
62384bba364Sbostic 
62484bba364Sbostic 
62584bba364Sbostic     default:
62684bba364Sbostic       return SCFREE;
62784bba364Sbostic     }
62884bba364Sbostic }
62984bba364Sbostic 
63084bba364Sbostic 
safefactor(p)63184bba364Sbostic LOCAL safefactor(p)
63284bba364Sbostic expptr p;
63384bba364Sbostic 
63484bba364Sbostic {
63584bba364Sbostic   if ( ! ISCONST(p))
63684bba364Sbostic     return NO;
63784bba364Sbostic 
63884bba364Sbostic   if (ISINT(p->constblock.vtype))
6395123cf85Sbostic     if (abs(p->constblock.constant.ci) <= 1)
64084bba364Sbostic       return YES;
64184bba364Sbostic 
64284bba364Sbostic   if (ISREAL(p->constblock.vtype))
6435123cf85Sbostic     if (abs(p->constblock.constant.cd[0]) <= 1.0)
64484bba364Sbostic       return YES;
64584bba364Sbostic 
64684bba364Sbostic   return NO;
64784bba364Sbostic }
64884bba364Sbostic 
64984bba364Sbostic 
worthcost(p)65084bba364Sbostic LOCAL int worthcost(p)
65184bba364Sbostic expptr p;
65284bba364Sbostic 
65384bba364Sbostic {
65484bba364Sbostic   int cost;
65584bba364Sbostic   chainp q;
65684bba364Sbostic   expptr memoffset,vleng;
65784bba364Sbostic 
65884bba364Sbostic   if (p == ENULL)
65984bba364Sbostic     return NO;
66084bba364Sbostic 
66184bba364Sbostic   switch (p->tag)
66284bba364Sbostic     {
66384bba364Sbostic     case TCONST:
66484bba364Sbostic       return NO;
66584bba364Sbostic 
66684bba364Sbostic     case TTEMP:
66784bba364Sbostic       return NO;
66884bba364Sbostic 
66984bba364Sbostic     case TADDR:
67084bba364Sbostic       if ((vleng = p->addrblock.vleng) && ! ISCONST(vleng))
67184bba364Sbostic 	return NO;	/* Can't make variable length temporaries */
67284bba364Sbostic       if ((memoffset = p->addrblock.memoffset) && ! ISCONST(memoffset))
67384bba364Sbostic 	return YES;
67484bba364Sbostic       else
67584bba364Sbostic 	return NO;
67684bba364Sbostic 
67784bba364Sbostic     case TEXPR:
67884bba364Sbostic       return YES;
67984bba364Sbostic 
68084bba364Sbostic     case TLIST:
68184bba364Sbostic       cost = 0;
68284bba364Sbostic       for (q = p->listblock.listp; q; q = q->nextp)
68384bba364Sbostic 	{
68484bba364Sbostic 	if (worthcost ((expptr) q->datap))
68584bba364Sbostic 	  return YES;
68684bba364Sbostic 	cost++;
68784bba364Sbostic 	}
68884bba364Sbostic       return (cost>2 ? YES : NO);
68984bba364Sbostic 
69084bba364Sbostic     default:
69184bba364Sbostic       return NO;
69284bba364Sbostic     }
69384bba364Sbostic }
69484bba364Sbostic 
69584bba364Sbostic 
removesafe(refexpr)69684bba364Sbostic LOCAL removesafe(refexpr)
69784bba364Sbostic expptr *refexpr;
69884bba364Sbostic 
69984bba364Sbostic {
70084bba364Sbostic   expptr ep;
70184bba364Sbostic   Tempp ap;
70284bba364Sbostic   Slotp newslot;
70384bba364Sbostic 
70484bba364Sbostic   extern Addrp gettemp();
70584bba364Sbostic 
70684bba364Sbostic   ep = *refexpr;
70784bba364Sbostic   if (! worthcost(ep))
70884bba364Sbostic     return;
70984bba364Sbostic 
71084bba364Sbostic   if (ep->tag == TEXPR && ep->exprblock.opcode == OPASSIGN)
71184bba364Sbostic     {
71284bba364Sbostic       if (ep->exprblock.leftp->tag != TTEMP)
71384bba364Sbostic 	fatal ("non-TEMP in assignment to be moved in optloop");
71484bba364Sbostic 
71584bba364Sbostic       newslot = optinsert (SKEQ, ep, 0, 0, first);
71684bba364Sbostic       *refexpr = (expptr) cpexpr (ep->exprblock.leftp);
71784bba364Sbostic     }
71884bba364Sbostic   else
71984bba364Sbostic     {
72084bba364Sbostic       ap = (Tempp) gettemp(ep);
72184bba364Sbostic       newslot = optinsert (SKEQ, mkexpr(OPASSIGN,cpexpr(ap),ep), 0, 0, first);
72284bba364Sbostic       *refexpr = (expptr) ap;
72384bba364Sbostic       optinsert (SKFRTEMP,ap->memalloc,0,0,last->next);
72484bba364Sbostic     }
72584bba364Sbostic 
72684bba364Sbostic   comocount++;
72784bba364Sbostic   if (!newcode)
72884bba364Sbostic     newcode = newslot;
72984bba364Sbostic 
73084bba364Sbostic   return;
73184bba364Sbostic }
73284bba364Sbostic 
73384bba364Sbostic 
gettemp(p)73484bba364Sbostic LOCAL Addrp gettemp(p)
73584bba364Sbostic expptr p;
73684bba364Sbostic 
73784bba364Sbostic {
73884bba364Sbostic   return mktemp(p->headblock.vtype, p->headblock.vleng);
73984bba364Sbostic }
74084bba364Sbostic 
74184bba364Sbostic 
74284bba364Sbostic 
movefrtemp(expr)74384bba364Sbostic LOCAL movefrtemp (expr)
74484bba364Sbostic Tempp	expr;
74584bba364Sbostic 
74684bba364Sbostic {
74784bba364Sbostic   Slotp	s;
74884bba364Sbostic 
74984bba364Sbostic   if (expr->tag != TTEMP)
75084bba364Sbostic     badtag ("movefrtemp",expr->tag);
75184bba364Sbostic 
75284bba364Sbostic   for (s = first; s; s = s->next)
75384bba364Sbostic     if (s->type == SKFRTEMP && s->expr == (expptr) expr->memalloc)
75484bba364Sbostic       {
75584bba364Sbostic 	removeslot (s);
75684bba364Sbostic 	insertslot (s,last->next);
75784bba364Sbostic 	return;
75884bba364Sbostic       }
75984bba364Sbostic }
760