xref: /plan9/sys/src/cmd/qc/peep.c (revision cb8c047aa49e908a428eac8b13623e1b242fa11e)
1 #include "gc.h"
2 
3 void
peep(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
excise(Reg * r)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*
uniqp(Reg * r)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*
uniqs(Reg * r)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  */
regzer(Adr * a)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 
regtyp(Adr * a)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
subprop(Reg * r0)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 
427 		case AFADD:
428 		case AFADDS:
429 		case AFSUB:
430 		case AFSUBS:
431 		case AFMUL:
432 		case AFMULS:
433 		case AFDIV:
434 		case AFDIVS:
435 			if(p->to.type == v1->type)
436 			if(p->to.reg == v1->reg) {
437 				if(p->reg == NREG)
438 					p->reg = p->to.reg;
439 				goto gotit;
440 			}
441 			break;
442 
443 		case AADDME:
444 		case AADDMECC:
445 		case AADDZE:
446 		case AADDZECC:
447 		case ASUBME:
448 		case ASUBMECC:
449 		case ASUBZE:
450 		case ASUBZECC:
451 		case ANEG:
452 		case ANEGCC:
453 		case AFNEG:
454 		case AFNEGCC:
455 		case AFMOVS:
456 		case AFMOVD:
457 		case AMOVW:
458 			if(p->to.type == v1->type)
459 			if(p->to.reg == v1->reg)
460 				goto gotit;
461 			break;
462 		}
463 		if(copyau(&p->from, v2) ||
464 		   copyau1(p, v2) ||
465 		   copyau(&p->to, v2))
466 			break;
467 		if(copysub(&p->from, v1, v2, 0) ||
468 		   copysub1(p, v1, v2, 0) ||
469 		   copysub(&p->to, v1, v2, 0))
470 			break;
471 	}
472 	return 0;
473 
474 gotit:
475 	copysub(&p->to, v1, v2, 1);
476 	if(debug['P']) {
477 		print("gotit: %D->%D\n%P", v1, v2, r->prog);
478 		if(p->from.type == v2->type)
479 			print(" excise");
480 		print("\n");
481 	}
482 	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
483 		p = r->prog;
484 		copysub(&p->from, v1, v2, 1);
485 		copysub1(p, v1, v2, 1);
486 		copysub(&p->to, v1, v2, 1);
487 		if(debug['P'])
488 			print("%P\n", r->prog);
489 	}
490 	t = v1->reg;
491 	v1->reg = v2->reg;
492 	v2->reg = t;
493 	if(debug['P'])
494 		print("%P last\n", r->prog);
495 	return 1;
496 }
497 
498 /*
499  * The idea is to remove redundant copies.
500  *	v1->v2	F=0
501  *	(use v2	s/v2/v1/)*
502  *	set v1	F=1
503  *	use v2	return fail
504  *	-----------------
505  *	v1->v2	F=0
506  *	(use v2	s/v2/v1/)*
507  *	set v1	F=1
508  *	set v2	return success
509  */
510 int
copyprop(Reg * r0)511 copyprop(Reg *r0)
512 {
513 	Prog *p;
514 	Adr *v1, *v2;
515 	Reg *r;
516 
517 	p = r0->prog;
518 	v1 = &p->from;
519 	v2 = &p->to;
520 	if(copyas(v1, v2))
521 		return 1;
522 	for(r=firstr; r!=R; r=r->link)
523 		r->active = 0;
524 	return copy1(v1, v2, r0->s1, 0);
525 }
526 
copy1(Adr * v1,Adr * v2,Reg * r,int f)527 copy1(Adr *v1, Adr *v2, Reg *r, int f)
528 {
529 	int t;
530 	Prog *p;
531 
532 	if(r->active) {
533 		if(debug['P'])
534 			print("act set; return 1\n");
535 		return 1;
536 	}
537 	r->active = 1;
538 	if(debug['P'])
539 		print("copy %D->%D f=%d\n", v1, v2, f);
540 	for(; r != R; r = r->s1) {
541 		p = r->prog;
542 		if(debug['P'])
543 			print("%P", p);
544 		if(!f && uniqp(r) == R) {
545 			f = 1;
546 			if(debug['P'])
547 				print("; merge; f=%d", f);
548 		}
549 		t = copyu(p, v2, A);
550 		switch(t) {
551 		case 2:	/* rar, cant split */
552 			if(debug['P'])
553 				print("; %Drar; return 0\n", v2);
554 			return 0;
555 
556 		case 3:	/* set */
557 			if(debug['P'])
558 				print("; %Dset; return 1\n", v2);
559 			return 1;
560 
561 		case 1:	/* used, substitute */
562 		case 4:	/* use and set */
563 			if(f) {
564 				if(!debug['P'])
565 					return 0;
566 				if(t == 4)
567 					print("; %Dused+set and f=%d; return 0\n", v2, f);
568 				else
569 					print("; %Dused and f=%d; return 0\n", v2, f);
570 				return 0;
571 			}
572 			if(copyu(p, v2, v1)) {
573 				if(debug['P'])
574 					print("; sub fail; return 0\n");
575 				return 0;
576 			}
577 			if(debug['P'])
578 				print("; sub%D/%D", v2, v1);
579 			if(t == 4) {
580 				if(debug['P'])
581 					print("; %Dused+set; return 1\n", v2);
582 				return 1;
583 			}
584 			break;
585 		}
586 		if(!f) {
587 			t = copyu(p, v1, A);
588 			if(!f && (t == 2 || t == 3 || t == 4)) {
589 				f = 1;
590 				if(debug['P'])
591 					print("; %Dset and !f; f=%d", v1, f);
592 			}
593 		}
594 		if(debug['P'])
595 			print("\n");
596 		if(r->s2)
597 			if(!copy1(v1, v2, r->s2, f))
598 				return 0;
599 	}
600 	return 1;
601 }
602 
603 /*
604  * return
605  * 1 if v only used (and substitute),
606  * 2 if read-alter-rewrite
607  * 3 if set
608  * 4 if set and used
609  * 0 otherwise (not touched)
610  */
611 int
copyu(Prog * p,Adr * v,Adr * s)612 copyu(Prog *p, Adr *v, Adr *s)
613 {
614 
615 	switch(p->as) {
616 
617 	default:
618 		if(debug['P'])
619 			print(" (???)");
620 		return 2;
621 
622 	case ANOP:	/* read, write */
623 	case AMOVW:
624 	case AMOVH:
625 	case AMOVHZ:
626 	case AMOVB:
627 	case AMOVBZ:
628 
629 	case ANEG:
630 	case ANEGCC:
631 	case AADDME:
632 	case AADDMECC:
633 	case AADDZE:
634 	case AADDZECC:
635 	case ASUBME:
636 	case ASUBMECC:
637 	case ASUBZE:
638 	case ASUBZECC:
639 
640 	case AFCTIW:
641 	case AFCTIWZ:
642 	case AFMOVS:
643 	case AFMOVD:
644 	case AFRSP:
645 	case AFNEG:
646 	case AFNEGCC:
647 		if(s != A) {
648 			if(copysub(&p->from, v, s, 1))
649 				return 1;
650 			if(!copyas(&p->to, v))
651 				if(copysub(&p->to, v, s, 1))
652 					return 1;
653 			return 0;
654 		}
655 		if(copyas(&p->to, v)) {
656 			if(copyau(&p->from, v))
657 				return 4;
658 			return 3;
659 		}
660 		if(copyau(&p->from, v))
661 			return 1;
662 		if(copyau(&p->to, v))
663 			return 1;
664 		return 0;
665 
666 	case ARLWMI:	/* read read rar */
667 	case ARLWMICC:
668 		if(copyas(&p->to, v))
669 			return 2;
670 		/* fall through */
671 
672 	case AADD:	/* read read write */
673 	case AADDC:
674 	case AADDE:
675 	case ASUB:
676 	case ASLW:
677 	case ASRW:
678 	case ASRAW:
679 	case AOR:
680 	case AORCC:
681 	case AORN:
682 	case AORNCC:
683 	case AAND:
684 	case AANDCC:
685 	case AANDN:
686 	case AANDNCC:
687 	case ANAND:
688 	case ANANDCC:
689 	case ANOR:
690 	case ANORCC:
691 	case AXOR:
692 	case AMULHW:
693 	case AMULHWU:
694 	case AMULLW:
695 	case ADIVW:
696 	case ADIVWU:
697 	case AREM:
698 	case AREMU:
699 	case ARLWNM:
700 	case ARLWNMCC:
701 
702 	case AFADDS:
703 	case AFADD:
704 	case AFSUBS:
705 	case AFSUB:
706 	case AFMULS:
707 	case AFMUL:
708 	case AFDIVS:
709 	case AFDIV:
710 		if(s != A) {
711 			if(copysub(&p->from, v, s, 1))
712 				return 1;
713 			if(copysub1(p, v, s, 1))
714 				return 1;
715 			if(!copyas(&p->to, v))
716 				if(copysub(&p->to, v, s, 1))
717 					return 1;
718 			return 0;
719 		}
720 		if(copyas(&p->to, v)) {
721 			if(p->reg == NREG)
722 				p->reg = p->to.reg;
723 			if(copyau(&p->from, v))
724 				return 4;
725 			if(copyau1(p, v))
726 				return 4;
727 			return 3;
728 		}
729 		if(copyau(&p->from, v))
730 			return 1;
731 		if(copyau1(p, v))
732 			return 1;
733 		if(copyau(&p->to, v))
734 			return 1;
735 		return 0;
736 
737 	case ABEQ:
738 	case ABGT:
739 	case ABGE:
740 	case ABLT:
741 	case ABLE:
742 	case ABNE:
743 	case ABVC:
744 	case ABVS:
745 		break;
746 
747 	case ACMP:	/* read read */
748 	case ACMPU:
749 	case AFCMPO:
750 	case AFCMPU:
751 		if(s != A) {
752 			if(copysub(&p->from, v, s, 1))
753 				return 1;
754 			return copysub(&p->to, v, s, 1);
755 		}
756 		if(copyau(&p->from, v))
757 			return 1;
758 		if(copyau(&p->to, v))
759 			return 1;
760 		break;
761 
762 	case ABR:	/* funny */
763 		if(s != A) {
764 			if(copysub(&p->to, v, s, 1))
765 				return 1;
766 			return 0;
767 		}
768 		if(copyau(&p->to, v))
769 			return 1;
770 		return 0;
771 
772 	case ARETURN:	/* funny */
773 		if(v->type == D_REG)
774 			if(v->reg == REGRET)
775 				return 2;
776 		if(v->type == D_FREG)
777 			if(v->reg == FREGRET)
778 				return 2;
779 
780 	case ABL:	/* funny */
781 		if(v->type == D_REG) {
782 			if(v->reg <= REGEXT && v->reg > exregoffset)
783 				return 2;
784 			if(v->reg == REGARG)
785 				return 2;
786 		}
787 		if(v->type == D_FREG) {
788 			if(v->reg <= FREGEXT && v->reg > exfregoffset)
789 				return 2;
790 		}
791 
792 		if(s != A) {
793 			if(copysub(&p->to, v, s, 1))
794 				return 1;
795 			return 0;
796 		}
797 		if(copyau(&p->to, v))
798 			return 4;
799 		return 3;
800 
801 	case ATEXT:	/* funny */
802 		if(v->type == D_REG)
803 			if(v->reg == REGARG)
804 				return 3;
805 		return 0;
806 	}
807 	return 0;
808 }
809 
810 int
a2type(Prog * p)811 a2type(Prog *p)
812 {
813 
814 	switch(p->as) {
815 	case AADD:
816 	case AADDC:
817 	case AADDCC:
818 	case AADDCCC:
819 	case AADDE:
820 	case AADDECC:
821 	case AADDME:
822 	case AADDMECC:
823 	case AADDZE:
824 	case AADDZECC:
825 	case ASUB:
826 	case ASUBC:
827 	case ASUBCC:
828 	case ASUBCCC:
829 	case ASUBE:
830 	case ASUBECC:
831 	case ASUBME:
832 	case ASUBMECC:
833 	case ASUBZE:
834 	case ASUBZECC:
835 	case ASLW:
836 	case ASLWCC:
837 	case ASRW:
838 	case ASRWCC:
839 	case ASRAW:
840 	case ASRAWCC:
841 	case AOR:
842 	case AORCC:
843 	case AORN:
844 	case AORNCC:
845 	case AAND:
846 	case AANDCC:
847 	case AANDN:
848 	case AANDNCC:
849 	case AXOR:
850 	case AXORCC:
851 	case ANEG:
852 	case ANEGCC:
853 	case AMULHW:
854 	case AMULHWU:
855 	case AMULLW:
856 	case AMULLWCC:
857 	case ADIVW:
858 	case ADIVWCC:
859 	case ADIVWU:
860 	case ADIVWUCC:
861 	case AREM:
862 	case AREMCC:
863 	case AREMU:
864 	case AREMUCC:
865 	case ANAND:
866 	case ANANDCC:
867 	case ANOR:
868 	case ANORCC:
869 	case ARLWMI:
870 	case ARLWMICC:
871 	case ARLWNM:
872 	case ARLWNMCC:
873 		return D_REG;
874 
875 	case AFADDS:
876 	case AFADDSCC:
877 	case AFADD:
878 	case AFADDCC:
879 	case AFSUBS:
880 	case AFSUBSCC:
881 	case AFSUB:
882 	case AFSUBCC:
883 	case AFMULS:
884 	case AFMULSCC:
885 	case AFMUL:
886 	case AFMULCC:
887 	case AFDIVS:
888 	case AFDIVSCC:
889 	case AFDIV:
890 	case AFDIVCC:
891 	case AFNEG:
892 	case AFNEGCC:
893 		return D_FREG;
894 	}
895 	return D_NONE;
896 }
897 
898 /*
899  * direct reference,
900  * could be set/use depending on
901  * semantics
902  */
903 int
copyas(Adr * a,Adr * v)904 copyas(Adr *a, Adr *v)
905 {
906 
907 	if(regtyp(v))
908 		if(a->type == v->type)
909 		if(a->reg == v->reg)
910 			return 1;
911 	return 0;
912 }
913 
914 /*
915  * either direct or indirect
916  */
917 int
copyau(Adr * a,Adr * v)918 copyau(Adr *a, Adr *v)
919 {
920 
921 	if(copyas(a, v))
922 		return 1;
923 	if(v->type == D_REG)
924 		if(a->type == D_OREG)
925 			if(v->reg == a->reg)
926 				return 1;
927 	return 0;
928 }
929 
930 int
copyau1(Prog * p,Adr * v)931 copyau1(Prog *p, Adr *v)
932 {
933 
934 	if(regtyp(v))
935 		if(p->from.type == v->type || p->to.type == v->type)
936 		if(p->reg == v->reg) {
937 			if(a2type(p) != v->type)
938 				print("botch a2type %P\n", p);
939 			return 1;
940 		}
941 	return 0;
942 }
943 
944 /*
945  * substitute s for v in a
946  * return failure to substitute
947  */
948 int
copysub(Adr * a,Adr * v,Adr * s,int f)949 copysub(Adr *a, Adr *v, Adr *s, int f)
950 {
951 
952 	if(f)
953 	if(copyau(a, v))
954 		a->reg = s->reg;
955 	return 0;
956 }
957 
958 int
copysub1(Prog * p1,Adr * v,Adr * s,int f)959 copysub1(Prog *p1, Adr *v, Adr *s, int f)
960 {
961 
962 	if(f)
963 	if(copyau1(p1, v))
964 		p1->reg = s->reg;
965 	return 0;
966 }
967