xref: /netbsd-src/external/bsd/pcc/dist/pcc/mip/match.c (revision 411dcbec990c8aa9c57d3bd2f4bcacadec0b1ab5)
1 /*      Id: match.c,v 1.104 2015/11/17 19:19:40 ragge Exp    */
2 /*      $NetBSD: match.c,v 1.1.1.7 2016/02/09 20:29:15 plunky Exp $   */
3 /*
4  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  *
37  * Redistributions of source code and documentation must retain the above
38  * copyright notice, this list of conditions and the following disclaimer.
39  * Redistributions in binary form must reproduce the above copyright
40  * notice, this list of conditionsand the following disclaimer in the
41  * documentation and/or other materials provided with the distribution.
42  * All advertising materials mentioning features or use of this software
43  * must display the following acknowledgement:
44  * 	This product includes software developed or owned by Caldera
45  *	International, Inc.
46  * Neither the name of Caldera International, Inc. nor the names of other
47  * contributors may be used to endorse or promote products derived from
48  * this software without specific prior written permission.
49  *
50  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
51  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
52  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
53  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
54  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
55  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
59  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
60  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61  * POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include "pass2.h"
65 
66 #ifdef HAVE_STRINGS_H
67 #include <strings.h>
68 #endif
69 
70 void setclass(int tmp, int class);
71 int getclass(int tmp);
72 
73 #ifdef PCC_DEBUG
74 static char *srtyp[] = { "SRNOPE", "SRDIR", "SROREG", "SRREG" };
75 #endif
76 
77 /*
78  * return true if shape is appropriate for the node p
79  *
80  * Return values:
81  * SRNOPE  Cannot match this shape.
82  * SRDIR   Direct match, may or may not traverse down.
83  * SRREG   Will match if put in a regster XXX - kill this?
84  */
85 int
tshape(NODE * p,int shape)86 tshape(NODE *p, int shape)
87 {
88 	int o, mask;
89 
90 	o = p->n_op;
91 
92 #ifdef PCC_DEBUG
93 	if (s2debug)
94 		printf("tshape(%p, %s) op = %s\n", p, prcook(shape), opst[o]);
95 #endif
96 
97 	if (shape & SPECIAL) {
98 
99 		switch (shape) {
100 		case SZERO:
101 		case SONE:
102 		case SMONE:
103 		case SSCON:
104 		case SCCON:
105 			if (o != ICON || p->n_name[0])
106 				return SRNOPE;
107 			if (getlval(p)== 0 && shape == SZERO)
108 				return SRDIR;
109 			if (getlval(p) == 1 && shape == SONE)
110 				return SRDIR;
111 			if (getlval(p) == -1 && shape == SMONE)
112 				return SRDIR;
113 			if (getlval(p) > -257 && getlval(p) < 256 &&
114 			    shape == SCCON)
115 				return SRDIR;
116 			if (getlval(p) > -32769 && getlval(p) < 32768 &&
117 			    shape == SSCON)
118 				return SRDIR;
119 			return SRNOPE;
120 
121 		case SSOREG:	/* non-indexed OREG */
122 			if (o == OREG && !R2TEST(p->n_rval))
123 				return SRDIR;
124 			return SRNOPE;
125 
126 		default:
127 			return (special(p, shape));
128 		}
129 	}
130 
131 	if (shape & SANY)
132 		return SRDIR;
133 
134 	if ((shape&INTEMP) && shtemp(p)) /* XXX remove? */
135 		return SRDIR;
136 
137 	if ((shape&SWADD) && (o==NAME||o==OREG))
138 		if (BYTEOFF(getlval(p)))
139 			return SRNOPE;
140 
141 	switch (o) {
142 
143 	case NAME:
144 		if (shape & SNAME)
145 			return SRDIR;
146 		break;
147 
148 	case ICON:
149 	case FCON:
150 		if (shape & SCON)
151 			return SRDIR;
152 		break;
153 
154 	case FLD:
155 		if (shape & SFLD)
156 			return flshape(p->n_left);
157 		break;
158 
159 	case CCODES:
160 		if (shape & SCC)
161 			return SRDIR;
162 		break;
163 
164 	case REG:
165 	case TEMP:
166 		mask = PCLASS(p);
167 		if (shape & mask)
168 			return SRDIR;
169 		break;
170 
171 	case OREG:
172 		if (shape & SOREG)
173 			return SRDIR;
174 		break;
175 
176 	case UMUL:
177 #if 0
178 		if (shumul(p->n_left) & shape)
179 			return SROREG;	/* Calls offstar to traverse down */
180 		break;
181 #else
182 		return shumul(p->n_left, shape);
183 #endif
184 
185 	}
186 	return SRNOPE;
187 }
188 
189 /*
190  * does the type t match tword
191  */
192 int
ttype(TWORD t,int tword)193 ttype(TWORD t, int tword)
194 {
195 	if (tword & TANY)
196 		return(1);
197 
198 #ifdef PCC_DEBUG
199 	if (t2debug)
200 		printf("ttype(0x%x, 0x%x)\n", t, tword);
201 #endif
202 	if (ISPTR(t) && ISFTN(DECREF(t)) && (tword & TFTN)) {
203 		/* For funny function pointers */
204 		return 1;
205 	}
206 	if (ISPTR(t) && (tword&TPTRTO)) {
207 		do {
208 			t = DECREF(t);
209 		} while (ISARY(t));
210 			/* arrays that are left are usually only
211 			 * in structure references...
212 			 */
213 		return (ttype(t, tword&(~TPTRTO)));
214 	}
215 	if (t != BTYPE(t))
216 		return (tword & TPOINT); /* TPOINT means not simple! */
217 	if (tword & TPTRTO)
218 		return(0);
219 
220 	switch (t) {
221 	case CHAR:
222 		return( tword & TCHAR );
223 	case SHORT:
224 		return( tword & TSHORT );
225 	case STRTY:
226 	case UNIONTY:
227 		return( tword & TSTRUCT );
228 	case INT:
229 		return( tword & TINT );
230 	case UNSIGNED:
231 		return( tword & TUNSIGNED );
232 	case USHORT:
233 		return( tword & TUSHORT );
234 	case UCHAR:
235 		return( tword & TUCHAR );
236 	case ULONG:
237 		return( tword & TULONG );
238 	case LONG:
239 		return( tword & TLONG );
240 	case LONGLONG:
241 		return( tword & TLONGLONG );
242 	case ULONGLONG:
243 		return( tword & TULONGLONG );
244 	case FLOAT:
245 		return( tword & TFLOAT );
246 	case DOUBLE:
247 		return( tword & TDOUBLE );
248 	case LDOUBLE:
249 		return( tword & TLDOUBLE );
250 	}
251 
252 	return(0);
253 }
254 
255 #define FLDSZ(x)	UPKFSZ(x)
256 #if TARGET_ENDIAN == TARGET_LE
257 #define	FLDSHF(x)	UPKFOFF(x)
258 #else
259 #define	FLDSHF(x)	(SZINT - FLDSZ(x) - UPKFOFF(x))
260 #endif
261 
262 /*
263  * generate code by interpreting table entry
264  */
265 void
expand(NODE * p,int cookie,char * cp)266 expand(NODE *p, int cookie, char *cp)
267 {
268 	CONSZ val;
269 
270 #if 0
271 	printf("expand\n");
272 	fwalk(p, e2print, 0);
273 #endif
274 
275 	for( ; *cp; ++cp ){
276 		switch( *cp ){
277 
278 		default:
279 			putchar(*cp);
280 			continue;  /* this is the usual case... */
281 
282 		case 'Z':  /* special machine dependent operations */
283 			zzzcode( p, *++cp );
284 			continue;
285 
286 		case 'F':  /* this line deleted if FOREFF is active */
287 			if (cookie & FOREFF) {
288 				while (*cp && *cp != '\n')
289 					cp++;
290 				if (*cp == 0)
291 					return;
292 			}
293 			continue;
294 
295 		case 'S':  /* field size */
296 			if (fldexpand(p, cookie, &cp))
297 				continue;
298 			printf("%d", FLDSZ(p->n_rval));
299 			continue;
300 
301 		case 'H':  /* field shift */
302 			if (fldexpand(p, cookie, &cp))
303 				continue;
304 			printf("%d", FLDSHF(p->n_rval));
305 			continue;
306 
307 		case 'M':  /* field mask */
308 		case 'N':  /* complement of field mask */
309 			if (fldexpand(p, cookie, &cp))
310 				continue;
311 			val = 1;
312 			val <<= FLDSZ(p->n_rval);
313 			--val;
314 			val <<= FLDSHF(p->n_rval);
315 			adrcon( *cp=='M' ? val : ~val );
316 			continue;
317 
318 		case 'L':  /* output special label field */
319 			if (*++cp == 'C')
320 				printf(LABFMT, p->n_label);
321 			else
322 				printf(LABFMT, (int)getlval(getlr(p,*cp)));
323 			continue;
324 
325 		case 'O':  /* opcode string */
326 #ifdef FINDMOPS
327 			if (p->n_op == ASSIGN)
328 				hopcode(*++cp, p->n_right->n_op);
329 			else
330 #endif
331 			hopcode( *++cp, p->n_op );
332 			continue;
333 
334 		case 'B':  /* byte offset in word */
335 			val = getlval(getlr(p,*++cp));
336 			val = BYTEOFF(val);
337 			printf( CONFMT, val );
338 			continue;
339 
340 		case 'C': /* for constant value only */
341 			conput(stdout, getlr( p, *++cp ) );
342 			continue;
343 
344 		case 'I': /* in instruction */
345 			insput( getlr( p, *++cp ) );
346 			continue;
347 
348 		case 'A': /* address of */
349 			adrput(stdout, getlr( p, *++cp ) );
350 			continue;
351 
352 		case 'U': /* for upper half of address, only */
353 			upput(getlr(p, *++cp), SZLONG);
354 			continue;
355 
356 			}
357 
358 		}
359 
360 	}
361 
362 NODE resc[NRESC];
363 
364 NODE *
getlr(NODE * p,int c)365 getlr(NODE *p, int c)
366 {
367 	/* return the pointer to the left or right side of p, or p itself,
368 	   depending on the optype of p */
369 
370 	switch (c) {
371 
372 	case '1':
373 	case '2':
374 	case '3':
375 	case 'D':
376 		if (c == 'D')
377 			c = 0;
378 		else
379 			c -= '0';
380 		if (resc[c].n_op == FREE)
381 			comperr("getlr: free node");
382 		return &resc[c];
383 
384 	case 'L':
385 		return( optype( p->n_op ) == LTYPE ? p : p->n_left );
386 
387 	case 'R':
388 		return( optype( p->n_op ) != BITYPE ? p : p->n_right );
389 
390 	}
391 	cerror( "bad getlr: %c", c );
392 	/* NOTREACHED */
393 	return NULL;
394 }
395 
396 #ifdef PCC_DEBUG
397 #define	F2DEBUG(x)	if (f2debug) printf x
398 #define	F2WALK(x)	if (f2debug) fwalk(x, e2print, 0)
399 #else
400 #define	F2DEBUG(x)
401 #define	F2WALK(x)
402 #endif
403 
404 /*
405  * Convert a node to REG or OREG.
406  * Shape is register class where we want the result.
407  * Returns register class if register nodes.
408  * If w is: (should be shapes)
409  *	- SRREG - result in register, call geninsn().
410  *	- SROREG - create OREG; call offstar().
411  *	- 0 - clear su, walk down.
412  */
413 static int
swmatch(NODE * p,int shape,int w)414 swmatch(NODE *p, int shape, int w)
415 {
416 	int rv = 0;
417 
418 	F2DEBUG(("swmatch: p=%p, shape=%s, w=%s\n", p, prcook(shape), srtyp[w]));
419 
420 	switch (w) {
421 	case SRREG:
422 		rv = geninsn(p, shape);
423 		break;
424 
425 	case SROREG:
426 		/* should be here only if op == UMUL */
427 		if (p->n_op != UMUL && p->n_op != FLD)
428 			comperr("swmatch %p", p);
429 		if (p->n_op == FLD) {
430 			offstar(p->n_left->n_left, shape);
431 			p->n_left->n_su = 0;
432 		} else
433 			offstar(p->n_left, shape);
434 		p->n_su = 0;
435 		rv = ffs(shape)-1;
436 		break;
437 
438 	case 0:
439 		if (optype(p->n_op) == BITYPE)
440 			swmatch(p->n_right, 0, 0);
441 		if (optype(p->n_op) != LTYPE)
442 			swmatch(p->n_left, 0, 0);
443 		p->n_su = 0;
444 	}
445 	return rv;
446 
447 }
448 
449 /*
450  * Help routines for find*() functions.
451  * If the node will be a REG node and it will be rewritten in the
452  * instruction, ask for it to be put in a register.
453  */
454 static int
chcheck(NODE * p,int shape,int rew)455 chcheck(NODE *p, int shape, int rew)
456 {
457 	int sh, sha;
458 
459 	sha = shape;
460 	if (shape & SPECIAL)
461 		shape = 0;
462 
463 	switch ((sh = tshape(p, sha))) {
464 	case SRNOPE:
465 		if (shape & INREGS)
466 			sh = SRREG;
467 		break;
468 
469 	case SROREG:
470 	case SRDIR:
471 		if (rew == 0)
472 			break;
473 		if (shape & INREGS)
474 			sh = SRREG;
475 		else
476 			sh = SRNOPE;
477 		break;
478 	}
479 	return sh;
480 }
481 
482 /*
483  * Check how to walk further down.
484  * Merge with swmatch()?
485  * 	sh - shape for return value (register class).
486  *	p - node (for this leg)
487  *	shape - given shape for this leg
488  *	cookie - cookie given for parent node
489  *	rew -
490  *	go - switch key for traversing down
491  *	returns register class.
492  */
493 static int
shswitch(int sh,NODE * p,int shape,int cookie,int rew,int go)494 shswitch(int sh, NODE *p, int shape, int cookie, int rew, int go)
495 {
496 	int lsh;
497 
498 	F2DEBUG(("shswitch: p=%p, shape=%s, ", p, prcook(shape)));
499 	F2DEBUG(("cookie=%s, rew=0x%x, go=%s\n", prcook(cookie), rew, srtyp[go]));
500 
501 	switch (go) {
502 	case SRDIR: /* direct match, just clear su */
503 		(void)swmatch(p, 0, 0);
504 		break;
505 
506 	case SROREG: /* call offstar to prepare for OREG conversion */
507 		(void)swmatch(p, shape, SROREG);
508 		break;
509 
510 	case SRREG: /* call geninsn() to get value into register */
511 		lsh = shape & (FORCC | INREGS);
512 		if (rew && cookie != FOREFF)
513 			lsh &= (cookie & (FORCC | INREGS));
514 		lsh = swmatch(p, lsh, SRREG);
515 		if (rew)
516 			sh = lsh;
517 		break;
518 	}
519 	return sh;
520 }
521 
522 /*
523  * Find the best instruction to evaluate the given tree.
524  * Best is to match both subnodes directly, second-best is if
525  * subnodes must be evaluated into OREGs, thereafter if nodes
526  * must be put into registers.
527  * Whether 2-op instructions or 3-op is preferred is depending on in
528  * which order they are found in the table.
529  * mtchno is set to the count of regs needed for its legs.
530  */
531 int
findops(NODE * p,int cookie)532 findops(NODE *p, int cookie)
533 {
534 	extern int *qtable[];
535 	struct optab *q, *qq = NULL;
536 	int i, shl, shr, *ixp, sh;
537 	int lvl = 10, idx = 0, gol = 0, gor = 0;
538 	NODE *l, *r;
539 
540 	F2DEBUG(("findops node %p (%s)\n", p, prcook(cookie)));
541 	F2WALK(p);
542 
543 	ixp = qtable[p->n_op];
544 	l = getlr(p, 'L');
545 	r = getlr(p, 'R');
546 	for (i = 0; ixp[i] >= 0; i++) {
547 		q = &table[ixp[i]];
548 
549 		F2DEBUG(("findop: ixp %d str %s\n", ixp[i], q->cstring));
550 		if (!acceptable(q))		/* target-dependent filter */
551 			continue;
552 
553 		if (ttype(l->n_type, q->ltype) == 0 ||
554 		    ttype(r->n_type, q->rtype) == 0)
555 			continue; /* Types must be correct */
556 
557 		if ((cookie & q->visit) == 0)
558 			continue; /* must get a result */
559 
560 		F2DEBUG(("findop got types\n"));
561 
562 		if ((shl = chcheck(l, q->lshape, q->rewrite & RLEFT)) == SRNOPE)
563 			continue;
564 
565 		F2DEBUG(("findop lshape %s\n", srtyp[shl]));
566 		F2WALK(l);
567 
568 		if ((shr = chcheck(r, q->rshape, q->rewrite & RRIGHT)) == SRNOPE)
569 			continue;
570 
571 		F2DEBUG(("findop rshape %s\n", srtyp[shr]));
572 		F2WALK(r);
573 
574 		/* Help register assignment after SSA by preferring */
575 		/* 2-op insns instead of 3-ops */
576 		if (xssa && (q->rewrite & RLEFT) == 0 && shl == SRDIR)
577 			shl = SRREG;
578 
579 		if (q->needs & REWRITE)
580 			break;  /* Done here */
581 
582 		if (lvl <= (shl + shr))
583 			continue;
584 		lvl = shl + shr;
585 		qq = q;
586 		idx = ixp[i];
587 		gol = shl;
588 		gor = shr;
589 	}
590 	if (lvl == 10) {
591 		F2DEBUG(("findops failed\n"));
592 		if (setbin(p))
593 			return FRETRY;
594 		return FFAIL;
595 	}
596 
597 	F2DEBUG(("findops entry %d(%s,%s)\n", idx, srtyp[gol], srtyp[gor]));
598 
599 	sh = -1;
600 
601 #ifdef mach_pdp11
602 	if (cookie == FORCC && p->n_op != AND)	/* XXX - fix */
603 		cookie = INREGS;
604 #else
605 	if (cookie == FORCC)
606 		cookie = INREGS;
607 #endif
608 
609 	sh = shswitch(sh, p->n_left, qq->lshape, cookie,
610 	    qq->rewrite & RLEFT, gol);
611 	sh = shswitch(sh, p->n_right, qq->rshape, cookie,
612 	    qq->rewrite & RRIGHT, gor);
613 
614 	if (sh == -1) {
615 		if (cookie == FOREFF || cookie == FORCC)
616 			sh = 0;
617 		else
618 			sh = ffs(cookie & qq->visit & INREGS)-1;
619 	}
620 	F2DEBUG(("findops: node %p sh %d (%s)\n", p, sh, prcook(1 << sh)));
621 	p->n_su = MKIDX(idx, 0);
622 	SCLASS(p->n_su, sh);
623 	return sh;
624 }
625 
626 /*
627  * Find the best relation op for matching the two trees it has.
628  * This is a sub-version of the function findops() above.
629  * The instruction with the lowest grading is emitted.
630  *
631  * Level assignment for priority:
632  *	left	right	prio
633  *	-	-	-
634  *	direct	direct	1
635  *	direct	OREG	2	# make oreg
636  *	OREG	direct	2	# make oreg
637  *	OREG	OREG	2	# make both oreg
638  *	direct	REG	3	# put in reg
639  *	OREG	REG	3	# put in reg, make oreg
640  *	REG	direct	3	# put in reg
641  *	REG	OREG	3	# put in reg, make oreg
642  *	REG	REG	4	# put both in reg
643  */
644 int
relops(NODE * p)645 relops(NODE *p)
646 {
647 	extern int *qtable[];
648 	struct optab *q;
649 	int i, shl = 0, shr = 0, sh;
650 	NODE *l, *r;
651 	int *ixp, idx = 0;
652 	int lvl = 10, gol = 0, gor = 0;
653 
654 	F2DEBUG(("relops tree:\n"));
655 	F2WALK(p);
656 
657 	l = getlr(p, 'L');
658 	r = getlr(p, 'R');
659 	ixp = qtable[p->n_op];
660 	for (i = 0; ixp[i] >= 0; i++) {
661 		q = &table[ixp[i]];
662 
663 		F2DEBUG(("relops: ixp %d\n", ixp[i]));
664 		if (!acceptable(q))		/* target-dependent filter */
665 			continue;
666 
667 		if (ttype(l->n_type, q->ltype) == 0 ||
668 		    ttype(r->n_type, q->rtype) == 0)
669 			continue; /* Types must be correct */
670 
671 		F2DEBUG(("relops got types\n"));
672 		if ((shl = chcheck(l, q->lshape, 0)) == SRNOPE)
673 			continue;
674 		F2DEBUG(("relops lshape %d\n", shl));
675 		F2WALK(p);
676 		if ((shr = chcheck(r, q->rshape, 0)) == SRNOPE)
677 			continue;
678 		F2DEBUG(("relops rshape %d\n", shr));
679 		F2WALK(p);
680 		if (q->needs & REWRITE)
681 			break;	/* Done here */
682 
683 		if (lvl <= (shl + shr))
684 			continue;
685 		lvl = shl + shr;
686 		idx = ixp[i];
687 		gol = shl;
688 		gor = shr;
689 	}
690 	if (lvl == 10) {
691 		F2DEBUG(("relops failed\n"));
692 		if (setbin(p))
693 			return FRETRY;
694 		return FFAIL;
695 	}
696 	F2DEBUG(("relops entry %d(%s %s)\n", idx, srtyp[gol], srtyp[gor]));
697 
698 	q = &table[idx];
699 
700 	(void)shswitch(-1, p->n_left, q->lshape, INREGS,
701 	    q->rewrite & RLEFT, gol);
702 
703 	(void)shswitch(-1, p->n_right, q->rshape, INREGS,
704 	    q->rewrite & RRIGHT, gor);
705 
706 	sh = 0;
707 	if (q->rewrite & RLEFT)
708 		sh = ffs(q->lshape & INREGS)-1;
709 	else if (q->rewrite & RRIGHT)
710 		sh = ffs(q->rshape & INREGS)-1;
711 
712 	F2DEBUG(("relops: node %p\n", p));
713 	p->n_su = MKIDX(idx, 0);
714 	SCLASS(p->n_su, sh);
715 	return 0;
716 }
717 
718 /*
719  * Find a matching assign op.
720  *
721  * Level assignment for priority:
722  *	left	right	prio
723  *	-	-	-
724  *	direct	direct	1
725  *	direct	REG	2
726  *	direct	OREG	3
727  *	OREG	direct	4
728  *	OREG	REG	5
729  *	OREG	OREG	6
730  */
731 int
findasg(NODE * p,int cookie)732 findasg(NODE *p, int cookie)
733 {
734 	extern int *qtable[];
735 	struct optab *q;
736 	int i, sh, shl, shr, lvl = 10;
737 	NODE *l, *r;
738 	int *ixp;
739 	struct optab *qq = NULL; /* XXX gcc */
740 	int idx = 0, gol = 0, gor = 0;
741 
742 	shl = shr = 0;
743 
744 	F2DEBUG(("findasg tree: %s\n", prcook(cookie)));
745 	F2WALK(p);
746 
747 	ixp = qtable[p->n_op];
748 	l = getlr(p, 'L');
749 	r = getlr(p, 'R');
750 	for (i = 0; ixp[i] >= 0; i++) {
751 		q = &table[ixp[i]];
752 
753 		F2DEBUG(("findasg: ixp %d\n", ixp[i]));
754 		if (!acceptable(q))		/* target-dependent filter */
755 			continue;
756 
757 		if (ttype(l->n_type, q->ltype) == 0 ||
758 		    ttype(r->n_type, q->rtype) == 0)
759 			continue; /* Types must be correct */
760 
761 		if ((cookie & q->visit) == 0)
762 			continue; /* must get a result */
763 
764 		F2DEBUG(("findasg got types\n"));
765 #ifdef mach_pdp11 /* XXX - check for other targets too */
766 		if (p->n_op == STASG && ISPTR(l->n_type)) {
767 			/* Accept lvalue to be in register */
768 			/* if struct assignment is given a pointer */
769 			if ((shl = chcheck(l, q->lshape,
770 			    q->rewrite & RLEFT)) == SRNOPE)
771 				continue;
772 		} else
773 #endif
774 		{
775 			if ((shl = tshape(l, q->lshape)) == SRNOPE)
776 				continue;
777 			if (shl == SRREG)
778 				continue;
779 		}
780 
781 		F2DEBUG(("findasg lshape %d\n", shl));
782 		F2WALK(l);
783 
784 		if ((shr = chcheck(r, q->rshape, q->rewrite & RRIGHT)) == SRNOPE)
785 			continue;
786 
787 		F2DEBUG(("findasg rshape %d\n", shr));
788 		F2WALK(r);
789 		if (q->needs & REWRITE)
790 			break;	/* Done here */
791 
792 		if (lvl <= (shl + shr))
793 			continue;
794 
795 		lvl = shl + shr;
796 		qq = q;
797 		idx = ixp[i];
798 		gol = shl;
799 		gor = shr;
800 	}
801 
802 	if (lvl == 10) {
803 		F2DEBUG(("findasg failed\n"));
804 		if (setasg(p, cookie))
805 			return FRETRY;
806 		return FFAIL;
807 	}
808 	F2DEBUG(("findasg entry %d(%s,%s)\n", idx, srtyp[gol], srtyp[gor]));
809 
810 	sh = -1;
811 	sh = shswitch(sh, p->n_left, qq->lshape, cookie,
812 	    qq->rewrite & RLEFT, gol);
813 
814 	sh = shswitch(sh, p->n_right, qq->rshape, cookie,
815 	    qq->rewrite & RRIGHT, gor);
816 
817 #ifdef mach_pdp11 /* XXX all targets? */
818 	lvl = 0;
819 	if (cookie == FOREFF)
820 		lvl = RVEFF, sh = 0;
821 	else if (cookie == FORCC)
822 		lvl = RVCC, sh = 0;
823 	else if (sh == -1) {
824 		sh = ffs(cookie & qq->visit & INREGS)-1;
825 #ifdef PCC_DEBUG
826 		if (sh == -1)
827 			comperr("findasg bad shape");
828 #endif
829 		SCLASS(lvl,sh);
830 	} else
831 		SCLASS(lvl,sh);
832 	p->n_su = MKIDX(idx, lvl);
833 #else
834 	if (sh == -1) {
835 		if (cookie == FOREFF)
836 			sh = 0;
837 		else
838 			sh = ffs(cookie & qq->visit & INREGS)-1;
839 	}
840 	F2DEBUG(("findasg: node %p class %d\n", p, sh));
841 
842 	p->n_su = MKIDX(idx, 0);
843 	SCLASS(p->n_su, sh);
844 #endif /* mach_pdp11 */
845 #ifdef FINDMOPS
846 	p->n_su &= ~ISMOPS;
847 #endif
848 	return sh;
849 }
850 
851 /*
852  * Search for an UMUL table entry that can turn an indirect node into
853  * a move from an OREG.
854  */
855 int
findumul(NODE * p,int cookie)856 findumul(NODE *p, int cookie)
857 {
858 	extern int *qtable[];
859 	struct optab *q = NULL; /* XXX gcc */
860 	int i, shl = 0, shr = 0, sh;
861 	int *ixp;
862 
863 	F2DEBUG(("findumul p %p (%s)\n", p, prcook(cookie)));
864 	F2WALK(p);
865 
866 	ixp = qtable[p->n_op];
867 	for (i = 0; ixp[i] >= 0; i++) {
868 		q = &table[ixp[i]];
869 
870 		F2DEBUG(("findumul: ixp %d\n", ixp[i]));
871 		if (!acceptable(q))		/* target-dependent filter */
872 			continue;
873 
874 		if ((q->visit & cookie) == 0)
875 			continue; /* wrong registers */
876 
877 		if (ttype(p->n_type, q->rtype) == 0)
878 			continue; /* Types must be correct */
879 
880 
881 		F2DEBUG(("findumul got types, rshape %s\n", prcook(q->rshape)));
882 		/*
883 		 * Try to create an OREG of the node.
884 		 * Fake left even though it's right node,
885 		 * to be sure of conversion if going down left.
886 		 */
887 		if ((shl = chcheck(p, q->rshape, 0)) == SRNOPE)
888 			continue;
889 
890 		shr = 0;
891 
892 		if (q->needs & REWRITE)
893 			break;	/* Done here */
894 
895 		F2DEBUG(("findumul got shape %s\n", srtyp[shl]));
896 
897 		break; /* XXX search better matches */
898 	}
899 	if (ixp[i] < 0) {
900 		F2DEBUG(("findumul failed\n"));
901 		if (setuni(p, cookie))
902 			return FRETRY;
903 		return FFAIL;
904 	}
905 	F2DEBUG(("findumul entry %d(%s %s)\n", ixp[i], srtyp[shl], srtyp[shr]));
906 
907 	sh = shswitch(-1, p, q->rshape, cookie, q->rewrite & RLEFT, shl);
908 	if (sh == -1)
909 		sh = ffs(cookie & q->visit & INREGS)-1;
910 
911 	F2DEBUG(("findumul: node %p (%s)\n", p, prcook(1 << sh)));
912 	p->n_su = MKIDX(ixp[i], 0);
913 	SCLASS(p->n_su, sh);
914 	return sh;
915 }
916 
917 /*
918  * Find a leaf type node that puts the value into a register.
919  */
920 int
findleaf(NODE * p,int cookie)921 findleaf(NODE *p, int cookie)
922 {
923 	extern int *qtable[];
924 	struct optab *q = NULL; /* XXX gcc */
925 	int i, sh;
926 	int *ixp;
927 
928 	F2DEBUG(("findleaf p %p (%s)\n", p, prcook(cookie)));
929 	F2WALK(p);
930 
931 	ixp = qtable[p->n_op];
932 	for (i = 0; ixp[i] >= 0; i++) {
933 		q = &table[ixp[i]];
934 
935 		F2DEBUG(("findleaf: ixp %d\n", ixp[i]));
936 		if (!acceptable(q))		/* target-dependent filter */
937 			continue;
938 		if ((q->visit & cookie) == 0)
939 			continue; /* wrong registers */
940 
941 		if (ttype(p->n_type, q->rtype) == 0 ||
942 		    ttype(p->n_type, q->ltype) == 0)
943 			continue; /* Types must be correct */
944 
945 		F2DEBUG(("findleaf got types, rshape %s\n", prcook(q->rshape)));
946 
947 		if (chcheck(p, q->rshape, 0) != SRDIR)
948 			continue;
949 
950 		if (q->needs & REWRITE)
951 			break;	/* Done here */
952 
953 		break;
954 	}
955 	if (ixp[i] < 0) {
956 		F2DEBUG(("findleaf failed\n"));
957 		if (setuni(p, cookie))
958 			return FRETRY;
959 		return FFAIL;
960 	}
961 	F2DEBUG(("findleaf entry %d\n", ixp[i]));
962 
963 	sh = ffs(cookie & q->visit & INREGS)-1;
964 	F2DEBUG(("findleaf: node %p (%s)\n", p, prcook(1 << sh)));
965 	p->n_su = MKIDX(ixp[i], 0);
966 	SCLASS(p->n_su, sh);
967 	return sh;
968 }
969 
970 /*
971  * Find a UNARY op that satisfy the needs.
972  * For now, the destination is always a register.
973  * Both source and dest types must match, but only source (left)
974  * shape is of interest.
975  */
976 int
finduni(NODE * p,int cookie)977 finduni(NODE *p, int cookie)
978 {
979 	extern int *qtable[];
980 	struct optab *q;
981 	NODE *l, *r;
982 	int i, shl = 0, num = 4;
983 	int *ixp, idx = 0;
984 	int sh;
985 
986 	F2DEBUG(("finduni tree: %s\n", prcook(cookie)));
987 	F2WALK(p);
988 
989 	l = getlr(p, 'L');
990 	if (p->n_op == CALL || p->n_op == FORTCALL || p->n_op == STCALL)
991 		r = p;
992 	else
993 		r = getlr(p, 'R');
994 	ixp = qtable[p->n_op];
995 	for (i = 0; ixp[i] >= 0; i++) {
996 		q = &table[ixp[i]];
997 
998 		F2DEBUG(("finduni: ixp %d\n", ixp[i]));
999 		if (!acceptable(q))		/* target-dependent filter */
1000 			continue;
1001 
1002 		if (ttype(l->n_type, q->ltype) == 0)
1003 			continue; /* Type must be correct */
1004 
1005 		F2DEBUG(("finduni got left type\n"));
1006 		if (ttype(r->n_type, q->rtype) == 0)
1007 			continue; /* Type must be correct */
1008 
1009 		F2DEBUG(("finduni got types\n"));
1010 		if ((shl = chcheck(l, q->lshape, q->rewrite & RLEFT)) == SRNOPE)
1011 			continue;
1012 
1013 		F2DEBUG(("finduni got shapes %d\n", shl));
1014 
1015 		if ((cookie & q->visit) == 0)	/* check correct return value */
1016 			continue;		/* XXX - should check needs */
1017 
1018 		/* avoid clobbering of longlived regs */
1019 		/* let register allocator coalesce */
1020 		if ((q->rewrite & RLEFT) && (shl == SRDIR) /* && isreg(l) */)
1021 			shl = SRREG;
1022 
1023 		F2DEBUG(("finduni got cookie\n"));
1024 		if (q->needs & REWRITE)
1025 			break;	/* Done here */
1026 
1027 		if (shl >= num)
1028 			continue;
1029 		num = shl;
1030 		idx = ixp[i];
1031 
1032 		if (shl == SRDIR)
1033 			break;
1034 	}
1035 
1036 	if (num == 4) {
1037 		F2DEBUG(("finduni failed\n"));
1038 	} else
1039 		F2DEBUG(("finduni entry %d(%s)\n", idx, srtyp[num]));
1040 
1041 	if (num == 4) {
1042 		if (setuni(p, cookie))
1043 			return FRETRY;
1044 		return FFAIL;
1045 	}
1046 	q = &table[idx];
1047 
1048 	sh = shswitch(-1, p->n_left, q->lshape, cookie,
1049 	    q->rewrite & RLEFT, num);
1050 	if (sh == -1)
1051 		sh = ffs(cookie & q->visit & INREGS)-1;
1052 	if (sh == -1)
1053 		sh = 0;
1054 
1055 	F2DEBUG(("finduni: node %p (%s)\n", p, prcook(1 << sh)));
1056 	p->n_su = MKIDX(idx, 0);
1057 	SCLASS(p->n_su, sh);
1058 	return sh;
1059 }
1060 
1061 #ifdef FINDMOPS
1062 /*
1063  * Try to find constructs like "a = a + 1;" and match them together
1064  * with instructions like "incl a" or "addl $1,a".
1065  *
1066  * Level assignment for priority:
1067  *	left	right	prio
1068  *	-	-	-
1069  *	direct	direct	1
1070  *	direct	REG	2
1071  *	direct	OREG	3
1072  *	OREG	direct	4
1073  *	OREG	REG	5
1074  *	OREG	OREG	6
1075  */
1076 int
findmops(NODE * p,int cookie)1077 findmops(NODE *p, int cookie)
1078 {
1079 	extern int *qtable[];
1080 	struct optab *q;
1081 	int i, sh, shl, shr, lvl = 10;
1082 	NODE *l, *r;
1083 	int *ixp;
1084 	struct optab *qq = NULL; /* XXX gcc */
1085 	int idx = 0, gol = 0, gor = 0;
1086 
1087 	shl = shr = 0;
1088 
1089 	F2DEBUG(("findmops tree: %s\n", prcook(cookie)));
1090 	F2WALK(p);
1091 
1092 	l = getlr(p, 'L');
1093 	r = getlr(p, 'R');
1094 	/* See if this is a usable tree to work with */
1095 	/* Currently only check for leaves */
1096 	if (optype(r->n_op) != BITYPE || treecmp(l, r->n_left) == 0)
1097 		return FFAIL;
1098 
1099 	F2DEBUG(("findmops is useable\n"));
1100 
1101 	/* We can try to find a match.  Use right op */
1102 	ixp = qtable[r->n_op];
1103 	l = getlr(r, 'L');
1104 	r = getlr(r, 'R');
1105 
1106 	for (i = 0; ixp[i] >= 0; i++) {
1107 		q = &table[ixp[i]];
1108 
1109 		F2DEBUG(("findmops: ixp %d\n", ixp[i]));
1110 		if (!acceptable(q))		/* target-dependent filter */
1111 			continue;
1112 
1113 		if (ttype(l->n_type, q->ltype) == 0 ||
1114 		    ttype(r->n_type, q->rtype) == 0)
1115 			continue; /* Types must be correct */
1116 
1117 		F2DEBUG(("findmops got types\n"));
1118 
1119 		switch (cookie) {
1120 		case FOREFF:
1121 			if ((q->visit & FOREFF) == 0)
1122 				continue; /* Not only for side effects */
1123 			break;
1124 		case FORCC:
1125 			if ((q->visit & FORCC) == 0)
1126 				continue; /* Not only for side effects */
1127 			break;
1128 		default:
1129 			if ((cookie & q->visit) == 0)
1130 				continue; /* Won't match requested shape */
1131 			if (((cookie & INREGS & q->lshape) == 0) || !isreg(l))
1132 				continue; /* Bad return register */
1133 			break;
1134 		}
1135 		F2DEBUG(("findmops cookie\n"));
1136 
1137 		/*
1138 		 * left shape must match left node.
1139 		 */
1140 		if ((shl = tshape(l, q->lshape)) != SRDIR && (shl != SROREG))
1141 			continue;
1142 
1143 		F2DEBUG(("findmops lshape %s\n", srtyp[shl]));
1144 		F2WALK(l);
1145 
1146 		if ((shr = chcheck(r, q->rshape, 0)) == SRNOPE)
1147 			continue;
1148 
1149 		F2DEBUG(("findmops rshape %s\n", srtyp[shr]));
1150 
1151 		/*
1152 		 * Only allow RLEFT. XXX
1153 		 */
1154 		if ((q->rewrite & (RLEFT|RRIGHT)) != RLEFT)
1155 			continue;
1156 
1157 		F2DEBUG(("rewrite OK\n"));
1158 
1159 		F2WALK(r);
1160 		if (q->needs & REWRITE)
1161 			break;	/* Done here */
1162 
1163 		if (lvl <= (shl + shr))
1164 			continue;
1165 
1166 		lvl = shl + shr;
1167 		qq = q;
1168 		idx = ixp[i];
1169 		gol = shl;
1170 		gor = shr;
1171 	}
1172 
1173 	if (lvl == 10)
1174 		return FFAIL;
1175 	F2DEBUG(("findmops entry %d(%s,%s)\n", idx, srtyp[gol], srtyp[gor]));
1176 
1177 	/*
1178 	 * Now we're here and have a match. left is semi-direct and
1179 	 * right may be anything.
1180 	 */
1181 
1182 	sh = -1;
1183 	sh = shswitch(sh, p->n_left, qq->lshape, cookie,
1184 	    qq->rewrite & RLEFT, gol);
1185 	sh = shswitch(sh, r, qq->rshape, cookie, 0, gor);
1186 
1187 	if (sh == -1) {
1188 		if (cookie & (FOREFF|FORCC))
1189 			sh = 0;
1190 		else
1191 			sh = ffs(cookie & qq->visit & INREGS)-1;
1192 	}
1193 	F2DEBUG(("findmops done: node %p class %d\n", p, sh));
1194 
1195 	/* Trickery:  Set table index on assign to op instead */
1196 	/* gencode() will remove useless nodes */
1197 	p->n_su = MKIDX(idx, 0);
1198 	p->n_su |= ISMOPS; /* XXX tell gencode to reduce the right tree */
1199 	SCLASS(p->n_su, sh);
1200 
1201 	return sh;
1202 }
1203 
1204 /*
1205  * Compare two trees; return 1 if equal and 0 if not.
1206  */
1207 int
treecmp(NODE * p1,NODE * p2)1208 treecmp(NODE *p1, NODE *p2)
1209 {
1210 	if (p1->n_op != p2->n_op)
1211 		return 0;
1212 
1213 	switch (p1->n_op) {
1214 	case SCONV:
1215 	case UMUL:
1216 		return treecmp(p1->n_left, p2->n_left);
1217 
1218 	case OREG:
1219 		if (getlval(p1) != getlval(p2) || p1->n_rval != p2->n_rval)
1220 			return 0;
1221 		break;
1222 
1223 	case NAME:
1224 	case ICON:
1225 		if (strcmp(p1->n_name, p2->n_name))
1226 			return 0;
1227 		/* FALLTHROUGH */
1228 		if (getlval(p1) != getlval(p2))
1229 			return 0;
1230 		break;
1231 
1232 	case TEMP:
1233 #ifdef notyet
1234 		/* SSA will put assignment in separate register */
1235 		/* Help out by accepting different regs here */
1236 		if (xssa)
1237 			break;
1238 #endif
1239 	case REG:
1240 		if (p1->n_rval != p2->n_rval)
1241 			return 0;
1242 		break;
1243 	case LS:
1244 	case RS:
1245 	case PLUS:
1246 	case MINUS:
1247 	case MUL:
1248 	case DIV:
1249 		if (treecmp(p1->n_left, p2->n_left) == 0 ||
1250 		    treecmp(p1->n_right, p2->n_right) == 0)
1251 			return 0;
1252 		break;
1253 
1254 	default:
1255 		return 0;
1256 	}
1257 	return 1;
1258 }
1259 #endif
1260