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 (at) 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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