Line data Source code
1 : /* src/vm/jit/allocator/simplereg.cpp - register allocator
2 :
3 : Copyright (C) 1996-2014
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 : Copyright (C) 2009 Theobroma Systems Ltd.
6 :
7 : This file is part of CACAO.
8 :
9 : This program is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU General Public License as
11 : published by the Free Software Foundation; either version 2, or (at
12 : your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 : 02111-1307, USA.
23 :
24 : */
25 :
26 :
27 : #include "config.h"
28 :
29 : #include <cassert>
30 : #include <stdint.h>
31 :
32 : #include "vm/types.hpp"
33 :
34 : #include "arch.hpp"
35 : #include "md-abi.hpp"
36 :
37 : #include "mm/memory.hpp"
38 : #include "mm/dumpmemory.hpp"
39 :
40 : #include "vm/descriptor.hpp" // for typedesc, methoddesc, etc
41 : #include "vm/exceptions.hpp"
42 : #include "vm/method.hpp"
43 : #include "vm/options.hpp"
44 : #include "vm/resolve.hpp"
45 :
46 : #include "vm/jit/allocator/simplereg.hpp"
47 : #include "vm/jit/abi.hpp"
48 : #include "vm/jit/builtin.hpp"
49 : #include "vm/jit/code.hpp"
50 : #include "vm/jit/reg.hpp"
51 : #include "vm/jit/show.hpp"
52 :
53 : #include "vm/jit/ir/instruction.hpp"
54 :
55 : #define DEBUG_NAME "simplereg"
56 :
57 :
58 : STAT_DECLARE_VAR(int,count_locals_spilled,0)
59 : STAT_DECLARE_VAR(int,count_locals_register,0)
60 : // currently not used!
61 : STAT_DECLARE_VAR(int,count_ss_spilled,0)
62 : // currently not used!
63 : STAT_DECLARE_VAR(int,count_ss_register,0)
64 : STAT_DECLARE_VAR(int,count_interface_size,0)
65 : // currently not used!
66 : STAT_DECLARE_VAR(int,count_argument_reg_ss,0)
67 : // currently not used!
68 : STAT_DECLARE_VAR(int,count_argument_mem_ss,0)
69 : STAT_REGISTER_VAR(int,count_method_in_register,0,"methods in register","Number of Methods kept in registers")
70 :
71 : /* function prototypes for this file ******************************************/
72 :
73 : static void simplereg_allocate_interfaces(jitdata *jd);
74 : static void simplereg_allocate_locals(jitdata *jd);
75 : static void simplereg_allocate_temporaries(jitdata *jd);
76 :
77 :
78 : /* size of a stackslot used by the internal ABI */
79 :
80 : #define SIZE_OF_STACKSLOT 8
81 :
82 :
83 : /* total number of registers */
84 :
85 : #define TOTAL_REG_CNT (INT_REG_CNT + FLT_REG_CNT)
86 :
87 :
88 : /* macros for handling register stacks ****************************************/
89 :
90 : #if !defined(NDEBUG)
91 : # define AVAIL_FRONT(cnt, limit) (!opt_RegallocSpillAll && ((cnt) < (limit)))
92 : # define AVAIL_BACK(cnt) (!opt_RegallocSpillAll && ((cnt) > 0))
93 : #else
94 : # define AVAIL_FRONT(cnt, limit) ((cnt) < (limit))
95 : # define AVAIL_BACK(cnt) ((cnt) > 0)
96 : #endif
97 :
98 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
99 : # if !defined(NDEBUG)
100 : # define AVAIL_FRONT_INT(cnt, limit) (!opt_RegallocSpillAll && ((cnt) < (limit) - intregsneeded))
101 : # define AVAIL_BACK_INT(cnt) (!opt_RegallocSpillAll && ((cnt) > intregsneeded))
102 : # else
103 : # define AVAIL_FRONT_INT(cnt, limit) ((cnt) < (limit) - intregsneeded)
104 : # define AVAIL_BACK_INT(cnt) ((cnt) > intregsneeded)
105 : # endif
106 : #else
107 : # define AVAIL_FRONT_INT(cnt, limit) AVAIL_FRONT(cnt, limit)
108 : # define AVAIL_BACK_INT(cnt) AVAIL_BACK(cnt)
109 : #endif
110 :
111 : #define POP_FRONT(stk, cnt, reg) do { reg = stk[cnt++]; } while (0)
112 : #define POP_BACK(stk, cnt, reg) do { reg = stk[--cnt]; } while (0)
113 : #define PUSH_FRONT(stk, cnt, reg) do { stk[--cnt] = (reg); } while (0)
114 : #define PUSH_BACK(stk, cnt, reg) do { stk[cnt++] = (reg); } while (0)
115 :
116 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
117 : #define POP_FRONT_INT(stk, cnt, reg) \
118 : do { \
119 : if (intregsneeded) { \
120 : reg = PACK_REGS(stk[cnt], stk[cnt+1]); \
121 : cnt += 2; \
122 : } \
123 : else \
124 : POP_FRONT(stk, cnt, reg); \
125 : } while (0)
126 : #else
127 : #define POP_FRONT_INT(stk, cnt, reg) POP_FRONT(stk, cnt, reg)
128 : #endif
129 :
130 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
131 : #define POP_BACK_INT(stk, cnt, reg) \
132 : do { \
133 : if (intregsneeded) { \
134 : cnt -= 2; \
135 : reg = PACK_REGS(stk[cnt], stk[cnt+1]); \
136 : } \
137 : else \
138 : POP_BACK(stk, cnt, reg); \
139 : } while (0)
140 : #else
141 : #define POP_BACK_INT(stk, cnt, reg) POP_BACK(stk, cnt, reg)
142 : #endif
143 :
144 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
145 : #define PUSH_BACK_INT(stk, cnt, reg) \
146 : do { \
147 : if (intregsneeded) { \
148 : stk[cnt] = GET_LOW_REG(reg); \
149 : stk[cnt + 1] = GET_HIGH_REG(reg); \
150 : cnt += 2; \
151 : } \
152 : else \
153 : PUSH_BACK(stk, cnt, reg); \
154 : } while (0)
155 : #else
156 : #define PUSH_BACK_INT(stk, cnt, reg) PUSH_BACK(stk, cnt, reg)
157 : #endif
158 :
159 : #define AVAIL_ARG_FLT AVAIL_FRONT(rd->argfltreguse, FLT_ARG_CNT)
160 : #define AVAIL_TMP_FLT AVAIL_BACK(rd->tmpfltreguse)
161 : #define AVAIL_SAV_FLT AVAIL_BACK(rd->savfltreguse)
162 :
163 : #define AVAIL_ARG_ADR AVAIL_FRONT(rd->argadrreguse, ADR_ARG_CNT)
164 : #define AVAIL_TMP_ADR AVAIL_BACK(rd->tmpadrreguse)
165 : #define AVAIL_SAV_ADR AVAIL_BACK(rd->savadrreguse)
166 :
167 : #define AVAIL_ARG_INT AVAIL_FRONT_INT(rd->argintreguse, INT_ARG_CNT)
168 : #define AVAIL_TMP_INT AVAIL_BACK_INT(rd->tmpintreguse)
169 : #define AVAIL_SAV_INT AVAIL_BACK_INT(rd->savintreguse)
170 :
171 : #define AVAIL_FREE_ARG_FLT AVAIL_BACK(rd->freeargflttop)
172 : #define AVAIL_FREE_TMP_FLT AVAIL_BACK(rd->freetmpflttop)
173 : #define AVAIL_FREE_SAV_FLT AVAIL_BACK(rd->freesavflttop)
174 :
175 : #define AVAIL_FREE_ARG_ADR AVAIL_BACK(rd->freeargadrtop)
176 : #define AVAIL_FREE_TMP_ADR AVAIL_BACK(rd->freetmpadrtop)
177 : #define AVAIL_FREE_SAV_ADR AVAIL_BACK(rd->freesavadrtop)
178 :
179 : #define AVAIL_FREE_ARG_INT AVAIL_BACK_INT(rd->freearginttop)
180 : #define AVAIL_FREE_TMP_INT AVAIL_BACK_INT(rd->freetmpinttop)
181 : #define AVAIL_FREE_SAV_INT AVAIL_BACK_INT(rd->freesavinttop)
182 :
183 : #define TAKE_ARG_FLT(r) POP_FRONT(abi_registers_float_argument, rd->argfltreguse, r)
184 : #define TAKE_TMP_FLT(r) POP_BACK(rd->tmpfltregs, rd->tmpfltreguse, r)
185 : #define TAKE_SAV_FLT(r) POP_BACK(rd->savfltregs, rd->savfltreguse, r)
186 :
187 : #define TAKE_ARG_ADR(r) POP_FRONT(rd->argadrregs, rd->argadrreguse, r)
188 : #define TAKE_TMP_ADR(r) POP_BACK(rd->tmpadrregs, rd->tmpadrreguse, r)
189 : #define TAKE_SAV_ADR(r) POP_BACK(rd->savadrregs, rd->savadrreguse, r)
190 :
191 : #define TAKE_ARG_INT(r) POP_FRONT_INT(abi_registers_integer_argument, rd->argintreguse, r)
192 : #define TAKE_TMP_INT(r) POP_BACK_INT(rd->tmpintregs, rd->tmpintreguse, r)
193 : #define TAKE_SAV_INT(r) POP_BACK_INT(rd->savintregs, rd->savintreguse, r)
194 :
195 : #define TAKE_FREE_ARG_FLT(r) POP_BACK(rd->freeargfltregs, rd->freeargflttop, r)
196 : #define TAKE_FREE_TMP_FLT(r) POP_BACK(rd->freetmpfltregs, rd->freetmpflttop, r)
197 : #define TAKE_FREE_SAV_FLT(r) POP_BACK(rd->freesavfltregs, rd->freesavflttop, r)
198 :
199 : #define TAKE_FREE_ARG_ADR(r) POP_BACK(rd->freeargadrregs, rd->freeargadrtop, r)
200 : #define TAKE_FREE_TMP_ADR(r) POP_BACK(rd->freetmpadrregs, rd->freetmpadrtop, r)
201 : #define TAKE_FREE_SAV_ADR(r) POP_BACK(rd->freesavadrregs, rd->freesavadrtop, r)
202 :
203 : #define TAKE_FREE_ARG_INT(r) POP_BACK_INT(rd->freeargintregs, rd->freearginttop, r)
204 : #define TAKE_FREE_TMP_INT(r) POP_BACK_INT(rd->freetmpintregs, rd->freetmpinttop, r)
205 : #define TAKE_FREE_SAV_INT(r) POP_BACK_INT(rd->freesavintregs, rd->freesavinttop, r)
206 :
207 : #define PUSH_FREE_ARG_FLT(r) PUSH_BACK(rd->freeargfltregs, rd->freeargflttop, r)
208 : #define PUSH_FREE_TMP_FLT(r) PUSH_BACK(rd->freetmpfltregs, rd->freetmpflttop, r)
209 : #define PUSH_FREE_SAV_FLT(r) PUSH_BACK(rd->freesavfltregs, rd->freesavflttop, r)
210 :
211 : #define PUSH_FREE_ARG_ADR(r) PUSH_BACK(rd->freeargadrregs, rd->freeargadrtop, r)
212 : #define PUSH_FREE_TMP_ADR(r) PUSH_BACK(rd->freetmpadrregs, rd->freetmpadrtop, r)
213 : #define PUSH_FREE_SAV_ADR(r) PUSH_BACK(rd->freesavadrregs, rd->freesavadrtop, r)
214 :
215 : #define PUSH_FREE_ARG_INT(r) PUSH_BACK_INT(rd->freeargintregs, rd->freearginttop, r)
216 : #define PUSH_FREE_TMP_INT(r) PUSH_BACK_INT(rd->freetmpintregs, rd->freetmpinttop, r)
217 : #define PUSH_FREE_SAV_INT(r) PUSH_BACK_INT(rd->freesavintregs, rd->freesavinttop, r)
218 :
219 :
220 : /* macros for allocating memory slots ****************************************/
221 :
222 : #define NEW_MEM_SLOT(r) \
223 : do { \
224 : (r) = rd->memuse * SIZE_OF_STACKSLOT; \
225 : rd->memuse += 1; \
226 : } while (0)
227 :
228 : #define NEW_MEM_SLOT_INT_LNG(r) NEW_MEM_SLOT(r)
229 : #define NEW_MEM_SLOT_FLT_DBL(r) NEW_MEM_SLOT(r)
230 : #define NEW_MEM_SLOT_REUSE_PADDING(r) NEW_MEM_SLOT(r)
231 :
232 :
233 : /* macros for creating/freeing temporary variables ***************************/
234 :
235 : #define NEW_TEMP_REG(index) \
236 : if ( ((index) >= jd->localcount) \
237 : && (!(VAR(index)->flags & (INOUT | PREALLOC))) ) \
238 : simplereg_new_temp(jd, (index))
239 :
240 :
241 : #define FREE_TEMP_REG(index) \
242 : if (((index) > jd->localcount) \
243 : && (!(VAR(index)->flags & (PREALLOC)))) \
244 : simplereg_free_temp(jd, (index))
245 :
246 :
247 : /* macro for getting a unique register index *********************************/
248 :
249 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
250 : #define REG_INDEX(regoff, type) (IS_FLT_DBL_TYPE(type) ? (INT_REG_CNT + (regoff)) : (GET_LOW_REG(regoff)))
251 : #else
252 : #define REG_INDEX(regoff, type) (IS_FLT_DBL_TYPE(type) ? (INT_REG_CNT + (regoff)) : (regoff))
253 : #endif
254 :
255 :
256 : /* regalloc ********************************************************************
257 :
258 : Does a simple register allocation.
259 :
260 : *******************************************************************************/
261 :
262 86399 : bool regalloc(jitdata *jd)
263 : {
264 : /* There is a problem with the use of unused float argument
265 : registers in leafmethods for stackslots on c7 (2 * Dual Core
266 : AMD Opteron(tm) Processor 270) - runtime for the jvm98 _mtrt
267 : benchmark is heaviliy increased. This could be prevented by
268 : setting rd->argfltreguse to FLT_ARG_CNT before calling
269 : simplereg_allocate_temporaries and setting it back to the original
270 : value before calling simplereg_allocate_locals. */
271 :
272 86399 : simplereg_allocate_interfaces(jd);
273 86399 : simplereg_allocate_temporaries(jd);
274 86399 : simplereg_allocate_locals(jd);
275 :
276 : /* everthing's ok */
277 :
278 86399 : return true;
279 : }
280 :
281 :
282 : /* simplereg_allocate_interfaces ***********************************************
283 :
284 : Allocates registers for all interface variables.
285 :
286 : *******************************************************************************/
287 :
288 86399 : static void simplereg_allocate_interfaces(jitdata *jd)
289 : {
290 : methodinfo *m;
291 : codeinfo *code;
292 : //codegendata *cd;
293 : registerdata *rd;
294 :
295 : int s, t, tt, saved;
296 : int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
297 : /* in case more vars are packed into this interface slot */
298 : /* Allocate LNG and DBL types first to ensure 2 registers */
299 : /* on some architectures. */
300 86399 : int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
301 : int flags, regoff;
302 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
303 : int intregsneeded;
304 : #endif
305 :
306 : /* get required compiler data */
307 :
308 86399 : m = jd->m;
309 86399 : code = jd->code;
310 : //cd = jd->cd;
311 86399 : rd = jd->rd;
312 :
313 : /* rd->memuse was already set in stack.c to allocate stack space
314 : for passing arguments to called methods. */
315 :
316 : #if defined(__I386__)
317 : if (checksync && code_is_synchronized(code)) {
318 : /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
319 : if (rd->memuse < 1)
320 : rd->memuse = 1;
321 : }
322 : #endif
323 :
324 86399 : if (code_is_leafmethod(code)) {
325 : /* Reserve argument register, which will be used for Locals acting */
326 : /* as Parameters */
327 10112 : if (rd->argintreguse < m->parseddesc->argintreguse)
328 9370 : rd->argintreguse = m->parseddesc->argintreguse;
329 10112 : if (rd->argfltreguse < m->parseddesc->argfltreguse)
330 1400 : rd->argfltreguse = m->parseddesc->argfltreguse;
331 : }
332 :
333 335720 : for (s = 0; s < jd->maxinterfaces; s++) {
334 249321 : intalloc = -1; fltalloc = -1;
335 :
336 : /* check if the interface at this stack depth must be a SAVEDVAR */
337 :
338 249321 : saved = 0;
339 :
340 1495926 : for (tt = 0; tt <=4; tt++) {
341 1246605 : if ((t = jd->interface_map[s * 5 + tt].flags) != jitdata::UNUSED) {
342 13554 : saved |= t & SAVEDVAR;
343 : }
344 : }
345 :
346 : /* allocate reg/mem for each type the interface is used as */
347 :
348 1495926 : for (tt = 0; tt <= 4; tt++) {
349 1246605 : t = typeloop[tt];
350 1246605 : if (jd->interface_map[s * 5 + t].flags == jitdata::UNUSED)
351 1233051 : continue;
352 :
353 13554 : flags = saved;
354 13554 : regoff = -1; /* initialize to invalid value */
355 :
356 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
357 : intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
358 : #endif
359 :
360 13554 : if (!saved) {
361 9407 : if (IS_FLT_DBL_TYPE(t)) {
362 0 : if (fltalloc >= 0) {
363 : /* Reuse memory slot(s)/register(s) for shared interface slots */
364 0 : flags |= jd->interface_map[fltalloc].flags & ~SAVEDVAR;
365 0 : regoff = jd->interface_map[fltalloc].regoff;
366 : }
367 0 : else if (AVAIL_ARG_FLT) {
368 0 : flags |= ARGREG;
369 0 : TAKE_ARG_FLT(regoff);
370 : }
371 0 : else if (AVAIL_TMP_FLT) {
372 0 : TAKE_TMP_FLT(regoff);
373 : }
374 0 : else if (AVAIL_SAV_FLT) {
375 0 : flags |= SAVREG;
376 0 : TAKE_SAV_FLT(regoff);
377 : }
378 : else {
379 0 : flags |= INMEMORY;
380 0 : NEW_MEM_SLOT_FLT_DBL(regoff);
381 : }
382 0 : fltalloc = s * 5 + t;
383 : }
384 : else { /* !IS_FLT_DBL_TYPE(t) */
385 : #if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
386 : /*
387 : * for i386 put all longs in memory
388 : */
389 : if (IS_2_WORD_TYPE(t)) {
390 : flags |= INMEMORY;
391 : NEW_MEM_SLOT_INT_LNG(regoff);
392 : }
393 : else
394 : #endif
395 9407 : if (intalloc >= 0) {
396 : /* Reuse memory slot(s)/register(s) for shared interface slots */
397 457 : flags |= jd->interface_map[intalloc].flags & ~SAVEDVAR;
398 457 : regoff = jd->interface_map[intalloc].regoff;
399 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
400 : /* reuse lower half */
401 : if (!(flags & INMEMORY) && IS_2_WORD_TYPE(intalloc % 5))
402 : regoff = GET_LOW_REG(regoff);
403 : #endif
404 : }
405 : else {
406 16725 : if (AVAIL_ARG_INT) {
407 7775 : flags |= ARGREG;
408 7775 : TAKE_ARG_INT(regoff);
409 : }
410 1778 : else if (AVAIL_TMP_INT) {
411 603 : TAKE_TMP_INT(regoff);
412 : }
413 1144 : else if (AVAIL_SAV_INT) {
414 572 : flags |= SAVREG;
415 572 : TAKE_SAV_INT(regoff);
416 : }
417 : else {
418 0 : flags |= INMEMORY;
419 0 : NEW_MEM_SLOT_INT_LNG(regoff);
420 : }
421 : }
422 :
423 9407 : intalloc = s * 5 + t;
424 : } /* if (IS_FLT_DBL_TYPE(t)) */
425 : }
426 : else { /* (saved) */
427 : /* now the same like above, but without a chance to take a temporary register */
428 4147 : if (IS_FLT_DBL_TYPE(t)) {
429 0 : if (fltalloc >= 0) {
430 0 : flags |= jd->interface_map[fltalloc].flags & ~SAVEDVAR;
431 0 : regoff = jd->interface_map[fltalloc].regoff;
432 : }
433 : else {
434 0 : if (AVAIL_SAV_FLT) {
435 0 : TAKE_SAV_FLT(regoff);
436 : }
437 : else {
438 0 : flags |= INMEMORY;
439 0 : NEW_MEM_SLOT_FLT_DBL(regoff);
440 : }
441 : }
442 0 : fltalloc = s * 5 + t;
443 : }
444 : else { /* IS_INT_LNG */
445 : #if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
446 : /*
447 : * for i386 put all longs in memory
448 : */
449 : if (IS_2_WORD_TYPE(t)) {
450 : flags |= INMEMORY;
451 : NEW_MEM_SLOT_INT_LNG(regoff);
452 : }
453 : else
454 : #endif
455 : {
456 4147 : if (intalloc >= 0) {
457 231 : flags |= jd->interface_map[intalloc].flags & ~SAVEDVAR;
458 231 : regoff = jd->interface_map[intalloc].regoff;
459 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
460 : /* reuse lower half */
461 : if (!(flags & INMEMORY) && IS_2_WORD_TYPE(intalloc % 5))
462 : regoff = GET_LOW_REG(regoff);
463 : #endif
464 : }
465 : else {
466 7602 : if (AVAIL_SAV_INT) {
467 3686 : TAKE_SAV_INT(regoff);
468 : }
469 : else {
470 230 : flags |= INMEMORY;
471 230 : NEW_MEM_SLOT_INT_LNG(regoff);
472 : }
473 : }
474 :
475 4147 : intalloc = s*5 + t;
476 : } /* if (IS_FLT_DBL_TYPE(t) else */
477 : } /* if (IS_ADR_TYPE(t)) else */
478 : } /* if (saved) else */
479 : /* if (type >= 0) */
480 :
481 13554 : assert(regoff >= 0);
482 13554 : jd->interface_map[5*s + t].flags = flags | INOUT;
483 13554 : jd->interface_map[5*s + t].regoff = regoff;
484 : } /* for t */
485 : } /* for s */
486 86399 : }
487 :
488 :
489 : /* simplereg_allocate_locals_leafmethod ****************************************
490 :
491 : Allocates registers for all local variables of a leafmethod.
492 :
493 : *******************************************************************************/
494 :
495 10112 : static void simplereg_allocate_locals_leafmethod(jitdata *jd)
496 : {
497 : methodinfo *m;
498 : //codegendata *cd;
499 : registerdata *rd;
500 : methoddesc *md;
501 :
502 : int p, s, t, tt, varindex;
503 : int intalloc, fltalloc;
504 : varinfo *v;
505 10112 : int intregsneeded = 0;
506 10112 : int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
507 : int fargcnt, iargcnt;
508 :
509 : /* get required compiler data */
510 :
511 10112 : m = jd->m;
512 : //cd = jd->cd;
513 10112 : rd = jd->rd;
514 :
515 10112 : md = m->parseddesc;
516 :
517 10112 : iargcnt = rd->argintreguse;
518 10112 : fargcnt = rd->argfltreguse;
519 :
520 23517 : for (p = 0, s = 0; s < jd->maxlocals; s++, p++) {
521 13405 : intalloc = -1; fltalloc = -1;
522 80430 : for (tt = 0; tt <= 4; tt++) {
523 67025 : t = typeloop[tt];
524 67025 : varindex = jd->local_map[s * 5 + t];
525 67025 : if (varindex == jitdata::UNUSED)
526 56587 : continue;
527 :
528 10438 : v = VAR(varindex);
529 :
530 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
531 : intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
532 : #endif
533 10438 : if (IS_FLT_DBL_TYPE(t)) {
534 23 : if (fltalloc >= 0) {
535 0 : v->flags = VAR(fltalloc)->flags;
536 0 : v->vv.regoff = VAR(fltalloc)->vv.regoff;
537 : }
538 : #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
539 : /* We can only use float arguments as local variables,
540 : * if we do not pass them in integer registers. */
541 46 : else if ((p < md->paramcount) && !md->params[p].inmemory) {
542 23 : v->flags = 0;
543 23 : v->vv.regoff = md->params[p].regoff;
544 : }
545 : #endif
546 0 : else if (AVAIL_TMP_FLT) {
547 0 : v->flags = 0;
548 0 : TAKE_TMP_FLT(v->vv.regoff);
549 : }
550 : /* use unused argument registers as local registers */
551 0 : else if ((p >= md->paramcount) && (fargcnt < FLT_ARG_CNT)) {
552 0 : v->flags = 0;
553 0 : POP_FRONT(abi_registers_float_argument,
554 : fargcnt, v->vv.regoff);
555 : }
556 0 : else if (AVAIL_SAV_FLT) {
557 0 : v->flags = 0;
558 0 : TAKE_SAV_FLT(v->vv.regoff);
559 : }
560 : else {
561 0 : v->flags = INMEMORY;
562 0 : NEW_MEM_SLOT_FLT_DBL(v->vv.regoff);
563 : }
564 23 : fltalloc = jd->local_map[s * 5 + t];
565 :
566 : }
567 : else {
568 : #if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
569 : /*
570 : * for i386 put all longs in memory
571 : */
572 : if (IS_2_WORD_TYPE(t)) {
573 : v->flags = INMEMORY;
574 : NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
575 : }
576 : else
577 : #endif
578 : {
579 10415 : if (intalloc >= 0) {
580 0 : v->flags = VAR(intalloc)->flags;
581 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
582 : if (!(v->flags & INMEMORY) && IS_2_WORD_TYPE(VAR(intalloc)->type))
583 : v->vv.regoff = GET_LOW_REG(VAR(intalloc)->vv.regoff);
584 : else
585 : #endif
586 0 : v->vv.regoff = VAR(intalloc)->vv.regoff;
587 : }
588 27688 : else if ((p < md->paramcount) &&
589 8638 : !md->params[p].inmemory)
590 : {
591 8635 : v->flags = 0;
592 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
593 : if (IS_2_WORD_TYPE(t))
594 : v->vv.regoff =
595 : PACK_REGS(GET_LOW_REG(md->params[p].regoff),
596 : GET_HIGH_REG(md->params[p].regoff));
597 : else
598 : #endif
599 8635 : v->vv.regoff = md->params[p].regoff;
600 : }
601 2604 : else if (AVAIL_TMP_INT) {
602 824 : v->flags = 0;
603 824 : TAKE_TMP_INT(v->vv.regoff);
604 : }
605 : /*
606 : * use unused argument registers as local registers
607 : */
608 1612 : else if ((p >= m->parseddesc->paramcount) &&
609 : (iargcnt + intregsneeded < INT_ARG_CNT))
610 : {
611 656 : v->flags = 0;
612 656 : POP_FRONT_INT(abi_registers_integer_argument,
613 : iargcnt, v->vv.regoff);
614 : }
615 600 : else if (AVAIL_SAV_INT) {
616 300 : v->flags = 0;
617 300 : TAKE_SAV_INT(v->vv.regoff);
618 : }
619 : else {
620 0 : v->flags = INMEMORY;
621 0 : NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
622 : }
623 : }
624 10415 : intalloc = jd->local_map[s * 5 + t];
625 : }
626 : } /* for (tt=0;...) */
627 :
628 : /* If the current parameter is a 2-word type, the next local slot */
629 : /* is skipped. */
630 :
631 13405 : if (p < md->paramcount)
632 11628 : if (IS_2_WORD_TYPE(md->paramtypes[p].type))
633 71 : s++;
634 : }
635 10112 : }
636 :
637 : /* simplereg_allocate_locals ***************************************************
638 :
639 : Allocates registers for all local variables.
640 :
641 : *******************************************************************************/
642 :
643 86399 : static void simplereg_allocate_locals(jitdata *jd)
644 : {
645 : codeinfo *code;
646 : //codegendata *cd;
647 : registerdata *rd;
648 :
649 : int s, t, tt, varindex;
650 : int intalloc, fltalloc;
651 : varinfo *v;
652 86399 : int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
653 : #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
654 : s4 intregsneeded;
655 : #endif
656 :
657 : /* get required compiler data */
658 :
659 86399 : code = jd->code;
660 : //cd = jd->cd;
661 86399 : rd = jd->rd;
662 :
663 86399 : if (code_is_leafmethod(code)) {
664 10112 : simplereg_allocate_locals_leafmethod(jd);
665 10112 : return;
666 : }
667 :
668 267448 : for (s = 0; s < jd->maxlocals; s++) {
669 191161 : intalloc = -1; fltalloc = -1;
670 1146966 : for (tt=0; tt<=4; tt++) {
671 955805 : t = typeloop[tt];
672 :
673 955805 : varindex = jd->local_map[s * 5 + t];
674 955805 : if (varindex == jitdata::UNUSED)
675 770860 : continue;
676 :
677 184945 : v = VAR(varindex);
678 :
679 : #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
680 : intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
681 : #endif
682 :
683 184945 : if (IS_FLT_DBL_TYPE(t)) {
684 1464 : if (fltalloc >= 0) {
685 0 : v->flags = VAR(fltalloc)->flags;
686 0 : v->vv.regoff = VAR(fltalloc)->vv.regoff;
687 : }
688 1464 : else if (AVAIL_SAV_FLT) {
689 0 : v->flags = 0;
690 0 : TAKE_SAV_FLT(v->vv.regoff);
691 : }
692 : else {
693 1464 : v->flags = INMEMORY;
694 1464 : NEW_MEM_SLOT_FLT_DBL(v->vv.regoff);
695 : }
696 1464 : fltalloc = jd->local_map[s * 5 + t];
697 : }
698 : else {
699 : #if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
700 : /*
701 : * for i386 put all longs in memory
702 : */
703 : if (IS_2_WORD_TYPE(t)) {
704 : v->flags = INMEMORY;
705 : NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
706 : }
707 : else {
708 : #endif
709 183481 : if (intalloc >= 0) {
710 1898 : v->flags = VAR(intalloc)->flags;
711 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
712 : if (!(v->flags & INMEMORY) && IS_2_WORD_TYPE(VAR(intalloc)->type))
713 : v->vv.regoff = GET_LOW_REG(VAR(intalloc)->vv.regoff);
714 : else
715 : #endif
716 1898 : v->vv.regoff = VAR(intalloc)->vv.regoff;
717 : }
718 328574 : else if (AVAIL_SAV_INT) {
719 146991 : v->flags = 0;
720 146991 : TAKE_SAV_INT(v->vv.regoff);
721 : }
722 : else {
723 34592 : v->flags = INMEMORY;
724 34592 : NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
725 : }
726 : #if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
727 : }
728 : #endif
729 183481 : intalloc = jd->local_map[s * 5 + t];
730 : }
731 : }
732 : }
733 : }
734 :
735 :
736 86399 : static void simplereg_init(jitdata *jd, registerdata *rd)
737 : {
738 : int i;
739 :
740 86399 : rd->freememtop = 0;
741 :
742 86399 : rd->freetmpinttop = 0;
743 86399 : rd->freesavinttop = 0;
744 86399 : rd->freetmpflttop = 0;
745 86399 : rd->freesavflttop = 0;
746 :
747 86399 : rd->freearginttop = 0;
748 86399 : rd->freeargflttop = 0;
749 :
750 86399 : rd->regisoutvar = DMNEW(int, TOTAL_REG_CNT);
751 86399 : rd->regcopycount = DMNEW(int, TOTAL_REG_CNT);
752 86399 : MZERO(rd->regcopycount, int, TOTAL_REG_CNT);
753 :
754 : /* memcopycount is dynamically allocated when needed */
755 :
756 86399 : rd->memcopycount = NULL;
757 86399 : rd->memcopycountsize = 0;
758 :
759 86399 : rd->intusedinout = DMNEW(int, INT_REG_CNT);
760 86399 : MZERO(rd->intusedinout, int, INT_REG_CNT);
761 86399 : rd->fltusedinout = DMNEW(int, FLT_REG_CNT);
762 86399 : MZERO(rd->fltusedinout, int, FLT_REG_CNT);
763 :
764 : /* record the interface registers as used */
765 :
766 273748 : for (i=0; i<rd->argintreguse; ++i)
767 187349 : rd->intusedinout[abi_registers_integer_argument[i]] = 1;
768 87002 : for (i=rd->tmpintreguse; i<INT_TMP_CNT; ++i)
769 603 : rd->intusedinout[rd->tmpintregs[i]] = 1;
770 90657 : for (i=rd->savintreguse; i<INT_SAV_CNT; ++i)
771 4258 : rd->intusedinout[rd->savintregs[i]] = 1;
772 :
773 144975 : for (i=0; i<rd->argfltreguse; ++i)
774 58576 : rd->fltusedinout[abi_registers_float_argument[i]] = 1;
775 86399 : for (i=rd->tmpfltreguse; i<FLT_TMP_CNT; ++i)
776 0 : rd->fltusedinout[rd->tmpfltregs[i]] = 1;
777 86399 : for (i=rd->savfltreguse; i<FLT_SAV_CNT; ++i)
778 0 : rd->fltusedinout[rd->savfltregs[i]] = 1;
779 86399 : }
780 :
781 :
782 319280 : static void simplereg_init_block(registerdata *rd)
783 : {
784 : int i;
785 :
786 : /* remove all interface registers from the free lists */
787 :
788 528219 : for (i=0; i<rd->freearginttop; ++i)
789 208939 : if (rd->intusedinout[rd->freeargintregs[i]]) {
790 49774 : rd->freeargintregs[i--] = rd->freeargintregs[--rd->freearginttop];
791 : }
792 345111 : for (i=0; i<rd->freetmpinttop; ++i)
793 25831 : if (rd->intusedinout[rd->freetmpintregs[i]]) {
794 12817 : rd->freetmpintregs[i--] = rd->freetmpintregs[--rd->freetmpinttop];
795 : }
796 501654 : for (i=0; i<rd->freesavinttop; ++i)
797 182374 : if (rd->intusedinout[rd->freesavintregs[i]]) {
798 62218 : rd->freesavintregs[i--] = rd->freesavintregs[--rd->freesavinttop];
799 : }
800 :
801 338227 : for (i=0; i<rd->freeargflttop; ++i)
802 18947 : if (rd->fltusedinout[rd->freeargfltregs[i]]) {
803 0 : rd->freeargfltregs[i--] = rd->freeargfltregs[--rd->freeargflttop];
804 : }
805 319280 : for (i=0; i<rd->freetmpflttop; ++i)
806 0 : if (rd->fltusedinout[rd->freetmpfltregs[i]]) {
807 0 : rd->freetmpfltregs[i--] = rd->freetmpfltregs[--rd->freetmpflttop];
808 : }
809 319280 : for (i=0; i<rd->freesavflttop; ++i)
810 0 : if (rd->fltusedinout[rd->freesavfltregs[i]]) {
811 0 : rd->freesavfltregs[i--] = rd->freesavfltregs[--rd->freesavflttop];
812 : }
813 319280 : }
814 :
815 :
816 957149 : static void simplereg_new_temp(jitdata *jd, s4 index)
817 : {
818 : #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
819 : s4 intregsneeded;
820 : #endif
821 : s4 tryagain;
822 : registerdata *rd;
823 : varinfo *v;
824 :
825 957149 : rd = jd->rd;
826 957149 : v = VAR(index);
827 :
828 : /* assert that constants are not allocated */
829 :
830 957149 : assert(v->type != TYPE_RET);
831 :
832 : /* Try to allocate a saved register if there is no temporary one */
833 : /* available. This is what happens during the second run. */
834 957149 : tryagain = (v->flags & SAVEDVAR) ? 1 : 2;
835 :
836 : #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
837 : intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
838 : #endif
839 :
840 958899 : for(; tryagain; --tryagain) {
841 958273 : if (tryagain == 1) {
842 199344 : if (!(v->flags & SAVEDVAR))
843 1124 : v->flags |= SAVREG;
844 :
845 199344 : if (IS_FLT_DBL_TYPE(v->type)) {
846 200 : if (AVAIL_FREE_SAV_FLT) {
847 0 : TAKE_FREE_SAV_FLT(v->vv.regoff);
848 0 : return;
849 : }
850 200 : else if (AVAIL_SAV_FLT) {
851 0 : TAKE_SAV_FLT(v->vv.regoff);
852 0 : return;
853 : }
854 : }
855 : else {
856 : #if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
857 : /*
858 : * for i386 put all longs in memory
859 : */
860 : if (!IS_2_WORD_TYPE(v->type))
861 : #endif
862 : {
863 199144 : if (AVAIL_FREE_SAV_INT) {
864 150506 : TAKE_FREE_SAV_INT(v->vv.regoff);
865 150506 : return;
866 : }
867 48638 : else if (AVAIL_SAV_INT) {
868 48212 : TAKE_SAV_INT(v->vv.regoff);
869 48212 : return;
870 : }
871 : }
872 : }
873 : }
874 : else { /* tryagain == 2 */
875 758929 : if (IS_FLT_DBL_TYPE(v->type)) {
876 8027 : if (AVAIL_FREE_ARG_FLT) {
877 5810 : v->flags |= ARGREG;
878 5810 : TAKE_FREE_ARG_FLT(v->vv.regoff);
879 5810 : return;
880 : }
881 2217 : else if (AVAIL_ARG_FLT) {
882 2214 : v->flags |= ARGREG;
883 2214 : TAKE_ARG_FLT(v->vv.regoff);
884 2214 : return;
885 : }
886 3 : else if (AVAIL_FREE_TMP_FLT) {
887 1 : TAKE_FREE_TMP_FLT(v->vv.regoff);
888 1 : return;
889 : }
890 2 : else if (AVAIL_TMP_FLT) {
891 2 : TAKE_TMP_FLT(v->vv.regoff);
892 2 : return;
893 : }
894 : }
895 : else {
896 : #if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
897 : /*
898 : * for i386 put all longs in memory
899 : */
900 : if (!IS_2_WORD_TYPE(v->type))
901 : #endif
902 : {
903 750902 : if (AVAIL_FREE_ARG_INT) {
904 679771 : v->flags |= ARGREG;
905 679771 : TAKE_FREE_ARG_INT(v->vv.regoff);
906 679771 : return;
907 : }
908 71131 : else if (AVAIL_ARG_INT) {
909 55475 : v->flags |= ARGREG;
910 55475 : TAKE_ARG_INT(v->vv.regoff);
911 55475 : return;
912 : }
913 15656 : else if (AVAIL_FREE_TMP_INT) {
914 11779 : TAKE_FREE_TMP_INT(v->vv.regoff);
915 11779 : return;
916 : }
917 3877 : else if (AVAIL_TMP_INT) {
918 2753 : TAKE_TMP_INT(v->vv.regoff);
919 2753 : return;
920 : }
921 : } /* if (!IS_2_WORD_TYPE(s->type)) */
922 : } /* if (IS_FLT_DBL_TYPE(s->type)) */
923 : } /* if (tryagain == 1) else */
924 : } /* for(; tryagain; --tryagain) */
925 :
926 : /* spill to memory */
927 :
928 626 : v->flags |= INMEMORY;
929 :
930 626 : if (rd->freememtop > 0)
931 202 : POP_BACK(rd->freemem, rd->freememtop, v->vv.regoff);
932 : else
933 424 : NEW_MEM_SLOT_REUSE_PADDING(v->vv.regoff);
934 : }
935 :
936 :
937 1689308 : static void simplereg_free(registerdata *rd, s4 flags, s4 regoff, s4 type)
938 : {
939 : /* assert that constants are not freed */
940 :
941 1689308 : assert(type != TYPE_RET);
942 :
943 : /* if this is a copy of another variable, just decrement the copy counter */
944 :
945 1689308 : if (flags & INMEMORY) {
946 : int32_t memindex;
947 :
948 785 : if (flags & INOUT)
949 3 : return;
950 :
951 782 : memindex = regoff / SIZE_OF_STACKSLOT;
952 :
953 782 : if (memindex < rd->memcopycountsize && rd->memcopycount[memindex]) {
954 156 : rd->memcopycount[memindex]--;
955 156 : return;
956 : }
957 : }
958 : else {
959 : s4 regindex;
960 :
961 1688523 : regindex = REG_INDEX(regoff, type);
962 :
963 : /* do not free interface registers that are needed as outvars */
964 :
965 1688523 : if (flags & INOUT) {
966 137561 : if (rd->regisoutvar[regindex]) {
967 : LOG("DONT FREE f=" << cacao::hex << cacao::setw(2)
968 : << cacao::fillzero << flags << cacao::dec
969 : << " r=" << regoff << " t=" << type << cacao::nl);
970 155 : return;
971 : }
972 :
973 : LOG("FREEING INVAR f=" << cacao::hex << cacao::setw(2)
974 : << cacao::fillzero << flags << cacao::dec
975 : << " r=" << regoff << " t=" << type << cacao::nl);
976 : }
977 :
978 1688368 : if (rd->regcopycount[regindex]) {
979 594439 : rd->regcopycount[regindex]--;
980 594439 : return;
981 : }
982 : }
983 :
984 1094555 : if (flags & INMEMORY) {
985 626 : PUSH_BACK(rd->freemem, rd->freememtop, regoff);
986 626 : return;
987 : }
988 :
989 : /* freeing a register */
990 :
991 1093929 : else if (IS_FLT_DBL_TYPE(type)) {
992 8027 : if (flags & (SAVEDVAR | SAVREG))
993 0 : PUSH_FREE_SAV_FLT(regoff);
994 8027 : else if (flags & ARGREG)
995 8024 : PUSH_FREE_ARG_FLT(regoff);
996 : else
997 3 : PUSH_FREE_TMP_FLT(regoff);
998 : }
999 : else { /* IS_INT_LNG_TYPE */
1000 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1001 : s4 intregsneeded = (IS_2_WORD_TYPE(type)) ? 1 : 0;
1002 : #endif
1003 :
1004 1085902 : if (flags & (SAVEDVAR | SAVREG))
1005 265158 : PUSH_FREE_SAV_INT(regoff);
1006 820744 : else if (flags & ARGREG)
1007 792792 : PUSH_FREE_ARG_INT(regoff);
1008 : else
1009 27952 : PUSH_FREE_TMP_INT(regoff);
1010 : }
1011 : }
1012 :
1013 :
1014 1572945 : static inline void simplereg_free_temp(jitdata *jd, s4 index)
1015 : {
1016 : varinfo *v;
1017 :
1018 1572945 : v = VAR(index);
1019 :
1020 1572945 : simplereg_free(jd->rd, v->flags, v->vv.regoff, v->type);
1021 1572945 : }
1022 :
1023 :
1024 648424 : static bool simplereg_alloc_dup(jitdata *jd, s4 srcindex, s4 dstindex)
1025 : {
1026 : varinfo *sv;
1027 : varinfo *dv;
1028 :
1029 : /* do not coalesce local variables here */
1030 :
1031 648424 : if (srcindex <= jd->localcount || dstindex <= jd->localcount)
1032 5551 : return false;
1033 :
1034 642873 : sv = VAR(srcindex);
1035 642873 : dv = VAR(dstindex);
1036 :
1037 : /* do not coalesce in/out vars or preallocated variables here */
1038 :
1039 642873 : if ((sv->flags | dv->flags) & (INOUT | PREALLOC))
1040 42767 : return false;
1041 :
1042 : /* if the source is in memory, we can coalesce in any case */
1043 :
1044 600106 : if (sv->flags & INMEMORY) {
1045 336 : dv->flags |= INMEMORY;
1046 336 : dv->vv.regoff = sv->vv.regoff;
1047 336 : return true;
1048 : }
1049 :
1050 : /* we do not allocate a REG_TMP to a REG_SAV variable */
1051 :
1052 599770 : if ((sv->flags & SAVEDVAR) != (dv->flags & SAVEDVAR))
1053 577 : return false;
1054 :
1055 : /* coalesce */
1056 599193 : dv->vv.regoff = sv->vv.regoff;
1057 599193 : dv->flags |= sv->flags & (SAVREG | ARGREG);
1058 :
1059 599193 : return true;
1060 : }
1061 :
1062 :
1063 : /* simplereg_allocate_temporaries **********************************************
1064 :
1065 : Allocate temporary (non-interface, non-local) registers.
1066 :
1067 : *******************************************************************************/
1068 :
1069 86399 : static void simplereg_allocate_temporaries(jitdata *jd)
1070 : {
1071 : //methodinfo *m;
1072 : registerdata *rd;
1073 : s4 i;
1074 : s4 len;
1075 : instruction *iptr;
1076 : basicblock *bptr;
1077 : builtintable_entry *bte;
1078 : methoddesc *md;
1079 : s4 *argp;
1080 : varinfo *v;
1081 : s4 flags;
1082 : s4 regoff;
1083 : s4 type;
1084 : s4 regindex;
1085 :
1086 : /* get required compiler data */
1087 :
1088 : //m = jd->m;
1089 86399 : rd = jd->rd;
1090 :
1091 : /* initialize temp registers */
1092 :
1093 86399 : simplereg_init(jd, rd);
1094 :
1095 86399 : bptr = jd->basicblocks;
1096 :
1097 578479 : while (bptr != NULL) {
1098 405681 : if (bptr->state >= basicblock::REACHED) {
1099 :
1100 : LOG(cacao::nl << "allocating block L" << cacao::setw(3)
1101 : << cacao::fillzero << bptr->nr << cacao::nl);
1102 :
1103 319280 : simplereg_init_block(rd);
1104 :
1105 : /* assert that all copy counts are zero */
1106 :
1107 : #if !defined(NDEBUG) && !defined(ENABLE_SSA)
1108 10536240 : for (i=0; i < TOTAL_REG_CNT; ++i)
1109 10216960 : assert(rd->regcopycount[i] == 0);
1110 : #endif
1111 :
1112 : /* reset outvar flags */
1113 :
1114 319280 : MZERO(rd->regisoutvar, int, TOTAL_REG_CNT);
1115 :
1116 : /* set allocation of invars */
1117 :
1118 350592 : for (i=0; i<bptr->indepth; ++i)
1119 : {
1120 31312 : v = VAR(bptr->invars[i]);
1121 31312 : if (v->type == TYPE_RET)
1122 19 : continue;
1123 :
1124 31293 : v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
1125 31293 : v->flags = jd->interface_map[5*i + v->type].flags;
1126 :
1127 31293 : if (!(v->flags & INMEMORY))
1128 31286 : rd->regcopycount[REG_INDEX(v->vv.regoff, v->type)] = 1;
1129 : }
1130 :
1131 : /* set allocation of outvars */
1132 :
1133 346593 : for (i=0; i<bptr->outdepth; ++i)
1134 : {
1135 27313 : v = VAR(bptr->outvars[i]);
1136 27313 : if (v->type == TYPE_RET)
1137 19 : continue;
1138 :
1139 27294 : v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
1140 27294 : v->flags = jd->interface_map[5*i + v->type].flags;
1141 :
1142 27294 : if (!(v->flags & INMEMORY)) {
1143 27059 : regindex = REG_INDEX(v->vv.regoff, v->type);
1144 27059 : rd->regcopycount[regindex] = 1;
1145 27059 : rd->regisoutvar[regindex] = 1;
1146 : }
1147 : }
1148 :
1149 : /* free interface registers not used in this block */
1150 :
1151 6313260 : for (i=0; i < 5 * jd->maxinterfaces; ++i) {
1152 5993980 : type = i%5;
1153 5993980 : regoff = jd->interface_map[i].regoff;
1154 5993980 : flags = jd->interface_map[i].flags;
1155 :
1156 5993980 : if (!(flags & INMEMORY)) {
1157 180190 : if (!rd->regcopycount[REG_INDEX(regoff, type)]) {
1158 : LOG("MAY REUSE interface register f="
1159 : << cacao::hex << cacao::setw(2) << cacao::fillzero
1160 : << flags << cacao::dec
1161 : << " r=" << regoff << " t=" << type << cacao::nl);
1162 116363 : simplereg_free(rd, flags, regoff, type);
1163 :
1164 : /* mark it, so it is not freed again */
1165 116363 : rd->regcopycount[REG_INDEX(regoff, type)] = -1;
1166 : }
1167 : }
1168 : }
1169 :
1170 : /* reset copy counts */
1171 :
1172 319280 : MZERO(rd->regcopycount, int, TOTAL_REG_CNT);
1173 :
1174 : /* iterate over ICMDS to allocate temporary variables */
1175 :
1176 319280 : iptr = bptr->iinstr;
1177 319280 : len = bptr->icount;
1178 :
1179 5057146 : while (--len >= 0) {
1180 :
1181 4418586 : switch (iptr->opc) {
1182 :
1183 : /* pop 0 push 0 */
1184 :
1185 : case ICMD_JSR:
1186 : case ICMD_NOP:
1187 : case ICMD_CHECKNULL:
1188 : case ICMD_IINC:
1189 : case ICMD_RET:
1190 : case ICMD_RETURN:
1191 : case ICMD_GOTO:
1192 : case ICMD_BREAKPOINT:
1193 : case ICMD_PUTSTATICCONST:
1194 : case ICMD_INLINE_START:
1195 : case ICMD_INLINE_END:
1196 : case ICMD_INLINE_BODY:
1197 885326 : break;
1198 :
1199 : /* pop 0 push 1 const */
1200 :
1201 : case ICMD_ICONST:
1202 : case ICMD_LCONST:
1203 : case ICMD_FCONST:
1204 : case ICMD_DCONST:
1205 : case ICMD_ACONST:
1206 : case ICMD_GETEXCEPTION:
1207 :
1208 : /* pop 0 push 1 load */
1209 :
1210 : case ICMD_ILOAD:
1211 : case ICMD_LLOAD:
1212 : case ICMD_FLOAD:
1213 : case ICMD_DLOAD:
1214 : case ICMD_ALOAD:
1215 1342270 : NEW_TEMP_REG(iptr->dst.varindex);
1216 1342270 : break;
1217 :
1218 : /* pop 2 push 1 */
1219 :
1220 : case ICMD_IALOAD:
1221 : case ICMD_LALOAD:
1222 : case ICMD_FALOAD:
1223 : case ICMD_DALOAD:
1224 : case ICMD_AALOAD:
1225 :
1226 : case ICMD_BALOAD:
1227 : case ICMD_CALOAD:
1228 : case ICMD_SALOAD:
1229 25314 : FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
1230 25314 : FREE_TEMP_REG(iptr->s1.varindex);
1231 25314 : NEW_TEMP_REG(iptr->dst.varindex);
1232 25314 : break;
1233 :
1234 : /* pop 3 push 0 */
1235 :
1236 : case ICMD_IASTORE:
1237 : case ICMD_LASTORE:
1238 : case ICMD_FASTORE:
1239 : case ICMD_DASTORE:
1240 : case ICMD_AASTORE:
1241 :
1242 : case ICMD_BASTORE:
1243 : case ICMD_CASTORE:
1244 : case ICMD_SASTORE:
1245 66116 : FREE_TEMP_REG(iptr->sx.s23.s3.varindex);
1246 66116 : FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
1247 66116 : FREE_TEMP_REG(iptr->s1.varindex);
1248 66116 : break;
1249 :
1250 : /* pop 1 push 0 store */
1251 :
1252 : case ICMD_ISTORE:
1253 : case ICMD_LSTORE:
1254 : case ICMD_FSTORE:
1255 : case ICMD_DSTORE:
1256 : case ICMD_ASTORE:
1257 :
1258 : /* pop 1 push 0 */
1259 :
1260 : case ICMD_POP:
1261 :
1262 : case ICMD_IRETURN:
1263 : case ICMD_LRETURN:
1264 : case ICMD_FRETURN:
1265 : case ICMD_DRETURN:
1266 : case ICMD_ARETURN:
1267 :
1268 : case ICMD_ATHROW:
1269 :
1270 : case ICMD_PUTSTATIC:
1271 : case ICMD_PUTFIELDCONST:
1272 :
1273 : /* pop 1 push 0 branch */
1274 :
1275 : case ICMD_IFNULL:
1276 : case ICMD_IFNONNULL:
1277 :
1278 : case ICMD_IFEQ:
1279 : case ICMD_IFNE:
1280 : case ICMD_IFLT:
1281 : case ICMD_IFGE:
1282 : case ICMD_IFGT:
1283 : case ICMD_IFLE:
1284 :
1285 : case ICMD_IF_LEQ:
1286 : case ICMD_IF_LNE:
1287 : case ICMD_IF_LLT:
1288 : case ICMD_IF_LGE:
1289 : case ICMD_IF_LGT:
1290 : case ICMD_IF_LLE:
1291 :
1292 : /* pop 1 push 0 table branch */
1293 :
1294 : case ICMD_TABLESWITCH:
1295 : case ICMD_LOOKUPSWITCH:
1296 :
1297 : case ICMD_MONITORENTER:
1298 : case ICMD_MONITOREXIT:
1299 309493 : FREE_TEMP_REG(iptr->s1.varindex);
1300 309493 : break;
1301 :
1302 : /* pop 2 push 0 branch */
1303 :
1304 : case ICMD_IF_ICMPEQ:
1305 : case ICMD_IF_ICMPNE:
1306 : case ICMD_IF_ICMPLT:
1307 : case ICMD_IF_ICMPGE:
1308 : case ICMD_IF_ICMPGT:
1309 : case ICMD_IF_ICMPLE:
1310 :
1311 : case ICMD_IF_LCMPEQ:
1312 : case ICMD_IF_LCMPNE:
1313 : case ICMD_IF_LCMPLT:
1314 : case ICMD_IF_LCMPGE:
1315 : case ICMD_IF_LCMPGT:
1316 : case ICMD_IF_LCMPLE:
1317 :
1318 : case ICMD_IF_ACMPEQ:
1319 : case ICMD_IF_ACMPNE:
1320 :
1321 : /* pop 2 push 0 */
1322 :
1323 : case ICMD_POP2:
1324 :
1325 : case ICMD_PUTFIELD:
1326 :
1327 : case ICMD_IASTORECONST:
1328 : case ICMD_LASTORECONST:
1329 : case ICMD_AASTORECONST:
1330 : case ICMD_BASTORECONST:
1331 : case ICMD_CASTORECONST:
1332 : case ICMD_SASTORECONST:
1333 574444 : FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
1334 574444 : FREE_TEMP_REG(iptr->s1.varindex);
1335 574444 : break;
1336 :
1337 : /* pop 0 push 1 copy */
1338 :
1339 : case ICMD_COPY:
1340 : /* src === dst->prev (identical Stackslot Element) */
1341 : /* src --> dst (copied value, take same reg/mem) */
1342 :
1343 642126 : if (!simplereg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
1344 47531 : NEW_TEMP_REG(iptr->dst.varindex);
1345 : }
1346 : else {
1347 594595 : v = VAROP(iptr->dst);
1348 :
1349 594595 : if (v->flags & INMEMORY) {
1350 156 : int32_t memindex = v->vv.regoff / SIZE_OF_STACKSLOT;
1351 156 : if (memindex >= rd->memcopycountsize) {
1352 8 : int newsize = (memindex + 1) * 2;
1353 8 : i = rd->memcopycountsize;
1354 8 : rd->memcopycount = DMREALLOC(rd->memcopycount, int, i, newsize);
1355 8 : MZERO(rd->memcopycount + i, int, newsize - i);
1356 8 : rd->memcopycountsize = newsize;
1357 : }
1358 156 : rd->memcopycount[memindex]++;
1359 : }
1360 : else {
1361 : /* XXX split reg/mem variables on arm may need special handling here */
1362 :
1363 594439 : s4 regindex = REG_INDEX(v->vv.regoff, v->type);
1364 :
1365 594439 : rd->regcopycount[regindex]++;
1366 : }
1367 : }
1368 642126 : break;
1369 :
1370 : /* pop 1 push 1 move */
1371 :
1372 : case ICMD_MOVE:
1373 6298 : if (!simplereg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
1374 1364 : NEW_TEMP_REG(iptr->dst.varindex);
1375 1364 : FREE_TEMP_REG(iptr->s1.varindex);
1376 : }
1377 6298 : break;
1378 :
1379 : /* pop 2 push 1 */
1380 :
1381 : case ICMD_IADD:
1382 : case ICMD_ISUB:
1383 : case ICMD_IMUL:
1384 : case ICMD_IDIV:
1385 : case ICMD_IREM:
1386 :
1387 : case ICMD_ISHL:
1388 : case ICMD_ISHR:
1389 : case ICMD_IUSHR:
1390 : case ICMD_IAND:
1391 : case ICMD_IOR:
1392 : case ICMD_IXOR:
1393 :
1394 : case ICMD_LADD:
1395 : case ICMD_LSUB:
1396 : case ICMD_LMUL:
1397 : case ICMD_LDIV:
1398 : case ICMD_LREM:
1399 :
1400 : case ICMD_LOR:
1401 : case ICMD_LAND:
1402 : case ICMD_LXOR:
1403 :
1404 : case ICMD_LSHL:
1405 : case ICMD_LSHR:
1406 : case ICMD_LUSHR:
1407 :
1408 : case ICMD_FADD:
1409 : case ICMD_FSUB:
1410 : case ICMD_FMUL:
1411 : case ICMD_FDIV:
1412 : case ICMD_FREM:
1413 :
1414 : case ICMD_DADD:
1415 : case ICMD_DSUB:
1416 : case ICMD_DMUL:
1417 : case ICMD_DDIV:
1418 : case ICMD_DREM:
1419 :
1420 : case ICMD_LCMP:
1421 : case ICMD_FCMPL:
1422 : case ICMD_FCMPG:
1423 : case ICMD_DCMPL:
1424 : case ICMD_DCMPG:
1425 17901 : FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
1426 17901 : FREE_TEMP_REG(iptr->s1.varindex);
1427 17901 : NEW_TEMP_REG(iptr->dst.varindex);
1428 17901 : break;
1429 :
1430 : /* pop 1 push 1 */
1431 :
1432 : case ICMD_IADDCONST:
1433 : case ICMD_ISUBCONST:
1434 : case ICMD_IMULCONST:
1435 : case ICMD_IMULPOW2:
1436 : case ICMD_IDIVPOW2:
1437 : case ICMD_IREMPOW2:
1438 : case ICMD_IANDCONST:
1439 : case ICMD_IORCONST:
1440 : case ICMD_IXORCONST:
1441 : case ICMD_ISHLCONST:
1442 : case ICMD_ISHRCONST:
1443 : case ICMD_IUSHRCONST:
1444 :
1445 : case ICMD_LADDCONST:
1446 : case ICMD_LSUBCONST:
1447 : case ICMD_LMULCONST:
1448 : case ICMD_LMULPOW2:
1449 : case ICMD_LDIVPOW2:
1450 : case ICMD_LREMPOW2:
1451 : case ICMD_LANDCONST:
1452 : case ICMD_LORCONST:
1453 : case ICMD_LXORCONST:
1454 : case ICMD_LSHLCONST:
1455 : case ICMD_LSHRCONST:
1456 : case ICMD_LUSHRCONST:
1457 :
1458 : case ICMD_INEG:
1459 : case ICMD_INT2BYTE:
1460 : case ICMD_INT2CHAR:
1461 : case ICMD_INT2SHORT:
1462 : case ICMD_LNEG:
1463 : case ICMD_FNEG:
1464 : case ICMD_DNEG:
1465 :
1466 : case ICMD_I2L:
1467 : case ICMD_I2F:
1468 : case ICMD_I2D:
1469 : case ICMD_L2I:
1470 : case ICMD_L2F:
1471 : case ICMD_L2D:
1472 : case ICMD_F2I:
1473 : case ICMD_F2L:
1474 : case ICMD_F2D:
1475 : case ICMD_D2I:
1476 : case ICMD_D2L:
1477 : case ICMD_D2F:
1478 :
1479 : case ICMD_CHECKCAST:
1480 :
1481 : case ICMD_ARRAYLENGTH:
1482 : case ICMD_INSTANCEOF:
1483 :
1484 : case ICMD_NEWARRAY:
1485 : case ICMD_ANEWARRAY:
1486 :
1487 : case ICMD_GETFIELD:
1488 141377 : FREE_TEMP_REG(iptr->s1.varindex);
1489 141377 : NEW_TEMP_REG(iptr->dst.varindex);
1490 141377 : break;
1491 :
1492 : /* pop 0 push 1 */
1493 :
1494 : case ICMD_GETSTATIC:
1495 :
1496 : case ICMD_NEW:
1497 48504 : NEW_TEMP_REG(iptr->dst.varindex);
1498 48504 : break;
1499 :
1500 : /* pop many push any */
1501 :
1502 : case ICMD_INVOKESTATIC:
1503 : case ICMD_INVOKESPECIAL:
1504 : case ICMD_INVOKEVIRTUAL:
1505 : case ICMD_INVOKEINTERFACE:
1506 282144 : INSTRUCTION_GET_METHODDESC(iptr,md);
1507 282144 : i = md->paramcount;
1508 282144 : argp = iptr->sx.s23.s2.args;
1509 1051240 : while (--i >= 0) {
1510 486952 : FREE_TEMP_REG(*argp);
1511 486952 : argp++;
1512 : }
1513 282144 : if (md->returntype.type != TYPE_VOID)
1514 173386 : NEW_TEMP_REG(iptr->dst.varindex);
1515 282144 : break;
1516 :
1517 : case ICMD_BUILTIN:
1518 77258 : bte = iptr->sx.s23.s3.bte;
1519 77258 : md = bte->md;
1520 77258 : i = md->paramcount;
1521 77258 : argp = iptr->sx.s23.s2.args;
1522 246122 : while (--i >= 0) {
1523 91606 : FREE_TEMP_REG(*argp);
1524 91606 : argp++;
1525 : }
1526 77258 : if (md->returntype.type != TYPE_VOID)
1527 68222 : NEW_TEMP_REG(iptr->dst.varindex);
1528 77258 : break;
1529 :
1530 : case ICMD_MULTIANEWARRAY:
1531 15 : i = iptr->s1.argcount;
1532 15 : argp = iptr->sx.s23.s2.args;
1533 67 : while (--i >= 0) {
1534 37 : FREE_TEMP_REG(*argp);
1535 37 : argp++;
1536 : }
1537 15 : NEW_TEMP_REG(iptr->dst.varindex);
1538 15 : break;
1539 :
1540 : default:
1541 : exceptions_throw_internalerror("Unknown ICMD %d during register allocation",
1542 0 : iptr->opc);
1543 0 : return;
1544 : } /* switch */
1545 4418586 : iptr++;
1546 : } /* while instructions */
1547 : } /* if */
1548 405681 : bptr = bptr->next;
1549 : } /* while blocks */
1550 : }
1551 :
1552 :
1553 : #if defined(ENABLE_STATISTICS)
1554 : void simplereg_make_statistics(jitdata *jd)
1555 : {
1556 : //methodinfo *m;
1557 : //codegendata *cd;
1558 : //registerdata *rd;
1559 : int i;
1560 : s4 len;
1561 : #if 0
1562 : stackelement_t* src, src_old;
1563 : stackelement_t* dst;
1564 : instruction *iptr;
1565 : #endif
1566 : basicblock *bptr;
1567 : int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1568 : bool in_register;
1569 : //varinfo *var;
1570 :
1571 : /* get required compiler data */
1572 :
1573 : //m = jd->m;
1574 : //cd = jd->cd;
1575 : //rd = jd->rd;
1576 :
1577 : in_register = true;
1578 :
1579 : size_interface = 0;
1580 :
1581 : /* count how many local variables are held in memory or register */
1582 : for(i=0; i < jd->localcount; i++) {
1583 : if (VAR(i)->flags & INMEMORY) {
1584 : STATISTICS(count_locals_spilled++);
1585 : in_register=false;
1586 : }
1587 : else {
1588 : STATISTICS(count_locals_register++);
1589 : }
1590 : }
1591 :
1592 : /* count how many stack slots are held in memory or register */
1593 :
1594 : bptr = jd->basicblocks;
1595 :
1596 : while (bptr != NULL) {
1597 : if (bptr->state >= basicblock::REACHED) {
1598 :
1599 : #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
1600 : if (!opt_lsra) {
1601 : #endif
1602 : /* check for memory moves from interface to BB instack */
1603 : len = bptr->indepth;
1604 :
1605 : if (len > size_interface) size_interface = len;
1606 :
1607 : while (len) {
1608 : len--;
1609 : //var = VAR(bptr->invars[len]);
1610 :
1611 : /* invars statistics (currently none) */
1612 : }
1613 :
1614 : /* check for memory moves from BB outstack to interface */
1615 : len = bptr->outdepth;
1616 : if (len > size_interface) size_interface = len;
1617 :
1618 : while (len) {
1619 : len--;
1620 : //var = VAR(bptr->outvars[len]);
1621 :
1622 : /* outvars statistics (currently none) */
1623 : }
1624 : #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
1625 : }
1626 : #endif
1627 :
1628 :
1629 : #if 0
1630 : dst = bptr->instack;
1631 : iptr = bptr->iinstr;
1632 : len = bptr->icount;
1633 : src_old = NULL;
1634 :
1635 : while (--len >= 0) {
1636 : src = dst;
1637 : dst = iptr->dst.var;
1638 :
1639 : if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1640 : switch (src->varkind) {
1641 : case TEMPVAR:
1642 : case STACKVAR:
1643 : if (!(src->flags & INMEMORY))
1644 : STATISTICS(count_ss_register++);
1645 : else {
1646 : STATISTICS(count_ss_spilled++);
1647 : in_register=false;
1648 : }
1649 : break;
1650 : /* case LOCALVAR: */
1651 : /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1652 : /* STATISTICS(count_ss_register++); */
1653 : /* else */
1654 : /* STATISTICS(count_ss_spilled++); */
1655 : /* break; */
1656 : case ARGVAR:
1657 : if (!(src->flags & INMEMORY))
1658 : STATISTICS(count_argument_mem_ss++);
1659 : else
1660 : STATISTICS(count_argument_reg_ss++);
1661 : break;
1662 :
1663 :
1664 : /* if (IS_FLT_DBL_TYPE(src->type)) { */
1665 : /* if (src->varnum < FLT_ARG_CNT) { */
1666 : /* STATISTICS(count_ss_register++); */
1667 : /* break; */
1668 : /* } */
1669 : /* } else { */
1670 : /* #if defined(__POWERPC__) */
1671 : /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1672 : /* #else */
1673 : /* if (src->varnum < INT_ARG_CNT) { */
1674 : /* #endif */
1675 : /* STATISTICS(count_ss_register++); */
1676 : /* break; */
1677 : /* } */
1678 : /* } */
1679 : /* STATISTICS(count_ss_spilled++); */
1680 : /* break; */
1681 : }
1682 : }
1683 : src_old = src;
1684 :
1685 : iptr++;
1686 : } /* while instructions */
1687 : #endif
1688 : } /* if */
1689 :
1690 : bptr = bptr->next;
1691 : } /* while blocks */
1692 :
1693 : STATISTICS(count_interface_size += size_interface); /* accummulate the size of the interface (between bb boundaries) */
1694 : if (in_register) {
1695 : STATISTICS(count_method_in_register++);
1696 : /* printf("INREGISTER: %s%s%s\n",UTF_TEXT(m->class->name), UTF_TEXT(m->name), UTF_TEXT(m->descriptor)); */
1697 : }
1698 : }
1699 : #endif /* defined(ENABLE_STATISTICS) */
1700 :
1701 :
1702 : /*
1703 : * These are local overrides for various environment variables in Emacs.
1704 : * Please do not remove this and leave it at the end of the file, where
1705 : * Emacs will automagically detect them.
1706 : * ---------------------------------------------------------------------
1707 : * Local variables:
1708 : * mode: c++
1709 : * indent-tabs-mode: t
1710 : * c-basic-offset: 4
1711 : * tab-width: 4
1712 : * End:
1713 : * vim:noexpandtab:sw=4:ts=4:
1714 : */
|