1 /* src/vm/jit/allocator/simplereg.c - register allocator
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
35 $Id: simplereg.c 4921 2006-05-15 14:24:36Z twisti $
48 #include "vm/builtin.h"
49 #include "vm/exceptions.h"
50 #include "mm/memory.h"
51 #include "vm/method.h"
52 #include "vm/options.h"
53 #include "vm/resolve.h"
54 #include "vm/stringlocal.h"
55 #include "vm/jit/reg.h"
56 #include "vm/jit/allocator/simplereg.h"
59 /* function prototypes for this file ******************************************/
61 static void interface_regalloc(jitdata *jd);
62 static void local_regalloc(jitdata *jd);
63 static void allocate_scratch_registers(jitdata *jd);
66 /* regalloc ********************************************************************
68 Does a simple register allocation.
70 *******************************************************************************/
72 bool regalloc(jitdata *jd)
74 /* There is a problem with the use of unused float argument
75 registers in leafmethods for stackslots on c7 (2 * Dual Core
76 AMD Opteron(tm) Processor 270) - runtime for the jvm98 _mtrt
77 benchmark is heaviliy increased. This could be prevented by
78 setting rd->argfltreguse to FLT_ARG_CNT before calling
79 allocate_scratch_registers and setting it back to the original
80 value before calling local_regalloc. */
82 interface_regalloc(jd);
83 allocate_scratch_registers(jd);
92 /* interface_regalloc **********************************************************
94 Allocates registers for all interface variables.
96 *******************************************************************************/
98 static void interface_regalloc(jitdata *jd)
105 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
106 /* in case a more vars are packed into this interface slot */
108 int intregsneeded = 0;
110 /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
111 /* on HAS_4BYTE_STACKSLOT architectures */
112 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
114 /* get required compiler data */
120 /* rd->memuse was already set in stack.c to allocate stack space
121 for passing arguments to called methods. */
123 #if defined(__I386__)
124 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
125 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
131 if (m->isleafmethod) {
132 /* Reserve argument register, which will be used for Locals acting */
134 if (rd->argintreguse < m->parseddesc->argintreguse)
135 rd->argintreguse = m->parseddesc->argintreguse;
136 if (rd->argfltreguse < m->parseddesc->argfltreguse)
137 rd->argfltreguse = m->parseddesc->argfltreguse;
138 #ifdef HAS_ADDRESS_REGISTER_FILE
139 if (rd->argadrreguse < m->parseddesc->argadrreguse)
140 rd->argadrreguse = m->parseddesc->argadrreguse;
145 for (s = 0; s < cd->maxstack; s++) {
146 intalloc = -1; fltalloc = -1;
147 saved = (rd->interfaces[s][TYPE_INT].flags |
148 rd->interfaces[s][TYPE_LNG].flags |
149 rd->interfaces[s][TYPE_FLT].flags |
150 rd->interfaces[s][TYPE_DBL].flags |
151 rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
153 for (tt = 0; tt <= 4; tt++) {
155 v = &rd->interfaces[s][t];
157 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
158 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
160 #if defined(HAS_4BYTE_STACKSLOT)
161 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
164 #if defined(HAS_ADDRESS_REGISTER_FILE)
165 if (IS_ADR_TYPE(t)) {
167 &&(rd->argadrreguse < ADR_ARG_CNT)) {
168 v->regoff = rd->argadrregs[rd->argadrreguse++];
169 } else if (rd->tmpadrreguse > 0) {
170 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
171 } else if (rd->savadrreguse > 0) {
172 v->regoff = rd->savadrregs[--rd->savadrreguse];
174 v->flags |= INMEMORY;
175 v->regoff = rd->memuse++;
177 } else /* !IS_ADR_TYPE */
178 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
180 if (IS_FLT_DBL_TYPE(t)) {
182 /* Reuse memory slot(s)/register(s) for shared interface slots */
183 v->flags |= rd->interfaces[s][fltalloc].flags
185 v->regoff = rd->interfaces[s][fltalloc].regoff;
186 } else if (rd->argfltreguse < FLT_ARG_CNT) {
187 v->regoff = rd->argfltregs[rd->argfltreguse++];
188 } else if (rd->tmpfltreguse > 0) {
189 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
190 } else if (rd->savfltreguse > 0) {
191 v->regoff = rd->savfltregs[--rd->savfltreguse];
193 v->flags |= INMEMORY;
194 #if defined(ALIGN_DOUBLES_IN_MEMORY)
195 /* Align doubles in Memory */
196 if ( (memneeded) && (rd->memuse & 1))
199 v->regoff = rd->memuse;
200 rd->memuse += memneeded + 1;
203 } else { /* !IS_FLT_DBL_TYPE(t) */
204 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
206 * for i386 put all longs in memory
208 if (IS_2_WORD_TYPE(t)) {
209 v->flags |= INMEMORY;
210 #if defined(ALIGN_LONGS_IN_MEMORY)
211 /* Align longs in Memory */
215 v->regoff = rd->memuse;
216 rd->memuse += memneeded + 1;
218 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
220 /* Reuse memory slot(s)/register(s) for shared interface slots */
222 rd->interfaces[s][intalloc].flags
224 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
225 if (!(v->flags & INMEMORY)
226 && IS_2_WORD_TYPE(intalloc))
227 v->regoff = GET_LOW_REG(
228 rd->interfaces[s][intalloc].regoff);
232 rd->interfaces[s][intalloc].regoff;
234 if (rd->argintreguse + intregsneeded
236 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
239 rd->argintregs[rd->argintreguse],
240 rd->argintregs[rd->argintreguse + 1]);
244 rd->argintregs[rd->argintreguse];
245 rd->argintreguse += intregsneeded + 1;
247 else if (rd->tmpintreguse > intregsneeded) {
248 rd->tmpintreguse -= intregsneeded + 1;
249 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
252 rd->tmpintregs[rd->tmpintreguse],
253 rd->tmpintregs[rd->tmpintreguse + 1]);
257 rd->tmpintregs[rd->tmpintreguse];
259 else if (rd->savintreguse > intregsneeded) {
260 rd->savintreguse -= intregsneeded + 1;
262 rd->savintregs[rd->savintreguse];
263 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
266 rd->savintregs[rd->savintreguse],
267 rd->savintregs[rd->savintreguse + 1]);
271 rd->savintregs[rd->savintreguse];
274 v->flags |= INMEMORY;
275 #if defined(ALIGN_LONGS_IN_MEMORY)
276 /* Align longs in Memory */
277 if ( (memneeded) && (rd->memuse & 1))
280 v->regoff = rd->memuse;
281 rd->memuse += memneeded + 1;
285 } /* if (IS_FLT_DBL_TYPE(t)) */
287 } else { /* (saved) */
288 /* now the same like above, but without a chance to take a temporary register */
289 #ifdef HAS_ADDRESS_REGISTER_FILE
290 if (IS_ADR_TYPE(t)) {
291 if (rd->savadrreguse > 0) {
292 v->regoff = rd->savadrregs[--rd->savadrreguse];
295 v->flags |= INMEMORY;
296 v->regoff = rd->memuse++;
301 if (IS_FLT_DBL_TYPE(t)) {
303 v->flags |= rd->interfaces[s][fltalloc].flags
305 v->regoff = rd->interfaces[s][fltalloc].regoff;
307 if (rd->savfltreguse > 0) {
308 v->regoff = rd->savfltregs[--rd->savfltreguse];
311 v->flags |= INMEMORY;
312 #if defined(ALIGN_DOUBLES_IN_MEMORY)
313 /* Align doubles in Memory */
314 if ( (memneeded) && (rd->memuse & 1))
317 v->regoff = rd->memuse;
318 rd->memuse += memneeded + 1;
322 else { /* IS_INT_LNG */
323 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
325 * for i386 put all longs in memory
327 if (IS_2_WORD_TYPE(t)) {
328 v->flags |= INMEMORY;
329 #if defined(ALIGN_LONGS_IN_MEMORY)
330 /* Align longs in Memory */
334 v->regoff = rd->memuse;
335 rd->memuse += memneeded + 1;
341 rd->interfaces[s][intalloc].flags & INMEMORY;
342 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
343 if (!(v->flags & INMEMORY)
344 && IS_2_WORD_TYPE(intalloc))
347 rd->interfaces[s][intalloc].regoff);
351 rd->interfaces[s][intalloc].regoff;
353 if (rd->savintreguse > intregsneeded) {
354 rd->savintreguse -= intregsneeded + 1;
355 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
357 v->regoff = PACK_REGS(
358 rd->savintregs[rd->savintreguse],
359 rd->savintregs[rd->savintreguse + 1]);
363 rd->savintregs[rd->savintreguse];
365 v->flags |= INMEMORY;
366 #if defined(ALIGN_LONGS_IN_MEMORY)
367 /* Align longs in Memory */
368 if ( (memneeded) && (rd->memuse & 1))
371 v->regoff = rd->memuse;
372 rd->memuse += memneeded + 1;
377 } /* if (IS_FLT_DBL_TYPE(t) else */
378 } /* if (IS_ADR_TYPE(t)) else */
379 } /* if (saved) else */
380 } /* if (type >= 0) */
386 /* local_regalloc **************************************************************
388 Allocates registers for all local variables.
390 *******************************************************************************/
392 static void local_regalloc(jitdata *jd)
399 int intalloc, fltalloc;
401 int intregsneeded = 0;
403 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
404 int fargcnt, iargcnt;
405 #ifdef HAS_ADDRESS_REGISTER_FILE
409 /* get required compiler data */
415 if (m->isleafmethod) {
416 methoddesc *md = m->parseddesc;
418 iargcnt = rd->argintreguse;
419 fargcnt = rd->argfltreguse;
420 #ifdef HAS_ADDRESS_REGISTER_FILE
421 aargcnt = rd->argadrreguse;
423 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
424 intalloc = -1; fltalloc = -1;
425 for (tt = 0; tt <= 4; tt++) {
427 v = &rd->locals[s][t];
432 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
433 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
435 #if defined(HAS_4BYTE_STACKSLOT)
436 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
442 * #ifdef HAS_ADDRESS_REGISTER_FILE
449 * } else { / int & lng
453 * must not to be changed!
456 #ifdef HAS_ADDRESS_REGISTER_FILE
457 if (IS_ADR_TYPE(t)) {
458 if ((p < md->paramcount) && !md->params[p].inmemory) {
460 v->regoff = rd->argadrregs[md->params[p].regoff];
462 else if (rd->tmpadrreguse > 0) {
464 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
466 /* use unused argument registers as local registers */
467 else if ((p >= md->paramcount) &&
468 (aargcnt < ADR_ARG_CNT)) {
470 v->regoff = rd->argadrregs[aargcnt++];
472 else if (rd->savadrreguse > 0) {
474 v->regoff = rd->savadrregs[--rd->savadrreguse];
477 v->flags |= INMEMORY;
478 v->regoff = rd->memuse++;
482 if (IS_FLT_DBL_TYPE(t)) {
484 v->flags = rd->locals[s][fltalloc].flags;
485 v->regoff = rd->locals[s][fltalloc].regoff;
487 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
488 /* We can only use float arguments as local variables,
489 * if we do not pass them in integer registers. */
490 else if ((p < md->paramcount) &&
491 !md->params[p].inmemory) {
493 v->regoff = rd->argfltregs[md->params[p].regoff];
496 else if (rd->tmpfltreguse > 0) {
498 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
500 /* use unused argument registers as local registers */
501 else if ((p >= md->paramcount) &&
502 (fargcnt < FLT_ARG_CNT)) {
504 v->regoff = rd->argfltregs[fargcnt];
507 else if (rd->savfltreguse > 0) {
509 v->regoff = rd->savfltregs[--rd->savfltreguse];
513 #if defined(ALIGN_DOUBLES_IN_MEMORY)
514 /* Align doubles in Memory */
515 if ( (memneeded) && (rd->memuse & 1))
518 v->regoff = rd->memuse;
519 rd->memuse += memneeded + 1;
524 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
526 * for i386 put all longs in memory
528 if (IS_2_WORD_TYPE(t)) {
530 #if defined(ALIGN_LONGS_IN_MEMORY)
531 /* Align longs in Memory */
535 v->regoff = rd->memuse;
536 rd->memuse += memneeded + 1;
541 v->flags = rd->locals[s][intalloc].flags;
542 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
543 if (!(v->flags & INMEMORY)
544 && IS_2_WORD_TYPE(intalloc))
545 v->regoff = GET_LOW_REG(
546 rd->locals[s][intalloc].regoff);
549 v->regoff = rd->locals[s][intalloc].regoff;
551 else if ((p < md->paramcount) &&
552 !md->params[p].inmemory) {
554 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
555 if (IS_2_WORD_TYPE(t))
556 v->regoff = PACK_REGS(
557 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
558 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
562 rd->argintregs[md->params[p].regoff];
564 else if (rd->tmpintreguse > intregsneeded) {
565 rd->tmpintreguse -= intregsneeded + 1;
567 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
569 v->regoff = PACK_REGS(
570 rd->tmpintregs[rd->tmpintreguse],
571 rd->tmpintregs[rd->tmpintreguse + 1]);
575 rd->tmpintregs[rd->tmpintreguse];
578 * use unused argument registers as local registers
580 else if ((p >= m->parseddesc->paramcount) &&
581 (iargcnt + intregsneeded < INT_ARG_CNT)) {
583 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
586 rd->argintregs[iargcnt],
587 rd->argintregs[iargcnt + 1]);
590 v->regoff = rd->argintregs[iargcnt];
591 iargcnt += intregsneeded + 1;
593 else if (rd->savintreguse > intregsneeded) {
594 rd->savintreguse -= intregsneeded + 1;
596 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
598 v->regoff = PACK_REGS(
599 rd->savintregs[rd->savintreguse],
600 rd->savintregs[rd->savintreguse + 1]);
603 v->regoff =rd->savintregs[rd->savintreguse];
607 #if defined(ALIGN_LONGS_IN_MEMORY)
608 /* Align longs in Memory */
609 if ( (memneeded) && (rd->memuse & 1))
612 v->regoff = rd->memuse;
613 rd->memuse += memneeded + 1;
618 #ifdef HAS_ADDRESS_REGISTER_FILE
621 } /* for (tt=0;...) */
623 /* If the current parameter is a 2-word type, the next local slot */
626 if (p < md->paramcount)
627 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
633 for (s = 0; s < cd->maxlocals; s++) {
634 intalloc = -1; fltalloc = -1;
635 for (tt=0; tt<=4; tt++) {
637 v = &rd->locals[s][t];
640 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
641 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
643 #if defined(HAS_4BYTE_STACKSLOT)
644 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
646 #ifdef HAS_ADDRESS_REGISTER_FILE
647 if ( IS_ADR_TYPE(t) ) {
648 if (rd->savadrreguse > 0) {
650 v->regoff = rd->savadrregs[--rd->savadrreguse];
654 v->regoff = rd->memuse++;
658 if (IS_FLT_DBL_TYPE(t)) {
660 v->flags = rd->locals[s][fltalloc].flags;
661 v->regoff = rd->locals[s][fltalloc].regoff;
663 else if (rd->savfltreguse > 0) {
665 v->regoff = rd->savfltregs[--rd->savfltreguse];
669 #if defined(ALIGN_DOUBLES_IN_MEMORY)
670 /* Align doubles in Memory */
671 if ( (memneeded) && (rd->memuse & 1))
674 v->regoff = rd->memuse;
675 rd->memuse += memneeded + 1;
680 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
682 * for i386 put all longs in memory
684 if (IS_2_WORD_TYPE(t)) {
686 #if defined(ALIGN_LONGS_IN_MEMORY)
687 /* Align longs in Memory */
691 v->regoff = rd->memuse;
692 rd->memuse += memneeded + 1;
696 v->flags = rd->locals[s][intalloc].flags;
697 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
698 if (!(v->flags & INMEMORY)
699 && IS_2_WORD_TYPE(intalloc))
700 v->regoff = GET_LOW_REG(
701 rd->locals[s][intalloc].regoff);
704 v->regoff = rd->locals[s][intalloc].regoff;
706 else if (rd->savintreguse > intregsneeded) {
707 rd->savintreguse -= intregsneeded+1;
709 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
711 v->regoff = PACK_REGS(
712 rd->savintregs[rd->savintreguse],
713 rd->savintregs[rd->savintreguse + 1]);
716 v->regoff =rd->savintregs[rd->savintreguse];
720 #if defined(ALIGN_LONGS_IN_MEMORY)
721 /* Align longs in Memory */
722 if ( (memneeded) && (rd->memuse & 1))
725 v->regoff = rd->memuse;
726 rd->memuse += memneeded + 1;
728 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
733 #ifdef HAS_ADDRESS_REGISTER_FILE
742 static void reg_init_temp(methodinfo *m, registerdata *rd)
745 #if defined(HAS_4BYTE_STACKSLOT)
746 rd->freememtop_2 = 0;
749 rd->freetmpinttop = 0;
750 rd->freesavinttop = 0;
751 rd->freetmpflttop = 0;
752 rd->freesavflttop = 0;
753 #ifdef HAS_ADDRESS_REGISTER_FILE
754 rd->freetmpadrtop = 0;
755 rd->freesavadrtop = 0;
758 rd->freearginttop = 0;
759 rd->freeargflttop = 0;
760 #ifdef HAS_ADDRESS_REGISTER_FILE
761 rd->freeargadrtop = 0;
766 #define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
768 static void reg_new_temp_func(registerdata *rd, stackptr s)
774 /* Try to allocate a saved register if there is no temporary one */
775 /* available. This is what happens during the second run. */
776 tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
778 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
779 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
783 #if defined(HAS_4BYTE_STACKSLOT)
784 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
789 for(; tryagain; --tryagain) {
791 if (!(s->flags & SAVEDVAR))
792 s->flags |= SAVEDTMP;
793 #ifdef HAS_ADDRESS_REGISTER_FILE
794 if (IS_ADR_TYPE(s->type)) {
795 if (rd->freesavadrtop > 0) {
796 s->regoff = rd->freesavadrregs[--rd->freesavadrtop];
798 } else if (rd->savadrreguse > 0) {
799 s->regoff = rd->savadrregs[--rd->savadrreguse];
805 if (IS_FLT_DBL_TYPE(s->type)) {
806 if (rd->freesavflttop > 0) {
807 s->regoff = rd->freesavfltregs[--rd->freesavflttop];
809 } else if (rd->savfltreguse > 0) {
810 s->regoff = rd->savfltregs[--rd->savfltreguse];
814 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
816 * for i386 put all longs in memory
818 if (!IS_2_WORD_TYPE(s->type))
821 if (rd->freesavinttop > intregsneeded) {
822 rd->freesavinttop -= intregsneeded + 1;
823 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
825 s->regoff = PACK_REGS(
826 rd->freesavintregs[rd->freesavinttop],
827 rd->freesavintregs[rd->freesavinttop + 1]);
831 rd->freesavintregs[rd->freesavinttop];
833 } else if (rd->savintreguse > intregsneeded) {
834 rd->savintreguse -= intregsneeded + 1;
835 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
837 s->regoff = PACK_REGS(
838 rd->savintregs[rd->savintreguse],
839 rd->savintregs[rd->savintreguse + 1]);
842 s->regoff = rd->savintregs[rd->savintreguse];
848 } else { /* tryagain == 2 */
849 #ifdef HAS_ADDRESS_REGISTER_FILE
850 if (IS_ADR_TYPE(s->type)) {
851 if (rd->freetmpadrtop > 0) {
852 s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
854 } else if (rd->tmpadrreguse > 0) {
855 s->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
861 if (IS_FLT_DBL_TYPE(s->type)) {
862 if (rd->freeargflttop > 0) {
863 s->regoff = rd->freeargfltregs[--rd->freeargflttop];
866 } else if (rd->argfltreguse < FLT_ARG_CNT) {
867 s->regoff = rd->argfltregs[rd->argfltreguse++];
870 } else if (rd->freetmpflttop > 0) {
871 s->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
873 } else if (rd->tmpfltreguse > 0) {
874 s->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
879 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
881 * for i386 put all longs in memory
883 if (!IS_2_WORD_TYPE(s->type))
886 if (rd->freearginttop > intregsneeded) {
887 rd->freearginttop -= intregsneeded + 1;
889 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
891 s->regoff = PACK_REGS(
892 rd->freeargintregs[rd->freearginttop],
893 rd->freeargintregs[rd->freearginttop + 1]);
897 rd->freeargintregs[rd->freearginttop];
899 } else if (rd->argintreguse
900 < INT_ARG_CNT - intregsneeded) {
901 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
903 s->regoff = PACK_REGS(
904 rd->argintregs[rd->argintreguse],
905 rd->argintregs[rd->argintreguse + 1]);
908 s->regoff = rd->argintregs[rd->argintreguse];
910 rd->argintreguse += intregsneeded + 1;
912 } else if (rd->freetmpinttop > intregsneeded) {
913 rd->freetmpinttop -= intregsneeded + 1;
914 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
916 s->regoff = PACK_REGS(
917 rd->freetmpintregs[rd->freetmpinttop],
918 rd->freetmpintregs[rd->freetmpinttop + 1]);
921 s->regoff = rd->freetmpintregs[rd->freetmpinttop];
923 } else if (rd->tmpintreguse > intregsneeded) {
924 rd->tmpintreguse -= intregsneeded + 1;
925 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
927 s->regoff = PACK_REGS(
928 rd->tmpintregs[rd->tmpintreguse],
929 rd->tmpintregs[rd->tmpintreguse + 1]);
932 s->regoff = rd->tmpintregs[rd->tmpintreguse];
935 } /* if (!IS_2_WORD_TYPE(s->type)) */
936 } /* if (IS_FLT_DBL_TYPE(s->type)) */
937 } /* if (IS_ADR_TYPE(s->type)) */
938 } /* if (tryagain == 1) else */
939 } /* for(; tryagain; --tryagain) */
941 #if defined(HAS_4BYTE_STACKSLOT)
942 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
944 s->regoff = rd->freemem_2[rd->freememtop_2];
946 #endif /*defined(HAS_4BYTE_STACKSLOT) */
947 if ((memneeded == 0) && (rd->freememtop > 0)) {
949 s->regoff = rd->freemem[rd->freememtop];
951 #if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
952 /* align 2 Word Types */
953 if ((memneeded) && ((rd->memuse & 1) == 1)) {
954 /* Put patched memory slot on freemem */
955 rd->freemem[rd->freememtop++] = rd->memuse;
958 #endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */
959 s->regoff = rd->memuse;
960 rd->memuse += memneeded + 1;
962 s->flags |= INMEMORY;
966 #define reg_free_temp(rd,s) if ((s->varkind == TEMPVAR) && (!(s->flags & STCOPY))) reg_free_temp_func(rd, s)
968 /* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */
969 /* alive using this reg/memory location */
971 static void reg_free_temp_func(registerdata *rd, stackptr s)
976 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
977 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
982 #if defined(HAS_4BYTE_STACKSLOT)
983 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
988 if (s->flags & INMEMORY) {
989 #if defined(HAS_4BYTE_STACKSLOT)
991 rd->freemem_2[rd->freememtop_2] = s->regoff;
996 rd->freemem[rd->freememtop] = s->regoff;
1000 #ifdef HAS_ADDRESS_REGISTER_FILE
1001 } else if (IS_ADR_TYPE(s->type)) {
1002 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1003 /* s->flags &= ~SAVEDTMP; */
1004 rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
1006 rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
1008 } else if (IS_FLT_DBL_TYPE(s->type)) {
1009 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1010 /* s->flags &= ~SAVEDTMP; */
1011 rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
1012 } else if (s->flags & TMPARG) {
1013 /* s->flags &= ~TMPARG; */
1014 rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
1016 rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
1017 } else { /* IS_INT_LNG_TYPE */
1018 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1019 /* s->flags &= ~SAVEDTMP; */
1020 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1021 if (intregsneeded) {
1022 rd->freesavintregs[rd->freesavinttop] =
1023 GET_LOW_REG(s->regoff);
1024 rd->freesavintregs[rd->freesavinttop + 1] =
1025 GET_HIGH_REG(s->regoff);
1028 rd->freesavintregs[rd->freesavinttop] = s->regoff;
1029 rd->freesavinttop += intregsneeded + 1;
1031 } else if (s->flags & TMPARG) {
1032 /* s->flags &= ~TMPARG; */
1033 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1034 if (intregsneeded) {
1035 rd->freeargintregs[rd->freearginttop] =
1036 GET_LOW_REG(s->regoff);
1037 rd->freeargintregs[rd->freearginttop + 1] =
1038 GET_HIGH_REG(s->regoff);
1041 rd->freeargintregs[rd->freearginttop] = s->regoff;
1042 rd->freearginttop += intregsneeded + 1;
1044 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1045 if (intregsneeded) {
1046 rd->freetmpintregs[rd->freetmpinttop] =
1047 GET_LOW_REG(s->regoff);
1048 rd->freetmpintregs[rd->freetmpinttop + 1] =
1049 GET_HIGH_REG(s->regoff);
1052 rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
1053 rd->freetmpinttop += intregsneeded + 1;
1058 static bool reg_alloc_dup(stackptr src, stackptr dst) {
1059 /* only copy TEMPVARS, do not mess with STACKVAR, */
1060 /* LOCALVAR, or ARGVAR */
1061 if ((src->varkind == TEMPVAR) && (dst->varkind == TEMPVAR)) {
1062 /* can not allocate a REG_TMP to a REG_SAV Slot */
1063 if (src->flags & INMEMORY) {
1064 dst->regoff = src->regoff;
1065 dst->flags |= INMEMORY;
1067 } else if ((src->flags & SAVEDVAR) == (dst->flags & SAVEDVAR)) {
1068 dst->regoff = src->regoff;
1069 dst->flags |= src->flags & SAVEDTMP;
1070 dst->flags |= src->flags & TMPARG;
1073 } else if ((dst->flags & SAVEDVAR) == 0) {
1074 /* can only use a REG_SAV as REG_TMP! */
1075 dst->regoff = src->regoff;
1076 dst->flags |= src->flags & TMPARG;
1077 dst->flags |= SAVEDTMP;
1082 /* no copy possible - allocate a new reg/memory location*/
1086 /* Mark the copies (STCOPY) at the dst stack right for DUPx and SWAP */
1087 static void reg_mark_copy(registerdata *rd, stackptr src_top, stackptr src_bottom, stackptr dst_top, stackptr dst_bottom) {
1090 stackptr dst_stackslots[6];
1091 int s_bottom, d_bottom, i, j;
1096 /* remember all different Registers/Memory Location of used TEMPVAR */
1097 /* instacks in src_varnum[] and src_flags[] _uniquely_. Take the STCOPY */
1098 /* flag of the last (deepest) occurence */
1099 for(s_bottom = 4, sp = src_top; sp >= src_bottom; sp = sp->prev) {
1100 if (sp->varkind == TEMPVAR) {
1102 for( i = 3; i >= s_bottom; i--) {
1103 if ((src_regoff[i] == sp->regoff) &&
1104 ((src_flags[i] & INMEMORY) == (sp->flags & INMEMORY)) ) {
1105 src_flags[i] &= (~STCOPY | (sp->flags & STCOPY));
1111 src_regoff[s_bottom] = sp->regoff;
1112 src_flags[s_bottom] = sp->flags;
1117 /* Remember used TEMPVAR dst Stackslots in dst_stackslots[], since they */
1118 /* have to be from the "lowest" upwards, and the stackelements list is */
1119 /* linked from only top downwards */
1121 for(d_bottom = 6, sp =dst_top; sp >= dst_bottom; sp = sp->prev) {
1122 if (sp->varkind == TEMPVAR) {
1124 dst_stackslots[d_bottom] = sp;
1128 /* Mark all reused reg/mem in dst stacklots with STCOPY, if the */
1129 /* corresponding src stackslot was marked STCOPY*/
1130 /* if the correspondig STCOPY from the src stackslot was not set, do not */
1131 /* mark the lowest occurence at dst stackslots */
1132 /* mark in src_flag reg/mem with STKEEP, if they where reused in the dst */
1133 /* stacklots, so they are not freed afterwards */
1134 for(i = d_bottom; i < 6; i++) {
1135 for(j = s_bottom; j < 4; j++) {
1136 if ( (src_regoff[j] == dst_stackslots[i]->regoff) &&
1137 ((src_flags[j] & INMEMORY) == (dst_stackslots[i]->flags & INMEMORY)) ) {
1138 if (src_flags[j] & STCOPY)
1139 dst_stackslots[i]->flags |= STCOPY;
1141 src_flags[j] |= STCOPY;
1142 dst_stackslots[i]->flags &= ~STCOPY;
1144 /* do not free reg/mem of src Stackslot */
1145 src_flags[j] |= STKEEP;
1150 /* free all reg/mem of src stack, which where not marked with STKEEP */
1151 for(j=s_bottom; j < 4; j++) {
1152 if ((src_flags[j] & STKEEP)==0) {
1153 /* free, if STCOPY of src stackslot is not set */
1154 /* STCOPY is already checked in reg_free_temp macro! */
1155 for(sp = src_top; sp >= src_bottom; sp = sp->prev)
1156 if ((src_regoff[j] == sp->regoff) &&
1157 ((src_flags[j] & INMEMORY) == (sp->flags & INMEMORY)) ) {
1158 reg_free_temp(rd, sp);
1165 /* allocate_scratch_registers **************************************************
1169 *******************************************************************************/
1171 static void allocate_scratch_registers(jitdata *jd)
1182 builtintable_entry *bte;
1185 /* get required compiler data */
1190 /* initialize temp registers */
1191 reg_init_temp(m, rd);
1193 bptr = m->basicblocks;
1195 while (bptr != NULL) {
1196 if (bptr->flags >= BBREACHED) {
1197 dst = bptr->instack;
1200 iptr = bptr->iinstr;
1203 while (--len >= 0) {
1206 opcode = iptr->opc & ICMD_OPCODE_MASK;
1213 case ICMD_ELSE_ICONST:
1214 case ICMD_CHECKNULL:
1220 case ICMD_PUTSTATICCONST:
1221 case ICMD_INLINE_START:
1222 case ICMD_INLINE_END:
1223 case ICMD_INLINE_GOTO:
1226 /* pop 0 push 1 const */
1234 /* pop 0 push 1 load */
1241 reg_new_temp(rd, dst);
1255 reg_free_temp(rd, src);
1256 reg_free_temp(rd, src->prev);
1257 reg_new_temp(rd, dst);
1271 reg_free_temp(rd, src);
1272 reg_free_temp(rd, src->prev);
1273 reg_free_temp(rd, src->prev->prev);
1276 /* pop 1 push 0 store */
1296 case ICMD_PUTSTATIC:
1297 case ICMD_PUTFIELDCONST:
1299 /* pop 1 push 0 branch */
1302 case ICMD_IFNONNULL:
1318 /* pop 1 push 0 table branch */
1320 case ICMD_TABLESWITCH:
1321 case ICMD_LOOKUPSWITCH:
1323 case ICMD_MONITORENTER:
1324 case ICMD_MONITOREXIT:
1325 reg_free_temp(rd, src);
1328 /* pop 2 push 0 branch */
1330 case ICMD_IF_ICMPEQ:
1331 case ICMD_IF_ICMPNE:
1332 case ICMD_IF_ICMPLT:
1333 case ICMD_IF_ICMPGE:
1334 case ICMD_IF_ICMPGT:
1335 case ICMD_IF_ICMPLE:
1337 case ICMD_IF_LCMPEQ:
1338 case ICMD_IF_LCMPNE:
1339 case ICMD_IF_LCMPLT:
1340 case ICMD_IF_LCMPGE:
1341 case ICMD_IF_LCMPGT:
1342 case ICMD_IF_LCMPLE:
1344 case ICMD_IF_FCMPEQ:
1345 case ICMD_IF_FCMPNE:
1347 case ICMD_IF_FCMPL_LT:
1348 case ICMD_IF_FCMPL_GE:
1349 case ICMD_IF_FCMPL_GT:
1350 case ICMD_IF_FCMPL_LE:
1352 case ICMD_IF_FCMPG_LT:
1353 case ICMD_IF_FCMPG_GE:
1354 case ICMD_IF_FCMPG_GT:
1355 case ICMD_IF_FCMPG_LE:
1357 case ICMD_IF_DCMPEQ:
1358 case ICMD_IF_DCMPNE:
1360 case ICMD_IF_DCMPL_LT:
1361 case ICMD_IF_DCMPL_GE:
1362 case ICMD_IF_DCMPL_GT:
1363 case ICMD_IF_DCMPL_LE:
1365 case ICMD_IF_DCMPG_LT:
1366 case ICMD_IF_DCMPG_GE:
1367 case ICMD_IF_DCMPG_GT:
1368 case ICMD_IF_DCMPG_LE:
1370 case ICMD_IF_ACMPEQ:
1371 case ICMD_IF_ACMPNE:
1379 case ICMD_IASTORECONST:
1380 case ICMD_LASTORECONST:
1381 case ICMD_AASTORECONST:
1382 case ICMD_BASTORECONST:
1383 case ICMD_CASTORECONST:
1384 case ICMD_SASTORECONST:
1385 reg_free_temp(rd, src);
1386 reg_free_temp(rd, src->prev);
1389 /* pop 0 push 1 dup */
1392 /* src === dst->prev (identical Stackslot Element) */
1393 /* src --> dst (copied value, take same reg/mem) */
1395 if (!reg_alloc_dup(src, dst)) {
1396 reg_new_temp(rd, dst);
1398 dst->flags |= STCOPY;
1402 /* pop 0 push 2 dup */
1405 /* src->prev === dst->prev->prev->prev (identical Stackslot Element) */
1406 /* src === dst->prev->prev (identical Stackslot Element) */
1407 /* src->prev --> dst->prev (copied value, take same reg/mem) */
1408 /* src --> dst (copied value, take same reg/mem) */
1410 if (!reg_alloc_dup(src->prev, dst->prev))
1411 reg_new_temp(rd, dst->prev);
1412 if (!reg_alloc_dup(src, dst))
1413 reg_new_temp(rd, dst);
1414 reg_mark_copy(rd, src, src->prev, dst, dst->prev->prev->prev);
1417 /* pop 2 push 3 dup */
1420 /* src->prev --> dst->prev (copied value, take same reg/mem) */
1421 /* src --> dst (copied value, take same reg/mem) */
1422 /* src --> dst->prev->prev (copied value, take same reg/mem) */
1424 if (!reg_alloc_dup(src, dst->prev->prev))
1425 reg_new_temp(rd, dst->prev->prev);
1426 if (!reg_alloc_dup(src, dst))
1427 reg_new_temp(rd, dst);
1428 if (!reg_alloc_dup(src->prev, dst->prev))
1429 reg_new_temp(rd, dst->prev);
1430 reg_mark_copy(rd, src, src->prev, dst, dst->prev->prev);
1433 /* pop 3 push 4 dup */
1436 /* src->prev->prev --> dst->prev->prev */
1437 /* src->prev --> dst->prev */
1439 /* src --> dst->prev->prev->prev */
1441 if (!reg_alloc_dup(src, dst->prev->prev->prev))
1442 reg_new_temp(rd, dst->prev->prev->prev);
1443 if (!reg_alloc_dup(src, dst))
1444 reg_new_temp(rd, dst);
1445 if (!reg_alloc_dup(src->prev, dst->prev))
1446 reg_new_temp(rd, dst->prev);
1447 if (!reg_alloc_dup(src->prev->prev, dst->prev->prev))
1448 reg_new_temp(rd, dst->prev->prev);
1449 reg_mark_copy(rd, src, src->prev->prev, dst, dst->prev->prev->prev);
1452 /* pop 3 push 5 dup */
1455 /* src->prev->prev --> dst->prev->prev */
1456 /* src->prev --> dst->prev */
1458 /* src->prev --> dst->prev->prev->prev->prev */
1459 /* src --> dst->prev->prev->prev */
1461 if (!reg_alloc_dup(src, dst->prev->prev->prev))
1462 reg_new_temp(rd, dst->prev->prev->prev);
1463 if (!reg_alloc_dup(src, dst))
1464 reg_new_temp(rd, dst);
1465 if (!reg_alloc_dup(src->prev, dst->prev->prev->prev->prev))
1466 reg_new_temp(rd, dst->prev->prev->prev->prev);
1467 if (!reg_alloc_dup(src->prev, dst->prev))
1468 reg_new_temp(rd, dst->prev);
1469 if (!reg_alloc_dup(src->prev->prev, dst->prev->prev))
1470 reg_new_temp(rd, dst->prev->prev);
1471 reg_mark_copy(rd, src, src->prev->prev, dst, dst->prev->prev->prev->prev);
1474 /* pop 4 push 6 dup */
1477 /* src->prev->prev->prev --> dst->prev->prev->prev */
1478 /* src->prev->prev --> dst->prev->prev */
1479 /* src->prev --> dst->prev */
1481 /* src->prev --> dst->prev->prev->prev->prev->prev */
1482 /* src --> dst->prev->prev->prev->prev */
1484 if (!reg_alloc_dup(src, dst->prev->prev->prev->prev))
1485 reg_new_temp(rd, dst->prev->prev->prev->prev);
1486 if (!reg_alloc_dup(src, dst))
1487 reg_new_temp(rd, dst);
1488 if (!reg_alloc_dup(src->prev, dst->prev->prev->prev->prev->prev))
1489 reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
1490 if (!reg_alloc_dup(src->prev, dst->prev))
1491 reg_new_temp(rd, dst->prev);
1492 if (!reg_alloc_dup(src->prev->prev, dst->prev->prev))
1493 reg_new_temp(rd, dst->prev->prev);
1494 if (!reg_alloc_dup(src->prev->prev->prev, dst->prev->prev->prev))
1495 reg_new_temp(rd, dst->prev->prev->prev);
1496 reg_mark_copy(rd, src, src->prev->prev->prev, dst, dst->prev->prev->prev->prev->prev);
1499 /* pop 2 push 2 swap */
1502 /* src --> dst->prev (copy) */
1503 /* src->prev --> dst (copy) */
1505 if (!reg_alloc_dup(src, dst->prev))
1506 reg_new_temp(rd, dst->prev);
1507 if (!reg_alloc_dup(src->prev, dst))
1508 reg_new_temp(rd, dst);
1509 reg_mark_copy(rd, src, src->prev, dst, dst->prev);
1558 reg_free_temp(rd, src);
1559 reg_free_temp(rd, src->prev);
1560 reg_new_temp(rd, dst);
1565 case ICMD_IADDCONST:
1566 case ICMD_ISUBCONST:
1567 case ICMD_IMULCONST:
1571 case ICMD_IANDCONST:
1573 case ICMD_IXORCONST:
1574 case ICMD_ISHLCONST:
1575 case ICMD_ISHRCONST:
1576 case ICMD_IUSHRCONST:
1578 case ICMD_LADDCONST:
1579 case ICMD_LSUBCONST:
1580 case ICMD_LMULCONST:
1584 case ICMD_LANDCONST:
1586 case ICMD_LXORCONST:
1587 case ICMD_LSHLCONST:
1588 case ICMD_LSHRCONST:
1589 case ICMD_LUSHRCONST:
1591 case ICMD_IFEQ_ICONST:
1592 case ICMD_IFNE_ICONST:
1593 case ICMD_IFLT_ICONST:
1594 case ICMD_IFGE_ICONST:
1595 case ICMD_IFGT_ICONST:
1596 case ICMD_IFLE_ICONST:
1601 case ICMD_INT2SHORT:
1619 case ICMD_CHECKCAST:
1621 case ICMD_ARRAYLENGTH:
1622 case ICMD_INSTANCEOF:
1625 case ICMD_ANEWARRAY:
1628 reg_free_temp(rd, src);
1629 reg_new_temp(rd, dst);
1634 case ICMD_GETSTATIC:
1637 reg_new_temp(rd, dst);
1640 /* pop many push any */
1642 case ICMD_INVOKESTATIC:
1643 case ICMD_INVOKESPECIAL:
1644 case ICMD_INVOKEVIRTUAL:
1645 case ICMD_INVOKEINTERFACE:
1646 INSTRUCTION_GET_METHODDESC(iptr,md);
1649 reg_free_temp(rd, src);
1652 if (md->returntype.type != TYPE_VOID)
1653 reg_new_temp(rd, dst);
1661 reg_free_temp(rd, src);
1664 if (md->returntype.type != TYPE_VOID)
1665 reg_new_temp(rd, dst);
1668 case ICMD_MULTIANEWARRAY:
1671 reg_free_temp(rd, src);
1674 reg_new_temp(rd, dst);
1679 new_internalerror("Unknown ICMD %d during register allocation",
1684 } /* while instructions */
1687 } /* while blocks */
1691 #if defined(ENABLE_STATISTICS)
1692 void reg_make_statistics(jitdata *jd)
1699 stackptr src, src_old;
1703 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1706 /* get required compiler data */
1716 /* count how many local variables are held in memory or register */
1717 for(i=0; i < cd->maxlocals; i++)
1718 for (type=0; type <=4; type++)
1719 if (rd->locals[i][type].type != -1) { /* valid local */
1720 if (rd->locals[i][type].flags & INMEMORY) {
1721 count_locals_spilled++;
1725 count_locals_register++;
1727 /* count how many stack slots are held in memory or register */
1729 bptr = m->basicblocks;
1730 while (bptr != NULL) {
1731 if (bptr->flags >= BBREACHED) {
1733 #if defined(ENABLE_LSRA)
1736 /* check for memory moves from interface to BB instack */
1737 dst = bptr->instack;
1738 len = bptr->indepth;
1740 if (len > size_interface) size_interface = len;
1742 while (dst != NULL) {
1744 if (dst->varkind != STACKVAR) {
1745 if ( (dst->flags & INMEMORY) ||
1746 (rd->interfaces[len][dst->type].flags & INMEMORY) ||
1747 ( (dst->flags & INMEMORY) &&
1748 (rd->interfaces[len][dst->type].flags & INMEMORY) &&
1749 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1751 /* one in memory or both inmemory at different offsets */
1752 count_mem_move_bb++;
1760 /* check for memory moves from BB outstack to interface */
1761 dst = bptr->outstack;
1762 len = bptr->outdepth;
1763 if (len > size_interface) size_interface = len;
1767 if (dst->varkind != STACKVAR) {
1768 if ( (dst->flags & INMEMORY) || \
1769 (rd->interfaces[len][dst->type].flags & INMEMORY) || \
1770 ( (dst->flags & INMEMORY) && \
1771 (rd->interfaces[len][dst->type].flags & INMEMORY) && \
1772 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1774 /* one in memory or both inmemory at different offsets */
1775 count_mem_move_bb++;
1782 #if defined(ENABLE_LSRA)
1787 dst = bptr->instack;
1788 iptr = bptr->iinstr;
1792 while (--len >= 0) {
1796 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1797 switch (src->varkind) {
1800 if (!(src->flags & INMEMORY))
1801 count_ss_register++;
1807 /* case LOCALVAR: */
1808 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1809 /* count_ss_register++; */
1811 /* count_ss_spilled++; */
1814 if (!(src->flags & INMEMORY))
1815 count_argument_mem_ss++;
1817 count_argument_reg_ss++;
1821 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1822 /* if (src->varnum < FLT_ARG_CNT) { */
1823 /* count_ss_register++; */
1827 /* #if defined(__POWERPC__) */
1828 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1830 /* if (src->varnum < INT_ARG_CNT) { */
1832 /* count_ss_register++; */
1836 /* count_ss_spilled++; */
1843 } /* while instructions */
1846 } /* while blocks */
1847 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1848 if (in_register) count_method_in_register++;
1850 #endif /* defined(ENABLE_STATISTICS) */
1854 * These are local overrides for various environment variables in Emacs.
1855 * Please do not remove this and leave it at the end of the file, where
1856 * Emacs will automagically detect them.
1857 * ---------------------------------------------------------------------
1860 * indent-tabs-mode: t
1864 * vim:noexpandtab:sw=4:ts=4: