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