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