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