1*47951Sbostic /*-
2*47951Sbostic  * Copyright (c) 1980 The Regents of the University of California.
3*47951Sbostic  * All rights reserved.
4*47951Sbostic  *
5*47951Sbostic  * %sccs.include.proprietary.c%
643218Sbostic  */
743218Sbostic 
843218Sbostic #ifndef lint
9*47951Sbostic static char sccsid[] = "@(#)optloop.c	5.3 (Berkeley) 04/12/91";
10*47951Sbostic #endif /* not lint */
1143218Sbostic 
1243218Sbostic /*
1343218Sbostic  * optloop.c
1443218Sbostic  *
1543218Sbostic  * Loop optimizations, f77 compiler pass 1, 4.2 BSD.
1643218Sbostic  *
1743218Sbostic  * University of Utah CS Dept. modification history:
1843218Sbostic  *
1943218Sbostic  * $Log:	optloop.c,v $
2043218Sbostic  * Revision 1.4  84/10/25  01:27:29  donn
2143218Sbostic  * Fixed a subtle bug in removesafe().  When the moved code is an assignment
2243218Sbostic  * into a temporary, we use the lhs to substitute for the expression inside
2343218Sbostic  * the loop.  Previously the data structure for the temporary was not copied,
2443218Sbostic  * so later on when the lhs was freed, the substitute was too, turning it
2543218Sbostic  * into garbage.
2643218Sbostic  *
2743218Sbostic  * Revision 1.3  84/08/05  17:04:03  donn
2843218Sbostic  * Changed worthcost() so that it skips variable length strings -- we can't
2943218Sbostic  * make temporaries for these...
3043218Sbostic  *
3143218Sbostic  * Revision 1.2  84/07/19  11:50:39  donn
3243218Sbostic  * Installed changes to force non-intrinsic subroutines and functions to define
3343218Sbostic  * their arguments (make them ineligible for optimization), function setsuses.
3443218Sbostic  * Fix from A.F.
3543218Sbostic  *
3643218Sbostic  */
3743218Sbostic 
3843218Sbostic #include "defs.h"
3943218Sbostic #include "optim.h"
4043218Sbostic 
4143218Sbostic 
4243218Sbostic #define SCFREE   0
4343218Sbostic #define SCSAFE   1
4443218Sbostic 
4543218Sbostic 
4643218Sbostic 
4743218Sbostic typedef
4843218Sbostic   struct varblock
4943218Sbostic     {
5043218Sbostic       struct varblock *next;
5143218Sbostic       field vstg;
5243218Sbostic       int memno;	/* holds memalloc for TTEMP */
5343218Sbostic       short sets;
5443218Sbostic       short uses;
5543218Sbostic       field setfirst;
5643218Sbostic     } VARBLOCK;
5743218Sbostic 
5843218Sbostic typedef VARBLOCK *Varp;
5943218Sbostic 
6043218Sbostic #define TABLESIZE 59
6143218Sbostic 
6243218Sbostic LOCAL Varp table[TABLESIZE];
6343218Sbostic 
6443218Sbostic 
6543218Sbostic 
mkbucket(vstg,memno)6643218Sbostic LOCAL Varp mkbucket(vstg,memno)
6743218Sbostic field vstg;
6843218Sbostic int memno;
6943218Sbostic 
7043218Sbostic {
7143218Sbostic   Varp q;
7243218Sbostic 
7343218Sbostic   q = ALLOC(varblock);
7443218Sbostic   q->vstg = vstg;
7543218Sbostic   q->memno = memno;
7643218Sbostic   return q;
7743218Sbostic }
7843218Sbostic 
7943218Sbostic 
8043218Sbostic 
lookup(p)8143218Sbostic LOCAL Varp lookup(p)
8243218Sbostic tagptr p;
8343218Sbostic 
8443218Sbostic {
8543218Sbostic int vstg, memno;
8643218Sbostic int key;
8743218Sbostic Varp q, r;
8843218Sbostic 
8943218Sbostic switch (p->tag)
9043218Sbostic 	{
9143218Sbostic 	case TTEMP:
9243218Sbostic 		vstg = 0;
9343218Sbostic 		memno = (int) p->tempblock.memalloc;
9443218Sbostic 		break;
9543218Sbostic 
9643218Sbostic 	case TADDR:
9743218Sbostic 		vstg = p->addrblock.vstg;
9843218Sbostic 		memno = p->addrblock.memno;
9943218Sbostic 		break;
10043218Sbostic 
10143218Sbostic 	default:
10243218Sbostic 		badtag ("lookup",p->tag);
10343218Sbostic 	}
10443218Sbostic key = memno % TABLESIZE;
10543218Sbostic q = table[key];
10643218Sbostic 
10743218Sbostic if (q)
10843218Sbostic 	{
10943218Sbostic 	for (; q; r = q, q = q->next)
11043218Sbostic 		if ((q->vstg == vstg) && (q->memno == memno))
11143218Sbostic 			return q;
11243218Sbostic 	return r->next = mkbucket(vstg,memno);
11343218Sbostic 	}
11443218Sbostic else
11543218Sbostic 	return table[key] = mkbucket(vstg,memno);
11643218Sbostic }
11743218Sbostic 
11843218Sbostic 
11943218Sbostic 
freetable()12043218Sbostic LOCAL freetable()
12143218Sbostic 
12243218Sbostic {
12343218Sbostic   int i;
12443218Sbostic   Varp p, q;
12543218Sbostic 
12643218Sbostic   for (i = 0; i < TABLESIZE; i++)
12743218Sbostic     if (table[i])
12843218Sbostic       {
12943218Sbostic 	p = table[i];
13043218Sbostic 	table[i] = NULL;
13143218Sbostic 
13243218Sbostic 	while (p)
13343218Sbostic 	  {
13443218Sbostic 	    q = p->next;
13543218Sbostic 	    free((char *) p);
13643218Sbostic 	    p = q;
13743218Sbostic 	  }
13843218Sbostic       }
13943218Sbostic }
14043218Sbostic 
14143218Sbostic 
14243218Sbostic 
14343218Sbostic Slotp newcode;
14443218Sbostic Slotp dohead, doend;
14543218Sbostic LOCAL Slotp first, last;
14643218Sbostic LOCAL commonset;
14743218Sbostic LOCAL int comocount;	/* count of number of code motions done */
14843218Sbostic 
14943218Sbostic 
optloops()15043218Sbostic optloops()
15143218Sbostic 
15243218Sbostic {
15343218Sbostic int	match;
15443218Sbostic Slotp	nextslot;
15543218Sbostic Slotp	sl1,sl2;
15643218Sbostic Slotp	lastlabslot;
15743218Sbostic int	lab;
15843218Sbostic 
15943218Sbostic if (! optimflag) return;
16043218Sbostic if (debugflag[6]) return;
16143218Sbostic 
16243218Sbostic lastlabslot = NULL;
16343218Sbostic comocount = 0;
16443218Sbostic for (sl1 = firstslot; sl1; sl1 = nextslot)
16543218Sbostic 	{
16643218Sbostic 	nextslot = sl1->next;
16743218Sbostic 	switch (sl1->type)
16843218Sbostic 	    {
16943218Sbostic 	    case SKLABEL:
17043218Sbostic 		lastlabslot = sl1;
17143218Sbostic 		break;
17243218Sbostic 
17343218Sbostic 	    case SKGOTO:
17443218Sbostic 		if (lastlabslot && sl1->label == lastlabslot->label)
17543218Sbostic 			{
17643218Sbostic 			lab = newlabel ();
17743218Sbostic 			first = optinsert (SKLABEL,0,lab,0,lastlabslot->next);
17843218Sbostic 			last = sl1;
17943218Sbostic 			last->label = lab;
18043218Sbostic 			optloop ();
18143218Sbostic 			}
18243218Sbostic 		break;
18343218Sbostic 
18443218Sbostic 	    case SKDOHEAD:
18543218Sbostic 		match = 0;
18643218Sbostic 		for (sl2 = sl1; sl2; sl2 = sl2->next)
18743218Sbostic 			{
18843218Sbostic 			if (sl2->type == SKDOHEAD) match++;
18943218Sbostic 			else if (sl2->type == SKENDDO) match--;
19043218Sbostic 			if (match == 0) break;
19143218Sbostic 			}
19243218Sbostic 		if (sl2)
19343218Sbostic 			last = sl2;
19443218Sbostic 		else
19543218Sbostic 			fatal ("unmatched do in code buffer");
19643218Sbostic 		if (sl2->type != SKENDDO)
19743218Sbostic 			fatal ("internal error in optloops");
19843218Sbostic 
19943218Sbostic 		/*  last now points to the SKENDDO slot; the SKNULL slot
20043218Sbostic 		 *  is reached through last->nullslot
20143218Sbostic 		 */
20243218Sbostic 		last = (Slotp) last->nullslot;
20343218Sbostic 
20443218Sbostic 		first = sl1;
20543218Sbostic 
20643218Sbostic 		optloop ();
20743218Sbostic 		break;
20843218Sbostic 
20943218Sbostic 	    default:
21043218Sbostic 		break;
21143218Sbostic 	    }
21243218Sbostic 	}
21343218Sbostic 
21443218Sbostic if (debugflag[0])
21543218Sbostic 	fprintf (diagfile,"%d code motion%s performed\n",comocount,
21643218Sbostic 		(comocount==1 ? "" : "s") );
21743218Sbostic return;
21843218Sbostic }
21943218Sbostic 
22043218Sbostic 
22143218Sbostic 
optloop()22243218Sbostic optloop()
22343218Sbostic 
22443218Sbostic {
22543218Sbostic newcode = NULL;
22643218Sbostic 
22743218Sbostic modify();
22843218Sbostic 
22943218Sbostic return;
23043218Sbostic }
23143218Sbostic 
23243218Sbostic 
modify()23343218Sbostic LOCAL modify()
23443218Sbostic 
23543218Sbostic {
23643218Sbostic   Slotp sp;
23743218Sbostic   int s;
23843218Sbostic 
23943218Sbostic   scanvars();
24043218Sbostic 
24143218Sbostic   for (sp = first; sp != last->next; sp = sp->next)
24243218Sbostic     switch (sp->type)
24343218Sbostic       {
24443218Sbostic       case SKEQ:
24543218Sbostic 	s = anex(sp->expr);
24643218Sbostic 	if (s == SCSAFE)
24743218Sbostic 	  removesafe (&sp->expr);
24843218Sbostic 	break;
24943218Sbostic 
25043218Sbostic       case SKARIF:
25143218Sbostic       case SKASGOTO:
25243218Sbostic       case SKCALL:
25343218Sbostic       case SKCMGOTO:
25443218Sbostic       case SKIFN:
25543218Sbostic       case SKSTOP:
25643218Sbostic       case SKRETURN:
25743218Sbostic       case SKPAUSE:
25843218Sbostic       case SKIOIFN:
25943218Sbostic 	s = anex(sp->expr);
26043218Sbostic 	if (s == SCSAFE)
26143218Sbostic 	  removesafe(&sp->expr);
26243218Sbostic 	break;
26343218Sbostic 
26443218Sbostic       default:
26543218Sbostic 	break;
26643218Sbostic       }
26743218Sbostic 
26843218Sbostic   freetable();
26943218Sbostic   return;
27043218Sbostic }
27143218Sbostic 
27243218Sbostic 
scanvars()27343218Sbostic LOCAL scanvars()
27443218Sbostic 
27543218Sbostic {
27643218Sbostic   Slotp sp;
27743218Sbostic   Varp varinfo;
27843218Sbostic   int i;
27943218Sbostic   Varp p;
28043218Sbostic 
28143218Sbostic   commonset = NO;
28243218Sbostic 
28343218Sbostic   for (sp = first; sp != last->next; sp = sp->next)
28443218Sbostic     {
28543218Sbostic       switch (sp->type)
28643218Sbostic 	{
28743218Sbostic 	case SKARIF:
28843218Sbostic 	case SKASGOTO:
28943218Sbostic 	case SKCALL:
29043218Sbostic 	case SKCMGOTO:
29143218Sbostic 	case SKIFN:
29243218Sbostic 	case SKSTOP:
29343218Sbostic 	case SKRETURN:
29443218Sbostic 	case SKPAUSE:
29543218Sbostic 	case SKIOIFN:
29643218Sbostic 	case SKEQ:
29743218Sbostic 	  setsuses(sp->expr);
29843218Sbostic 	  break;
29943218Sbostic 
30043218Sbostic 	default:
30143218Sbostic 	  break;
30243218Sbostic 	}
30343218Sbostic     }
30443218Sbostic 
30543218Sbostic   if (commonset)
30643218Sbostic     for (i = 0; i < TABLESIZE; i++)
30743218Sbostic       for (p = table[i]; p; p = p->next)
30843218Sbostic 	if (p->vstg == STGCOMMON)
30943218Sbostic 	  {
31043218Sbostic 	    p->sets++;
31143218Sbostic 	    p->setfirst = NO;
31243218Sbostic 	  }
31343218Sbostic }
31443218Sbostic 
31543218Sbostic 
setsuses(p)31643218Sbostic LOCAL setsuses(p)
31743218Sbostic expptr p;
31843218Sbostic 
31943218Sbostic {
32043218Sbostic   Addrp lhs;
32143218Sbostic   Varp varinfo;
32243218Sbostic   chainp args;
32343218Sbostic 
32443218Sbostic   if (!p) return;
32543218Sbostic 
32643218Sbostic   switch (p->tag)
32743218Sbostic     {
32843218Sbostic     case TEXPR:
32943218Sbostic       switch (p->exprblock.opcode)
33043218Sbostic 	{
33143218Sbostic 	default:
33243218Sbostic 	  setsuses(p->exprblock.leftp);
33343218Sbostic 	  setsuses(p->exprblock.rightp);
33443218Sbostic 	  setsuses(p->exprblock.vleng);
33543218Sbostic 	  break;
33643218Sbostic 
33743218Sbostic 	case OPASSIGN:
33843218Sbostic 	  switch (p->exprblock.leftp->tag)
33943218Sbostic 	    {
34043218Sbostic 	    case TTEMP:
34143218Sbostic 	      lhs = (Addrp) p->exprblock.leftp;
34243218Sbostic 	      goto taddr;
34343218Sbostic 
34443218Sbostic 	    case TADDR:
34543218Sbostic 	      lhs = (Addrp) p->exprblock.leftp;
34643218Sbostic 	      setsuses(lhs->memoffset);
34743218Sbostic 	      setsuses(lhs->vleng);
34843218Sbostic 	    taddr:
34943218Sbostic 	      setsuses(p->exprblock.rightp);
35043218Sbostic 	      setsuses(p->exprblock.vleng);
35143218Sbostic 	      varinfo = lookup(lhs);
35243218Sbostic 	      varinfo->sets++;
35343218Sbostic               if (varinfo->uses == 0)
35443218Sbostic 	        varinfo->setfirst = YES;
35543218Sbostic 	      break;
35643218Sbostic 
35743218Sbostic 	    default:
35843218Sbostic 	      fatal("O6:  l-value expected");
35943218Sbostic 	    }
36043218Sbostic 	  break;
36143218Sbostic 
36243218Sbostic 	case OPSTAREQ:
36343218Sbostic 	case OPPLUSEQ:
36443218Sbostic 	  switch (p->exprblock.leftp->tag)
36543218Sbostic 	    {
36643218Sbostic 	    case TADDR:
36743218Sbostic 	      lhs = (Addrp) p->exprblock.leftp;
36843218Sbostic 	      break;
36943218Sbostic 	    case TTEMP:
37043218Sbostic 	      lhs = (Addrp) p->exprblock.leftp;
37143218Sbostic 	      break;
37243218Sbostic 	    default:
37343218Sbostic 	      fatal("O7:  l-value expected");
37443218Sbostic 	    }
37543218Sbostic 	  setsuses(p->exprblock.leftp);
37643218Sbostic 	  setsuses(p->exprblock.rightp);
37743218Sbostic 	  setsuses(p->exprblock.vleng);
37843218Sbostic 	  varinfo = lookup(lhs);
37943218Sbostic 	  varinfo->sets++;
38043218Sbostic 	  break;
38143218Sbostic 
38243218Sbostic 	case OPCALL:
38343218Sbostic 	  if (p->exprblock.leftp->tag != TADDR)
38443218Sbostic 	    fatal("O8:  subprogram expected");
38543218Sbostic 	  setsuses(p->exprblock.rightp);
38643218Sbostic 	  setsuses(p->exprblock.vleng);
38743218Sbostic 	  if (p->exprblock.leftp->addrblock.vstg == STGINTR) break;
38843218Sbostic 	  commonset = YES;
38943218Sbostic 	  if (p->exprblock.rightp == NULL) break;
39043218Sbostic 	  args = p->exprblock.rightp->listblock.listp;
39143218Sbostic 	  for (; args; args = args->nextp)
39243218Sbostic 	    if (args->datap->tag == TADDR)
39343218Sbostic 	      {
39443218Sbostic 		lhs = (Addrp) args->datap;
39543218Sbostic 		switch (lhs->vstg)
39643218Sbostic 		  {
39743218Sbostic 		  case STGARG:
39843218Sbostic 		  case STGAUTO:
39943218Sbostic 		  case STGBSS:
40043218Sbostic 		  case STGINIT:
40143218Sbostic 		  case STGCOMMON:
40243218Sbostic 		  case STGEQUIV:
40343218Sbostic 		  case STGREG:
40443218Sbostic 		  case STGPREG:
40543218Sbostic 		    varinfo = lookup(lhs);
40643218Sbostic 		    varinfo->sets++;
40743218Sbostic 		  }
40843218Sbostic 	      }
40943218Sbostic 	    else if (args->datap->tag == TTEMP)
41043218Sbostic 	      {
41143218Sbostic 		lhs = (Addrp) args->datap;
41243218Sbostic 		varinfo = lookup (lhs);
41343218Sbostic 		varinfo->sets++;
41443218Sbostic 	      }
41543218Sbostic 	  break;
41643218Sbostic         }
41743218Sbostic 
41843218Sbostic       return;
41943218Sbostic 
42043218Sbostic     case TTEMP:
42143218Sbostic       varinfo = lookup((Addrp) p);
42243218Sbostic       varinfo->uses++;
42343218Sbostic       return;
42443218Sbostic 
42543218Sbostic     case TADDR:
42643218Sbostic       setsuses(p->addrblock.memoffset);
42743218Sbostic       setsuses(p->addrblock.vleng);
42843218Sbostic       varinfo = lookup((Addrp) p);
42943218Sbostic       varinfo->uses++;
43043218Sbostic       return;
43143218Sbostic 
43243218Sbostic     case TLIST:
43343218Sbostic       for (args = p->listblock.listp; args; args = args->nextp)
43443218Sbostic 	setsuses(args->datap);
43543218Sbostic 
43643218Sbostic     case TCONST:
43743218Sbostic     case TERROR:
43843218Sbostic       return;
43943218Sbostic 
44043218Sbostic     default:
44143218Sbostic       fatal("O9:  bad tag value");
44243218Sbostic     }
44343218Sbostic }
44443218Sbostic 
44543218Sbostic 
anex(p)44643218Sbostic LOCAL int anex(p)
44743218Sbostic expptr p;
44843218Sbostic 
44943218Sbostic {
45043218Sbostic   int s1, s2, s3;
45143218Sbostic   expptr q;
45243218Sbostic   Varp varinfo;
45343218Sbostic   chainp ch;
45443218Sbostic   int setfirst;
45543218Sbostic   expptr expr;
45643218Sbostic 
45743218Sbostic 
45843218Sbostic   if (p == ENULL)
45943218Sbostic     return SCSAFE;
46043218Sbostic 
46143218Sbostic   switch (p->tag)
46243218Sbostic     {
46343218Sbostic     case TCONST:
46443218Sbostic       return SCSAFE;
46543218Sbostic 
46643218Sbostic     case TLIST:
46743218Sbostic       for (ch = p->listblock.listp; ch; ch = ch->nextp)
46843218Sbostic 	{
46943218Sbostic 	  s1 = anex (ch->datap);
47043218Sbostic 	  if (s1 == SCSAFE)
47143218Sbostic 	    removesafe (&ch->datap);
47243218Sbostic 	}
47343218Sbostic       return SCFREE;
47443218Sbostic 
47543218Sbostic     case TEXPR:
47643218Sbostic       s1 = anex(p->exprblock.leftp);
47743218Sbostic       s2 = anex(p->exprblock.rightp);
47843218Sbostic       s3 = anex(p->exprblock.vleng);
47943218Sbostic 
48043218Sbostic       switch (p->exprblock.opcode)
48143218Sbostic 	{
48243218Sbostic 	case OPASSIGN:
48343218Sbostic 	  expr = p->exprblock.leftp;
48443218Sbostic 	  varinfo = lookup(expr);
48543218Sbostic 	  setfirst = varinfo->setfirst && (varinfo->sets == 1);
48643218Sbostic 	  if (expr->tag == TTEMP && setfirst &&
48743218Sbostic 		s2 == SCSAFE && s3 == SCSAFE)
48843218Sbostic 	    {
48943218Sbostic 	      movefrtemp (expr);
49043218Sbostic 	      return SCSAFE;
49143218Sbostic 	    }
49243218Sbostic 	  else
49343218Sbostic 	    {
49443218Sbostic 	      if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);
49543218Sbostic 	      if (s3 == SCSAFE) removesafe (&p->exprblock.vleng);
49643218Sbostic 	      return SCFREE;
49743218Sbostic 	    }
49843218Sbostic 
49943218Sbostic 	case OPNEG:
50043218Sbostic 	case OPNOT:
50143218Sbostic 	case OPABS:
50243218Sbostic 	case OPADDR:
50343218Sbostic 	case OPBITNOT:
50443218Sbostic 	  if ((s2 == SCSAFE) && (s3 == SCSAFE))
50543218Sbostic 	    return s1;
50643218Sbostic 	  else
50743218Sbostic 	    return SCFREE;
50843218Sbostic 
50943218Sbostic 	case OPCONV:
51043218Sbostic 	  if ((s2 != SCSAFE) || (s3 != SCSAFE))
51143218Sbostic 	    return SCFREE;
51243218Sbostic 
51343218Sbostic 	  if (ISINT(p->exprblock.vtype))
51443218Sbostic 	    return s1;
51543218Sbostic 	  if (ISINT(p->exprblock.leftp->headblock.vtype))
51643218Sbostic 	    return s1;
51743218Sbostic 
51843218Sbostic 	  return SCFREE;
51943218Sbostic 
52043218Sbostic 
52143218Sbostic 	case OPSTAR:
52243218Sbostic 	  if (ISINT(p->exprblock.vtype))
52343218Sbostic 	    goto safeop;
52443218Sbostic 
52543218Sbostic 	  if (safefactor(p->exprblock.leftp) ||
52643218Sbostic 	      safefactor(p->exprblock.rightp))
52743218Sbostic 	    goto safeop;
52843218Sbostic 
52943218Sbostic 	  goto floatop;
53043218Sbostic 
53143218Sbostic 
53243218Sbostic 	case OPPLUS:
53343218Sbostic 	case OPMINUS:
53443218Sbostic 	  if (ISINT(p->exprblock.vtype))
53543218Sbostic 	    goto safeop;
53643218Sbostic 
53743218Sbostic 	floatop:
53843218Sbostic 	  if (!(ISREAL(p->exprblock.vtype) || ISCOMPLEX(p->exprblock.vtype)))
53943218Sbostic 	    return SCFREE;
54043218Sbostic 
54143218Sbostic 	  switch (s1)
54243218Sbostic 	    {
54343218Sbostic 	    case SCSAFE:
54443218Sbostic 	      removesafe(&p->exprblock.leftp);
54543218Sbostic 	      if (s2 == SCSAFE)
54643218Sbostic 		removesafe(&p->exprblock.leftp);
54743218Sbostic 	      return SCFREE;
54843218Sbostic 
54943218Sbostic 	    case SCFREE:
55043218Sbostic 	      if (s2 == SCSAFE)
55143218Sbostic 		removesafe(&p->exprblock.rightp);
55243218Sbostic 	      return SCFREE;
55343218Sbostic 	    }
55443218Sbostic 
55543218Sbostic 	case OPOR:
55643218Sbostic 	case OPAND:
55743218Sbostic 	case OPEQV:
55843218Sbostic 	case OPNEQV:
55943218Sbostic 	case OPLT:
56043218Sbostic 	case OPEQ:
56143218Sbostic 	case OPGT:
56243218Sbostic 	case OPLE:
56343218Sbostic 	case OPNE:
56443218Sbostic 	case OPGE:
56543218Sbostic 	case OPLSHIFT:
56643218Sbostic 	case OPMIN:
56743218Sbostic 	case OPMAX:
56843218Sbostic 	case OPBITOR:
56943218Sbostic 	case OPBITAND:
57043218Sbostic 	case OPBITXOR:
57143218Sbostic 	case OPRSHIFT:
57243218Sbostic 	safeop:
57343218Sbostic 	  if ((p->exprblock.vleng != ENULL) && ( ! ISCONST(p->exprblock.vleng)))
57443218Sbostic 	    return SCFREE;
57543218Sbostic 
57643218Sbostic 	  switch (s1)
57743218Sbostic 	    {
57843218Sbostic 	    case SCSAFE:
57943218Sbostic 		if (s2 == SCFREE) removesafe (&p->exprblock.leftp);
58043218Sbostic 		return s2;
58143218Sbostic 
58243218Sbostic 	    case SCFREE:
58343218Sbostic 		if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);
58443218Sbostic 		return SCFREE;
58543218Sbostic 	    }
58643218Sbostic 
58743218Sbostic 	default:
58843218Sbostic 	  if (s1 == SCSAFE) removesafe(&p->exprblock.leftp);
58943218Sbostic 	  if (s2 == SCSAFE) removesafe(&p->exprblock.rightp);
59043218Sbostic 	  if (s3 == SCSAFE) removesafe(&p->exprblock.vleng);
59143218Sbostic 	  return SCFREE;
59243218Sbostic 	}
59343218Sbostic 
59443218Sbostic 
59543218Sbostic     case TTEMP:
59643218Sbostic       varinfo = lookup(p);
59743218Sbostic       if (varinfo->sets == 0)
59843218Sbostic 	return SCSAFE;
59943218Sbostic       else
60043218Sbostic 	return SCFREE;
60143218Sbostic 
60243218Sbostic     case TADDR:
60343218Sbostic       s1 = anex(p->addrblock.memoffset);
60443218Sbostic       s2 = anex(p->addrblock.vleng);
60543218Sbostic 
60643218Sbostic       varinfo = lookup(p);
60743218Sbostic 
60843218Sbostic       if (varinfo->sets == 0)
60943218Sbostic 	switch (s1)
61043218Sbostic 	  {
61143218Sbostic 	  case SCSAFE:
61243218Sbostic 		if (s2 == SCFREE) removesafe(&p->addrblock.memoffset);
61343218Sbostic 		return s2;
61443218Sbostic 
61543218Sbostic 	  case SCFREE:
61643218Sbostic 		if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);
61743218Sbostic 		return SCFREE;
61843218Sbostic 	  }
61943218Sbostic 
62043218Sbostic       if (s1 == SCSAFE) removesafe(&p->addrblock.memoffset);
62143218Sbostic       if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);
62243218Sbostic       return SCFREE;
62343218Sbostic 
62443218Sbostic 
62543218Sbostic     default:
62643218Sbostic       return SCFREE;
62743218Sbostic     }
62843218Sbostic }
62943218Sbostic 
63043218Sbostic 
safefactor(p)63143218Sbostic LOCAL safefactor(p)
63243218Sbostic expptr p;
63343218Sbostic 
63443218Sbostic {
63543218Sbostic   if ( ! ISCONST(p))
63643218Sbostic     return NO;
63743218Sbostic 
63843218Sbostic   if (ISINT(p->constblock.vtype))
63946305Sbostic     if (abs(p->constblock.constant.ci) <= 1)
64043218Sbostic       return YES;
64143218Sbostic 
64243218Sbostic   if (ISREAL(p->constblock.vtype))
64346305Sbostic     if (abs(p->constblock.constant.cd[0]) <= 1.0)
64443218Sbostic       return YES;
64543218Sbostic 
64643218Sbostic   return NO;
64743218Sbostic }
64843218Sbostic 
64943218Sbostic 
worthcost(p)65043218Sbostic LOCAL int worthcost(p)
65143218Sbostic expptr p;
65243218Sbostic 
65343218Sbostic {
65443218Sbostic   int cost;
65543218Sbostic   chainp q;
65643218Sbostic   expptr memoffset,vleng;
65743218Sbostic 
65843218Sbostic   if (p == ENULL)
65943218Sbostic     return NO;
66043218Sbostic 
66143218Sbostic   switch (p->tag)
66243218Sbostic     {
66343218Sbostic     case TCONST:
66443218Sbostic       return NO;
66543218Sbostic 
66643218Sbostic     case TTEMP:
66743218Sbostic       return NO;
66843218Sbostic 
66943218Sbostic     case TADDR:
67043218Sbostic       if ((vleng = p->addrblock.vleng) && ! ISCONST(vleng))
67143218Sbostic 	return NO;	/* Can't make variable length temporaries */
67243218Sbostic       if ((memoffset = p->addrblock.memoffset) && ! ISCONST(memoffset))
67343218Sbostic 	return YES;
67443218Sbostic       else
67543218Sbostic 	return NO;
67643218Sbostic 
67743218Sbostic     case TEXPR:
67843218Sbostic       return YES;
67943218Sbostic 
68043218Sbostic     case TLIST:
68143218Sbostic       cost = 0;
68243218Sbostic       for (q = p->listblock.listp; q; q = q->nextp)
68343218Sbostic 	{
68443218Sbostic 	if (worthcost ((expptr) q->datap))
68543218Sbostic 	  return YES;
68643218Sbostic 	cost++;
68743218Sbostic 	}
68843218Sbostic       return (cost>2 ? YES : NO);
68943218Sbostic 
69043218Sbostic     default:
69143218Sbostic       return NO;
69243218Sbostic     }
69343218Sbostic }
69443218Sbostic 
69543218Sbostic 
removesafe(refexpr)69643218Sbostic LOCAL removesafe(refexpr)
69743218Sbostic expptr *refexpr;
69843218Sbostic 
69943218Sbostic {
70043218Sbostic   expptr ep;
70143218Sbostic   Tempp ap;
70243218Sbostic   Slotp newslot;
70343218Sbostic 
70443218Sbostic   extern Addrp gettemp();
70543218Sbostic 
70643218Sbostic   ep = *refexpr;
70743218Sbostic   if (! worthcost(ep))
70843218Sbostic     return;
70943218Sbostic 
71043218Sbostic   if (ep->tag == TEXPR && ep->exprblock.opcode == OPASSIGN)
71143218Sbostic     {
71243218Sbostic       if (ep->exprblock.leftp->tag != TTEMP)
71343218Sbostic 	fatal ("non-TEMP in assignment to be moved in optloop");
71443218Sbostic 
71543218Sbostic       newslot = optinsert (SKEQ, ep, 0, 0, first);
71643218Sbostic       *refexpr = (expptr) cpexpr (ep->exprblock.leftp);
71743218Sbostic     }
71843218Sbostic   else
71943218Sbostic     {
72043218Sbostic       ap = (Tempp) gettemp(ep);
72143218Sbostic       newslot = optinsert (SKEQ, mkexpr(OPASSIGN,cpexpr(ap),ep), 0, 0, first);
72243218Sbostic       *refexpr = (expptr) ap;
72343218Sbostic       optinsert (SKFRTEMP,ap->memalloc,0,0,last->next);
72443218Sbostic     }
72543218Sbostic 
72643218Sbostic   comocount++;
72743218Sbostic   if (!newcode)
72843218Sbostic     newcode = newslot;
72943218Sbostic 
73043218Sbostic   return;
73143218Sbostic }
73243218Sbostic 
73343218Sbostic 
gettemp(p)73443218Sbostic LOCAL Addrp gettemp(p)
73543218Sbostic expptr p;
73643218Sbostic 
73743218Sbostic {
73843218Sbostic   return mktemp(p->headblock.vtype, p->headblock.vleng);
73943218Sbostic }
74043218Sbostic 
74143218Sbostic 
74243218Sbostic 
movefrtemp(expr)74343218Sbostic LOCAL movefrtemp (expr)
74443218Sbostic Tempp	expr;
74543218Sbostic 
74643218Sbostic {
74743218Sbostic   Slotp	s;
74843218Sbostic 
74943218Sbostic   if (expr->tag != TTEMP)
75043218Sbostic     badtag ("movefrtemp",expr->tag);
75143218Sbostic 
75243218Sbostic   for (s = first; s; s = s->next)
75343218Sbostic     if (s->type == SKFRTEMP && s->expr == (expptr) expr->memalloc)
75443218Sbostic       {
75543218Sbostic 	removeslot (s);
75643218Sbostic 	insertslot (s,last->next);
75743218Sbostic 	return;
75843218Sbostic       }
75943218Sbostic }
760