|
|
1.1 root 1:
2: #ifndef lint
3: static char sccsid[] = "@(#)coalesce.c 1.1 86/02/03 Copyr 1985 Sun Micro";
4: #endif
5:
6: /*
7: * Copyright (c) 1985 by Sun Microsystems, Inc.
8: */
9:
10: #include "as.h"
11: #include "c2.h"
12:
13: extern struct oper *newoperand();
14: extern struct ins_bkt *moveq;
15:
16: #define previ( p ) { do p=p->back; while( ISDIRECTIVE(p->op) ); }
17: #define nexti( p ) { do p=p->forw; while( ISDIRECTIVE(p->op) ); }
18:
19: #define ispushop(o) ((o)->type_o == T_PREDEC && (o)->value_o == SPREG)
20: #define ispopop(o) ((o)->type_o == T_POSTINC && (o)->value_o == SPREG)
21:
22: extern int bytesize[];
23: #define BYTESIZE( s ) (bytesize[ (int)(s)])
24:
25: /*
26: * Can register r1 be replaced by a new register r2?
27: * The answer is yes, provided that:
28: * 1. all uses of r1 in (p) are explicit
29: * 2. r1 and r2 are of the same type (a-reg, d-reg, or fp-reg)
30: * Certain exceptions to rule 2 are permissible if both r1 and r2 are
31: * a-regs or d-regs.
32: */
33: int
34: can_replace(p, r1, r2)
35: register NODE *p;
36: register r1,r2;
37: {
38: register struct oper *o;
39: register i;
40: int r1_found;
41:
42: /* search for explicit uses of r1 */
43: r1_found = 0;
44: for (i = 0; i < p->nref; i++) {
45: o = p->ref[i];
46: switch(o->type_o) {
47: case T_REG:
48: if (o->value_o == r1) {
49: r1_found++;
50: if ((p->op == OP_MOVE || p->op == OP_ADD || p->op == OP_SUB)
51: && p->subop == SUBOP_L
52: && !inmask(CCREG, p->forw->rlive)
53: && !inmask(FPCCREG, p->forw->rlive)) {
54: int ok;
55: o->value_o = r2;
56: ok = operand_ok(p->instr, p->ref[0], p->ref[1], 0);
57: o->value_o = r1;
58: if (ok) continue;
59: }
60: if (reg_access[r1] == reg_access[r2]) {
61: continue;
62: }
63: return 0;
64: }
65: continue;
66: case T_DEFER:
67: case T_POSTINC:
68: case T_PREDEC:
69: if (o->value_o == r1) {
70: return 0;
71: }
72: continue;
73: case T_DISPL:
74: if (o->reg_o == r1) {
75: return 0;
76: }
77: continue;
78: case T_INDEX:
79: if (o->reg_o == r1) {
80: return 0;
81: }
82: if (o->value_o == r1) {
83: /* a-regs and d-regs can be used interchangeably here */
84: r1_found++;
85: }
86: continue;
87: case T_REGPAIR:
88: if (o->reg_o == r1 || o->value_o == r1) {
89: return 0;
90: }
91: continue;
92: }
93: if (o->flags_o&O_BFLD) {
94: if (o->flags_o&O_BFOREG && o->bfoffset_o == r1) {
95: return 0;
96: }
97: if (o->flags_o&O_BFWREG && o->bfwidth_o == r1) {
98: return 0;
99: }
100: }
101: }
102: /*
103: * we know that r1 is used or set by p,
104: * but if r1_found == 0, we haven't found an
105: * explicit use. In this case we should bail out.
106: */
107: return(r1_found);
108: }
109:
110: void
111: replace(p, r1, r2)
112: register NODE *p;
113: register r1, r2;
114: {
115: register struct oper *o;
116: register i;
117:
118: /* search for explicit uses of r1 */
119: for (i = 0; i < p->nref; i++) {
120: o = p->ref[i];
121: switch(o->type_o) {
122: case T_REG:
123: case T_DEFER:
124: case T_POSTINC:
125: case T_PREDEC:
126: if (o->value_o == r1) {
127: o->value_o = r2;
128: }
129: continue;
130: case T_DISPL:
131: if (o->reg_o == r1) {
132: o->reg_o = r2;
133: }
134: continue;
135: case T_INDEX:
136: case T_REGPAIR:
137: if (o->reg_o == r1) {
138: o->reg_o = r2;
139: }
140: if (o->value_o == r1) {
141: o->value_o = r2;
142: }
143: continue;
144: }
145: if (o->flags_o&O_BFLD) {
146: if (o->flags_o&O_BFOREG && o->bfoffset_o == r1) {
147: o->bfoffset_o = r2;
148: }
149: if (o->flags_o&O_BFWREG && o->bfwidth_o == r1) {
150: o->bfwidth_o = r2;
151: }
152: continue;
153: } /* if */
154: } /* for */
155: installinstruct(p, p->instr);
156: } /* replace */
157:
158: int
159: next_member(regtype, regset)
160: int regtype;
161: regmask regset;
162: {
163: register regno;
164:
165: switch(regtype) {
166: case AM_DREG:
167: /* try for d-reg first */
168: for(regno = D0REG; regno <= D7REG; regno++) {
169: if (inmask(regno,regset))
170: return(regno);
171: }
172: for(regno = A0REG; regno < A6REG; regno++) {
173: if (inmask(regno,regset))
174: return(regno);
175: }
176: break;
177: case AM_AREG:
178: /* try for a-reg first */
179: for(regno = A0REG; regno < A6REG; regno++) {
180: if (inmask(regno,regset))
181: return(regno);
182: }
183: for(regno = D0REG; regno <= D7REG; regno++) {
184: if (inmask(regno,regset))
185: return(regno);
186: }
187: break;
188: case AM_FREG:
189: /* only another fp-reg will do */
190: for(regno = FP0REG; regno <= FP7REG; regno++) {
191: if (inmask(regno,regset))
192: return(regno);
193: }
194: break;
195: }
196: return(-1);
197: }
198:
199: /*
200: * look for a register that is not live anywhere in (b)..(n).
201: * regtype is the type of register preferred (or required,
202: * in the case of a floating point register). Returns -1 if
203: * no suitable register is found.
204: */
205: int
206: find_freereg(b, n, regtype)
207: register NODE *b, *n;
208: int regtype;
209: {
210: register NODE *p,*bb;
211: regmask liveset;
212: register regno;
213:
214: bb = b->back;
215: liveset = n->rlive;
216: for (p = n; p != bb; p = p->back) {
217: liveset = addmask(liveset, p->rlive);
218: }
219: liveset = addmask(liveset, p->rlive);
220: return(next_member(regtype, notmask(liveset)));
221: }
222:
223: /*
224: * try to replace register r1 with register r2 in the
225: * set of nodes (b)..(n) (assumed to be a basic block).
226: * r2 is assumed to be available in (b)..(n).
227: * Returns 1 if the new assignment succeeds.
228: * Otherwise returns 0 and leaves (b)..(n) unchanged.
229: */
230: int
231: can_reassign_reg(b,n,r1,r2)
232: register NODE *b,*n;
233: register r1;
234: register r2;
235: {
236: register NODE *p,*bb;
237: regmask l;
238:
239: if (!inmask(r1, b->rlive) && !inmask(r1, n->forw->rlive)) {
240: /* r1 and r2 must have the same type or must both be a/d regs */
241: if (reg_access[r1] != reg_access[r2]
242: && (!dareg(r1) || !dareg(r2))) {
243: return(0);
244: }
245: /* (b)..(n) contains the lifetime of r1 */
246: bb = b->back;
247: for (p = n; p != bb; p = p->back) {
248: if (ISINSTRUC(p->op)) {
249: if ((inmask(r1, p->ruse) || inmask(r1, p->rset))
250: && !can_replace(p, r1, r2)) {
251: return(0);
252: }
253: }
254: }
255: return(1);
256: }
257: return(0);
258: } /* can_reassign_reg */
259:
260: void
261: reassign_reg(b,n,r1,r2)
262: register NODE *b,*n;
263: register r1;
264: register r2;
265: {
266: register NODE *p,*bb;
267: regmask l;
268:
269: l = n->forw->rlive;
270: bb = b->back;
271: for (p = n; p != bb; p = p->back) {
272: if (ISINSTRUC(p->op)
273: && (inmask(r1, p->ruse) || inmask(r1, p->rset)))
274: replace(p, r1, r2);
275: l = p->rlive = compute_normal(p, l);
276: }
277: }
278:
279:
280: static struct ins_bkt *
281: move_inst(b,n,x,y)
282: register NODE *b, *n;
283: register struct oper *x, *y;
284: {
285: if (operand_ok(b->instr, x, y, 0)) {
286: return(b->instr);
287: } else if (operand_ok(n->instr, x, y, 0)) {
288: return(n->instr);
289: } else {
290: /* try special cases involving floating point */
291: int Xisfp, Yisfp;
292: Xisfp = Yisfp = 0;
293: if (x->type_o==T_REG && freg(x->value_o))
294: Xisfp = 1;
295: if (y->type_o==T_REG && freg(y->value_o))
296: Yisfp = 1;
297: if (!Xisfp && !Yisfp
298: && !inmask(FPCCREG, n->forw->rlive)) {
299: /* rewrite as (b) mov{b,w,l} X,Y */
300: switch(b->subop) {
301: case SUBOP_B:
302: return(sopcode("movb"));
303: case SUBOP_W:
304: return(sopcode("movw"));
305: case SUBOP_L:
306: case SUBOP_S:
307: return(sopcode("movl"));
308: default:
309: /* if larger than a word, forget it */
310: return(NULL);
311: }
312: } else if (Xisfp && Yisfp) {
313: /* floating point reg-reg move */
314: return(sopcode("fmovex"));
315: }
316: }
317: return(NULL);
318: }
319:
320: /*
321: * Is this instruction a reg-reg operation ?
322: * To be safe, we require the instruction to use all of
323: * both registers, with no data conversions.
324: */
325: static int
326: reg_reg_op(p)
327: register NODE *p;
328: {
329: register struct oper *rm, *rn;
330:
331: if (p->nref == 2) {
332: rm = p->ref[0]; rn = p->ref[1];
333: if(rm != NULL && rm->type_o == T_REG && datareg(rm->value_o)
334: && rn != NULL && rn->type_o == T_REG && datareg(rn->value_o)) {
335: switch (p->subop) {
336: case SUBOP_L:
337: return(dareg(rm->value_o) && dareg(rn->value_o));
338: case SUBOP_X:
339: return(freg(rm->value_o) && freg(rn->value_o));
340: }
341: }
342: }
343: return(0);
344: }
345:
346: static int
347: iscommuteop(p)
348: NODE *p;
349: {
350: char *s;
351:
352: switch(p->op){
353: case OP_ADD:
354: case OP_AND:
355: case OP_OR:
356: case OP_EOR:
357: return(reg_reg_op(p));
358: case OP_OTHER:
359: /*
360: * careful: multiplication isn't really commutative
361: * unless it is also known to be reg-reg
362: */
363: s = p->instr->text_i;
364: if (!strcmp(s,"mulsl") || !strcmp(s,"mulul")
365: || !strcmp(s,"fmulx") || !strcmp(s, "faddx"))
366: return(reg_reg_op(p));
367: }
368: return(0);
369: }
370:
371: /*
372: * returns 1 if an instruction does implied data conversion
373: * to match its destination operand (assumed to be the last operand).
374: * In the 68xxx processors this occurs in cases involving address
375: * registers or floating point registers.
376: */
377: int
378: implied_conversion(p)
379: register NODE *p;
380: {
381: struct oper *o;
382:
383: if (p->nref > 0) {
384: o = p->ref[p->nref-1];
385: if (datareg_addr(o)) {
386: if (areg(o->value_o)) return (p->subop != SUBOP_L);
387: if (freg(o->value_o)) return (p->subop != SUBOP_X);
388: }
389: }
390: return 0;
391: }
392:
393: /*
394: * coalesce register usage over subranges of a basic block,
395: * eliminating unnecessary reg-reg moves.
396: */
397: int
398: coalesce()
399: {
400: register NODE *n;
401: register NODE *p,*b;
402: register struct oper *o;
403: register struct ins_bkt *ip;
404: struct oper *rm, *rn;
405: NODE *q;
406: register int regno;
407: extern NODE *deletenode();
408: int changes;
409: regmask l;
410:
411: changes = 0;
412: for (n=first.forw; n != &first; n=n->forw) {
413:
414: /*
415: * Pattern #1: given
416: * (b) move X,rn
417: * ....
418: * (n) move rn,Y
419: *
420: * rewrite #1: if possible, rewrite as:
421: * (b) move X,Y
422: * ....
423: * (n) (deleted)
424: *
425: * rewrite #2: if possible, rewrite as:
426: * (b) (deleted)
427: * ....
428: * (n) move X,Y
429: *
430: * requirements:
431: * -- (b) and (n) must be moves of the same type
432: * -- (n) must not do sign-extension or other data conversion
433: * -- X must not be an immediate operand.
434: * -- Y must be a legal replacement for rn in (b).
435: * -- neither X nor Y can be a control register or i/o device
436: * -- rn must not be live at (n).
437: * -- rn must be neither used nor set in the interim.
438: * -- side effects of X and Y must not be used in the interim.
439: * -- condition codes should not be live at either (b) or (n).
440: *
441: * for #1:
442: * -- Y must not be used or modified in the interim.
443: *
444: * for #2:
445: * -- X must not be modified in the interim.
446: */
447: o = n->ref[0];
448: if (n->op == OP_MOVE && o->type_o == T_REG && datareg(o->value_o)
449: && !implied_conversion(n)
450: && !inmask(o->value_o, n->forw->rlive)) {
451: struct oper *x, *y;
452: x = y = NULL;
453: regno = o->value_o;
454: b = n;
455: do {
456: previ(b);
457: if (b->op == OP_FIRST || b->op == OP_LABEL
458: || ISBRANCH(b->op)) {
459: /* flow of control to reach this point is unknown */
460: break;
461: }
462: if (b->op == OP_MOVE && b->subop == n->subop
463: && b->ref[1]->type_o == T_REG
464: && b->ref[1]->value_o == o->value_o) {
465: /* have move x,rn;...;move rn,y */
466: x = b->ref[0];
467: y = n->ref[1];
468: /* do checks on x,y */
469: if (x->type_o == T_IMMED
470: || x->type_o == T_REG && !datareg(x->value_o)
471: || y->type_o == T_REG && !datareg(y->value_o)
472: || inmask(CCREG, b->forw->rlive)
473: || inmask(CCREG, n->forw->rlive)
474: || inmask(FPCCREG, b->forw->rlive)
475: || inmask(FPCCREG, n->forw->rlive)) {
476: /* can't optimize */
477: x = y = NULL;
478: }
479: break;
480: }
481: if (inmask(regno,b->rset) || inmask(regno,b->ruse)) {
482: /* unknown use/modification of regno */
483: break;
484: }
485: } while (1);
486: /*
487: * if the preceding search yielded a suitable operand
488: * pair, try to delete either node (b) or node (n).
489: */
490: if (y != NULL) {
491: int can_move_x = (x->type_o == T_REG || cancache(x));
492: int can_move_y = (y->type_o == T_REG || cancache(y));
493: /* determine side effects of (n) other than defining Y */
494: if (y->type_o == T_REG) {
495: l = submask(n->rset, MAKEWMASK(y->value_o, BW|WW|LW));
496: } else {
497: l = n->rset;
498: }
499: if (emptymask(andmask(l, n->forw->rlive))) {
500: /*
501: * search for defs/uses of Y and defs affecting access to Y;
502: * if none are found, move def of Y back to node (b).
503: */
504: p = n;
505: previ(p);
506: while (p != b) {
507: if (may_touch(p, y, n->subop, RMASK|WMASK)) {
508: can_move_y = 0;
509: break;
510: }
511: if (!emptymask(andmask(n->ruse, p->rset))) {
512: /* try salvaging by reassigning registers */
513: int r1, r2;
514: if (p->op != OP_MOVE
515: || p->ref[1]->type_o != T_REG ) {
516: /* def is implicit; give up */
517: can_move_y = 0;
518: break;
519: }
520: r1 = p->ref[1]->value_o;
521: r2 = find_freereg(p, n, reg_access[r1]);
522: if (r2 == -1 || !can_reassign_reg(p, n, r1, r2)) {
523: can_move_y = 0;
524: break;
525: }
526: reassign_reg(p, n, r1, r2);
527: }
528: previ(p);
529: }
530: if (can_move_y && (ip = move_inst(b, n, x, y)) != NULL) {
531: /* rewrite */
532: freeoperand(b->ref[1]);
533: b->ref[1] = newoperand(y);
534: installinstruct(b, ip);
535: n = deletenode(n);
536: changes++;
537: meter.redunm++;
538: if (ispopop(x) && ispushop(y)) {
539: b = deletenode(b);
540: changes++;
541: meter.redunm++;
542: }
543: l = n->forw->rlive;
544: for (p = n; p != b; p = p->back) {
545: l = p->rlive = compute_normal(p, l);
546: }
547: continue;
548: } /* if can_move_y */
549: } /* if */
550: /*
551: * search for defs of X and defs affecting access to X;
552: * if none are found, move use of X forward to node (n).
553: */
554: p = n;
555: previ(p);
556: while (p != b) {
557: if (may_touch(p, x, n->subop, WMASK)) {
558: can_move_x = 0;
559: break;
560: }
561: if (!emptymask(andmask(b->ruse, p->rset))) {
562: /* try salvaging by reassigning registers */
563: int r1, r2;
564: if (p->op != OP_MOVE
565: || p->ref[1]->type_o != T_REG ) {
566: /* def is implicit; give up */
567: can_move_x = 0;
568: break;
569: }
570: r1 = p->ref[1]->value_o;
571: r2 = find_freereg(p, n, reg_access[r1]);
572: if (r2 == -1 || !can_reassign_reg(p, n, r1, r2)) {
573: can_move_x = 0;
574: break;
575: }
576: reassign_reg(p, n, r1, r2);
577: }
578: previ(p);
579: }
580: if (can_move_x && (ip = move_inst(b, n, x, y)) != NULL) {
581: /* rewrite */
582: freeoperand(n->ref[0]);
583: n->ref[0] = newoperand(x);
584: installinstruct(n, ip);
585: b = deletenode(b);
586: changes++;
587: meter.redunm++;
588: if (ispopop(x) && ispushop(y)) {
589: n = deletenode(n);
590: changes++;
591: meter.redunm++;
592: }
593: l = n->forw->rlive;
594: for (p = n; p != b; p = p->back) {
595: l = p->rlive = compute_normal(p, l);
596: }
597: continue;
598: } /* if can_move_x */
599: } /* y != NULL */
600: } /* if */
601:
602: /*
603: * Pattern #2: given
604: * (b) move X,rn
605: * ....
606: * (computations involving rn)
607: * ....
608: * (n) move rn,rm
609: *
610: * if possible, rewrite as:
611: * (b) move X,rm
612: * ....
613: * (all defs/uses of rn changed to def/use rm)
614: * ....
615: * (n) (deleted)
616: *
617: * requirements:
618: * -- rn must not be live at (n).
619: * -- condition codes should not be live at (n).
620: * -- rm must neither be used nor set in the interim.
621: * -- all defs/uses of rn in (b)..(n) must be replaceable with rm.
622: */
623: o = n->ref[0];
624: if (n->op == OP_MOVE && reg_reg_op(n)
625: && !inmask(CCREG, n->forw->rlive)
626: && !inmask(FPCCREG, n->forw->rlive)
627: && !inmask(o->value_o, n->forw->rlive)) {
628: regno = n->ref[1]->value_o;
629: b = n;
630: do {
631: previ(b);
632: if (b->op == OP_FIRST || b->op == OP_LABEL
633: || ISBRANCH(b->op)) {
634: /* flow of control to reach this point is unknown */
635: break;
636: }
637: if (b->op == OP_MOVE && b->subop == n->subop
638: && sameops(o, b->ref[1])
639: && !inmask(regno, b->forw->rlive)) {
640: /* have move x,rn;...;move rn,rm */
641: if (can_reassign_reg(b, n, o->value_o, regno)) {
642: reassign_reg(b, n, o->value_o, regno);
643: b->ref[1]->value_o = regno;
644: n = deletenode(n);
645: changes++;
646: meter.redunm++;
647: l = n->forw->rlive;
648: for (p = n; p != b; p = p->back) {
649: l = p->rlive = compute_normal(p, l);
650: }
651: }
652: break;
653: }
654: if (inmask(regno,b->rset) || inmask(regno,b->ruse)) {
655: /* unknown use/modification of regno */
656: break;
657: }
658: } while (1);
659: } /* if */
660:
661: /*
662: * Pattern #3: (forward copy propagation)
663: * (n) move rm,rn (rm is dead after (n))
664: * ....
665: * (computations involving rn)
666: * ....
667: * (p) lastuse(rn) (rn is dead after (p))
668: *
669: * if possible, rewrite as:
670: * (n) (deleted)
671: * ....
672: * (all defs/uses of rn changed to def/use rm)
673: * ....
674: * (p) lastuse(rm)
675: *
676: * requirements:
677: * -- the move at (n) must not involve data conversions.
678: * -- rm must not be live after (n).
679: * -- rn must not be live after (p).
680: * -- rm must neither be used nor set in the interim.
681: * -- condition codes must not be live after (n).
682: * -- if condition codes are live at (p), rm and rn must be
683: * of the same type.
684: * -- all defs/uses of rn in (n)..(p) must be replaceable with rm.
685: */
686: if (n->op == OP_MOVE && reg_reg_op(n)
687: && !inmask(CCREG, n->forw->rlive)
688: && !inmask(FPCCREG, n->forw->rlive)
689: && !inmask(n->ref[0]->value_o, n->forw->rlive)) {
690: rm = n->ref[0];
691: rn = n->ref[1];
692: regno = rn->value_o;
693: p = n;
694: do {
695: /* scan forward for last use of value in rn */
696: nexti(p);
697: if (p->op == OP_FIRST || p->op == OP_LABEL
698: || ISBRANCH(p->op)) {
699: /* flow of control to reach this point is unknown */
700: break;
701: }
702: if (!inmask(regno, p->forw->rlive)) {
703: if (can_reassign_reg(n, p, regno, rm->value_o)) {
704: reassign_reg(n, p, regno, rm->value_o);
705: n = deletenode(n);
706: changes++;
707: meter.redunm++;
708: n->rlive = compute_normal(n, n->forw->rlive);
709: }
710: break;
711: }
712: if (inmask(rm->value_o,p->rset)||inmask(rm->value_o,p->ruse)) {
713: /* unknown use/modification of rm */
714: break;
715: }
716: } while(1);
717: } /* if */
718:
719: /*
720: * Pattern #4: (similar to #3, but exploits commutativity)
721: * (n) move rm,rn
722: * (q) <op> ro,rn (ro is dead after (q))
723: * ....
724: * (computations involving rn)
725: * ....
726: * (p) lastuse(rn) (rn is dead after (p))
727: *
728: * if possible, rewrite as:
729: * (n) (deleted)
730: * (q) <op> rm,ro
731: * ....
732: * (all defs/uses of rn changed to def/use ro)
733: * ....
734: * (p) lastuse(ro)
735: *
736: * requirements:
737: * -- the move at (n) must not involve data conversions.
738: * -- <op> must be commutative
739: * -- ro must not be live after (q).
740: * -- condition codes must not be live after (q).
741: * -- if condition codes are live after (p), rn and ro
742: * must be registers of the same type.
743: * -- rn must not be live after (p).
744: * -- ro must neither be used nor set in the interim.
745: * -- all defs/uses of rn in (q)..(p) must be replaceable with ro.
746: */
747: if (n->op == OP_MOVE && reg_reg_op(n)) {
748: rm = n->ref[0];
749: rn = n->ref[1];
750: q = n;
751: nexti(q);
752: if (iscommuteop(q)
753: && sameops(rn, q->ref[1])
754: && operand_ok(q->instr, rm, (o = q->ref[0]), 0)
755: && !inmask(o->value_o, q->forw->rlive)
756: && !inmask(CCREG, q->forw->rlive)
757: && !inmask(FPCCREG, q->forw->rlive) ) {
758: /*
759: * ro is dead, and its last use is in
760: * a commutative operator with rn. Scan for
761: * the last use of the value in rn.
762: */
763: regno = rn->value_o;
764: p = q;
765: do {
766: nexti(p);
767: if (p->op == OP_FIRST || p->op == OP_LABEL
768: || ISBRANCH(p->op)) {
769: /* flow of control to reach this point is unknown */
770: break;
771: }
772: if (!inmask(regno, p->forw->rlive)) {
773: if (can_reassign_reg(n, p, regno, o->value_o)) {
774: /*
775: * use rm as the first operand of q,
776: * propagate ro through the lifetime of rn,
777: * and delete the move from rm to rn.
778: */
779: q->ref[0] = newoperand(rm);
780: reassign_reg(n, p, regno, o->value_o);
781: freeoperand(o);
782: n = deletenode(n);
783: changes++;
784: meter.redunm++;
785: n->rlive = compute_normal(n, n->forw->rlive);
786: }
787: break;
788: } /* if */
789: if(inmask(o->value_o,p->ruse)||inmask(o->value_o,p->rset)) {
790: /* unknown use/def of ro */
791: break;
792: }
793: } while (1);
794: } /* if */
795: } /* if */
796:
797: } /* for */
798: return(changes);
799: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.