|
|
1.1 ! root 1: /* @(#) optutil.c: 1.3 3/27/84 */ ! 2: /* optutil.c ! 3: ** ! 4: ** Optimizer utilities for 3B code improver (PCI). ! 5: ** ! 6: ** ! 7: ** This module contains utility routines for the various peephole ! 8: ** window optimizations. ! 9: */ ! 10: ! 11: /* #include <ctype.h> -- optim.h takes care of this */ ! 12: /* #include "defs" -- optim.h takes care of this; machine-dependent defs */ ! 13: #include "optim.h" /* machine independent optimizer defs */ ! 14: ! 15: extern long atol(); ! 16: /* isreg -- is operand string a register reference? ! 17: ** ! 18: ** This routine tells whether an operand string is a register reference. ! 19: */ ! 20: ! 21: boolean ! 22: isreg(s) ! 23: char * s; /* operand string */ ! 24: { ! 25: /* assume operand is a register reference if it begins with a % */ ! 26: ! 27: return(*s == '%'); ! 28: } ! 29: ! 30: ! 31: ! 32: /* isnib -- is operand a nibble? ! 33: ** ! 34: ** This routine tests an operand string and tells whether it is an ! 35: ** immediate operand that can fit in a nibble (4 bits). ! 36: */ ! 37: ! 38: boolean ! 39: isnib(s) ! 40: char * s; /* operand string to check */ ! 41: { ! 42: long x; /* temporary to hold value */ ! 43: ! 44: /* Return true if the operand begins with a '&', it is numeric, ! 45: ** and the numeric value is between 0 and 15. ! 46: */ ! 47: ! 48: return( *s == '&' /* begins with & */ ! 49: && isdigit(*++s) /* operand is numeric */ ! 50: && (x = atol(s)) >= 0 /* is positive */ ! 51: && x <= 15 /* and <= 15 */ ! 52: ); ! 53: } ! 54: /* isnegnib -- is operand a negative nibble? ! 55: ** ! 56: ** This routine tests whether an operand string is an immediate operand ! 57: ** with a value between -1 and -15. Another condition tested is that ! 58: ** the minus sign immediately follows an '&'. (This condition is ! 59: ** important if the operand is overwritten.) ! 60: */ ! 61: ! 62: boolean ! 63: isnegnib(s) ! 64: char * s; /* operand string */ ! 65: { ! 66: long n; /* temporary operand value */ ! 67: ! 68: return( ! 69: s != NULL ! 70: && *s++ == '&' /* operand starts with & */ ! 71: && *s++ == '-' /* followed by - */ ! 72: && isdigit(*s) /* operand is numeric */ ! 73: && 1 <= (n = atol(s)) /* (positive) value between 1... */ ! 74: && n <= 15 /* and 15 */ ! 75: ); ! 76: } ! 77: /* getbit -- get bit number for power of 2 ! 78: ** ! 79: ** This routine tests whether an operand is a power of 2. If not, it ! 80: ** returns -1. Otherwise it returns a bit number, which is also the ! 81: ** exponent of 2. ! 82: */ ! 83: ! 84: int ! 85: getbit(s) ! 86: char * s; /* pointer to operand string */ ! 87: { ! 88: int bit = 0; /* initialize bit number for later */ ! 89: long n; /* numeric value of operand */ ! 90: boolean isnumlit(); ! 91: ! 92: if ( (! isnumlit(s)) || (n = atol(s+1)) < 0 ) ! 93: return(-1); /* check for numeric literal with ! 94: ** good value ! 95: */ ! 96: ! 97: /* This test really works, although it looks suspicious. A power of two ! 98: ** has only one bit set, so that value minus one has all of the bits to ! 99: ** the right of the original bit set. Anding them together gives zero. ! 100: ** No other value yields zero. ! 101: */ ! 102: ! 103: if ( ( n & (n-1) ) != 0) ! 104: return(-1); /* not a power of 2 */ ! 105: ! 106: /* Shift right until the word is zero */ ! 107: ! 108: while ((n = n>>1) != 0) ! 109: bit++; /* bump bit number each time */ ! 110: ! 111: return(bit); /* return bit number */ ! 112: } ! 113: /* insert -- insert new instruction node ! 114: ** ! 115: ** This routine inserts a new instruction node after the one pointed ! 116: ** to. The fields in the node are initialized to null values. ! 117: */ ! 118: ! 119: NODE * /* return pointer to the new node */ ! 120: insert(pn) ! 121: NODE * pn; /* node to add pointer after */ ! 122: { ! 123: NODE * Saveop(); /* in machine-independent part */ ! 124: NODE * new = Saveop(0,"",0,GHOST); /* create isolated node, init. */ ! 125: ! 126: APPNODE(new,pn); /* append new node after current */ ! 127: ! 128: return(new); /* return pointer to the new one */ ! 129: } ! 130: /* chgop -- change op code number and op code string in node ! 131: ** ! 132: ** This routine changes the op code information in a node. The ! 133: ** operand information is unaffected. ! 134: */ ! 135: ! 136: void ! 137: chgop(n,op,op_code) ! 138: NODE * n; /* pointer to node to change */ ! 139: int op; /* op code number */ ! 140: char * op_code; /* pointer to op code string */ ! 141: { ! 142: n->op = op; /* set op code number */ ! 143: n->opcode = op_code; /* and string */ ! 144: return; ! 145: } ! 146: /* copyopn -- copy operand string ! 147: ** ! 148: ** This routine duplicates an operand string in a new piece of memory. ! 149: ** The caller can specify a +/- number of additional bytes required, ! 150: ** as well as an offset for copying. ! 151: */ ! 152: ! 153: char * /* return duplicate string */ ! 154: copyopn(s,extra,offset) ! 155: char * s; /* original operand string */ ! 156: int extra; /* number of extra (or fewer) chars */ ! 157: int offset; /* offset in original operand from ! 158: ** which to start copying. ! 159: */ ! 160: { ! 161: int len = strlen(s) + extra; /* length of duplicate */ ! 162: char * stemp; /* future duplicate string */ ! 163: ! 164: if (len <= 0) ! 165: return(NULL); /* deleted everything */ ! 166: ! 167: stemp = getspace(len+1); /* get new string (+1 for null byte) */ ! 168: return(strcpy(stemp,s+offset)); /* return copy */ ! 169: } ! 170: /* isdyadic -- is instruction dyadic ! 171: ** ! 172: ** This routine tells whether an instruction is dyadic according ! 173: ** to the following conditions: ! 174: ** ! 175: ** 1. It takes two operands. ! 176: ** 2. It reads the first operand, writes the second. ! 177: ** 3. It sets the condition codes according to the value stored in ! 178: ** the second operand. ! 179: ** 4. The operands have normal address mode meanings: disallow, ! 180: ** for example, MOVAW, which does address arithmetic of op1. ! 181: */ ! 182: ! 183: boolean ! 184: isdyadic(n) ! 185: NODE * n; /* instruction node to test */ ! 186: { ! 187: switch(n->op) /* dispatch on op code number */ ! 188: { ! 189: case MCOMW: ! 190: case MOVZBH: ! 191: case MOVZBW: ! 192: case MOVZHW: ! 193: case ANDW2: ! 194: case ORW2: ! 195: case XORW2: ! 196: case LLSW2: ! 197: case LRSW2: ! 198: case MOVW: ! 199: case MOVBBH: ! 200: case MOVBBW: ! 201: case MOVBHW: ! 202: case MOVTHB: ! 203: case MOVTWB: ! 204: case MOVTWH: ! 205: case MNEGW: ! 206: case ADDW2: ! 207: case SUBW2: ! 208: case MULW2: ! 209: case UMULW2: ! 210: case DIVW2: ! 211: case UDIVW2: ! 212: case UMODW2: ! 213: case ALSW2: ! 214: case ARSW2: ! 215: return(true); /* all of these are dyadic */ ! 216: default: ! 217: return(false); /* others are not */ ! 218: } ! 219: } ! 220: /* istriadic -- is instruction triadic? ! 221: ** ! 222: ** This routine serves a similar function to isdyadic, except that ! 223: ** it also returns the related dyadic op code number and string. ! 224: ** The only instructions included here are the obvious ones. They ! 225: ** are assumed to have integer operands (by callers). ! 226: */ ! 227: ! 228: /* define macro to use below */ ! 229: ! 230: #define CHANGE(op,new,newst) case op: *pnewop=new;*pnewopcode=newst;break; ! 231: ! 232: ! 233: boolean ! 234: istriadic(n,pnewop,pnewopcode) ! 235: NODE * n; /* node to test */ ! 236: int * pnewop; /* place to put equiv. dyadic # */ ! 237: char ** pnewopcode; /* place to put equiv. dyadic string */ ! 238: { ! 239: switch (n->op) /* dispatch on op code number */ ! 240: { ! 241: CHANGE(ADDW3,ADDW2,"addw2"); ! 242: CHANGE(SUBW3,SUBW2,"subw2"); ! 243: CHANGE(MULW3,MULW2,"mulw2"); ! 244: CHANGE(UMULW3,UMULW2,"umulw2"); ! 245: CHANGE(DIVW3,DIVW2,"divw2"); ! 246: CHANGE(UDIVW3,UDIVW2,"udivw2"); ! 247: CHANGE(MODW3,MODW2,"modw2"); ! 248: CHANGE(UMODW3,UMODW2,"umodw2"); ! 249: CHANGE(ALSW3,ALSW2,"alsw2"); ! 250: CHANGE(ARSW3,ARSW2,"arsw2"); ! 251: CHANGE(ANDW3,ANDW2,"andw2"); ! 252: CHANGE(ORW3,ORW2,"orw2"); ! 253: CHANGE(XORW3,XORW2,"xorw2"); ! 254: CHANGE(LLSW3,LLSW2,"llsw2"); ! 255: CHANGE(LRSW3,LRSW2,"lrsw2"); ! 256: default: /* for op codes not found */ ! 257: return(false); ! 258: } ! 259: return(true); /* found op code */ ! 260: } ! 261: /* totriadic -- can dyadic be made triadic? ! 262: ** ! 263: ** This routine checks a dyadic instruction to see if it can be ! 264: ** made triadic. If so, it returns the opcode number and string ! 265: ** for the corresponding triadic. Totriadic is really the inverse ! 266: ** of istriadic. ! 267: */ ! 268: ! 269: boolean ! 270: totriadic(n,pnewop,pnewopcode) ! 271: NODE * n; /* node to test */ ! 272: int * pnewop; /* place to put equiv. triadic # */ ! 273: char ** pnewopcode; /* place to put equiv. triadic string */ ! 274: { ! 275: switch (n->op) /* dispatch on op code number */ ! 276: { ! 277: CHANGE(ADDW2,ADDW3,"addw3"); ! 278: CHANGE(SUBW2,SUBW3,"subw3"); ! 279: CHANGE(MULW2,MULW3,"mulw3"); ! 280: CHANGE(UMULW2,UMULW3,"umulw3"); ! 281: CHANGE(DIVW2,DIVW3,"divw3"); ! 282: CHANGE(UDIVW2,UDIVW3,"udivw3"); ! 283: CHANGE(MODW2,MODW3,"modw3"); ! 284: CHANGE(UMODW2,UMODW3,"umodw3"); ! 285: CHANGE(ALSW2,ALSW3,"alsw3"); ! 286: CHANGE(ARSW2,ARSW3,"arsw3"); ! 287: CHANGE(ANDW2,ANDW3,"andw3"); ! 288: CHANGE(ORW2,ORW3,"orw3"); ! 289: CHANGE(XORW2,XORW3,"xorw3"); ! 290: CHANGE(LLSW2,LLSW3,"llsw3"); ! 291: CHANGE(LRSW2,LRSW3,"lrsw3"); ! 292: default: /* for op codes not found */ ! 293: return(false); ! 294: } ! 295: return(true); /* found op code */ ! 296: } ! 297: /* makelive -- make register live ! 298: ** ! 299: ** This routine marks a register operand as live. ! 300: */ ! 301: ! 302: void ! 303: makelive(s,n) ! 304: char * s; /* operand string (to %r0) */ ! 305: NODE * n; /* pointer to node to enliven */ ! 306: { ! 307: n->nlive |= setreg(s); ! 308: return; ! 309: } ! 310: ! 311: ! 312: ! 313: /* makedead -- make register dead ! 314: ** ! 315: ** This routine marks a register operand as dead. ! 316: */ ! 317: ! 318: void ! 319: makedead(s,n) ! 320: char * s; /* operand string (to %rn) */ ! 321: NODE * n; /* pointer to node to kill */ ! 322: { ! 323: n->nlive &= ~ setreg(s); ! 324: return; ! 325: } ! 326: /* isindex -- is operand an index off a register? ! 327: ** ! 328: ** This routine checks whether an operand string is of the ! 329: ** form: ! 330: ** ! 331: ** n(%rn) ! 332: ** ! 333: ** and whether it uses a designated register. ! 334: ** ! 335: ** Actually, it cheats: it just checks for an initial digit or sign followed ! 336: ** by a (. In fact the ( test is a cheat, because we just check to see ! 337: ** if there's a ( in the string. ! 338: */ ! 339: ! 340: boolean ! 341: isindex(s,r) ! 342: char * s; /* operand string to test */ ! 343: char * r; /* register operand string to check ! 344: ** for ! 345: */ ! 346: ! 347: { ! 348: char * strchr(); ! 349: ! 350: if(*s == '*') ! 351: s++; ! 352: return( ! 353: usesreg(s,r) ! 354: && (isdigit(*s) || *s == '-') /* could be leading sign, too */ ! 355: && strchr(s,'(') != (char *) 0 ! 356: ); ! 357: } ! 358: /* ismove -- is instruction a move? ! 359: ** ! 360: ** This routine determines whether an instruction is a move-type. ! 361: ** There is a multiplicity of move instructions which copy, zero- ! 362: ** or sign-extend, and truncate. This routine returns the natural ! 363: ** size of the source and destination operands. ! 364: */ ! 365: ! 366: boolean ! 367: ismove(n,srcsize,dstsize) ! 368: NODE * n; /* pointer to instruction node */ ! 369: int * srcsize; /* place to put size of source ! 370: ** operand (in bytes) ! 371: */ ! 372: int * dstsize; /* place to put size of destination */ ! 373: { ! 374: register int srctemp = 1; /* temporary source size */ ! 375: register int dsttemp = 4; /* temporary destination size */ ! 376: /* Initial values chosen on basis of most common value of each. */ ! 377: ! 378: switch (n->op) /* dispatch on op-code number */ ! 379: { ! 380: case MOVZBH: ! 381: dsttemp = 2; break; ! 382: case MOVZBW: ! 383: break; ! 384: case MOVZHW: ! 385: srctemp = 2; break; ! 386: ! 387: case MOVB: ! 388: dsttemp = 1; break; ! 389: case MOVH: ! 390: srctemp = 2; dsttemp = 2; break; ! 391: case MOVW: ! 392: srctemp = 4; break; ! 393: ! 394: case MOVBBH: ! 395: dsttemp = 2; break; ! 396: case MOVBBW: ! 397: break; ! 398: case MOVBHW: ! 399: srctemp = 2; break; ! 400: ! 401: case MOVTHB: ! 402: srctemp = 2; dsttemp = 1; break; ! 403: case MOVTWB: ! 404: srctemp = 4; dsttemp = 1; break; ! 405: case MOVTWH: ! 406: srctemp = 4; dsttemp = 2; break; ! 407: default: ! 408: return(false); /* not a move instruction */ ! 409: } ! 410: *srcsize = srctemp; /* copy out correct values */ ! 411: *dstsize = dsttemp; ! 412: return(true); /* found a move */ ! 413: } ! 414: /* iszoffset -- is operand zero offset from register ! 415: ** ! 416: ** This routine determines whether a given operand is an indexed ! 417: ** operation from a designated register, where the index is zero. ! 418: */ ! 419: ! 420: boolean ! 421: iszoffset(operand,reg) ! 422: register char * operand; /* operand string */ ! 423: char * reg; /* register string */ ! 424: { ! 425: ! 426: /* We use a quick and dirty strategy here: we test the operand for ! 427: ** zero, followed by (, with matching register numbers in the right ! 428: ** place. We assume register designations are "%rn". ! 429: */ ! 430: ! 431: return( ! 432: *operand == '0' ! 433: && *(operand+1) == '(' ! 434: && *(operand+4) == *(reg+2) ! 435: ); ! 436: } ! 437: /* exchange -- exchange node and successor ! 438: ** ! 439: ** This routine reverses the linkages of two nodes so the first is ! 440: ** the second and the second is the first. ! 441: */ ! 442: ! 443: void ! 444: exchange(first) ! 445: NODE * first; /* pointer to first of two nodes */ ! 446: { ! 447: ! 448: /* This can probably be done with fewer temporaries, but it's a lot ! 449: ** easier to understand what's going on this way.... ! 450: */ ! 451: ! 452: NODE * prev = first->back; /* predecessor of first node */ ! 453: NODE * second = first->forw; /* second node of pair to exchange */ ! 454: NODE * next = second->forw; /* successor of second node */ ! 455: ! 456: prev->forw = second; /* second will now be first */ ! 457: second->back = prev; ! 458: ! 459: first->forw = next; /* successor of old first is now ! 460: ** 'next' ! 461: */ ! 462: next->back=first; /* 'next's' predecessor now 'first' */ ! 463: ! 464: second->forw = first; ! 465: first->back = second; /* re-link connection of node pair */ ! 466: ! 467: return; ! 468: } ! 469: /* doindirect -- resolve indirect references ! 470: ** ! 471: ** This routine changes variable references of the form ! 472: ** 0(%rn) ! 473: ** to ! 474: ** *var ! 475: ** where possible. Its purpose is to make it possible to discard a ! 476: ** register load. ! 477: ** ! 478: ** Here's the scenario: we're handed an instruction, the name of the ! 479: ** register whose zero-index use we want to change, and the real location ! 480: ** of the variable. For example, in the sequence ! 481: ** ! 482: ** movw xyz,%r0 ! 483: ** addw2 0(%r0),%r1 ! 484: ** ! 485: ** the instruction we would be handed is the addw2, the register would be ! 486: ** %r0, and the real location of the variable is 'xyz'. ! 487: ** ! 488: ** Complications: ! 489: ** 1. The register must be dead after the instruction. ! 490: ** 2. We want to change all such references in the instruction. ! 491: ** 3. If there are any other uses of the register than a zero ! 492: ** index, like actually using the register contents or ! 493: ** using an index other than zero (e.g., 4(%r0)), we ! 494: ** can't make the transformation, since we're going to ! 495: ** eliminate the preceding register load. ! 496: ** 4. ... except that if the destination of a triadic instruction or ! 497: ** move is the register it's safe to proceed. ! 498: ** ! 499: ** One, possibly unsafe assumption: ! 500: ** The algorithm assumes that unused operands in an instruction (like ! 501: ** operands 3 and 4 in a dyadic) are always NULL. We also assume that ! 502: ** an instruction has a "destination" (returned by 'dst') if and only ! 503: ** if it can alter something. We further assume that the destination ! 504: ** is always the last operand. ! 505: */ ! 506: ! 507: boolean /* true if the transformation ! 508: ** was made ! 509: */ ! 510: doindirect(n,reg,repl) ! 511: NODE * n; /* instruction node to examine */ ! 512: char * reg; /* register (string) to look for */ ! 513: char * repl; /* operand string to use */ ! 514: { ! 515: boolean first = true; /* if examining first real operand */ ! 516: int indmask = 0; /* will have bits set telling which ! 517: ** operands to change ! 518: */ ! 519: int i; /* loop index */ ! 520: char * operand; /* current operand */ ! 521: int src,dest; /* for ismove (but unused) */ ! 522: /* Begin: check whether transformation can be made, note which operands ! 523: ** to change if so. ! 524: */ ! 525: ! 526: if ( ! 527: isret(n) /* will show register dead, which ! 528: ** will confuse us ! 529: */ ! 530: || ! ( ! 531: isdead(reg,n) /* reg must be dead after n */ ! 532: || ( ismove(n,&src,&dest) && samereg(n->op2,reg) ) ! 533: ) /* unless set by this inst. as move */ ! 534: || *repl == '*' /* can't do it if replacement is ! 535: ** already an indirect... ! 536: */ ! 537: || *repl == '&' /* or an immediate */ ! 538: ) ! 539: return(false); /* can't do it */ ! 540: ! 541: /* Now scan operands for things that can't be transformed. We do this ! 542: ** backward from higher numbered operands on the assumption that a ! 543: ** destination, which we treat differently, is the highest numbered ! 544: ** non-null operand. ! 545: */ ! 546: ! 547: for ( i = MAXOPS; i > 0; i-- ) ! 548: { ! 549: int opn; /* op code number in istriadic */ ! 550: char * opst; /* op code string in istriadic */ ! 551: ! 552: if ( (operand = n->ops[i]) != NULL ) ! 553: { /* found an operand */ ! 554: if (iszoffset(operand,reg)) /* this is what we want! */ ! 555: indmask |= 1<<i; /* remember where it is */ ! 556: ! 557: /* otherwise can only use register if this is the last ! 558: ** operand (but the first we'll find) and the instruction ! 559: ** is triadic ! 560: */ ! 561: ! 562: else if ( ! 563: ! ( samereg(operand,reg) ! 564: && first ! 565: && ( ! 566: istriadic(n,&opn,&opst) ! 567: || ismove(n,&src,&dest) ! 568: ) ! 569: ) ! 570: && usesreg(operand,reg) ! 571: ) ! 572: return(false); /* bad use of register */ ! 573: ! 574: first = false; /* no longer looking at first (last) ! 575: ** operand ! 576: */ ! 577: } ! 578: } ! 579: /* Reaching here, we have successfully scanned all operands without ! 580: ** finding any register references that violate the required conditions. ! 581: */ ! 582: ! 583: if (indmask == 0) /* if no register references... */ ! 584: return(false); /* say we didn't change anything */ ! 585: if ( !isiros(repl) ) return( false ); /* check for mmio */ ! 586: /* Now we're ready to do the actual transformations. If the replacement ! 587: ** operand is a register reference, we create a new operand reference ! 588: ** of the form: ! 589: ** 0(reg) --> 0(repl) ! 590: ** ! 591: ** Otherwise we have a vanilla operand. Rewrite it as ! 592: ** ! 593: ** 0(reg) --> *repl ! 594: */ ! 595: ! 596: { /* for some more variables */ ! 597: char * indstring; /* new operand string */ ! 598: int extra; /* number of extra chars in xform */ ! 599: char * format; /* sprintf format string for xform */ ! 600: ! 601: if (isreg(repl)) /* replacement is also reference */ ! 602: { ! 603: format = "0(%s)"; /* to form 0(repl) */ ! 604: extra = 3; /* for 0 ( ) */ ! 605: } ! 606: else ! 607: { ! 608: format = "*%s"; /* rewrite as *repl */ ! 609: extra = 1; /* prepend * only */ ! 610: } ! 611: ! 612: indstring = getspace(strlen(repl) + extra + 1); ! 613: /* allocate space + 1 for null */ ! 614: (void) sprintf(indstring,format,repl); ! 615: /* build replacement */ ! 616: ! 617: wchange(); /* Finally! About to make changes */ ! 618: ! 619: /* loop through operands, replacing ones whose bit is set in mask */ ! 620: ! 621: for ( i = MAXOPS; i > 0; i-- ) ! 622: { ! 623: if ( (indmask & (1<<i)) != 0) ! 624: n->ops[i] = indstring; /* stick in replacement string */ ! 625: } ! 626: ! 627: return(true); /* say we changed stuff */ ! 628: } /* end extra block */ ! 629: } ! 630: /* isnumlit -- is operand a numeric literal ! 631: ** ! 632: ** This routine tests operand strings for the form ! 633: ** ! 634: ** &[-]n ! 635: ** ! 636: ** where n is a positive integer. ! 637: */ ! 638: ! 639: boolean ! 640: isnumlit(s) ! 641: char * s; /* pointer to operand string */ ! 642: { ! 643: if (*s++ != '&') ! 644: return(false); ! 645: ! 646: if (*s == '-') /* sign okay */ ! 647: s++; ! 648: ! 649: while (*s != '\0') /* check for all digits */ ! 650: if ( ! isdigit(*s++) ) ! 651: return(false); ! 652: ! 653: return(true); /* passed all tests */ ! 654: } ! 655: /* usesvar -- does first operand use second? ! 656: ** ! 657: ** This routine is a generalization of "usesreg": it returns true ! 658: ** if the first operand uses the second. An example is ! 659: ** v1 = "*p", v2 = "p". v1 uses the contents of v2. ! 660: */ ! 661: ! 662: boolean ! 663: usesvar(v1,v2) ! 664: char * v1; /* using operand */ ! 665: char * v2; /* used operand */ ! 666: { ! 667: if (isreg(v2) && usesreg(v1,v2)) ! 668: return(true); /* handle register case specially */ ! 669: ! 670: if (*v1 == '*') /* check for initial indirect */ ! 671: v1++; ! 672: ! 673: return(strcmp(v1,v2) == 0); /* result is result of compare */ ! 674: } ! 675: ! 676: ! 677: /* These routines try to preserve the line number information. ! 678: The criterion for saving or discarding line number information is ! 679: that the state of the machine from a C point of view should be the ! 680: same at any given line both before and after the optimization. ! 681: If it would not be then the line number is deleted. ! 682: The exceptions to the above are that the state of the condition codes ! 683: and of dead registers is ignored. ! 684: ! 685: May 1983 */ ! 686: ! 687: /* NOTE: All instruction nodes that these routines assume will be tossed ! 688: have their uniqids set to IDVAL. For example, in the merges, ! 689: the uniqids of the original instructions are set to IDVAL ! 690: and then the uniqid of the resultant instruction is computed. ! 691: This has the effect of setting the uniqid of the instruction ! 692: not corresponding to the resultant to IDVAL. This fact is used ! 693: in some instances where lnmrginst2 is called -- see w2opt.c */ ! 694: ! 695: /* delete instruction -- save line number ! 696: if the instruction below has no line number or has a line number ! 697: greater than the present instruction, the present number ! 698: is transfered down */ ! 699: ! 700: void ! 701: ldelin(nodep) ! 702: NODE * nodep; ! 703: { ! 704: if(nodep->uniqid == IDVAL) ! 705: return; ! 706: ! 707: if(nodep->forw != &ntail && ! 708: (nodep->forw->uniqid > nodep->uniqid ! 709: || nodep->forw->uniqid == IDVAL)) ! 710: nodep->forw->uniqid = nodep->uniqid; ! 711: ! 712: nodep->uniqid = IDVAL; ! 713: ! 714: } ! 715: ! 716: /* more conservative version of lndelinst that does not overwrite ! 717: line numbers below */ ! 718: void ! 719: ldelin2(nodep) ! 720: NODE *nodep; ! 721: { ! 722: if(nodep == IDVAL) ! 723: return; ! 724: ! 725: if(nodep->forw != &ntail && nodep->forw->uniqid == IDVAL) ! 726: nodep->forw->uniqid = nodep->uniqid; ! 727: ! 728: nodep->uniqid = IDVAL; ! 729: ! 730: } ! 731: ! 732: ! 733: /* exchange instructions ! 734: The line number of the first instruction, if any, is given to the ! 735: second instruction. The line number of the second instruction is ! 736: deleted. */ ! 737: void ! 738: lexchin(nodep1,nodep2) ! 739: NODE *nodep1, *nodep2; ! 740: { ! 741: if(nodep1->uniqid != IDVAL) { ! 742: nodep2->uniqid = nodep1->uniqid; ! 743: nodep1->uniqid = IDVAL; ! 744: } ! 745: else { ! 746: nodep2->uniqid = IDVAL; ! 747: } ! 748: } ! 749: ! 750: ! 751: /* merge instructions - case 1 ! 752: The result instruction is given the line number of the ! 753: top instruction, if it exists, or else it is given the line ! 754: number of the bottom instruction. */ ! 755: void ! 756: lmrgin1(nodep1,nodep2,resnode) ! 757: NODE *nodep1, *nodep2, *resnode; ! 758: { ! 759: IDTYPE val1, val2; ! 760: ! 761: val1 = nodep1->uniqid; ! 762: val2 = nodep2->uniqid; ! 763: ! 764: nodep1->uniqid = nodep2->uniqid = IDVAL; ! 765: ! 766: if(val1 != IDVAL) ! 767: resnode->uniqid = val1; ! 768: else ! 769: resnode->uniqid = val2; ! 770: ! 771: } ! 772: ! 773: ! 774: /* instruction merge - case 2 ! 775: The resultant instruction is given the line number of the ! 776: top instruction, if it exists, else it is not given a line number */ ! 777: void ! 778: lmrgin2(nodep1,nodep2,resnode) ! 779: NODE *nodep1, *nodep2, *resnode; ! 780: { ! 781: IDTYPE val1; ! 782: ! 783: val1 = nodep1->uniqid; ! 784: ! 785: nodep1->uniqid = nodep2->uniqid = IDVAL; ! 786: ! 787: resnode->uniqid = val1; ! 788: ! 789: } ! 790: ! 791: /* instruction merge - case 3 ! 792: The resultant instruction is given the line number of the first ! 793: instruction, if it exists. The instruction below the pair to be ! 794: merged is given the line number of the second instruction, ! 795: if it exists */ ! 796: void ! 797: lmrgin3(nodep1,nodep2,resnode) ! 798: NODE *nodep1, *nodep2, *resnode; ! 799: { ! 800: IDTYPE val1; ! 801: ! 802: ldelin2(nodep2); ! 803: ! 804: val1 = nodep1->uniqid; ! 805: ! 806: nodep1->uniqid = nodep2->uniqid = IDVAL; ! 807: ! 808: resnode->uniqid = val1; ! 809: } ! 810: ! 811: /* isiros -- is operand either immediate, register or on stack? ! 812: ** ! 813: ** This routine returns true if the the operand ! 814: ** pointed to by its argument has address mode ! 815: ** ! 816: ** immediate, ! 817: ** register, or ! 818: ** offset from a stack pointer (fp, ap, or sp). ! 819: ** ! 820: ** This test is provided for checking operands to see whether they ! 821: ** can be memory mapped i/o references. ! 822: */ ! 823: ! 824: boolean ! 825: isiros( op ) ! 826: char *op; ! 827: { ! 828: return( *op == '&' || ! 829: *op == '%' || ! 830: ( *op != '*' && ! 831: ( usesreg( op, "%fp" ) || ! 832: usesreg( op, "%ap" ) || ! 833: usesreg( op, "%sp" ) ! 834: ) ! 835: ) ! 836: ); ! 837: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.