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