xref: /plan9-contrib/sys/src/cmd/9c/peep.c (revision fbadb1c4d4463e58337ffb1ed396c9caee5d1889)
1 #include "gc.h"
2 
3 static Reg*
rnops(Reg * r)4 rnops(Reg *r)
5 {
6 	Prog *p;
7 	Reg *r1;
8 
9 	if(r != R)
10 	for(;;){
11 		p = r->prog;
12 		if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
13 			break;
14 		r1 = uniqs(r);
15 		if(r1 == R)
16 			break;
17 		r = r1;
18 	}
19 	return r;
20 }
21 
22 void
peep(void)23 peep(void)
24 {
25 	Reg *r, *r1, *r2;
26 	Prog *p, *p1;
27 	int t;
28 /*
29  * complete R structure
30  */
31 	t = 0;
32 	for(r=firstr; r!=R; r=r1) {
33 		r1 = r->link;
34 		if(r1 == R)
35 			break;
36 		p = r->prog->link;
37 		while(p != r1->prog)
38 		switch(p->as) {
39 		default:
40 			r2 = rega();
41 			r->link = r2;
42 			r2->link = r1;
43 
44 			r2->prog = p;
45 			r2->p1 = r;
46 			r->s1 = r2;
47 			r2->s1 = r1;
48 			r1->p1 = r2;
49 
50 			r = r2;
51 			t++;
52 
53 		case ADATA:
54 		case AGLOBL:
55 		case ANAME:
56 		case ASIGNAME:
57 			p = p->link;
58 		}
59 	}
60 
61 loop1:
62 	t = 0;
63 	for(r=firstr; r!=R; r=r->link) {
64 		p = r->prog;
65 		if(p->as == AMOVW || p->as == AMOVD || p->as == AFMOVS || p->as == AFMOVD)
66 		if(regtyp(&p->to)) {
67 			if(regtyp(&p->from))
68 			if(p->from.type == p->to.type) {
69 				if(copyprop(r)) {
70 					excise(r);
71 					t++;
72 				} else
73 				if(subprop(r) && copyprop(r)) {
74 					excise(r);
75 					t++;
76 				}
77 			}
78 			if(regzer(&p->from))
79 			if(p->to.type == D_REG) {
80 				p->from.type = D_REG;
81 				p->from.reg = REGZERO;
82 				if(copyprop(r)) {
83 					excise(r);
84 					t++;
85 				} else
86 				if(subprop(r) && copyprop(r)) {
87 					excise(r);
88 					t++;
89 				}
90 			}
91 		}
92 	}
93 	if(t)
94 		goto loop1;
95 	/*
96 	 * look for MOVB x,R; MOVB R,R
97 	 */
98 	for(r=firstr; r!=R; r=r->link) {
99 		p = r->prog;
100 		switch(p->as) {
101 		default:
102 			continue;
103 		case AMOVH:
104 		case AMOVHZ:
105 		case AMOVB:
106 		case AMOVBZ:
107 		case AMOVW:
108 		case AMOVWZ:
109 			if(p->to.type != D_REG)
110 				continue;
111 			break;
112 		}
113 		r1 = r->link;
114 		if(r1 == R)
115 			continue;
116 		p1 = r1->prog;
117 		if(p1->as != p->as)
118 			continue;
119 		if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
120 			continue;
121 		if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
122 			continue;
123 		excise(r1);
124 	}
125 
126 	if(debug['D'] > 1)
127 		return;	/* allow following code improvement to be suppressed */
128 
129 	/*
130 	 * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R
131 	 * when OP can set condition codes correctly
132 	 */
133 	for(r=firstr; r!=R; r=r->link) {
134 		p = r->prog;
135 		switch(p->as) {
136 		case ACMP:
137 		case ACMPW:		/* always safe? */
138 			if(!regzer(&p->to))
139 				continue;
140 			r1 = r->s1;
141 			if(r1 == R)
142 				continue;
143 			switch(r1->prog->as) {
144 			default:
145 				continue;
146 			case ABCL:
147 			case ABC:
148 				/* the conditions can be complex and these are currently little used */
149 				continue;
150 			case ABEQ:
151 			case ABGE:
152 			case ABGT:
153 			case ABLE:
154 			case ABLT:
155 			case ABNE:
156 			case ABVC:
157 			case ABVS:
158 				break;
159 			}
160 			r1 = r;
161 			do
162 				r1 = uniqp(r1);
163 			while (r1 != R && r1->prog->as == ANOP);
164 			if(r1 == R)
165 				continue;
166 			p1 = r1->prog;
167 			if(p1->to.type != D_REG || p1->to.reg != p->from.reg)
168 				continue;
169 			switch(p1->as) {
170 			case ASUB:
171 			case AADD:
172 			case AXOR:
173 			case AOR:
174 				/* irregular instructions */
175 				if(p1->from.type == D_CONST)
176 					continue;
177 				break;
178 			}
179 			switch(p1->as) {
180 			default:
181 				continue;
182 			case AMOVW:
183 			case AMOVD:
184 				if(p1->from.type != D_REG)
185 					continue;
186 				continue;
187 			case AANDCC:
188 			case AANDNCC:
189 			case AORCC:
190 			case AORNCC:
191 			case AXORCC:
192 			case ASUBCC:
193 			case ASUBECC:
194 			case ASUBMECC:
195 			case ASUBZECC:
196 			case AADDCC:
197 			case AADDCCC:
198 			case AADDECC:
199 			case AADDMECC:
200 			case AADDZECC:
201 			case ARLWMICC:
202 			case ARLWNMCC:
203 				t = p1->as;
204 				break;
205 			/* don't deal with floating point instructions for now */
206 /*
207 			case AFABS:	t = AFABSCC; break;
208 			case AFADD:	t = AFADDCC; break;
209 			case AFADDS:	t = AFADDSCC; break;
210 			case AFCTIW:	t = AFCTIWCC; break;
211 			case AFCTIWZ:	t = AFCTIWZCC; break;
212 			case AFDIV:	t = AFDIVCC; break;
213 			case AFDIVS:	t = AFDIVSCC; break;
214 			case AFMADD:	t = AFMADDCC; break;
215 			case AFMADDS:	t = AFMADDSCC; break;
216 			case AFMOVD:	t = AFMOVDCC; break;
217 			case AFMSUB:	t = AFMSUBCC; break;
218 			case AFMSUBS:	t = AFMSUBSCC; break;
219 			case AFMUL:	t = AFMULCC; break;
220 			case AFMULS:	t = AFMULSCC; break;
221 			case AFNABS:	t = AFNABSCC; break;
222 			case AFNEG:	t = AFNEGCC; break;
223 			case AFNMADD:	t = AFNMADDCC; break;
224 			case AFNMADDS:	t = AFNMADDSCC; break;
225 			case AFNMSUB:	t = AFNMSUBCC; break;
226 			case AFNMSUBS:	t = AFNMSUBSCC; break;
227 			case AFRSP:	t = AFRSPCC; break;
228 			case AFSUB:	t = AFSUBCC; break;
229 			case AFSUBS:	t = AFSUBSCC; break;
230 			case ACNTLZW:	t = ACNTLZWCC; break;
231 			case AMTFSB0:	t = AMTFSB0CC; break;
232 			case AMTFSB1:	t = AMTFSB1CC; break;
233 */
234 			case AADD:	t = AADDCC; break;
235 			case AADDV:	t = AADDVCC; break;
236 			case AADDC:	t = AADDCCC; break;
237 			case AADDCV:	t = AADDCVCC; break;
238 			case AADDME:	t = AADDMECC; break;
239 			case AADDMEV:	t = AADDMEVCC; break;
240 			case AADDE:	t = AADDECC; break;
241 			case AADDEV:	t = AADDEVCC; break;
242 			case AADDZE:	t = AADDZECC; break;
243 			case AADDZEV:	t = AADDZEVCC; break;
244 			case AAND:	t = AANDCC; break;
245 			case AANDN:	t = AANDNCC; break;
246 			case ADIVW:	t = ADIVWCC; break;
247 			case ADIVWV:	t = ADIVWVCC; break;
248 			case ADIVWU:	t = ADIVWUCC; break;
249 			case ADIVWUV:	t = ADIVWUVCC; break;
250 			case ADIVD:	t = ADIVDCC; break;
251 			case ADIVDV:	t = ADIVDVCC; break;
252 			case ADIVDU:	t = ADIVDUCC; break;
253 			case ADIVDUV:	t = ADIVDUVCC; break;
254 			case AEQV:	t = AEQVCC; break;
255 			case AEXTSB:	t = AEXTSBCC; break;
256 			case AEXTSH:	t = AEXTSHCC; break;
257 			case AEXTSW:	t = AEXTSWCC; break;
258 			case AMULHW:	t = AMULHWCC; break;
259 			case AMULHWU:	t = AMULHWUCC; break;
260 			case AMULLW:	t = AMULLWCC; break;
261 			case AMULLWV:	t = AMULLWVCC; break;
262 			case AMULHD:	t = AMULHDCC; break;
263 			case AMULHDU:	t = AMULHDUCC; break;
264 			case AMULLD:	t = AMULLDCC; break;
265 			case AMULLDV:	t = AMULLDVCC; break;
266 			case ANAND:	t = ANANDCC; break;
267 			case ANEG:	t = ANEGCC; break;
268 			case ANEGV:	t = ANEGVCC; break;
269 			case ANOR:	t = ANORCC; break;
270 			case AOR:	t = AORCC; break;
271 			case AORN:	t = AORNCC; break;
272 			case AREM:	t = AREMCC; break;
273 			case AREMV:	t = AREMVCC; break;
274 			case AREMU:	t = AREMUCC; break;
275 			case AREMUV:	t = AREMUVCC; break;
276 			case AREMD:	t = AREMDCC; break;
277 			case AREMDV:	t = AREMDVCC; break;
278 			case AREMDU:	t = AREMDUCC; break;
279 			case AREMDUV:	t = AREMDUVCC; break;
280 			case ARLWMI:	t = ARLWMICC; break;
281 			case ARLWNM:	t = ARLWNMCC; break;
282 			case ASLW:	t = ASLWCC; break;
283 			case ASRAW:	t = ASRAWCC; break;
284 			case ASRW:	t = ASRWCC; break;
285 			case ASLD:	t = ASLDCC; break;
286 			case ASRAD:	t = ASRADCC; break;
287 			case ASRD:	t = ASRDCC; break;
288 			case ASUB:	t = ASUBCC; break;
289 			case ASUBV:	t = ASUBVCC; break;
290 			case ASUBC:	t = ASUBCCC; break;
291 			case ASUBCV:	t = ASUBCVCC; break;
292 			case ASUBME:	t = ASUBMECC; break;
293 			case ASUBMEV:	t = ASUBMEVCC; break;
294 			case ASUBE:	t = ASUBECC; break;
295 			case ASUBEV:	t = ASUBEVCC; break;
296 			case ASUBZE:	t = ASUBZECC; break;
297 			case ASUBZEV:	t = ASUBZEVCC; break;
298 			case AXOR:	t = AXORCC; break;
299 				break;
300 			}
301 			if(debug['D'])
302 				print("cmp %P; %P -> ", p1, p);
303 			p1->as = t;
304 			if(debug['D'])
305 				print("%P\n", p1);
306 			excise(r);
307 			continue;
308 		}
309 	}
310 }
311 
312 void
excise(Reg * r)313 excise(Reg *r)
314 {
315 	Prog *p;
316 
317 	p = r->prog;
318 	p->as = ANOP;
319 	p->from = zprog.from;
320 	p->from3 = zprog.from3;
321 	p->to = zprog.to;
322 	p->reg = zprog.reg; /**/
323 }
324 
325 Reg*
uniqp(Reg * r)326 uniqp(Reg *r)
327 {
328 	Reg *r1;
329 
330 	r1 = r->p1;
331 	if(r1 == R) {
332 		r1 = r->p2;
333 		if(r1 == R || r1->p2link != R)
334 			return R;
335 	} else
336 		if(r->p2 != R)
337 			return R;
338 	return r1;
339 }
340 
341 Reg*
uniqs(Reg * r)342 uniqs(Reg *r)
343 {
344 	Reg *r1;
345 
346 	r1 = r->s1;
347 	if(r1 == R) {
348 		r1 = r->s2;
349 		if(r1 == R)
350 			return R;
351 	} else
352 		if(r->s2 != R)
353 			return R;
354 	return r1;
355 }
356 
357 /*
358  * if the system forces R0 to be zero,
359  * convert references to $0 to references to R0.
360  */
regzer(Adr * a)361 regzer(Adr *a)
362 {
363 	if(R0ISZERO) {
364 		if(a->type == D_CONST)
365 			if(a->sym == S)
366 				if(a->offset == 0)
367 					return 1;
368 		if(a->type == D_REG)
369 			if(a->reg == REGZERO)
370 				return 1;
371 	}
372 	return 0;
373 }
374 
regtyp(Adr * a)375 regtyp(Adr *a)
376 {
377 
378 	if(a->type == D_REG) {
379 		if(!R0ISZERO || a->reg != REGZERO)
380 			return 1;
381 		return 0;
382 	}
383 	if(a->type == D_FREG)
384 		return 1;
385 	return 0;
386 }
387 
388 /*
389  * the idea is to substitute
390  * one register for another
391  * from one MOV to another
392  *	MOV	a, R0
393  *	ADD	b, R0	/ no use of R1
394  *	MOV	R0, R1
395  * would be converted to
396  *	MOV	a, R1
397  *	ADD	b, R1
398  *	MOV	R1, R0
399  * hopefully, then the former or latter MOV
400  * will be eliminated by copy propagation.
401  */
402 int
subprop(Reg * r0)403 subprop(Reg *r0)
404 {
405 	Prog *p;
406 	Adr *v1, *v2;
407 	Reg *r;
408 	int t;
409 
410 	p = r0->prog;
411 	v1 = &p->from;
412 	if(!regtyp(v1))
413 		return 0;
414 	v2 = &p->to;
415 	if(!regtyp(v2))
416 		return 0;
417 	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
418 		if(uniqs(r) == R)
419 			break;
420 		p = r->prog;
421 		switch(p->as) {
422 		case ABL:
423 			return 0;
424 
425 		case AADD:
426 		case AADDC:
427 		case AADDCC:
428 		case AADDE:
429 		case AADDECC:
430 		case ASUB:
431 		case ASUBCC:
432 		case ASUBC:
433 		case ASUBCCC:
434 		case ASUBE:
435 		case ASUBECC:
436 		case ASLW:
437 		case ASRW:
438 		case ASRWCC:
439 		case ASRAW:
440 		case ASRAWCC:
441 		case ASLD:
442 		case ASRD:
443 		case ASRAD:
444 		case AOR:
445 		case AORCC:
446 		case AORN:
447 		case AORNCC:
448 		case AAND:
449 		case AANDCC:
450 		case AANDN:
451 		case AANDNCC:
452 		case ANAND:
453 		case ANANDCC:
454 		case ANOR:
455 		case ANORCC:
456 		case AXOR:
457 		case AXORCC:
458 		case AMULHW:
459 		case AMULHWU:
460 		case AMULLW:
461 		case AMULLD:
462 		case ADIVW:
463 		case ADIVWU:
464 		case ADIVD:
465 		case ADIVDU:
466 		case AREM:
467 		case AREMU:
468 		case AREMD:
469 		case AREMDU:
470 		case ARLWNM:
471 		case ARLWNMCC:
472 
473 		case AFADD:
474 		case AFADDS:
475 		case AFSUB:
476 		case AFSUBS:
477 		case AFMUL:
478 		case AFMULS:
479 		case AFDIV:
480 		case AFDIVS:
481 			if(p->to.type == v1->type)
482 			if(p->to.reg == v1->reg) {
483 				if(p->reg == NREG)
484 					p->reg = p->to.reg;
485 				goto gotit;
486 			}
487 			break;
488 
489 		case AADDME:
490 		case AADDMECC:
491 		case AADDZE:
492 		case AADDZECC:
493 		case ASUBME:
494 		case ASUBMECC:
495 		case ASUBZE:
496 		case ASUBZECC:
497 		case ANEG:
498 		case ANEGCC:
499 		case AFNEG:
500 		case AFNEGCC:
501 		case AFMOVS:
502 		case AFMOVD:
503 		case AMOVW:
504 		case AMOVD:
505 			if(p->to.type == v1->type)
506 			if(p->to.reg == v1->reg)
507 				goto gotit;
508 			break;
509 		}
510 		if(copyau(&p->from, v2) ||
511 		   copyau1(p, v2) ||
512 		   copyau(&p->to, v2))
513 			break;
514 		if(copysub(&p->from, v1, v2, 0) ||
515 		   copysub1(p, v1, v2, 0) ||
516 		   copysub(&p->to, v1, v2, 0))
517 			break;
518 	}
519 	return 0;
520 
521 gotit:
522 	copysub(&p->to, v1, v2, 1);
523 	if(debug['P']) {
524 		print("gotit: %D->%D\n%P", v1, v2, r->prog);
525 		if(p->from.type == v2->type)
526 			print(" excise");
527 		print("\n");
528 	}
529 	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
530 		p = r->prog;
531 		copysub(&p->from, v1, v2, 1);
532 		copysub1(p, v1, v2, 1);
533 		copysub(&p->to, v1, v2, 1);
534 		if(debug['P'])
535 			print("%P\n", r->prog);
536 	}
537 	t = v1->reg;
538 	v1->reg = v2->reg;
539 	v2->reg = t;
540 	if(debug['P'])
541 		print("%P last\n", r->prog);
542 	return 1;
543 }
544 
545 /*
546  * The idea is to remove redundant copies.
547  *	v1->v2	F=0
548  *	(use v2	s/v2/v1/)*
549  *	set v1	F=1
550  *	use v2	return fail
551  *	-----------------
552  *	v1->v2	F=0
553  *	(use v2	s/v2/v1/)*
554  *	set v1	F=1
555  *	set v2	return success
556  */
557 int
copyprop(Reg * r0)558 copyprop(Reg *r0)
559 {
560 	Prog *p;
561 	Adr *v1, *v2;
562 	Reg *r;
563 
564 	p = r0->prog;
565 	v1 = &p->from;
566 	v2 = &p->to;
567 	if(copyas(v1, v2))
568 		return 1;
569 	for(r=firstr; r!=R; r=r->link)
570 		r->active = 0;
571 	return copy1(v1, v2, r0->s1, 0);
572 }
573 
copy1(Adr * v1,Adr * v2,Reg * r,int f)574 copy1(Adr *v1, Adr *v2, Reg *r, int f)
575 {
576 	int t;
577 	Prog *p;
578 
579 	if(r->active) {
580 		if(debug['P'])
581 			print("act set; return 1\n");
582 		return 1;
583 	}
584 	r->active = 1;
585 	if(debug['P'])
586 		print("copy %D->%D f=%d\n", v1, v2, f);
587 	for(; r != R; r = r->s1) {
588 		p = r->prog;
589 		if(debug['P'])
590 			print("%P", p);
591 		if(!f && uniqp(r) == R) {
592 			f = 1;
593 			if(debug['P'])
594 				print("; merge; f=%d", f);
595 		}
596 		t = copyu(p, v2, A);
597 		switch(t) {
598 		case 2:	/* rar, cant split */
599 			if(debug['P'])
600 				print("; %Drar; return 0\n", v2);
601 			return 0;
602 
603 		case 3:	/* set */
604 			if(debug['P'])
605 				print("; %Dset; return 1\n", v2);
606 			return 1;
607 
608 		case 1:	/* used, substitute */
609 		case 4:	/* use and set */
610 			if(f) {
611 				if(!debug['P'])
612 					return 0;
613 				if(t == 4)
614 					print("; %Dused+set and f=%d; return 0\n", v2, f);
615 				else
616 					print("; %Dused and f=%d; return 0\n", v2, f);
617 				return 0;
618 			}
619 			if(copyu(p, v2, v1)) {
620 				if(debug['P'])
621 					print("; sub fail; return 0\n");
622 				return 0;
623 			}
624 			if(debug['P'])
625 				print("; sub%D/%D", v2, v1);
626 			if(t == 4) {
627 				if(debug['P'])
628 					print("; %Dused+set; return 1\n", v2);
629 				return 1;
630 			}
631 			break;
632 		}
633 		if(!f) {
634 			t = copyu(p, v1, A);
635 			if(!f && (t == 2 || t == 3 || t == 4)) {
636 				f = 1;
637 				if(debug['P'])
638 					print("; %Dset and !f; f=%d", v1, f);
639 			}
640 		}
641 		if(debug['P'])
642 			print("\n");
643 		if(r->s2)
644 			if(!copy1(v1, v2, r->s2, f))
645 				return 0;
646 	}
647 	return 1;
648 }
649 
650 /*
651  * return
652  * 1 if v only used (and substitute),
653  * 2 if read-alter-rewrite
654  * 3 if set
655  * 4 if set and used
656  * 0 otherwise (not touched)
657  */
658 int
copyu(Prog * p,Adr * v,Adr * s)659 copyu(Prog *p, Adr *v, Adr *s)
660 {
661 
662 	switch(p->as) {
663 
664 	default:
665 		if(debug['P'])
666 			print(" (???)");
667 		return 2;
668 
669 
670 	case ANOP:	/* read, write */
671 	case AMOVH:
672 	case AMOVHZ:
673 	case AMOVB:
674 	case AMOVBZ:
675 	case AMOVW:
676 	case AMOVWZ:
677 	case AMOVD:
678 
679 	case ANEG:
680 	case ANEGCC:
681 	case AADDME:
682 	case AADDMECC:
683 	case AADDZE:
684 	case AADDZECC:
685 	case ASUBME:
686 	case ASUBMECC:
687 	case ASUBZE:
688 	case ASUBZECC:
689 
690 	case AFCTIW:
691 	case AFCTIWZ:
692 	case AFMOVS:
693 	case AFMOVD:
694 	case AFRSP:
695 	case AFNEG:
696 	case AFNEGCC:
697 		if(s != A) {
698 			if(copysub(&p->from, v, s, 1))
699 				return 1;
700 			if(!copyas(&p->to, v))
701 				if(copysub(&p->to, v, s, 1))
702 					return 1;
703 			return 0;
704 		}
705 		if(copyas(&p->to, v)) {
706 			if(copyau(&p->from, v))
707 				return 4;
708 			return 3;
709 		}
710 		if(copyau(&p->from, v))
711 			return 1;
712 		if(copyau(&p->to, v))
713 			return 1;
714 		return 0;
715 
716 	case ARLWMI:	/* read read rar */
717 	case ARLWMICC:
718 		if(copyas(&p->to, v))
719 			return 2;
720 		/* fall through */
721 
722 	case AADD:	/* read read write */
723 	case AADDC:
724 	case AADDE:
725 	case ASUB:
726 	case ASLW:
727 	case ASRW:
728 	case ASRAW:
729 	case ASLD:
730 	case ASRD:
731 	case ASRAD:
732 	case AOR:
733 	case AORCC:
734 	case AORN:
735 	case AORNCC:
736 	case AAND:
737 	case AANDCC:
738 	case AANDN:
739 	case AANDNCC:
740 	case ANAND:
741 	case ANANDCC:
742 	case ANOR:
743 	case ANORCC:
744 	case AXOR:
745 	case AMULHW:
746 	case AMULHWU:
747 	case AMULLW:
748 	case AMULLD:
749 	case ADIVW:
750 	case ADIVD:
751 	case ADIVWU:
752 	case ADIVDU:
753 	case AREM:
754 	case AREMU:
755 	case AREMD:
756 	case AREMDU:
757 	case ARLWNM:
758 	case ARLWNMCC:
759 
760 	case AFADDS:
761 	case AFADD:
762 	case AFSUBS:
763 	case AFSUB:
764 	case AFMULS:
765 	case AFMUL:
766 	case AFDIVS:
767 	case AFDIV:
768 		if(s != A) {
769 			if(copysub(&p->from, v, s, 1))
770 				return 1;
771 			if(copysub1(p, v, s, 1))
772 				return 1;
773 			if(!copyas(&p->to, v))
774 				if(copysub(&p->to, v, s, 1))
775 					return 1;
776 			return 0;
777 		}
778 		if(copyas(&p->to, v)) {
779 			if(p->reg == NREG)
780 				p->reg = p->to.reg;
781 			if(copyau(&p->from, v))
782 				return 4;
783 			if(copyau1(p, v))
784 				return 4;
785 			return 3;
786 		}
787 		if(copyau(&p->from, v))
788 			return 1;
789 		if(copyau1(p, v))
790 			return 1;
791 		if(copyau(&p->to, v))
792 			return 1;
793 		return 0;
794 
795 	case ABEQ:
796 	case ABGT:
797 	case ABGE:
798 	case ABLT:
799 	case ABLE:
800 	case ABNE:
801 	case ABVC:
802 	case ABVS:
803 		break;
804 
805 	case ACMP:	/* read read */
806 	case ACMPU:
807 	case ACMPW:
808 	case ACMPWU:
809 	case AFCMPO:
810 	case AFCMPU:
811 		if(s != A) {
812 			if(copysub(&p->from, v, s, 1))
813 				return 1;
814 			return copysub(&p->to, v, s, 1);
815 		}
816 		if(copyau(&p->from, v))
817 			return 1;
818 		if(copyau(&p->to, v))
819 			return 1;
820 		break;
821 
822 	case ABR:	/* funny */
823 		if(s != A) {
824 			if(copysub(&p->to, v, s, 1))
825 				return 1;
826 			return 0;
827 		}
828 		if(copyau(&p->to, v))
829 			return 1;
830 		return 0;
831 
832 	case ARETURN:	/* funny */
833 		if(v->type == D_REG)
834 			if(v->reg == REGRET)
835 				return 2;
836 		if(v->type == D_FREG)
837 			if(v->reg == FREGRET)
838 				return 2;
839 
840 	case ABL:	/* funny */
841 		if(v->type == D_REG) {
842 			if(v->reg <= REGEXT && v->reg > exregoffset)
843 				return 2;
844 			if(v->reg == REGARG)
845 				return 2;
846 		}
847 		if(v->type == D_FREG) {
848 			if(v->reg <= FREGEXT && v->reg > exfregoffset)
849 				return 2;
850 		}
851 
852 		if(s != A) {
853 			if(copysub(&p->to, v, s, 1))
854 				return 1;
855 			return 0;
856 		}
857 		if(copyau(&p->to, v))
858 			return 4;
859 		return 3;
860 
861 	case ATEXT:	/* funny */
862 		if(v->type == D_REG)
863 			if(v->reg == REGARG)
864 				return 3;
865 		return 0;
866 	}
867 	return 0;
868 }
869 
870 int
a2type(Prog * p)871 a2type(Prog *p)
872 {
873 
874 	switch(p->as) {
875 	case AADD:
876 	case AADDC:
877 	case AADDCC:
878 	case AADDCCC:
879 	case AADDE:
880 	case AADDECC:
881 	case AADDME:
882 	case AADDMECC:
883 	case AADDZE:
884 	case AADDZECC:
885 	case ASUB:
886 	case ASUBC:
887 	case ASUBCC:
888 	case ASUBCCC:
889 	case ASUBE:
890 	case ASUBECC:
891 	case ASUBME:
892 	case ASUBMECC:
893 	case ASUBZE:
894 	case ASUBZECC:
895 	case ASLW:
896 	case ASLWCC:
897 	case ASRW:
898 	case ASRWCC:
899 	case ASRAW:
900 	case ASRAWCC:
901 	case ASLD:
902 	case ASLDCC:
903 	case ASRD:
904 	case ASRDCC:
905 	case ASRAD:
906 	case ASRADCC:
907 	case AOR:
908 	case AORCC:
909 	case AORN:
910 	case AORNCC:
911 	case AAND:
912 	case AANDCC:
913 	case AANDN:
914 	case AANDNCC:
915 	case AXOR:
916 	case AXORCC:
917 	case ANEG:
918 	case ANEGCC:
919 	case AMULHW:
920 	case AMULHWU:
921 	case AMULLW:
922 	case AMULLWCC:
923 	case ADIVW:
924 	case ADIVWCC:
925 	case ADIVWU:
926 	case ADIVWUCC:
927 	case AREM:
928 	case AREMCC:
929 	case AREMU:
930 	case AREMUCC:
931 	case AMULLD:
932 	case AMULLDCC:
933 	case ADIVD:
934 	case ADIVDCC:
935 	case ADIVDU:
936 	case ADIVDUCC:
937 	case AREMD:
938 	case AREMDCC:
939 	case AREMDU:
940 	case AREMDUCC:
941 	case ANAND:
942 	case ANANDCC:
943 	case ANOR:
944 	case ANORCC:
945 	case ARLWMI:
946 	case ARLWMICC:
947 	case ARLWNM:
948 	case ARLWNMCC:
949 		return D_REG;
950 
951 	case AFADDS:
952 	case AFADDSCC:
953 	case AFADD:
954 	case AFADDCC:
955 	case AFSUBS:
956 	case AFSUBSCC:
957 	case AFSUB:
958 	case AFSUBCC:
959 	case AFMULS:
960 	case AFMULSCC:
961 	case AFMUL:
962 	case AFMULCC:
963 	case AFDIVS:
964 	case AFDIVSCC:
965 	case AFDIV:
966 	case AFDIVCC:
967 	case AFNEG:
968 	case AFNEGCC:
969 		return D_FREG;
970 	}
971 	return D_NONE;
972 }
973 
974 /*
975  * direct reference,
976  * could be set/use depending on
977  * semantics
978  */
979 int
copyas(Adr * a,Adr * v)980 copyas(Adr *a, Adr *v)
981 {
982 
983 	if(regtyp(v))
984 		if(a->type == v->type)
985 		if(a->reg == v->reg)
986 			return 1;
987 	return 0;
988 }
989 
990 /*
991  * either direct or indirect
992  */
993 int
copyau(Adr * a,Adr * v)994 copyau(Adr *a, Adr *v)
995 {
996 
997 	if(copyas(a, v))
998 		return 1;
999 	if(v->type == D_REG)
1000 		if(a->type == D_OREG)
1001 			if(v->reg == a->reg)
1002 				return 1;
1003 	return 0;
1004 }
1005 
1006 int
copyau1(Prog * p,Adr * v)1007 copyau1(Prog *p, Adr *v)
1008 {
1009 
1010 	if(regtyp(v))
1011 		if(p->from.type == v->type || p->to.type == v->type)
1012 		if(p->reg == v->reg) {
1013 			if(a2type(p) != v->type)
1014 				print("botch a2type %P\n", p);
1015 			return 1;
1016 		}
1017 	return 0;
1018 }
1019 
1020 /*
1021  * substitute s for v in a
1022  * return failure to substitute
1023  */
1024 int
copysub(Adr * a,Adr * v,Adr * s,int f)1025 copysub(Adr *a, Adr *v, Adr *s, int f)
1026 {
1027 
1028 	if(f)
1029 	if(copyau(a, v))
1030 		a->reg = s->reg;
1031 	return 0;
1032 }
1033 
1034 int
copysub1(Prog * p1,Adr * v,Adr * s,int f)1035 copysub1(Prog *p1, Adr *v, Adr *s, int f)
1036 {
1037 
1038 	if(f)
1039 	if(copyau1(p1, v))
1040 		p1->reg = s->reg;
1041 	return 0;
1042 }
1043