1 /* $Id: match.c,v 1.93 2010/06/04 05:58:31 ragge Exp $ */
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
36 * Redistributions of source code and documentation must retain the above
37 * copyright notice, this list of conditions and the following disclaimer.
38 * Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditionsand the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed or owned by Caldera
45 * Neither the name of Caldera International, Inc. nor the names of other
46 * contributors may be used to endorse or promote products derived from
47 * this software without specific prior written permission.
49 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
50 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
54 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
58 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
59 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
69 void setclass(int tmp
, int class);
70 int getclass(int tmp
);
74 extern char *ltyp
[], *rtyp
[];
76 static char *srtyp
[] = { "SRNOPE", "SRDIR", "SROREG", "SRREG" };
79 * return true if shape is appropriate for the node p
80 * side effect for SFLD is to set up fldsz, etc
83 * SRNOPE Cannot match this shape.
84 * SRDIR Direct match, may or may not traverse down.
85 * SRREG Will match if put in a regster XXX - kill this?
88 tshape(NODE
*p
, int shape
)
96 printf("tshape(%p, %s) op = %s\n", p
, prcook(shape
), opst
[o
]);
99 if (shape
& SPECIAL
) {
107 if (o
!= ICON
|| p
->n_name
[0])
109 if (p
->n_lval
== 0 && shape
== SZERO
)
111 if (p
->n_lval
== 1 && shape
== SONE
)
113 if (p
->n_lval
== -1 && shape
== SMONE
)
115 if (p
->n_lval
> -257 && p
->n_lval
< 256 &&
118 if (p
->n_lval
> -32769 && p
->n_lval
< 32768 &&
123 case SSOREG
: /* non-indexed OREG */
124 if (o
== OREG
&& !R2TEST(p
->n_rval
))
129 return (special(p
, shape
));
136 if ((shape
&INTEMP
) && shtemp(p
)) /* XXX remove? */
139 if ((shape
&SWADD
) && (o
==NAME
||o
==OREG
))
140 if (BYTEOFF(p
->n_lval
))
158 return flshape(p
->n_left
);
180 if (shumul(p
->n_left
) & shape
)
181 return SROREG
; /* Calls offstar to traverse down */
184 return shumul(p
->n_left
, shape
);
192 * does the type t match tword
195 ttype(TWORD t
, int tword
)
202 printf("ttype(%o, %o)\n", t
, tword
);
204 if (ISPTR(t
) && ISFTN(DECREF(t
)) && (tword
& TFTN
)) {
205 /* For funny function pointers */
208 if (ISPTR(t
) && (tword
&TPTRTO
)) {
212 /* arrays that are left are usually only
213 * in structure references...
215 return (ttype(t
, tword
&(~TPTRTO
)));
218 return (tword
& TPOINT
); /* TPOINT means not simple! */
224 return( tword
& TCHAR
);
226 return( tword
& TSHORT
);
229 return( tword
& TSTRUCT
);
231 return( tword
& TINT
);
233 return( tword
& TUNSIGNED
);
235 return( tword
& TUSHORT
);
237 return( tword
& TUCHAR
);
239 return( tword
& TULONG
);
241 return( tword
& TLONG
);
243 return( tword
& TLONGLONG
);
245 return( tword
& TULONGLONG
);
247 return( tword
& TFLOAT
);
249 return( tword
& TDOUBLE
);
251 return( tword
& TLDOUBLE
);
257 #define FLDSZ(x) UPKFSZ(x)
259 #define FLDSHF(x) UPKFOFF(x)
261 #define FLDSHF(x) (SZINT - FLDSZ(x) - UPKFOFF(x))
265 * generate code by interpreting table entry
268 expand(NODE
*p
, int cookie
, char *cp
)
274 fwalk(p
, e2print
, 0);
282 continue; /* this is the usual case... */
284 case 'Z': /* special machine dependent operations */
288 case 'F': /* this line deleted if FOREFF is active */
289 if (cookie
& FOREFF
) {
290 while (*cp
&& *cp
!= '\n')
297 case 'S': /* field size */
298 if (fldexpand(p
, cookie
, &cp
))
300 printf("%d", FLDSZ(p
->n_rval
));
303 case 'H': /* field shift */
304 if (fldexpand(p
, cookie
, &cp
))
306 printf("%d", FLDSHF(p
->n_rval
));
309 case 'M': /* field mask */
310 case 'N': /* complement of field mask */
311 if (fldexpand(p
, cookie
, &cp
))
314 val
<<= FLDSZ(p
->n_rval
);
316 val
<<= FLDSHF(p
->n_rval
);
317 adrcon( *cp
=='M' ? val
: ~val
);
320 case 'L': /* output special label field */
322 printf(LABFMT
, p
->n_label
);
324 printf(LABFMT
, (int)getlr(p
,*cp
)->n_lval
);
327 case 'O': /* opcode string */
329 if (p
->n_op
== ASSIGN
)
330 hopcode(*++cp
, p
->n_right
->n_op
);
333 hopcode( *++cp
, p
->n_op
);
336 case 'B': /* byte offset in word */
337 val
= getlr(p
,*++cp
)->n_lval
;
339 printf( CONFMT
, val
);
342 case 'C': /* for constant value only */
343 conput(stdout
, getlr( p
, *++cp
) );
346 case 'I': /* in instruction */
347 insput( getlr( p
, *++cp
) );
350 case 'A': /* address of */
351 adrput(stdout
, getlr( p
, *++cp
) );
354 case 'U': /* for upper half of address, only */
355 upput(getlr(p
, *++cp
), SZLONG
);
367 getlr(NODE
*p
, int c
)
371 /* return the pointer to the left or right side of p, or p itself,
372 depending on the optype of p */
386 q
->n_type
= p
->n_type
; /* XXX should be correct type */
387 q
->n_rval
= DECRA(p
->n_reg
, c
);
392 return( optype( p
->n_op
) == LTYPE
? p
: p
->n_left
);
395 return( optype( p
->n_op
) != BITYPE
? p
: p
->n_right
);
398 cerror( "bad getlr: %c", c
);
404 #define F2DEBUG(x) if (f2debug) printf x
405 #define F2WALK(x) if (f2debug) fwalk(x, e2print, 0)
412 * Convert a node to REG or OREG.
413 * Shape is register class where we want the result.
414 * Returns register class if register nodes.
415 * If w is: (should be shapes)
416 * - SRREG - result in register, call geninsn().
417 * - SROREG - create OREG; call offstar().
418 * - 0 - clear su, walk down.
421 swmatch(NODE
*p
, int shape
, int w
)
425 F2DEBUG(("swmatch: p=%p, shape=%s, w=%s\n", p
, prcook(shape
), srtyp
[w
]));
429 rv
= geninsn(p
, shape
);
433 /* should be here only if op == UMUL */
434 if (p
->n_op
!= UMUL
&& p
->n_op
!= FLD
)
435 comperr("swmatch %p", p
);
436 if (p
->n_op
== FLD
) {
437 offstar(p
->n_left
->n_left
, shape
);
440 offstar(p
->n_left
, shape
);
446 if (optype(p
->n_op
) == BITYPE
)
447 swmatch(p
->n_right
, 0, 0);
448 if (optype(p
->n_op
) != LTYPE
)
449 swmatch(p
->n_left
, 0, 0);
457 * Help routines for find*() functions.
458 * If the node will be a REG node and it will be rewritten in the
459 * instruction, ask for it to be put in a register.
462 chcheck(NODE
*p
, int shape
, int rew
)
470 switch ((sh
= tshape(p
, sha
))) {
490 * Check how to walk further down.
491 * Merge with swmatch()?
492 * sh - shape for return value (register class).
493 * p - node (for this leg)
494 * shape - given shape for this leg
495 * cookie - cookie given for parent node
497 * go - switch key for traversing down
498 * returns register class.
501 shswitch(int sh
, NODE
*p
, int shape
, int cookie
, int rew
, int go
)
505 F2DEBUG(("shswitch: p=%p, shape=%s, ", p
, prcook(shape
)));
506 F2DEBUG(("cookie=%s, rew=0x%x, go=%s\n", prcook(cookie
), rew
, srtyp
[go
]));
509 case SRDIR
: /* direct match, just clear su */
510 (void)swmatch(p
, 0, 0);
513 case SROREG
: /* call offstar to prepare for OREG conversion */
514 (void)swmatch(p
, shape
, SROREG
);
517 case SRREG
: /* call geninsn() to get value into register */
518 lsh
= shape
& (FORCC
| INREGS
);
519 if (rew
&& cookie
!= FOREFF
)
520 lsh
&= (cookie
& (FORCC
| INREGS
));
521 lsh
= swmatch(p
, lsh
, SRREG
);
530 * Find the best instruction to evaluate the given tree.
531 * Best is to match both subnodes directly, second-best is if
532 * subnodes must be evaluated into OREGs, thereafter if nodes
533 * must be put into registers.
534 * Whether 2-op instructions or 3-op is preferred is depending on in
535 * which order they are found in the table.
536 * mtchno is set to the count of regs needed for its legs.
539 findops(NODE
*p
, int cookie
)
541 extern int *qtable
[];
542 struct optab
*q
, *qq
= NULL
;
543 int i
, shl
, shr
, *ixp
, sh
;
544 int lvl
= 10, idx
= 0, gol
= 0, gor
= 0;
547 F2DEBUG(("findops node %p (%s)\n", p
, prcook(cookie
)));
550 ixp
= qtable
[p
->n_op
];
553 for (i
= 0; ixp
[i
] >= 0; i
++) {
556 F2DEBUG(("findop: ixp %d str %s\n", ixp
[i
], q
->cstring
));
557 if (!acceptable(q
)) /* target-dependent filter */
560 if (ttype(l
->n_type
, q
->ltype
) == 0 ||
561 ttype(r
->n_type
, q
->rtype
) == 0)
562 continue; /* Types must be correct */
564 if ((cookie
& q
->visit
) == 0)
565 continue; /* must get a result */
567 F2DEBUG(("findop got types\n"));
569 if ((shl
= chcheck(l
, q
->lshape
, q
->rewrite
& RLEFT
)) == SRNOPE
)
572 F2DEBUG(("findop lshape %s\n", srtyp
[shl
]));
575 if ((shr
= chcheck(r
, q
->rshape
, q
->rewrite
& RRIGHT
)) == SRNOPE
)
578 F2DEBUG(("findop rshape %s\n", srtyp
[shr
]));
581 /* Help register assignment after SSA by preferring */
582 /* 2-op insns instead of 3-ops */
583 if (xssaflag
&& (q
->rewrite
& RLEFT
) == 0 && shl
== SRDIR
)
586 if (q
->needs
& REWRITE
)
587 break; /* Done here */
589 if (lvl
<= (shl
+ shr
))
598 F2DEBUG(("findops failed\n"));
604 F2DEBUG(("findops entry %d(%s,%s)\n", idx
, srtyp
[gol
], srtyp
[gor
]));
609 if (cookie
== FORCC
&& p
->n_op
!= AND
) /* XXX - fix */
616 sh
= shswitch(sh
, p
->n_left
, qq
->lshape
, cookie
,
617 qq
->rewrite
& RLEFT
, gol
);
618 sh
= shswitch(sh
, p
->n_right
, qq
->rshape
, cookie
,
619 qq
->rewrite
& RRIGHT
, gor
);
622 if (cookie
== FOREFF
|| cookie
== FORCC
)
625 sh
= ffs(cookie
& qq
->visit
& INREGS
)-1;
627 F2DEBUG(("findops: node %p sh %d (%s)\n", p
, sh
, prcook(1 << sh
)));
628 p
->n_su
= MKIDX(idx
, 0);
634 * Find the best relation op for matching the two trees it has.
635 * This is a sub-version of the function findops() above.
636 * The instruction with the lowest grading is emitted.
638 * Level assignment for priority:
642 * direct OREG 2 # make oreg
643 * OREG direct 2 # make oreg
644 * OREG OREG 2 # make both oreg
645 * direct REG 3 # put in reg
646 * OREG REG 3 # put in reg, make oreg
647 * REG direct 3 # put in reg
648 * REG OREG 3 # put in reg, make oreg
649 * REG REG 4 # put both in reg
654 extern int *qtable
[];
656 int i
, shl
= 0, shr
= 0;
659 int lvl
= 10, gol
= 0, gor
= 0;
661 F2DEBUG(("relops tree:\n"));
666 ixp
= qtable
[p
->n_op
];
667 for (i
= 0; ixp
[i
] >= 0; i
++) {
670 F2DEBUG(("relops: ixp %d\n", ixp
[i
]));
671 if (!acceptable(q
)) /* target-dependent filter */
674 if (ttype(l
->n_type
, q
->ltype
) == 0 ||
675 ttype(r
->n_type
, q
->rtype
) == 0)
676 continue; /* Types must be correct */
678 F2DEBUG(("relops got types\n"));
679 if ((shl
= chcheck(l
, q
->lshape
, 0)) == SRNOPE
)
681 F2DEBUG(("relops lshape %d\n", shl
));
683 if ((shr
= chcheck(r
, q
->rshape
, 0)) == SRNOPE
)
685 F2DEBUG(("relops rshape %d\n", shr
));
687 if (q
->needs
& REWRITE
)
688 break; /* Done here */
690 if (lvl
<= (shl
+ shr
))
698 F2DEBUG(("relops failed\n"));
703 F2DEBUG(("relops entry %d(%s %s)\n", idx
, srtyp
[gol
], srtyp
[gor
]));
707 (void)shswitch(-1, p
->n_left
, q
->lshape
, FORCC
,
708 q
->rewrite
& RLEFT
, gol
);
710 (void)shswitch(-1, p
->n_right
, q
->rshape
, FORCC
,
711 q
->rewrite
& RRIGHT
, gor
);
713 F2DEBUG(("relops: node %p\n", p
));
714 p
->n_su
= MKIDX(idx
, 0);
715 SCLASS(p
->n_su
, CLASSA
); /* XXX */
720 * Find a matching assign op.
722 * Level assignment for priority:
733 findasg(NODE
*p
, int cookie
)
735 extern int *qtable
[];
737 int i
, sh
, shl
, shr
, lvl
= 10;
740 struct optab
*qq
= NULL
; /* XXX gcc */
741 int idx
= 0, gol
= 0, gor
= 0;
745 F2DEBUG(("findasg tree: %s\n", prcook(cookie
)));
748 ixp
= qtable
[p
->n_op
];
751 for (i
= 0; ixp
[i
] >= 0; i
++) {
754 F2DEBUG(("findasg: ixp %d\n", ixp
[i
]));
755 if (!acceptable(q
)) /* target-dependent filter */
758 if (ttype(l
->n_type
, q
->ltype
) == 0 ||
759 ttype(r
->n_type
, q
->rtype
) == 0)
760 continue; /* Types must be correct */
762 if ((cookie
& q
->visit
) == 0)
763 continue; /* must get a result */
765 F2DEBUG(("findasg got types\n"));
766 #ifdef mach_pdp11 /* XXX - check for other targets too */
767 if (p
->n_op
== STASG
&& ISPTR(l
->n_type
)) {
768 /* Accept lvalue to be in register */
769 /* if struct assignment is given a pointer */
770 if ((shl
= chcheck(l
, q
->lshape
,
771 q
->rewrite
& RLEFT
)) == SRNOPE
)
776 if ((shl
= tshape(l
, q
->lshape
)) == SRNOPE
)
782 F2DEBUG(("findasg lshape %d\n", shl
));
785 if ((shr
= chcheck(r
, q
->rshape
, q
->rewrite
& RRIGHT
)) == SRNOPE
)
788 F2DEBUG(("findasg rshape %d\n", shr
));
790 if (q
->needs
& REWRITE
)
791 break; /* Done here */
793 if (lvl
<= (shl
+ shr
))
804 F2DEBUG(("findasg failed\n"));
805 if (setasg(p
, cookie
))
809 F2DEBUG(("findasg entry %d(%s,%s)\n", idx
, srtyp
[gol
], srtyp
[gor
]));
812 sh
= shswitch(sh
, p
->n_left
, qq
->lshape
, cookie
,
813 qq
->rewrite
& RLEFT
, gol
);
815 sh
= shswitch(sh
, p
->n_right
, qq
->rshape
, cookie
,
816 qq
->rewrite
& RRIGHT
, gor
);
818 #ifdef mach_pdp11 /* XXX all targets? */
820 if (cookie
== FOREFF
)
822 else if (cookie
== FORCC
)
825 sh
= ffs(cookie
& qq
->visit
& INREGS
)-1;
828 comperr("findasg bad shape");
833 p
->n_su
= MKIDX(idx
, lvl
);
836 if (cookie
== FOREFF
)
839 sh
= ffs(cookie
& qq
->visit
& INREGS
)-1;
841 F2DEBUG(("findasg: node %p class %d\n", p
, sh
));
843 p
->n_su
= MKIDX(idx
, 0);
845 #endif /* mach_pdp11 */
853 * Search for an UMUL table entry that can turn an indirect node into
854 * a move from an OREG.
857 findumul(NODE
*p
, int cookie
)
859 extern int *qtable
[];
860 struct optab
*q
= NULL
; /* XXX gcc */
861 int i
, shl
= 0, shr
= 0, sh
;
864 F2DEBUG(("findumul p %p (%s)\n", p
, prcook(cookie
)));
867 ixp
= qtable
[p
->n_op
];
868 for (i
= 0; ixp
[i
] >= 0; i
++) {
871 F2DEBUG(("findumul: ixp %d\n", ixp
[i
]));
872 if (!acceptable(q
)) /* target-dependent filter */
875 if ((q
->visit
& cookie
) == 0)
876 continue; /* wrong registers */
878 if (ttype(p
->n_type
, q
->rtype
) == 0)
879 continue; /* Types must be correct */
882 F2DEBUG(("findumul got types, rshape %s\n", prcook(q
->rshape
)));
884 * Try to create an OREG of the node.
885 * Fake left even though it's right node,
886 * to be sure of conversion if going down left.
888 if ((shl
= chcheck(p
, q
->rshape
, 0)) == SRNOPE
)
893 if (q
->needs
& REWRITE
)
894 break; /* Done here */
896 F2DEBUG(("findumul got shape %s\n", srtyp
[shl
]));
898 break; /* XXX search better matches */
901 F2DEBUG(("findumul failed\n"));
902 if (setuni(p
, cookie
))
906 F2DEBUG(("findumul entry %d(%s %s)\n", ixp
[i
], srtyp
[shl
], srtyp
[shr
]));
908 sh
= shswitch(-1, p
, q
->rshape
, cookie
, q
->rewrite
& RLEFT
, shl
);
910 sh
= ffs(cookie
& q
->visit
& INREGS
)-1;
912 F2DEBUG(("findumul: node %p (%s)\n", p
, prcook(1 << sh
)));
913 p
->n_su
= MKIDX(ixp
[i
], 0);
919 * Find a leaf type node that puts the value into a register.
922 findleaf(NODE
*p
, int cookie
)
924 extern int *qtable
[];
925 struct optab
*q
= NULL
; /* XXX gcc */
929 F2DEBUG(("findleaf p %p (%s)\n", p
, prcook(cookie
)));
932 ixp
= qtable
[p
->n_op
];
933 for (i
= 0; ixp
[i
] >= 0; i
++) {
936 F2DEBUG(("findleaf: ixp %d\n", ixp
[i
]));
937 if (!acceptable(q
)) /* target-dependent filter */
939 if ((q
->visit
& cookie
) == 0)
940 continue; /* wrong registers */
942 if (ttype(p
->n_type
, q
->rtype
) == 0 ||
943 ttype(p
->n_type
, q
->ltype
) == 0)
944 continue; /* Types must be correct */
946 F2DEBUG(("findleaf got types, rshape %s\n", prcook(q
->rshape
)));
948 if (chcheck(p
, q
->rshape
, 0) != SRDIR
)
951 if (q
->needs
& REWRITE
)
952 break; /* Done here */
957 F2DEBUG(("findleaf failed\n"));
958 if (setuni(p
, cookie
))
962 F2DEBUG(("findleaf entry %d\n", ixp
[i
]));
964 sh
= ffs(cookie
& q
->visit
& INREGS
)-1;
965 F2DEBUG(("findleaf: node %p (%s)\n", p
, prcook(1 << sh
)));
966 p
->n_su
= MKIDX(ixp
[i
], 0);
972 * Find a UNARY op that satisfy the needs.
973 * For now, the destination is always a register.
974 * Both source and dest types must match, but only source (left)
975 * shape is of interest.
978 finduni(NODE
*p
, int cookie
)
980 extern int *qtable
[];
983 int i
, shl
= 0, num
= 4;
987 F2DEBUG(("finduni tree: %s\n", prcook(cookie
)));
991 if (p
->n_op
== CALL
|| p
->n_op
== FORTCALL
|| p
->n_op
== STCALL
)
995 ixp
= qtable
[p
->n_op
];
996 for (i
= 0; ixp
[i
] >= 0; i
++) {
999 F2DEBUG(("finduni: ixp %d\n", ixp
[i
]));
1000 if (!acceptable(q
)) /* target-dependent filter */
1003 if (ttype(l
->n_type
, q
->ltype
) == 0)
1004 continue; /* Type must be correct */
1006 F2DEBUG(("finduni got left type\n"));
1007 if (ttype(r
->n_type
, q
->rtype
) == 0)
1008 continue; /* Type must be correct */
1010 F2DEBUG(("finduni got types\n"));
1011 if ((shl
= chcheck(l
, q
->lshape
, q
->rewrite
& RLEFT
)) == SRNOPE
)
1014 F2DEBUG(("finduni got shapes %d\n", shl
));
1016 if ((cookie
& q
->visit
) == 0) /* check correct return value */
1017 continue; /* XXX - should check needs */
1019 /* avoid clobbering of longlived regs */
1020 /* let register allocator coalesce */
1021 if ((q
->rewrite
& RLEFT
) && (shl
== SRDIR
) /* && isreg(l) */)
1024 F2DEBUG(("finduni got cookie\n"));
1025 if (q
->needs
& REWRITE
)
1026 break; /* Done here */
1038 F2DEBUG(("finduni failed\n"));
1040 F2DEBUG(("finduni entry %d(%s)\n", idx
, srtyp
[num
]));
1043 if (setuni(p
, cookie
))
1049 sh
= shswitch(-1, p
->n_left
, q
->lshape
, cookie
,
1050 q
->rewrite
& RLEFT
, num
);
1052 sh
= ffs(cookie
& q
->visit
& INREGS
)-1;
1056 F2DEBUG(("finduni: node %p (%s)\n", p
, prcook(1 << sh
)));
1057 p
->n_su
= MKIDX(idx
, 0);
1058 SCLASS(p
->n_su
, sh
);
1064 * Try to find constructs like "a = a + 1;" and match them together
1065 * with instructions like "incl a" or "addl $1,a".
1067 * Level assignment for priority:
1078 findmops(NODE
*p
, int cookie
)
1080 extern int *qtable
[];
1082 int i
, sh
, shl
, shr
, lvl
= 10;
1085 struct optab
*qq
= NULL
; /* XXX gcc */
1086 int idx
= 0, gol
= 0, gor
= 0;
1090 F2DEBUG(("findmops tree: %s\n", prcook(cookie
)));
1095 /* See if this is a usable tree to work with */
1096 /* Currently only check for leaves */
1097 if (optype(r
->n_op
) != BITYPE
|| treecmp(l
, r
->n_left
) == 0)
1100 F2DEBUG(("findmops is useable\n"));
1102 /* We can try to find a match. Use right op */
1103 ixp
= qtable
[r
->n_op
];
1107 for (i
= 0; ixp
[i
] >= 0; i
++) {
1110 F2DEBUG(("findmops: ixp %d\n", ixp
[i
]));
1111 if (!acceptable(q
)) /* target-dependent filter */
1114 if (ttype(l
->n_type
, q
->ltype
) == 0 ||
1115 ttype(r
->n_type
, q
->rtype
) == 0)
1116 continue; /* Types must be correct */
1118 F2DEBUG(("findmops got types\n"));
1122 if ((q
->visit
& FOREFF
) == 0)
1123 continue; /* Not only for side effects */
1126 if ((q
->visit
& FORCC
) == 0)
1127 continue; /* Not only for side effects */
1130 if ((cookie
& q
->visit
) == 0)
1131 continue; /* Won't match requested shape */
1132 if (((cookie
& INREGS
& q
->lshape
) == 0) || !isreg(l
))
1133 continue; /* Bad return register */
1136 F2DEBUG(("findmops cookie\n"));
1139 * left shape must match left node.
1141 if ((shl
= tshape(l
, q
->lshape
)) != SRDIR
&& (shl
!= SROREG
))
1144 F2DEBUG(("findmops lshape %s\n", srtyp
[shl
]));
1147 if ((shr
= chcheck(r
, q
->rshape
, 0)) == SRNOPE
)
1150 F2DEBUG(("findmops rshape %s\n", srtyp
[shr
]));
1153 * Only allow RLEFT. XXX
1155 if ((q
->rewrite
& (RLEFT
|RRIGHT
)) != RLEFT
)
1158 F2DEBUG(("rewrite OK\n"));
1161 if (q
->needs
& REWRITE
)
1162 break; /* Done here */
1164 if (lvl
<= (shl
+ shr
))
1176 F2DEBUG(("findmops entry %d(%s,%s)\n", idx
, srtyp
[gol
], srtyp
[gor
]));
1179 * Now we're here and have a match. left is semi-direct and
1180 * right may be anything.
1184 sh
= shswitch(sh
, p
->n_left
, qq
->lshape
, cookie
,
1185 qq
->rewrite
& RLEFT
, gol
);
1186 sh
= shswitch(sh
, r
, qq
->rshape
, cookie
, 0, gor
);
1189 if (cookie
& (FOREFF
|FORCC
))
1192 sh
= ffs(cookie
& qq
->visit
& INREGS
)-1;
1194 F2DEBUG(("findmops done: node %p class %d\n", p
, sh
));
1196 /* Trickery: Set table index on assign to op instead */
1197 /* gencode() will remove useless nodes */
1198 p
->n_su
= MKIDX(idx
, 0);
1199 p
->n_flags
|= 1; /* XXX tell gencode to reduce the right tree */
1200 SCLASS(p
->n_su
, sh
);
1206 * Compare two trees; return 1 if equal and 0 if not.
1209 treecmp(NODE
*p1
, NODE
*p2
)
1211 if (p1
->n_op
!= p2
->n_op
)
1217 return treecmp(p1
->n_left
, p2
->n_left
);
1220 if (p1
->n_lval
!= p2
->n_lval
|| p1
->n_rval
!= p2
->n_rval
)
1226 if (strcmp(p1
->n_name
, p2
->n_name
))
1229 if (p1
->n_lval
!= p2
->n_lval
)
1235 /* SSA will put assignment in separate register */
1236 /* Help out by accepting different regs here */
1241 if (p1
->n_rval
!= p2
->n_rval
)
1250 if (treecmp(p1
->n_left
, p2
->n_left
) == 0 ||
1251 treecmp(p1
->n_right
, p2
->n_right
) == 0)