|
|
1.1 root 1: /*
2: * n2/optim.c
3: * C compiler.
4: * Jump and shape optimization.
5: * Jump to jump, etc.
6: * Common sequences.
7: * Cross jumping.
8: */
9:
10: #ifdef vax
11: #include "INC$LIB:cc2.h"
12: #else
13: #include "cc2.h"
14: #endif
15:
16: #define NLHASH 64
17: #define LHMASK 077
18:
19: static INS *labhash[NLHASH];
20:
21: /*
22: * Shuffle segments,
23: * Move all non 'SHRI' segments to the front,
24: * then squash any extra switches out of the stream.
25: * This is necessary to make code that is together in
26: * memory together in the 'ins' lists.
27: */
28: shuffle()
29: {
30: register INS *fp, *ip;
31: register INS *niloc;
32: INS *bep, *bfp;
33: register int curseg;
34:
35: niloc = &ins;
36: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) {
37: if (ip->i_type != ENTER)
38: continue;
39: bfp = ip;
40: do {
41: ip = ip->i_fp;
42: } while (ip->i_type != ENTER);
43: if (bfp != ins.i_fp) {
44: bep = ip;
45: ip = bfp->i_bp;
46: bfp->i_bp->i_fp = bep->i_fp;
47: bep->i_fp->i_bp = bfp->i_bp;
48: niloc->i_fp->i_bp = bep;
49: bfp->i_bp = niloc;
50: bep->i_fp = niloc->i_fp;
51: niloc->i_fp = bfp;
52: niloc = bep;
53: }
54: }
55: curseg = dotseg;
56: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) {
57: if (ip->i_type != ENTER)
58: continue;
59: while ((fp=ip->i_fp)!=&ins && fp->i_type==ENTER)
60: ip = deleteins(ip, ip->i_fp)->i_fp;
61: if (ip->i_seg == curseg) {
62: ip = deleteins(ip, ip->i_fp);
63: continue;
64: }
65: curseg = ip->i_seg;
66: }
67: }
68:
69: /*
70: * Delete node ip.
71: * Return a pointer to the previous node.
72: * Merge any line number references onto ip1.
73: */
74: INS *
75: deleteins(ip, ip1)
76: register INS *ip;
77: INS *ip1;
78: {
79: register INS *bp, *fp;
80:
81: mrgdbgt(ip, ip1);
82: if ((ip->i_type==JUMP || ip->i_type==LLLINK) && ((fp=ip->i_ip)!=NULL))
83: decrefc(fp);
84: bp = ip->i_bp;
85: fp = ip->i_fp;
86: bp->i_fp = fp;
87: fp->i_bp = bp;
88: free((char *) ip);
89: return bp;
90: }
91:
92: /*
93: * Decrement the reference count on a label.
94: * Delete it if the label is now unreferenced.
95: * It is a fatal error to hand this routine a non label.
96: */
97: decrefc(ip)
98: register INS *ip;
99: {
100: if (ip->i_type != LLABEL)
101: cbotch("decrefc passed non label");
102: if (--ip->i_refc == 0)
103: deleteins(ip, ip->i_fp);
104: }
105:
106: /*
107: * Set up label reference counts and delete any unused labels.
108: */
109: labels()
110: {
111: register INS *fp, *ip, *lp;
112: INS *findlab();
113: register int curseg, i;
114:
115: for (i=0; i<NLHASH; ++i)
116: labhash[i] = NULL;
117: curseg = dotseg;
118: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) {
119: if (ip->i_type == ENTER)
120: curseg = ip->i_seg;
121: else if (ip->i_type == LLABEL) {
122: ip->i_refc = 0;
123: /*
124: * Hack the reference count on the
125: * label if it is the label on a switch
126: * table to prevent it from being deleted
127: * by the next bit of code. Kludgy.
128: */
129: if (curseg != SCODE)
130: ++ip->i_refc;
131: else if ((fp=ip->i_fp) != &ins) {
132: if (fp->i_type == LLLINK)
133: ++ip->i_refc;
134: else if (fp->i_type == CODE
135: && fp->i_op >= ZBYTE
136: && fp->i_op <= ZGPTR)
137: ++ip->i_refc;
138: }
139: labhash[ip->i_labno&LHMASK] = ip;
140: }
141: }
142: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) {
143: if (ip->i_type!=JUMP && ip->i_type!=LLLINK)
144: continue;
145: if ((lp=findlab(ip->i_labno)) != NULL) {
146: while ((fp=lp->i_fp)!=&ins && fp->i_type==LLABEL)
147: lp = fp;
148: ip->i_labno = lp->i_labno;
149: ++lp->i_refc;
150: }
151: ip->i_ip = lp;
152: }
153: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) {
154: if (ip->i_type!=LLABEL || ip->i_refc!=0)
155: continue;
156: ip = deleteins(ip, ip->i_fp);
157: ++nlabdel;
158: }
159: }
160:
161: /*
162: * Find label.
163: * Quick test using hashtable.
164: * Long linear search if that fails.
165: */
166: INS *
167: findlab(n)
168: register int n;
169: {
170: register INS *lp;
171:
172: if ((lp=labhash[n&LHMASK])!=NULL && lp->i_labno==n)
173: return lp;
174: for (lp=ins.i_fp; lp!=&ins; lp=lp->i_fp)
175: if (lp->i_type==LLABEL && lp->i_labno==n)
176: return lp;
177: return NULL;
178: }
179:
180: /*
181: * Delete dead code.
182: * Dead code begins after an unconditional jump and continues
183: * until the next label, segment change or the EPILOG.
184: */
185: deadcode()
186: {
187: register INS *fp, *ip;
188: register int t;
189:
190: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) {
191: t = ip->i_type;
192: if (t == LLLINK) { /* Switch table */
193: while ((fp=ip->i_fp) != &ins && (fp->i_type == LLLINK
194: || (fp->i_type == CODE && opinfo[fp->i_op].op_style
195: == OF_WORD)))
196: ip = fp;
197: } else if (t != JUMP || ip->i_rel != UNCON)
198: continue;
199: fp = ip->i_fp;
200: while (fp != &ins) {
201: t = fp->i_type;
202: if (t==LLABEL || t==EPILOG || t==ENTER)
203: break;
204: fp = deleteins(fp, fp->i_fp)->i_fp;
205: ++ndead;
206: ++changes;
207: }
208: }
209: }
210:
211: /*
212: * Fix some of the more common funny things
213: * associated with jump instructions and labels.
214: * There are more things that could be done.
215: * These five things should get most of the common things.
216: */
217: fixbr()
218: {
219: register INS *ip, *ip1, *ip2;
220: INS *ip3, *ip4;
221: int t;
222:
223: again:
224: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) {
225: t = ip->i_type;
226: /* Jump to jump. */
227: if ((t==JUMP && ischnrel(ip->i_rel)) || t==LLLINK) {
228: ip1 = ip->i_ip;
229: if (ip1 != NULL) {
230: ip2 = ip1;
231: for (;;) {
232: while (ip2->i_type == LLABEL)
233: ip2 = ip2->i_fp;
234: if (ip2->i_type!=JUMP
235: || ip2->i_rel!=UNCON)
236: break;
237: ip3 = ip2->i_ip;
238: if (ip3==NULL
239: || ip3==ip1
240: || ip3==ip2->i_bp)
241: break;
242: ip2 = ip3;
243: }
244: ip2 = ip2->i_bp;
245: if (ip1 != ip2) {
246: decrefc(ip1);
247: increfc(ip2);
248: ip->i_labno = ip2->i_labno;
249: ip->i_ip = ip2;
250: ++nbrbr;
251: ++changes;
252: }
253: }
254: }
255: /* Reversible jump over unconditional jump. */
256: if (t==JUMP && isrevrel(ip->i_rel)) {
257: ip1 = ip->i_fp;
258: if (ip1->i_type==JUMP && ip1->i_rel==UNCON) {
259: ip2 = ip1->i_fp;
260: if (ip2->i_type==LLABEL && ip->i_ip==ip2) {
261: ip1->i_rel = revrel(ip->i_rel);
262: deleteins(ip, ip1);
263: ++ncbrbr;
264: ++changes;
265: goto again;
266: }
267: }
268: }
269: /* Jump to next instruction. */
270: if (t==JUMP && ip->i_ip==ip->i_fp) {
271: deleteins(ip, ip->i_fp);
272: ++nbrnext;
273: ++changes;
274: goto again;
275: }
276: /* Conditional jump followed by unconditional jump to same loc. */
277: if (t==JUMP && ip->i_rel!=UNCON
278: && (ip1=ip->i_fp)->i_type==JUMP && ip1->i_rel==UNCON
279: && ip->i_ip==ip1->i_ip) {
280: deleteins(ip, ip->i_fp);
281: ++nexbr;
282: ++changes;
283: goto again;
284: }
285: /*
286: * The preceding optimizations do not change the code order,
287: * so they can be executed even if VNOOPT.
288: * The following optimizations do change the code order,
289: * so they are suppressed if VNOOPT.
290: */
291: if (isvariant(VNOOPT))
292: continue;
293: /*
294: * [ip]JUMP L1; [ip1]L2:...; [ip2]L1:...; [ip3]JUMP L2; ...
295: * becomes [ip2]L1:...; [ip1]L2:...; [ip]JUMP L1; ...
296: * Saves a jump in every for loop.
297: */
298: if (t==JUMP && ip->i_rel==UNCON) {
299: ip1 = ip->i_fp;
300: if (ip1!=&ins && ip1->i_type==LLABEL) {
301: ip2 = NULL;
302: for (ip3=ip1->i_fp; ip3!=&ins; ip3=ip3->i_fp) {
303: if (ip3->i_type==LLABEL
304: && ip->i_ip==ip3)
305: ip2 = ip3;
306: else if (ip2!=NULL
307: && ip3->i_type==JUMP
308: && ip3->i_rel==UNCON
309: && ip3->i_ip==ip1) {
310: ip4 = ip2->i_bp;
311: ip->i_bp->i_fp = ip2;
312: ip3->i_bp->i_fp = ip1;
313: ip4->i_fp = ip;
314: ip->i_fp = ip3;
315: ip2->i_bp = ip->i_bp;
316: ip1->i_bp = ip3->i_bp;
317: ip->i_bp = ip4;
318: ip3->i_bp = ip;
319: deleteins(ip3, ip1);
320: ++nexbr;
321: ++changes;
322: goto again;
323: }
324: }
325: }
326: }
327: /*
328: * [ip] JUMP L1; <code1>; [ip2] JUMP L2; [ip1] L1: <code2>; [ip3] L2:
329: * becomes [ip1] L1: <code2>; [ip] JUMP L2; <code1>; [ip3] L2:
330: * Saves a jump in every switch and restores natural code order.
331: * <code2> often ends in JUMP or LLLINK, in which case JUMP L2
332: * gets optimized out later.
333: */
334: if (t==JUMP && ip->i_rel==UNCON && precedes(ip, ip->i_ip)) {
335: ip1 = ip->i_ip;
336: ip2 = ip1->i_bp;
337: if (ip2->i_type==JUMP && ip2->i_rel==UNCON
338: && precedes(ip1, ip2->i_ip)) {
339: ip3 = ip2->i_ip;
340: /* Rearrange the code. */
341: ip->i_bp->i_fp = ip1;
342: ip3->i_bp->i_fp = ip;
343: ip2->i_fp = ip3;
344: ip1->i_bp = ip->i_bp;
345: ip->i_bp = ip3->i_bp;
346: ip3->i_bp = ip2;
347: /* Change JUMP L1 at ip into JUMP L2. */
348: ip->i_ip = ip3;
349: ip->i_labno = ip3->i_labno;
350: increfc(ip3);
351: decrefc(ip1);
352: /* Delete the now extraneous JUMP. */
353: deleteins(ip2, ip3);
354: ++nexbr;
355: ++changes;
356: goto again;
357: }
358: }
359: }
360: }
361:
362: /*
363: * Return true iff ip1 precedes ip2 in the INS node chain.
364: */
365: static
366: precedes(ip1, ip2)
367: register INS *ip1, *ip2;
368: {
369: while ((ip1 = ip1->i_fp) != &ins)
370: if (ip1 == ip2)
371: return 1;
372: return 0;
373: }
374:
375: /*
376: * Increment the reference count on a label.
377: * It is a fatal error to hand this routine a non label.
378: */
379: increfc(ip)
380: register INS *ip;
381: {
382: if (ip->i_type != LLABEL)
383: cbotch("increfc passed non label");
384: ++ip->i_refc;
385: }
386:
387: /*
388: * Insert a label.
389: * It has been 'increfc'ed.
390: * Return pointer to the new label.
391: */
392: INS *
393: inslab(ip)
394: register INS *ip;
395: {
396: register INS *lp, *bp;
397:
398: if (ip->i_type == LLABEL) {
399: increfc(ip);
400: return ip;
401: }
402: lp = (INS *) malloc(sizeof(INS));
403: if (lp != NULL) {
404: lp->i_type = LLABEL;
405: lp->i_labno = newlab();
406: lp->i_sp = NULL;
407: lp->i_refc = 1;
408: bp = ip->i_bp;
409: bp->i_fp = lp;
410: lp->i_fp = ip;
411: ip->i_bp = lp;
412: lp->i_bp = bp;
413: }
414: return lp;
415: }
416:
417: /*
418: * Cross jumps.
419: * If the same code precedes an unconditional jump and
420: * the label to which it jumps, replace the former with
421: * a jump to a new local label.
422: */
423: xjumps()
424: {
425: register INS *ip, *lp;
426:
427: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) {
428: if (ip->i_type!=JUMP || ip->i_rel!=UNCON
429: || (lp = ip->i_ip)==NULL)
430: continue;
431: if (!docomseq(lp, ip, &nxjump))
432: return;
433: }
434: }
435:
436: /*
437: * Compare two nodes.
438: * True return if the same.
439: * Never called on strange stuff
440: * or labels.
441: */
442: xeq(ip1, ip2)
443: register INS *ip1, *ip2;
444: {
445: register int t;
446:
447: if ((t=ip1->i_type) != ip2->i_type)
448: return 0;
449: if (t==JUMP || t==LLLINK) {
450: if (ip1->i_labno != ip2->i_labno)
451: return 0;
452: if (t==JUMP && ip1->i_rel!=ip2->i_rel)
453: return 0;
454: return 1;
455: }
456: if (t != CODE)
457: cbotch("xeq");
458: if (ip1->i_op != ip2->i_op)
459: return 0;
460: if (ip1->i_naddr != ip2->i_naddr)
461: return 0;
462: return cmpfield(ip1, ip2);
463: }
464:
465: /*
466: * Detect common sequences before jumps.
467: * When found, replace the later with a jump to a new
468: * local label preceding the former.
469: */
470: comseq()
471: {
472: register INS *ip, *xp, *yp;
473:
474: for (xp=ins.i_fp; xp!=&ins; xp=xp->i_fp) {
475: if (xp->i_type!=JUMP || xp->i_rel!=UNCON)
476: continue;
477: ip = xp->i_ip;
478: if (ip==NULL || ip->i_type != LLABEL)
479: continue;
480: for (yp=xp->i_fp; yp!=&ins; yp=yp->i_fp) {
481: if (yp->i_type==JUMP && yp->i_rel==UNCON
482: && yp->i_ip==ip) {
483: if (!docomseq(xp, yp, &ncomseq))
484: return;
485: }
486: }
487: }
488: }
489:
490:
491: /*
492: * Back up through the code looking for valid cross jumps.
493: * When found, insert a new local label before the first
494: * and change the second into an unconditional jump to it.
495: * Called from xjumps and comseq.
496: * Returns 0 if the new node allocation fails.
497: */
498: docomseq(xp, yp, countp)
499: register INS *xp, *yp;
500: int *countp;
501: {
502: for (;;) {
503: xp = xp->i_bp;
504: if (xp==&ins || xp->i_type==LLABEL || xp->i_type==LLLINK)
505: break;
506: yp = yp->i_bp;
507: if (yp==&ins || yp->i_type==LLABEL || yp->i_type==LLLINK
508: || xeq(xp, yp)==0)
509: break;
510: xp = inslab(xp);
511: if (xp == NULL)
512: return 0;
513: mrgdbgt(yp, xp->i_fp);
514: if ((yp->i_type==JUMP || yp->i_type==LLLINK) && yp->i_ip!=NULL)
515: decrefc(yp->i_ip);
516: yp->i_type = JUMP;
517: yp->i_labno = xp->i_labno;
518: yp->i_sp = NULL;
519: yp->i_ip = xp;
520: yp->i_rel = UNCON;
521: yp->i_long = 0;
522: ++*countp;
523: ++changes;
524: }
525: return 1;
526: }
527:
528: /* end of n2/optim.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.