1: // Copyright (C) 1985-1998 by Symantec
   2: // Copyright (C) 2000-2010 by Digital Mars
   3: // All Rights Reserved
   4: // http://www.digitalmars.com
   5: // Written by Walter Bright
   6: /*
   7:  * This source file is made available for personal use
   8:  * only. The license is in /dmd/src/dmd/backendlicense.txt
   9:  * or /dm/src/dmd/backendlicense.txt
  10:  * For any other uses, please contact Digital Mars.
  11:  */
  12: 
  13: 
  14: #if !SPP
  15: 
  16: #include        <stdio.h>
  17: #include        <string.h>
  18: #include        <stdlib.h>
  19: #include        <time.h>
  20: #include        "cc.h"
  21: #include        "el.h"
  22: #include        "oper.h"
  23: #include        "code.h"
  24: #include        "global.h"
  25: #include        "type.h"
  26: 
  27: static char __file__[] = __FILE__;      /* for tassert.h                */
  28: #include        "tassert.h"
  29: 
  30: STATIC void el_weights(int bi,elem *e,unsigned weight);
  31: 
  32: #ifndef __DMC__
  33: #undef __cdecl
  34: #define __cdecl
  35: #endif
  36: 
  37: static int __cdecl weight_compare(const void *e1,const void *e2);
  38: 
  39: static int nretblocks;
  40: 
  41: static vec_t regrange[REGMAX];
  42: 
  43: static int *weights;
  44: #define WEIGHTS(bi,si)  weights[bi * globsym.top + si]
  45: 
  46: /******************************************
  47:  */
  48: 
  49: void cgreg_init()
  50: {   block *b;
  51:     int bi;
  52: 
  53:     if (!config.flags4 & CFG4optimized)
warning C4806: '&' : unsafe operation: no value of type 'bool' promoted to type 'int' can equal the given constant
warning C6290: Bitwise operation on logical result: ! has higher precedence than &. Use && or (!(x & y)) instead
54: return; 55: 56: // Use calloc() instead because sometimes the alloc is too large 57: //printf("1weights: dfotop = %d, globsym.top = %d\n", dfotop, globsym.top); 58: weights = (int *) calloc(1,dfotop * globsym.top * sizeof(weights[0])); 59: assert(weights); 60: 61: nretblocks = 0; 62: for (bi = 0; bi < dfotop; bi++)
warning C4018: '<' : signed/unsigned mismatch
63: { b = dfo[bi]; 64: if (b->BC == BCret || b->BC == BCretexp) 65: nretblocks++; 66: if (b->Belem) 67: { 68: //printf("b->Bweight = x%x\n",b->Bweight); 69: el_weights(bi,b->Belem,b->Bweight); 70: } 71: } 72: memset(regrange,0,sizeof(regrange)); 73: 74: // Make adjustments to symbols we might stick in registers 75: for (int i = 0; i < globsym.top; i++) 76: { unsigned sz; 77: symbol *s = globsym.tab[i]; 78: 79: if (s->Srange) 80: s->Srange = vec_realloc(s->Srange,dfotop); 81: 82: // Determine symbols that are not candidates 83: if (!(s->Sflags & GTregcand) || 84: !s->Srange || 85: (sz = type_size(s->Stype)) == 0 || 86: (tysize(s->ty()) == -1) || 87: (I16 && sz > REGSIZE) ||
warning C4018: '>' : signed/unsigned mismatch
88: ((I32 || I64) && tyfloating(s->ty())) 89: ) 90: { 91: s->Sflags &= ~GTregcand; 92: continue; 93: } 94: 95: switch (s->Sclass) 96: { case SCparameter: 97: case SCfastpar: 98: // Do not put parameters in registers if they are not used 99: // more than twice (otherwise we have a net loss). 100: if (s->Sweight <= 2) 101: { 102: #ifdef DEBUG 103: if (debugr) 104: printf("parameter '%s' weight %d is not enough\n",s->Sident,s->Sweight); 105: #endif 106: s->Sflags &= ~GTregcand; 107: continue; 108: } 109: break; 110: } 111: 112: if (sz == 1) 113: s->Sflags |= GTbyte; 114: 115: if (!s->Slvreg) 116: s->Slvreg = vec_calloc(dfotop); 117: 118: //printf("dfotop = %d, numbits = %d\n",dfotop,vec_numbits(s->Srange)); 119: assert(vec_numbits(s->Srange) == dfotop); 120: } 121: } 122: 123: /****************************************** 124: */ 125: 126: void cgreg_term() 127: { int i; 128: Symbol *s; 129: 130: if (config.flags4 & CFG4optimized) 131: { 132: for (i = 0; i < globsym.top; i++) 133: { 134: s = globsym.tab[i]; 135: vec_free(s->Srange); 136: vec_free(s->Slvreg); 137: s->Srange = NULL; 138: s->Slvreg = NULL; 139: } 140: 141: for (i = 0; i < arraysize(regrange); i++) 142: if (regrange[i]) 143: { vec_free(regrange[i]); 144: regrange[i] = NULL; 145: } 146: 147: free(weights); 148: weights = NULL; 149: } 150: } 151: 152: /********************************* 153: */ 154: 155: void cgreg_reset() 156: { unsigned j; 157: 158: for (j = 0; j < arraysize(regrange); j++) 159: if (!regrange[j]) 160: regrange[j] = vec_calloc(dfotop); 161: else 162: vec_clear(regrange[j]); 163: } 164: 165: /******************************* 166: * Registers used in block bi. 167: */ 168: 169: void cgreg_used(unsigned bi,regm_t used) 170: { int j; 171: 172: for (j = 0; used; j++) 173: { if (used & 1) // if register j is used 174: vec_setbit(bi,regrange[j]); 175: used >>= 1; 176: } 177: } 178: 179: /************************* 180: * Run through a tree calculating symbol weights. 181: */ 182: 183: STATIC void el_weights(int bi,elem *e,unsigned weight) 184: { int op; 185: Symbol *s; 186: 187: while (1) 188: { elem_debug(e); 189: 190: op = e->Eoper; 191: if (!OTleaf(op)) 192: { 193: // This prevents variable references within common subexpressions 194: // from adding to the variable's usage count. 195: if (e->Ecount) 196: { 197: if (e->Ecomsub) 198: weight = 0; 199: else 200: e->Ecomsub = 1; 201: } 202: 203: if (OTbinary(op)) 204: { el_weights(bi,e->E2,weight); 205: if ((OTopeq(op) || OTpost(op)) && e->E1->Eoper == OPvar) 206: { 207: if (weight >= 10) 208: weight += 10; 209: else 210: weight++; 211: } 212: } 213: e = e->E1; 214: } 215: else 216: { 217: switch (op) 218: { 219: case OPvar: 220: s = e->EV.sp.Vsym; 221: if (s->Ssymnum != -1 && s->Sflags & GTregcand) 222: { 223: s->Sweight += weight; 224: //printf("adding %d weight to '%s' (block %d, Ssymnum %d), giving Sweight %d\n",weight,s->Sident,bi,s->Ssymnum,s->Sweight); 225: if (weights) 226: WEIGHTS(bi,s->Ssymnum) += weight; 227: } 228: break; 229: } 230: return; 231: } 232: } 233: } 234: 235: /***************************************** 236: * Determine 'benefit' of assigning symbol s to register reg. 237: * Benefit is roughly the number of clocks saved. 238: * A negative value means that s cannot or should not be assigned to reg. 239: */ 240: 241: int cgreg_benefit(Symbol *s,int reg, Symbol *retsym) 242: { 243: int benefit; 244: int benefit2; 245: block *b; 246: list_t bl; 247: int bi; 248: int si; 249: int gotoepilog; 250: int retsym_cnt; 251: 252: //printf("cgreg_benefit(s = '%s', reg = %d)\n", s->Sident, reg); 253: 254: vec_sub(s->Slvreg,s->Srange,regrange[reg]); 255: si = s->Ssymnum; 256: 257: Lagain: 258: //printf("again\n"); 259: benefit = 0; 260: retsym_cnt = 0; 261: 262: // Make sure we have enough uses to justify 263: // using a register we must save 264: if (fregsaved & mask[reg] & mfuncreg) 265: benefit -= 1 + nretblocks; 266: 267: foreach (bi,dfotop,s->Srange)
warning C4018: '<' : signed/unsigned mismatch
268: { int inoutp; 269: int inout; 270: 271: b = dfo[bi]; 272: switch (b->BC) 273: { 274: case BCjcatch: 275: case BCcatch: 276: case BC_except: 277: case BC_finally: 278: case BC_ret: 279: s->Sflags &= ~GTregcand; 280: goto Lcant; // can't assign to register 281: } 282: if (vec_testbit(bi,s->Slvreg)) 283: { benefit += WEIGHTS(bi,si); 284: //printf("WEIGHTS(%d,%d) = %d, benefit = %d\n",bi,si,WEIGHTS(bi,si),benefit); 285: inout = 1; 286: 287: if (s == retsym && reg == AX && b->BC == BCretexp) 288: { benefit += 1; 289: retsym_cnt++; 290: //printf("retsym, benefit = %d\n",benefit); 291: if (s->Sfl == FLreg && !vec_disjoint(s->Srange,regrange[reg])) 292: goto Lcant; // don't spill if already in register 293: } 294: } 295: else 296: inout = -1; 297: 298: // Look at predecessors to see if we need to load in/out of register 299: gotoepilog = 0; 300: L2: 301: inoutp = 0; 302: benefit2 = 0; 303: for (bl = b->Bpred; bl; bl = list_next(bl)) 304: { block *bp; 305: int bpi; 306: 307: bp = list_block(bl); 308: bpi = bp->Bdfoidx; 309: if (!vec_testbit(bpi,s->Srange)) 310: continue; 311: if (gotoepilog && bp->BC == BCgoto) 312: { 313: if (vec_testbit(bpi,s->Slvreg)) 314: { 315: if (inout == -1) 316: benefit2 -= bp->Bweight; // need to mov into mem 317: } 318: else 319: { 320: if (inout == 1) 321: benefit2 -= bp->Bweight; // need to mov into reg 322: } 323: } 324: else if (vec_testbit(bpi,s->Slvreg)) 325: { 326: switch (inoutp) 327: { 328: case 0: 329: inoutp = 1; 330: if (inout != 1) 331: { if (gotoepilog) 332: { vec_clearbit(bpi,s->Slvreg); 333: goto Lagain; 334: } 335: benefit2 -= b->Bweight; // need to mov into mem 336: } 337: break; 338: case 1: 339: break; 340: case -1: 341: if (gotoepilog == 0) 342: { gotoepilog = 1; 343: goto L2; 344: } 345: vec_clearbit(bpi,s->Slvreg); 346: goto Lagain; 347: } 348: } 349: else 350: { 351: switch (inoutp) 352: { 353: case 0: 354: inoutp = -1; 355: if (inout != -1) 356: { if (gotoepilog) 357: { vec_clearbit(bi,s->Slvreg); 358: goto Lagain; 359: } 360: benefit2 -= b->Bweight; // need to mov into reg 361: } 362: break; 363: case 1: 364: if (gotoepilog == 0) 365: { gotoepilog = 1; 366: goto L2; 367: } 368: if (inout == 1) 369: { vec_clearbit(bi,s->Slvreg); 370: goto Lagain; 371: } 372: goto Lcant; 373: case -1: 374: break; 375: } 376: } 377: } 378: //printf("benefit2 = %d\n", benefit2); 379: benefit += benefit2; 380: } 381: 382: #ifdef DEBUG 383: //printf("2weights: dfotop = %d, globsym.top = %d\n", dfotop, globsym.top); 384: if (benefit > s->Sweight + retsym_cnt) 385: printf("s = '%s', benefit = %d, Sweight = %d, retsym_cnt = x%x\n",s->Sident,benefit,s->Sweight, retsym_cnt); 386: #endif 387: assert(benefit <= s->Sweight + retsym_cnt); 388: return benefit; 389: 390: Lcant: 391: return -1; // can't assign to reg 392: } 393: 394: /********************************************* 395: * Determine if block gets symbol loaded by predecessor epilog (1), 396: * or by prolog (0). 397: */ 398: 399: int cgreg_gotoepilog(block *b,Symbol *s) 400: { 401: list_t bl; 402: int bi; 403: int gotoepilog; 404: int inoutp; 405: int inout; 406: 407: bi = b->Bdfoidx; 408: 409: if (vec_testbit(bi,s->Slvreg)) 410: inout = 1; 411: else 412: inout = -1; 413: 414: // Look at predecessors to see if we need to load in/out of register 415: gotoepilog = 0; 416: inoutp = 0; 417: for (bl = b->Bpred; bl; bl = list_next(bl)) 418: { block *bp; 419: int bpi; 420: 421: bp = list_block(bl); 422: bpi = bp->Bdfoidx; 423: if (!vec_testbit(bpi,s->Srange)) 424: continue; 425: if (vec_testbit(bpi,s->Slvreg)) 426: { 427: switch (inoutp) 428: { 429: case 0: 430: inoutp = 1; 431: if (inout != 1) 432: { if (gotoepilog) 433: goto Lcant; 434: } 435: break; 436: case 1: 437: break; 438: case -1: 439: if (gotoepilog == 0) 440: { gotoepilog = 1; 441: goto Lret; 442: } 443: goto Lcant; 444: } 445: } 446: else 447: { 448: switch (inoutp) 449: { 450: case 0: 451: inoutp = -1; 452: if (inout != -1) 453: { if (gotoepilog) 454: goto Lcant; 455: } 456: break; 457: case 1: 458: if (gotoepilog == 0) 459: { gotoepilog = 1; 460: goto Lret; 461: } 462: goto Lcant; 463: case -1: 464: break; 465: } 466: } 467: } 468: Lret: 469: return gotoepilog; 470: 471: Lcant: 472: assert(0); 473: return -1; // can't assign to reg 474: } 475: 476: /********************************** 477: * Determine block prolog code - it's either 478: * assignments to register, or storing register back in memory. 479: */ 480: 481: void cgreg_spillreg_prolog(block *b,Symbol *s,code **pcstore,code **pcload) 482: { 483: list_t bl; 484: code *cload; 485: code *cstore; 486: code *c; 487: code cs; 488: int inoutp; 489: int sz; 490: elem *e; 491: regm_t keepmsk; 492: int bi; 493: 494: e = NULL; 495: cstore = *pcstore; 496: cload = *pcload; 497: bi = b->Bdfoidx; 498: sz = type_size(s->Stype); 499: 500: //printf("cgreg_spillreg_prolog(block %d, s = '%s')\n",bi,s->Sident); 501: 502: if (vec_testbit(bi,s->Slvreg)) 503: { inoutp = 1; 504: // If it's startblock, and it's a spilled parameter, we 505: // need to load it 506: if (s->Sflags & SFLspill && bi == 0 && 507: (s->Sclass == SCparameter || s->Sclass == SCfastpar)) 508: { 509: goto Lload; 510: } 511: } 512: else 513: inoutp = -1; 514: 515: if (cgreg_gotoepilog(b,s)) 516: return; 517: 518: // Look at predecessors to see if we need to load in/out of register 519: for (bl = b->Bpred; bl; bl = list_next(bl)) 520: { block *bp; 521: int bpi; 522: 523: bp = list_block(bl); 524: bpi = bp->Bdfoidx; 525: if (!vec_testbit(bpi,s->Srange)) 526: continue; 527: // if (bp->BC == BCgoto) 528: // continue; // already taken care of 529: if (vec_testbit(bpi,s->Slvreg)) 530: { 531: if (inoutp == -1) 532: { // MOV mem[ESP],reg 533: cs.Iop = 0x89; 534: keepmsk = RMstore; 535: #ifdef DEBUG 536: if (debugr) 537: printf("B%d: prolog moving %s into '%s'\n",bi,regstring[s->Sreglsw],s->Sident); 538: #endif 539: } 540: else 541: continue; 542: } 543: else 544: { 545: if (inoutp == 1) 546: { 547: Lload: 548: // MOV reg,mem[ESP] 549: cs.Iop = 0x8B; 550: keepmsk = RMload; 551: #ifdef DEBUG 552: if (debugr) 553: { if (sz > REGSIZE) 554: printf("B%d: prolog moving '%s' into %s:%s\n",bi,s->Sident,regstring[s->Sregmsw],regstring[s->Sreglsw]); 555: else 556: printf("B%d: prolog moving '%s' into %s\n",bi,s->Sident,regstring[s->Sreglsw]); 557: } 558: #endif 559: } 560: else 561: continue; 562: } 563: if (!e) 564: e = el_var(s); // so we can trick getlvalue() into 565: // working for us 566: cs.Iop ^= (sz == 1); 567: c = getlvalue(&cs,e,keepmsk); 568: cs.orReg(s->Sreglsw); 569: if (I64 && sz == 1 && s->Sreglsw >= 4) 570: cs.Irex |= REX; 571: c = gen(c,&cs); 572: if (sz > REGSIZE) 573: { 574: cs.setReg(s->Sregmsw); 575: getlvalue_msw(&cs); 576: c = gen(c,&cs); 577: } 578: if (inoutp == -1) 579: cstore = cat(cstore,c); 580: else 581: cload = cat(cload,c); 582: break; 583: } 584: el_free(e); 585: 586: // Store old register values before loading in new ones 587: *pcstore = cstore; 588: *pcload = cload; 589: } 590: 591: /********************************** 592: * Determine block epilog code - it's either 593: * assignments to register, or storing register back in memory. 594: */ 595: 596: void cgreg_spillreg_epilog(block *b,Symbol *s,code **pcstore,code **pcload) 597: { 598: list_t bl; 599: code *cload; 600: code *cstore; 601: code *c; 602: code cs; 603: int inoutp; 604: int sz; 605: elem *e; 606: regm_t keepmsk; 607: int bi; 608: 609: e = NULL; 610: cstore = *pcstore; 611: cload = *pcload; 612: bi = b->Bdfoidx; 613: sz = type_size(s->Stype); 614: 615: //printf("cgreg_spillreg_epilog(block %d, s = '%s')\n",bi,s->Sident); 616: //assert(b->BC == BCgoto); 617: if (!cgreg_gotoepilog(list_block(b->Bsucc),s)) 618: return; 619: 620: if (vec_testbit(bi,s->Slvreg)) 621: inoutp = 1; 622: else 623: inoutp = -1; 624: 625: // Look at successors to see if we need to load in/out of register 626: for (bl = b->Bsucc; bl; bl = list_next(bl)) 627: { block *bp; 628: int bpi; 629: 630: bp = list_block(bl); 631: bpi = bp->Bdfoidx; 632: if (!vec_testbit(bpi,s->Srange)) 633: continue; 634: if (vec_testbit(bpi,s->Slvreg)) 635: { 636: if (inoutp == -1) 637: { 638: // MOV reg,mem[ESP] 639: cs.Iop = 0x8B; 640: keepmsk = RMload; 641: #ifdef DEBUG 642: if (debugr) 643: printf("B%d: epilog moving '%s' into %s\n",bi,s->Sident,regstring[s->Sreglsw]); 644: #endif 645: } 646: else 647: continue; 648: } 649: else 650: { 651: if (inoutp == 1) 652: { // MOV mem[ESP],reg 653: cs.Iop = 0x89; 654: keepmsk = RMstore; 655: #ifdef DEBUG 656: if (debugr) 657: printf("B%d: epilog moving %s into '%s'\n",bi,regstring[s->Sreglsw],s->Sident); 658: #endif 659: } 660: else 661: continue; 662: } 663: if (!e) 664: e = el_var(s); // so we can trick getlvalue() into 665: // working for us 666: cs.Iop ^= (sz == 1); 667: c = getlvalue(&cs,e,keepmsk); 668: cs.orReg(s->Sreglsw); 669: if (I64 && sz == 1 && s->Sreglsw >= 4) 670: cs.Irex |= REX; 671: c = gen(c,&cs); 672: if (sz > REGSIZE) 673: { 674: cs.setReg(s->Sregmsw); 675: getlvalue_msw(&cs); 676: c = gen(c,&cs); 677: } 678: if (inoutp == 1) 679: cstore = cat(cstore,c); 680: else 681: cload = cat(cload,c); 682: break; 683: } 684: el_free(e); 685: 686: // Store old register values before loading in new ones 687: *pcstore = cstore; 688: *pcload = cload; 689: } 690: 691: /*************************** 692: * Map symbol s into registers [NOREG,reglsw] or [regmsw, reglsw]. 693: */ 694: 695: void cgreg_map(Symbol *s, unsigned regmsw, unsigned reglsw) 696: { 697: assert(I64 || reglsw < 8); 698: 699: if (vec_disjoint(s->Srange,regrange[reglsw]) &&
warning C6385: Invalid data: accessing 'regrange', the readable size is '116' bytes, but '128' bytes might be read: Lines: 697, 699
700: (regmsw == NOREG || vec_disjoint(s->Srange,regrange[regmsw])) 701: ) 702: { 703: s->Sfl = FLreg; 704: vec_copy(s->Slvreg,s->Srange); 705: } 706: else 707: { 708: s->Sflags |= SFLspill; 709: 710: // Already computed by cgreg_benefit() 711: //vec_sub(s->Slvreg,s->Srange,regrange[reglsw]); 712: 713: if (s->Sfl == FLreg) // if reassigned 714: { 715: switch (s->Sclass) 716: { 717: case SCauto: 718: case SCregister: 719: case SCtmp: 720: case SCfastpar: 721: s->Sfl = FLauto; 722: break; 723: case SCbprel: 724: s->Sfl = FLbprel; 725: break; 726: case SCparameter: 727: s->Sfl = FLpara; 728: break; 729: #if PSEUDO_REGS 730: case SCpseudo: 731: s->Sfl = FLpseudo; 732: break; 733: #endif 734: case SCstack: 735: s->Sfl = FLstack; 736: break; 737: default: 738: #ifdef DEBUG 739: symbol_print(s); 740: #endif 741: assert(0); 742: } 743: } 744: } 745: s->Sreglsw = reglsw; 746: s->Sregm = mask[reglsw]; 747: mfuncreg &= ~mask[reglsw]; 748: if (regmsw != NOREG) 749: vec_subass(s->Slvreg,regrange[regmsw]); 750: vec_orass(regrange[reglsw],s->Slvreg); 751: 752: if (regmsw == NOREG) 753: { 754: #if DEBUG 755: if (debugr) 756: { 757: printf("symbol '%s' %s in register %s\n ", 758: s->Sident, 759: (s->Sflags & SFLspill) ? "spilled" : "put", 760: regstring[reglsw]); 761: vec_println(s->Slvreg); 762: } 763: #endif 764: } 765: else 766: { 767: assert(regmsw < 8); 768: s->Sregmsw = regmsw; 769: s->Sregm |= mask[regmsw]; 770: mfuncreg &= ~mask[regmsw]; 771: vec_orass(regrange[regmsw],s->Slvreg); 772: 773: #if DEBUG 774: if (debugr) 775: printf("symbol '%s' %s in register pair %s\n", 776: s->Sident, 777: (s->Sflags & SFLspill) ? "spilled" : "put", 778: regm_str(s->Sregm)); 779: #endif 780: } 781: } 782: 783: /******************************************** 784: * The register variables in this mask can not be in registers. 785: * "Unregister" them. 786: */ 787: 788: void cgreg_unregister(regm_t conflict) 789: { 790: if (pass == PASSfinal) 791: pass = PASSreg; // have to codegen at least one more time 792: for (int i = 0; i < globsym.top; i++) 793: { symbol *s = globsym.tab[i]; 794: if (s->Sfl == FLreg && s->Sregm & conflict) 795: { 796: s->Sflags |= GTunregister; 797: } 798: } 799: } 800: 801: /****************************************** 802: * Do register assignments. 803: * Returns: 804: * !=0 redo code generation 805: * 0 no more register assignments 806: */ 807: 808: struct Reg // data for trial register assignment 809: { 810: Symbol *sym; 811: int reglsw; 812: int regmsw; 813: int benefit; 814: }; 815: 816: int cgreg_assign(Symbol *retsym) 817: { 818: Reg t; 819: vec_t v; 820: 821: int si; 822: int flag = FALSE; 823: 824: /* First do any 'unregistering' which might have happened in the last 825: * code gen pass. 826: */ 827: for (si = 0; si < globsym.top; si++) 828: { symbol *s = globsym.tab[si]; 829: 830: if (s->Sflags & GTunregister) 831: { 832: #if DEBUG 833: if (debugr) 834: { 835: printf("symbol '%s' %s register %s\n ", 836: s->Sident, 837: (s->Sflags & SFLspill) ? "unspilled" : "unregistered", 838: regstring[s->Sreglsw]); 839: vec_println(s->Slvreg); 840: } 841: #endif 842: flag = TRUE; 843: s->Sflags &= ~(GTregcand | GTunregister | SFLspill); 844: if (s->Sfl == FLreg) 845: { 846: switch (s->Sclass) 847: { 848: case SCauto: 849: case SCregister: 850: case SCtmp: 851: case SCfastpar: 852: s->Sfl = FLauto; 853: break; 854: case SCbprel: 855: s->Sfl = FLbprel; 856: break; 857: case SCparameter: 858: s->Sfl = FLpara; 859: break; 860: #if PSEUDO_REGS 861: case SCpseudo: 862: s->Sfl = FLpseudo; 863: break; 864: #endif 865: case SCstack: 866: s->Sfl = FLstack; 867: break; 868: default: 869: #ifdef DEBUG 870: symbol_print(s); 871: #endif 872: assert(0); 873: } 874: } 875: } 876: } 877: 878: v = vec_calloc(dfotop); 879: 880: // Find symbol t, which is the most 'deserving' symbol that should be 881: // placed into a register. 882: t.sym = NULL; 883: t.benefit = 0; 884: for (si = 0; si < globsym.top; si++) 885: { symbol *s = globsym.tab[si]; 886: Reg u; 887: unsigned reg; 888: tym_t ty; 889: unsigned sz; 890: 891: 892: u.sym = s; 893: if (!(s->Sflags & GTregcand) || 894: s->Sflags & SFLspill || 895: // Keep trying to reassign retsym into AX 896: (s->Sfl == FLreg && !(s == retsym && s->Sregm != mAX)) 897: ) 898: { 899: #ifdef DEBUG 900: if (debugr) 901: if (s->Sfl == FLreg) 902: printf("symbol '%s' is in reg %s\n",s->Sident,regm_str(s->Sregm)); 903: else if (s->Sflags & SFLspill) 904: printf("symbol '%s' spilled in reg %s\n",s->Sident,regm_str(s->Sregm)); 905: else 906: printf("symbol '%s' is not a candidate\n",s->Sident); 907: #endif 908: continue; 909: } 910: 911: char *pseq; 912: char *pseqmsw = NULL; 913: 914: ty = s->ty(); 915: sz = tysize(ty); 916: 917: #ifdef DEBUG 918: if (debugr) 919: { printf("symbol '%3s', ty x%x weight x%x sz %d\n ", 920: s->Sident,ty,s->Sweight,(int)sz); 921: vec_println(s->Srange); 922: } 923: #endif 924: 925: if (I64) 926: { 927: if (sz == REGSIZE * 2) 928: { 929: static char seqmsw[] = {CX,DX,NOREG}; 930: static char seqlsw[] = {AX,BX,SI,DI,NOREG}; 931: pseq = seqlsw; 932: pseqmsw = seqmsw; 933: } 934: else 935: { // R10 is reserved for the static link 936: static char sequence[] = {AX,CX,DX,SI,DI,R8,R9,R11,BX,R12,R13,R14,R15,BP,NOREG}; 937: pseq = sequence; 938: } 939: } 940: else if (I32) 941: { 942: if (sz == REGSIZE * 2) 943: { 944: static char seqlsw[] = {AX,BX,SI,DI,NOREG}; 945: static char seqmsw[] = {CX,DX,NOREG}; 946: pseq = seqlsw; 947: pseqmsw = seqmsw; 948: } 949: else 950: { 951: static char sequence[] = {AX,CX,DX,BX,SI,DI,BP,NOREG}; 952: pseq = sequence; 953: } 954: } 955: else 956: { assert(I16); 957: if (typtr(ty)) 958: { 959: // For pointer types, try to pick index register first 960: static char seqidx[] = {BX,SI,DI,AX,CX,DX,BP,NOREG}; 961: pseq = seqidx; 962: } 963: else 964: { 965: // Otherwise, try to pick index registers last 966: static char sequence[] = {AX,CX,DX,BX,SI,DI,BP,NOREG}; 967: pseq = sequence; 968: } 969: } 970: 971: u.benefit = 0; 972: for (int i = 0; pseq[i] != NOREG; i++) 973: { int benefit; 974: 975: reg = pseq[i]; 976: 977: if (reg != AX && s == retsym) 978: continue; 979: if (reg == BP && !(allregs & mBP)) 980: continue; 981: #if 0 && TARGET_LINUX 982: // Need EBX for static pointer 983: if (reg == BX && !(allregs & mBX)) 984: continue; 985: #endif 986: 987: if (s->Sflags & GTbyte && 988: !(mask[reg] & BYTEREGS)) 989: continue; 990: 991: benefit = cgreg_benefit(s,reg,retsym); 992: 993: #ifdef DEBUG 994: if (debugr) 995: { printf(" %s",regstring[reg]); 996: vec_print(regrange[reg]); 997: printf(" %d\n",benefit); 998: } 999: #endif 1000: 1001: if (benefit > u.benefit) 1002: { // successful assigning of lsw 1003: unsigned regmsw = NOREG; 1004: 1005: // Now assign in MSW 1006: if (sz > REGSIZE && sz <= 2 * REGSIZE)
warning C4018: '>' : signed/unsigned mismatch
warning C4018: '<=' : signed/unsigned mismatch
1007: { unsigned regj; 1008: 1009: for (regj = 0; 1; regj++) 1010: { 1011: regmsw = pseqmsw[regj]; 1012: if (regmsw == NOREG) 1013: goto Ltried; 1014: if (regmsw == reg) 1015: continue; 1016: #ifdef DEBUG 1017: if (debugr) 1018: { printf(".%s",regstring[regmsw]); 1019: vec_println(regrange[regmsw]); 1020: } 1021: #endif 1022: if (vec_disjoint(s->Slvreg,regrange[regmsw])) 1023: break; 1024: } 1025: } 1026: vec_copy(v,s->Slvreg); 1027: u.benefit = benefit; 1028: u.reglsw = reg; 1029: u.regmsw = regmsw; 1030: } 1031: Ltried: ; 1032: } 1033: 1034: if (u.benefit > t.benefit) 1035: { t = u; 1036: vec_copy(t.sym->Slvreg,v); 1037: } 1038: } 1039: 1040: if (t.sym && t.benefit > 0) 1041: { 1042: cgreg_map(t.sym,t.regmsw,t.reglsw); 1043: flag = TRUE; 1044: } 1045: 1046: // See if any registers have become available that we can use. 1047: if ((I32 || I64) && !flag && (mfuncreg & ~fregsaved) & ALLREGS && 1048: !(funcsym_p->Sflags & SFLexit)) 1049: { 1050: for (int i = 0; i < globsym.top; i++) 1051: { symbol *s; 1052: 1053: s = globsym.tab[i]; 1054: if (s->Sfl == FLreg && mask[s->Sreglsw] & fregsaved && 1055: type_size(s->Stype) <= REGSIZE)
warning C4018: '<=' : signed/unsigned mismatch
1056: { 1057: s->Sreglsw = findreg((mfuncreg & ~fregsaved) & ALLREGS); 1058: s->Sregm = mask[s->Sreglsw]; 1059: flag = TRUE; 1060: #ifdef DEBUG 1061: if (debugr) 1062: printf("re-assigned '%s' to %s\n",s->Sident,regstring[s->Sreglsw]); 1063: #endif 1064: break; 1065: } 1066: } 1067: } 1068: vec_free(v); 1069: 1070: return flag; 1071: } 1072: 1073: ////////////////////////////////////// 1074: // Qsort() comparison routine for array of pointers to Symbol's. 1075: 1076: static int __cdecl weight_compare(const void *e1,const void *e2) 1077: { Symbol **psp1; 1078: Symbol **psp2; 1079: 1080: psp1 = (Symbol **)e1; 1081: psp2 = (Symbol **)e2; 1082: 1083: return (*psp2)->Sweight - (*psp1)->Sweight; 1084: } 1085: 1086: 1087: #endif 1088: