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: