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%
622855Smckusick  */
722855Smckusick 
822855Smckusick #ifndef lint
9*47955Sbostic static char sccsid[] = "@(#)optloop.c	5.3 (Berkeley) 04/12/91";
10*47955Sbostic #endif /* not lint */
1122855Smckusick 
1222855Smckusick /*
1322855Smckusick  * optloop.c
1422855Smckusick  *
1522855Smckusick  * Loop optimizations, f77 compiler pass 1, 4.2 BSD.
1622855Smckusick  *
1722855Smckusick  * University of Utah CS Dept. modification history:
1822855Smckusick  *
1922855Smckusick  * $Log:	optloop.c,v $
2022855Smckusick  * Revision 1.4  84/10/25  01:27:29  donn
2122855Smckusick  * Fixed a subtle bug in removesafe().  When the moved code is an assignment
2222855Smckusick  * into a temporary, we use the lhs to substitute for the expression inside
2322855Smckusick  * the loop.  Previously the data structure for the temporary was not copied,
2422855Smckusick  * so later on when the lhs was freed, the substitute was too, turning it
2522855Smckusick  * into garbage.
2622855Smckusick  *
2722855Smckusick  * Revision 1.3  84/08/05  17:04:03  donn
2822855Smckusick  * Changed worthcost() so that it skips variable length strings -- we can't
2922855Smckusick  * make temporaries for these...
3022855Smckusick  *
3122855Smckusick  * Revision 1.2  84/07/19  11:50:39  donn
3222855Smckusick  * Installed changes to force non-intrinsic subroutines and functions to define
3322855Smckusick  * their arguments (make them ineligible for optimization), function setsuses.
3422855Smckusick  * Fix from A.F.
3522855Smckusick  *
3622855Smckusick  */
3722855Smckusick 
3822855Smckusick #include "defs.h"
3922855Smckusick #include "optim.h"
4022855Smckusick 
4122855Smckusick 
4222855Smckusick #define SCFREE   0
4322855Smckusick #define SCSAFE   1
4422855Smckusick 
4522855Smckusick 
4622855Smckusick 
4722855Smckusick typedef
4822855Smckusick   struct varblock
4922855Smckusick     {
5022855Smckusick       struct varblock *next;
5122855Smckusick       field vstg;
5222855Smckusick       int memno;	/* holds memalloc for TTEMP */
5322855Smckusick       short sets;
5422855Smckusick       short uses;
5522855Smckusick       field setfirst;
5622855Smckusick     } VARBLOCK;
5722855Smckusick 
5822855Smckusick typedef VARBLOCK *Varp;
5922855Smckusick 
6022855Smckusick #define TABLESIZE 59
6122855Smckusick 
6222855Smckusick LOCAL Varp table[TABLESIZE];
6322855Smckusick 
6422855Smckusick 
6522855Smckusick 
mkbucket(vstg,memno)6622855Smckusick LOCAL Varp mkbucket(vstg,memno)
6722855Smckusick field vstg;
6822855Smckusick int memno;
6922855Smckusick 
7022855Smckusick {
7122855Smckusick   Varp q;
7222855Smckusick 
7322855Smckusick   q = ALLOC(varblock);
7422855Smckusick   q->vstg = vstg;
7522855Smckusick   q->memno = memno;
7622855Smckusick   return q;
7722855Smckusick }
7822855Smckusick 
7922855Smckusick 
8022855Smckusick 
lookup(p)8122855Smckusick LOCAL Varp lookup(p)
8222855Smckusick tagptr p;
8322855Smckusick 
8422855Smckusick {
8522855Smckusick int vstg, memno;
8622855Smckusick int key;
8722855Smckusick Varp q, r;
8822855Smckusick 
8922855Smckusick switch (p->tag)
9022855Smckusick 	{
9122855Smckusick 	case TTEMP:
9222855Smckusick 		vstg = 0;
9322855Smckusick 		memno = (int) p->tempblock.memalloc;
9422855Smckusick 		break;
9522855Smckusick 
9622855Smckusick 	case TADDR:
9722855Smckusick 		vstg = p->addrblock.vstg;
9822855Smckusick 		memno = p->addrblock.memno;
9922855Smckusick 		break;
10022855Smckusick 
10122855Smckusick 	default:
10222855Smckusick 		badtag ("lookup",p->tag);
10322855Smckusick 	}
10422855Smckusick key = memno % TABLESIZE;
10522855Smckusick q = table[key];
10622855Smckusick 
10722855Smckusick if (q)
10822855Smckusick 	{
10922855Smckusick 	for (; q; r = q, q = q->next)
11022855Smckusick 		if ((q->vstg == vstg) && (q->memno == memno))
11122855Smckusick 			return q;
11222855Smckusick 	return r->next = mkbucket(vstg,memno);
11322855Smckusick 	}
11422855Smckusick else
11522855Smckusick 	return table[key] = mkbucket(vstg,memno);
11622855Smckusick }
11722855Smckusick 
11822855Smckusick 
11922855Smckusick 
freetable()12022855Smckusick LOCAL freetable()
12122855Smckusick 
12222855Smckusick {
12322855Smckusick   int i;
12422855Smckusick   Varp p, q;
12522855Smckusick 
12622855Smckusick   for (i = 0; i < TABLESIZE; i++)
12722855Smckusick     if (table[i])
12822855Smckusick       {
12922855Smckusick 	p = table[i];
13022855Smckusick 	table[i] = NULL;
13122855Smckusick 
13222855Smckusick 	while (p)
13322855Smckusick 	  {
13422855Smckusick 	    q = p->next;
13522855Smckusick 	    free((char *) p);
13622855Smckusick 	    p = q;
13722855Smckusick 	  }
13822855Smckusick       }
13922855Smckusick }
14022855Smckusick 
14122855Smckusick 
14222855Smckusick 
14322855Smckusick Slotp newcode;
14422855Smckusick Slotp dohead, doend;
14522855Smckusick LOCAL Slotp first, last;
14622855Smckusick LOCAL commonset;
14722855Smckusick LOCAL int comocount;	/* count of number of code motions done */
14822855Smckusick 
14922855Smckusick 
optloops()15022855Smckusick optloops()
15122855Smckusick 
15222855Smckusick {
15322855Smckusick int	match;
15422855Smckusick Slotp	nextslot;
15522855Smckusick Slotp	sl1,sl2;
15622855Smckusick Slotp	lastlabslot;
15722855Smckusick int	lab;
15822855Smckusick 
15922855Smckusick if (! optimflag) return;
16022855Smckusick if (debugflag[6]) return;
16122855Smckusick 
16222855Smckusick lastlabslot = NULL;
16322855Smckusick comocount = 0;
16422855Smckusick for (sl1 = firstslot; sl1; sl1 = nextslot)
16522855Smckusick 	{
16622855Smckusick 	nextslot = sl1->next;
16722855Smckusick 	switch (sl1->type)
16822855Smckusick 	    {
16922855Smckusick 	    case SKLABEL:
17022855Smckusick 		lastlabslot = sl1;
17122855Smckusick 		break;
17222855Smckusick 
17322855Smckusick 	    case SKGOTO:
17422855Smckusick 		if (lastlabslot && sl1->label == lastlabslot->label)
17522855Smckusick 			{
17622855Smckusick 			lab = newlabel ();
17722855Smckusick 			first = optinsert (SKLABEL,0,lab,0,lastlabslot->next);
17822855Smckusick 			last = sl1;
17922855Smckusick 			last->label = lab;
18022855Smckusick 			optloop ();
18122855Smckusick 			}
18222855Smckusick 		break;
18322855Smckusick 
18422855Smckusick 	    case SKDOHEAD:
18522855Smckusick 		match = 0;
18622855Smckusick 		for (sl2 = sl1; sl2; sl2 = sl2->next)
18722855Smckusick 			{
18822855Smckusick 			if (sl2->type == SKDOHEAD) match++;
18922855Smckusick 			else if (sl2->type == SKENDDO) match--;
19022855Smckusick 			if (match == 0) break;
19122855Smckusick 			}
19222855Smckusick 		if (sl2)
19322855Smckusick 			last = sl2;
19422855Smckusick 		else
19522855Smckusick 			fatal ("unmatched do in code buffer");
19622855Smckusick 		if (sl2->type != SKENDDO)
19722855Smckusick 			fatal ("internal error in optloops");
19822855Smckusick 
19922855Smckusick 		/*  last now points to the SKENDDO slot; the SKNULL slot
20022855Smckusick 		 *  is reached through last->nullslot
20122855Smckusick 		 */
20222855Smckusick 		last = (Slotp) last->nullslot;
20322855Smckusick 
20422855Smckusick 		first = sl1;
20522855Smckusick 
20622855Smckusick 		optloop ();
20722855Smckusick 		break;
20822855Smckusick 
20922855Smckusick 	    default:
21022855Smckusick 		break;
21122855Smckusick 	    }
21222855Smckusick 	}
21322855Smckusick 
21422855Smckusick if (debugflag[0])
21522855Smckusick 	fprintf (diagfile,"%d code motion%s performed\n",comocount,
21622855Smckusick 		(comocount==1 ? "" : "s") );
21722855Smckusick return;
21822855Smckusick }
21922855Smckusick 
22022855Smckusick 
22122855Smckusick 
optloop()22222855Smckusick optloop()
22322855Smckusick 
22422855Smckusick {
22522855Smckusick newcode = NULL;
22622855Smckusick 
22722855Smckusick modify();
22822855Smckusick 
22922855Smckusick return;
23022855Smckusick }
23122855Smckusick 
23222855Smckusick 
modify()23322855Smckusick LOCAL modify()
23422855Smckusick 
23522855Smckusick {
23622855Smckusick   Slotp sp;
23722855Smckusick   int s;
23822855Smckusick 
23922855Smckusick   scanvars();
24022855Smckusick 
24122855Smckusick   for (sp = first; sp != last->next; sp = sp->next)
24222855Smckusick     switch (sp->type)
24322855Smckusick       {
24422855Smckusick       case SKEQ:
24522855Smckusick 	s = anex(sp->expr);
24622855Smckusick 	if (s == SCSAFE)
24722855Smckusick 	  removesafe (&sp->expr);
24822855Smckusick 	break;
24922855Smckusick 
25022855Smckusick       case SKARIF:
25122855Smckusick       case SKASGOTO:
25222855Smckusick       case SKCALL:
25322855Smckusick       case SKCMGOTO:
25422855Smckusick       case SKIFN:
25522855Smckusick       case SKSTOP:
25622855Smckusick       case SKRETURN:
25722855Smckusick       case SKPAUSE:
25822855Smckusick       case SKIOIFN:
25922855Smckusick 	s = anex(sp->expr);
26022855Smckusick 	if (s == SCSAFE)
26122855Smckusick 	  removesafe(&sp->expr);
26222855Smckusick 	break;
26322855Smckusick 
26422855Smckusick       default:
26522855Smckusick 	break;
26622855Smckusick       }
26722855Smckusick 
26822855Smckusick   freetable();
26922855Smckusick   return;
27022855Smckusick }
27122855Smckusick 
27222855Smckusick 
scanvars()27322855Smckusick LOCAL scanvars()
27422855Smckusick 
27522855Smckusick {
27622855Smckusick   Slotp sp;
27722855Smckusick   Varp varinfo;
27822855Smckusick   int i;
27922855Smckusick   Varp p;
28022855Smckusick 
28122855Smckusick   commonset = NO;
28222855Smckusick 
28322855Smckusick   for (sp = first; sp != last->next; sp = sp->next)
28422855Smckusick     {
28522855Smckusick       switch (sp->type)
28622855Smckusick 	{
28722855Smckusick 	case SKARIF:
28822855Smckusick 	case SKASGOTO:
28922855Smckusick 	case SKCALL:
29022855Smckusick 	case SKCMGOTO:
29122855Smckusick 	case SKIFN:
29222855Smckusick 	case SKSTOP:
29322855Smckusick 	case SKRETURN:
29422855Smckusick 	case SKPAUSE:
29522855Smckusick 	case SKIOIFN:
29622855Smckusick 	case SKEQ:
29722855Smckusick 	  setsuses(sp->expr);
29822855Smckusick 	  break;
29922855Smckusick 
30022855Smckusick 	default:
30122855Smckusick 	  break;
30222855Smckusick 	}
30322855Smckusick     }
30422855Smckusick 
30522855Smckusick   if (commonset)
30622855Smckusick     for (i = 0; i < TABLESIZE; i++)
30722855Smckusick       for (p = table[i]; p; p = p->next)
30822855Smckusick 	if (p->vstg == STGCOMMON)
30922855Smckusick 	  {
31022855Smckusick 	    p->sets++;
31122855Smckusick 	    p->setfirst = NO;
31222855Smckusick 	  }
31322855Smckusick }
31422855Smckusick 
31522855Smckusick 
setsuses(p)31622855Smckusick LOCAL setsuses(p)
31722855Smckusick expptr p;
31822855Smckusick 
31922855Smckusick {
32022855Smckusick   Addrp lhs;
32122855Smckusick   Varp varinfo;
32222855Smckusick   chainp args;
32322855Smckusick 
32422855Smckusick   if (!p) return;
32522855Smckusick 
32622855Smckusick   switch (p->tag)
32722855Smckusick     {
32822855Smckusick     case TEXPR:
32922855Smckusick       switch (p->exprblock.opcode)
33022855Smckusick 	{
33122855Smckusick 	default:
33222855Smckusick 	  setsuses(p->exprblock.leftp);
33322855Smckusick 	  setsuses(p->exprblock.rightp);
33422855Smckusick 	  setsuses(p->exprblock.vleng);
33522855Smckusick 	  break;
33622855Smckusick 
33722855Smckusick 	case OPASSIGN:
33822855Smckusick 	  switch (p->exprblock.leftp->tag)
33922855Smckusick 	    {
34022855Smckusick 	    case TTEMP:
34122855Smckusick 	      lhs = (Addrp) p->exprblock.leftp;
34222855Smckusick 	      goto taddr;
34322855Smckusick 
34422855Smckusick 	    case TADDR:
34522855Smckusick 	      lhs = (Addrp) p->exprblock.leftp;
34622855Smckusick 	      setsuses(lhs->memoffset);
34722855Smckusick 	      setsuses(lhs->vleng);
34822855Smckusick 	    taddr:
34922855Smckusick 	      setsuses(p->exprblock.rightp);
35022855Smckusick 	      setsuses(p->exprblock.vleng);
35122855Smckusick 	      varinfo = lookup(lhs);
35222855Smckusick 	      varinfo->sets++;
35322855Smckusick               if (varinfo->uses == 0)
35422855Smckusick 	        varinfo->setfirst = YES;
35522855Smckusick 	      break;
35622855Smckusick 
35722855Smckusick 	    default:
35822855Smckusick 	      fatal("O6:  l-value expected");
35922855Smckusick 	    }
36022855Smckusick 	  break;
36122855Smckusick 
36222855Smckusick 	case OPSTAREQ:
36322855Smckusick 	case OPPLUSEQ:
36422855Smckusick 	  switch (p->exprblock.leftp->tag)
36522855Smckusick 	    {
36622855Smckusick 	    case TADDR:
36722855Smckusick 	      lhs = (Addrp) p->exprblock.leftp;
36822855Smckusick 	      break;
36922855Smckusick 	    case TTEMP:
37022855Smckusick 	      lhs = (Addrp) p->exprblock.leftp;
37122855Smckusick 	      break;
37222855Smckusick 	    default:
37322855Smckusick 	      fatal("O7:  l-value expected");
37422855Smckusick 	    }
37522855Smckusick 	  setsuses(p->exprblock.leftp);
37622855Smckusick 	  setsuses(p->exprblock.rightp);
37722855Smckusick 	  setsuses(p->exprblock.vleng);
37822855Smckusick 	  varinfo = lookup(lhs);
37922855Smckusick 	  varinfo->sets++;
38022855Smckusick 	  break;
38122855Smckusick 
38222855Smckusick 	case OPCALL:
38322855Smckusick 	  if (p->exprblock.leftp->tag != TADDR)
38422855Smckusick 	    fatal("O8:  subprogram expected");
38522855Smckusick 	  setsuses(p->exprblock.rightp);
38622855Smckusick 	  setsuses(p->exprblock.vleng);
38722855Smckusick 	  if (p->exprblock.leftp->addrblock.vstg == STGINTR) break;
38822855Smckusick 	  commonset = YES;
38922855Smckusick 	  if (p->exprblock.rightp == NULL) break;
39022855Smckusick 	  args = p->exprblock.rightp->listblock.listp;
39122855Smckusick 	  for (; args; args = args->nextp)
39222855Smckusick 	    if (args->datap->tag == TADDR)
39322855Smckusick 	      {
39422855Smckusick 		lhs = (Addrp) args->datap;
39522855Smckusick 		switch (lhs->vstg)
39622855Smckusick 		  {
39722855Smckusick 		  case STGARG:
39822855Smckusick 		  case STGAUTO:
39922855Smckusick 		  case STGBSS:
40022855Smckusick 		  case STGINIT:
40122855Smckusick 		  case STGCOMMON:
40222855Smckusick 		  case STGEQUIV:
40322855Smckusick 		  case STGREG:
40422855Smckusick 		  case STGPREG:
40522855Smckusick 		    varinfo = lookup(lhs);
40622855Smckusick 		    varinfo->sets++;
40722855Smckusick 		  }
40822855Smckusick 	      }
40922855Smckusick 	    else if (args->datap->tag == TTEMP)
41022855Smckusick 	      {
41122855Smckusick 		lhs = (Addrp) args->datap;
41222855Smckusick 		varinfo = lookup (lhs);
41322855Smckusick 		varinfo->sets++;
41422855Smckusick 	      }
41522855Smckusick 	  break;
41622855Smckusick         }
41722855Smckusick 
41822855Smckusick       return;
41922855Smckusick 
42022855Smckusick     case TTEMP:
42122855Smckusick       varinfo = lookup((Addrp) p);
42222855Smckusick       varinfo->uses++;
42322855Smckusick       return;
42422855Smckusick 
42522855Smckusick     case TADDR:
42622855Smckusick       setsuses(p->addrblock.memoffset);
42722855Smckusick       setsuses(p->addrblock.vleng);
42822855Smckusick       varinfo = lookup((Addrp) p);
42922855Smckusick       varinfo->uses++;
43022855Smckusick       return;
43122855Smckusick 
43222855Smckusick     case TLIST:
43322855Smckusick       for (args = p->listblock.listp; args; args = args->nextp)
43422855Smckusick 	setsuses(args->datap);
43522855Smckusick 
43622855Smckusick     case TCONST:
43722855Smckusick     case TERROR:
43822855Smckusick       return;
43922855Smckusick 
44022855Smckusick     default:
44122855Smckusick       fatal("O9:  bad tag value");
44222855Smckusick     }
44322855Smckusick }
44422855Smckusick 
44522855Smckusick 
anex(p)44622855Smckusick LOCAL int anex(p)
44722855Smckusick expptr p;
44822855Smckusick 
44922855Smckusick {
45022855Smckusick   int s1, s2, s3;
45122855Smckusick   expptr q;
45222855Smckusick   Varp varinfo;
45322855Smckusick   chainp ch;
45422855Smckusick   int setfirst;
45522855Smckusick   expptr expr;
45622855Smckusick 
45722855Smckusick 
45822855Smckusick   if (p == ENULL)
45922855Smckusick     return SCSAFE;
46022855Smckusick 
46122855Smckusick   switch (p->tag)
46222855Smckusick     {
46322855Smckusick     case TCONST:
46422855Smckusick       return SCSAFE;
46522855Smckusick 
46622855Smckusick     case TLIST:
46722855Smckusick       for (ch = p->listblock.listp; ch; ch = ch->nextp)
46822855Smckusick 	{
46922855Smckusick 	  s1 = anex (ch->datap);
47022855Smckusick 	  if (s1 == SCSAFE)
47122855Smckusick 	    removesafe (&ch->datap);
47222855Smckusick 	}
47322855Smckusick       return SCFREE;
47422855Smckusick 
47522855Smckusick     case TEXPR:
47622855Smckusick       s1 = anex(p->exprblock.leftp);
47722855Smckusick       s2 = anex(p->exprblock.rightp);
47822855Smckusick       s3 = anex(p->exprblock.vleng);
47922855Smckusick 
48022855Smckusick       switch (p->exprblock.opcode)
48122855Smckusick 	{
48222855Smckusick 	case OPASSIGN:
48322855Smckusick 	  expr = p->exprblock.leftp;
48422855Smckusick 	  varinfo = lookup(expr);
48522855Smckusick 	  setfirst = varinfo->setfirst && (varinfo->sets == 1);
48622855Smckusick 	  if (expr->tag == TTEMP && setfirst &&
48722855Smckusick 		s2 == SCSAFE && s3 == SCSAFE)
48822855Smckusick 	    {
48922855Smckusick 	      movefrtemp (expr);
49022855Smckusick 	      return SCSAFE;
49122855Smckusick 	    }
49222855Smckusick 	  else
49322855Smckusick 	    {
49422855Smckusick 	      if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);
49522855Smckusick 	      if (s3 == SCSAFE) removesafe (&p->exprblock.vleng);
49622855Smckusick 	      return SCFREE;
49722855Smckusick 	    }
49822855Smckusick 
49922855Smckusick 	case OPNEG:
50022855Smckusick 	case OPNOT:
50122855Smckusick 	case OPABS:
50222855Smckusick 	case OPADDR:
50322855Smckusick 	case OPBITNOT:
50422855Smckusick 	  if ((s2 == SCSAFE) && (s3 == SCSAFE))
50522855Smckusick 	    return s1;
50622855Smckusick 	  else
50722855Smckusick 	    return SCFREE;
50822855Smckusick 
50922855Smckusick 	case OPCONV:
51022855Smckusick 	  if ((s2 != SCSAFE) || (s3 != SCSAFE))
51122855Smckusick 	    return SCFREE;
51222855Smckusick 
51322855Smckusick 	  if (ISINT(p->exprblock.vtype))
51422855Smckusick 	    return s1;
51522855Smckusick 	  if (ISINT(p->exprblock.leftp->headblock.vtype))
51622855Smckusick 	    return s1;
51722855Smckusick 
51822855Smckusick 	  return SCFREE;
51922855Smckusick 
52022855Smckusick 
52122855Smckusick 	case OPSTAR:
52222855Smckusick 	  if (ISINT(p->exprblock.vtype))
52322855Smckusick 	    goto safeop;
52422855Smckusick 
52522855Smckusick 	  if (safefactor(p->exprblock.leftp) ||
52622855Smckusick 	      safefactor(p->exprblock.rightp))
52722855Smckusick 	    goto safeop;
52822855Smckusick 
52922855Smckusick 	  goto floatop;
53022855Smckusick 
53122855Smckusick 
53222855Smckusick 	case OPPLUS:
53322855Smckusick 	case OPMINUS:
53422855Smckusick 	  if (ISINT(p->exprblock.vtype))
53522855Smckusick 	    goto safeop;
53622855Smckusick 
53722855Smckusick 	floatop:
53822855Smckusick 	  if (!(ISREAL(p->exprblock.vtype) || ISCOMPLEX(p->exprblock.vtype)))
53922855Smckusick 	    return SCFREE;
54022855Smckusick 
54122855Smckusick 	  switch (s1)
54222855Smckusick 	    {
54322855Smckusick 	    case SCSAFE:
54422855Smckusick 	      removesafe(&p->exprblock.leftp);
54522855Smckusick 	      if (s2 == SCSAFE)
54622855Smckusick 		removesafe(&p->exprblock.leftp);
54722855Smckusick 	      return SCFREE;
54822855Smckusick 
54922855Smckusick 	    case SCFREE:
55022855Smckusick 	      if (s2 == SCSAFE)
55122855Smckusick 		removesafe(&p->exprblock.rightp);
55222855Smckusick 	      return SCFREE;
55322855Smckusick 	    }
55422855Smckusick 
55522855Smckusick 	case OPOR:
55622855Smckusick 	case OPAND:
55722855Smckusick 	case OPEQV:
55822855Smckusick 	case OPNEQV:
55922855Smckusick 	case OPLT:
56022855Smckusick 	case OPEQ:
56122855Smckusick 	case OPGT:
56222855Smckusick 	case OPLE:
56322855Smckusick 	case OPNE:
56422855Smckusick 	case OPGE:
56522855Smckusick 	case OPLSHIFT:
56622855Smckusick 	case OPMIN:
56722855Smckusick 	case OPMAX:
56822855Smckusick 	case OPBITOR:
56922855Smckusick 	case OPBITAND:
57022855Smckusick 	case OPBITXOR:
57122855Smckusick 	case OPRSHIFT:
57222855Smckusick 	safeop:
57322855Smckusick 	  if ((p->exprblock.vleng != ENULL) && ( ! ISCONST(p->exprblock.vleng)))
57422855Smckusick 	    return SCFREE;
57522855Smckusick 
57622855Smckusick 	  switch (s1)
57722855Smckusick 	    {
57822855Smckusick 	    case SCSAFE:
57922855Smckusick 		if (s2 == SCFREE) removesafe (&p->exprblock.leftp);
58022855Smckusick 		return s2;
58122855Smckusick 
58222855Smckusick 	    case SCFREE:
58322855Smckusick 		if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);
58422855Smckusick 		return SCFREE;
58522855Smckusick 	    }
58622855Smckusick 
58722855Smckusick 	default:
58822855Smckusick 	  if (s1 == SCSAFE) removesafe(&p->exprblock.leftp);
58922855Smckusick 	  if (s2 == SCSAFE) removesafe(&p->exprblock.rightp);
59022855Smckusick 	  if (s3 == SCSAFE) removesafe(&p->exprblock.vleng);
59122855Smckusick 	  return SCFREE;
59222855Smckusick 	}
59322855Smckusick 
59422855Smckusick 
59522855Smckusick     case TTEMP:
59622855Smckusick       varinfo = lookup(p);
59722855Smckusick       if (varinfo->sets == 0)
59822855Smckusick 	return SCSAFE;
59922855Smckusick       else
60022855Smckusick 	return SCFREE;
60122855Smckusick 
60222855Smckusick     case TADDR:
60322855Smckusick       s1 = anex(p->addrblock.memoffset);
60422855Smckusick       s2 = anex(p->addrblock.vleng);
60522855Smckusick 
60622855Smckusick       varinfo = lookup(p);
60722855Smckusick 
60822855Smckusick       if (varinfo->sets == 0)
60922855Smckusick 	switch (s1)
61022855Smckusick 	  {
61122855Smckusick 	  case SCSAFE:
61222855Smckusick 		if (s2 == SCFREE) removesafe(&p->addrblock.memoffset);
61322855Smckusick 		return s2;
61422855Smckusick 
61522855Smckusick 	  case SCFREE:
61622855Smckusick 		if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);
61722855Smckusick 		return SCFREE;
61822855Smckusick 	  }
61922855Smckusick 
62022855Smckusick       if (s1 == SCSAFE) removesafe(&p->addrblock.memoffset);
62122855Smckusick       if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);
62222855Smckusick       return SCFREE;
62322855Smckusick 
62422855Smckusick 
62522855Smckusick     default:
62622855Smckusick       return SCFREE;
62722855Smckusick     }
62822855Smckusick }
62922855Smckusick 
63022855Smckusick 
safefactor(p)63122855Smckusick LOCAL safefactor(p)
63222855Smckusick expptr p;
63322855Smckusick 
63422855Smckusick {
63522855Smckusick   if ( ! ISCONST(p))
63622855Smckusick     return NO;
63722855Smckusick 
63822855Smckusick   if (ISINT(p->constblock.vtype))
63933257Sbostic     if (abs(p->constblock.constant.ci) <= 1)
64022855Smckusick       return YES;
64122855Smckusick 
64222855Smckusick   if (ISREAL(p->constblock.vtype))
64333257Sbostic     if (abs(p->constblock.constant.cd[0]) <= 1.0)
64422855Smckusick       return YES;
64522855Smckusick 
64622855Smckusick   return NO;
64722855Smckusick }
64822855Smckusick 
64922855Smckusick 
worthcost(p)65022855Smckusick LOCAL int worthcost(p)
65122855Smckusick expptr p;
65222855Smckusick 
65322855Smckusick {
65422855Smckusick   int cost;
65522855Smckusick   chainp q;
65622855Smckusick   expptr memoffset,vleng;
65722855Smckusick 
65822855Smckusick   if (p == ENULL)
65922855Smckusick     return NO;
66022855Smckusick 
66122855Smckusick   switch (p->tag)
66222855Smckusick     {
66322855Smckusick     case TCONST:
66422855Smckusick       return NO;
66522855Smckusick 
66622855Smckusick     case TTEMP:
66722855Smckusick       return NO;
66822855Smckusick 
66922855Smckusick     case TADDR:
67022855Smckusick       if ((vleng = p->addrblock.vleng) && ! ISCONST(vleng))
67122855Smckusick 	return NO;	/* Can't make variable length temporaries */
67222855Smckusick       if ((memoffset = p->addrblock.memoffset) && ! ISCONST(memoffset))
67322855Smckusick 	return YES;
67422855Smckusick       else
67522855Smckusick 	return NO;
67622855Smckusick 
67722855Smckusick     case TEXPR:
67822855Smckusick       return YES;
67922855Smckusick 
68022855Smckusick     case TLIST:
68122855Smckusick       cost = 0;
68222855Smckusick       for (q = p->listblock.listp; q; q = q->nextp)
68322855Smckusick 	{
68422855Smckusick 	if (worthcost ((expptr) q->datap))
68522855Smckusick 	  return YES;
68622855Smckusick 	cost++;
68722855Smckusick 	}
68822855Smckusick       return (cost>2 ? YES : NO);
68922855Smckusick 
69022855Smckusick     default:
69122855Smckusick       return NO;
69222855Smckusick     }
69322855Smckusick }
69422855Smckusick 
69522855Smckusick 
removesafe(refexpr)69622855Smckusick LOCAL removesafe(refexpr)
69722855Smckusick expptr *refexpr;
69822855Smckusick 
69922855Smckusick {
70022855Smckusick   expptr ep;
70122855Smckusick   Tempp ap;
70222855Smckusick   Slotp newslot;
70322855Smckusick 
70422855Smckusick   extern Addrp gettemp();
70522855Smckusick 
70622855Smckusick   ep = *refexpr;
70722855Smckusick   if (! worthcost(ep))
70822855Smckusick     return;
70922855Smckusick 
71022855Smckusick   if (ep->tag == TEXPR && ep->exprblock.opcode == OPASSIGN)
71122855Smckusick     {
71222855Smckusick       if (ep->exprblock.leftp->tag != TTEMP)
71322855Smckusick 	fatal ("non-TEMP in assignment to be moved in optloop");
71422855Smckusick 
71522855Smckusick       newslot = optinsert (SKEQ, ep, 0, 0, first);
71622855Smckusick       *refexpr = (expptr) cpexpr (ep->exprblock.leftp);
71722855Smckusick     }
71822855Smckusick   else
71922855Smckusick     {
72022855Smckusick       ap = (Tempp) gettemp(ep);
72122855Smckusick       newslot = optinsert (SKEQ, mkexpr(OPASSIGN,cpexpr(ap),ep), 0, 0, first);
72222855Smckusick       *refexpr = (expptr) ap;
72322855Smckusick       optinsert (SKFRTEMP,ap->memalloc,0,0,last->next);
72422855Smckusick     }
72522855Smckusick 
72622855Smckusick   comocount++;
72722855Smckusick   if (!newcode)
72822855Smckusick     newcode = newslot;
72922855Smckusick 
73022855Smckusick   return;
73122855Smckusick }
73222855Smckusick 
73322855Smckusick 
gettemp(p)73422855Smckusick LOCAL Addrp gettemp(p)
73522855Smckusick expptr p;
73622855Smckusick 
73722855Smckusick {
73822855Smckusick   return mktemp(p->headblock.vtype, p->headblock.vleng);
73922855Smckusick }
74022855Smckusick 
74122855Smckusick 
74222855Smckusick 
movefrtemp(expr)74322855Smckusick LOCAL movefrtemp (expr)
74422855Smckusick Tempp	expr;
74522855Smckusick 
74622855Smckusick {
74722855Smckusick   Slotp	s;
74822855Smckusick 
74922855Smckusick   if (expr->tag != TTEMP)
75022855Smckusick     badtag ("movefrtemp",expr->tag);
75122855Smckusick 
75222855Smckusick   for (s = first; s; s = s->next)
75322855Smckusick     if (s->type == SKFRTEMP && s->expr == (expptr) expr->memalloc)
75422855Smckusick       {
75522855Smckusick 	removeslot (s);
75622855Smckusick 	insertslot (s,last->next);
75722855Smckusick 	return;
75822855Smckusick       }
75922855Smckusick }
760