1 /* src/vm/jit/allocator/liveness.c - liveness analysis for lsra
3 Copyright (C) 2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Christian Ullrich
38 #include "mm/memory.h"
40 #include "toolbox/logging.h"
41 #include "toolbox/worklist.h"
43 #include "vm/builtin.h"
44 #include "vm/exceptions.h"
45 #include "vm/global.h"
46 #include "vm/method.h"
47 #include "vm/resolve.h"
48 #include "vm/jit/codegen-common.h"
49 #include "vm/jit/jit.h"
50 #include "vm/jit/allocator/lsra.h"
51 #include "vm/jit/allocator/liveness.h"
53 /* function prototypes */
54 void liveness_scan_registers_canditates(jitdata *jd, int b_index, int iindex,
55 stackptr src, lv_sets *sets);
56 void liveness_set_stack(lsradata *ls, int block, int g_iindex, stackptr s,
57 lv_sets *sets, int op);
58 void liveness_set_local(lsradata *ls, int block, int g_iindex, s4 v_index,
59 int type, lv_sets *sets, int op);
61 void liveness_add_ss(struct lifetime *lt, stackptr s) {
63 /* Stackslot noch nicht eingetragen? */
65 if (s->varnum != lt->v_index) {
66 ss = DNEW(struct stackslot);
68 ss->s->varnum = lt->v_index;
69 ss->next = lt->local_ss;
71 if (s != NULL) lt->savedvar |= s->flags & SAVEDVAR;
72 if (s != NULL) lt->type = s->type;
76 void liveness_join_ss( struct lsradata *ls, struct stackelement *in,
77 struct stackelement *out) {
78 struct lifetime *lt, *lto;
79 struct stackslot *ss, *ss_last;
82 if (in->varnum != out->varnum) {
83 lt = &(ls->lifetime[-in->varnum - 1]);
87 #ifdef LV_DEBUG_VERBOSE
88 log_text("liveness_join_ss: lifetime for instack not found\n");
94 if (out->varnum >= 0) { /* no lifetime for this slot till now */
95 liveness_add_ss(lt, out);
97 lto = &(ls->lifetime[-out->varnum - 1]);
100 if (lto->type == -1) {
101 #ifdef LV_DEBUG_VERBOSE
102 log_text("liveness_join_ss: lifetime for outstack not found\n");
107 #ifdef LV_DEBUG_CHECK
108 if (lto->type != lt->type) {
109 #ifdef LV_DEBUG_VERBOSE
110 log_text("liveness_join_ss: in/out stack type mismatch\n");
116 /* take Lifetime lto out of ls->lifetimes */
119 /* merge lto into lt of in */
121 /* change varnums of all lto->local_ss->s to lt->v_index */
122 ss_last = ss = lto->local_ss;
125 ss->s->varnum = lt->v_index;
128 /* link both lto->local_ss list to lt->local_ss */
129 if (ss_last != NULL) {
130 ss_last->next = lt->local_ss;
131 lt->local_ss = lto->local_ss;
134 lt->savedvar |= lto->savedvar;
135 lt->flags |= lto->flags;
136 lt->usagecount += lto->usagecount;
138 /*join of [bb|i]_first_def und [bb|i]_last_use */
139 if (lto->bb_first_def < lt->bb_first_def) {
140 lt->bb_first_def = lto->bb_first_def;
141 lt->i_first_def = lto->i_first_def;
142 } else if ((lto->bb_first_def == lt->bb_first_def) &&
143 ( lto->i_first_def < lt->i_first_def)) {
144 lt->i_first_def = lto->i_first_def;
146 if (lto->bb_last_use > lt->bb_last_use) {
147 lt->bb_last_use = lto->bb_last_use;
148 lt->i_last_use = lto->i_last_use;
149 } else if ((lto->bb_last_use == lt->bb_last_use) &&
150 ( lto->i_last_use > lt->i_last_use)) {
151 lt->i_last_use = lto->i_last_use;
157 /* join instack of Basic Block b_index with outstack of predecessors */
158 void liveness_join_lifetimes(jitdata *jd, int b_index) {
159 struct stackelement *in, *i, *out;
168 /* do not join instack of Exception Handler */
169 if (m->basicblocks[b_index].type == BBTYPE_EXH)
171 in=m->basicblocks[b_index].instack;
172 /* do not join first instack element of a subroutine header */
173 if (m->basicblocks[b_index].type == BBTYPE_SBR)
177 for (pred = ls->pred[b_index]; pred != NULL; pred = pred->next) {
178 out = m->basicblocks[pred->value].outstack;
179 for (i=in; (i != NULL); i = i->prev, out=out->prev) {
180 liveness_join_ss(ls, i, out);
186 void liveness_setup(jitdata *jd) {
187 int i, icount, b_index;
195 ls->icount_block = DMNEW(int, m->basicblockcount);
196 ls->icount_block[0] = icount = 0;
197 for(i = 0; i < m->basicblockcount; i++) {
199 /* create a global instruction index in icount_block */
200 if (ls->sorted[i-1] != -1)
201 icount += m->basicblocks[ ls->sorted[i-1] ].icount;
202 ls->icount_block[i] = icount;
205 if ((b_index = ls->sorted[i]) != -1) {
206 /* 'valid' Basic Block */
208 /* adapt in- and outstacks for LSRA */
209 src = m->basicblocks[b_index].instack;
210 if (m->basicblocks[b_index].type != BBTYPE_STD) {
211 #ifdef LV_DEBUG_CHECK
213 #ifdef LV_DEBUG_VERBOSE
214 log_text("No Incoming Stackslot for Exception/Subroutine BB\n");
219 if (src->varkind == STACKVAR)
220 src->varkind = TEMPVAR;
223 for (;src != NULL; src=src->prev) {
224 /* no ARGVAR possible at BB Boundaries with LSRA! */
225 /* -> change to TEMPVAR */
226 if (src->varkind == ARGVAR ) {
227 src->varkind = TEMPVAR;
228 /* On Architectures with own return registers a return
229 stackslot is marked as varkind=ARGVAR with varnum=-1
230 but for lsra a varkind==TEMPVAR, varnum=-1 would mean,
231 that already a lifetime was allocated! */
232 if (src->varnum < 0) src->varnum = 0;
234 else if (src->varkind == LOCALVAR ) {
235 /* only allowed for top most ss at sbr or exh entries! */
236 #ifdef LV_DEBUG_VERBOSE
237 log_text("LOCALVAR at basicblock instack\n");
241 if (src->varkind == STACKVAR )
242 /* no Interfaces at BB Boundaries with LSRA! */
243 /* -> change to TEMPVAR */
244 src->varkind = TEMPVAR;
248 src = m->basicblocks[b_index].outstack;
249 for (;src != NULL; src=src->prev) {
250 if (src->varkind == ARGVAR ) {
251 #ifdef LV_DEBUG_VERBOSE
252 log_text("ARGVAR at basicblock outstack\n");
255 } else if (src->varkind == LOCALVAR ) {
256 #ifdef LV_DEBUG_VERBOSE
257 log_text("LOCALVAR at basicblock outstack\n");
261 /* no Interfaces at BB Boundaries with LSRA! */
262 /* -> change to TEMPVAR */
263 if (src->varkind == STACKVAR )
264 src->varkind = TEMPVAR;
271 void liveness_init(jitdata *jd) {
284 for(i = 0; i < m->basicblockcount; i++) {
285 if ((b_index = ls->sorted[i]) != -1) {
286 /* 'valid' Basic Block */
288 /* Scan Number of Stack Lifetimes */
289 lifetimes += m->basicblocks[b_index].indepth;
291 dst = m->basicblocks[b_index].instack;
292 len = m->basicblocks[b_index].icount;
293 iptr = m->basicblocks[b_index].iinstr;
294 for (;len>0; len--, iptr++) {
317 if (( dst != NULL) && (src != dst))
323 ls->maxlifetimes = lifetimes;
324 ls->lifetimecount = lifetimes + jd->maxlocals * (TYPE_ADR+1);
327 void liveness_scan_basicblock(jitdata *jd, int b_index,
328 lv_sets *sets, int lifetimes) {
339 src = m->basicblocks[b_index].instack;
341 iindex = m->basicblocks[b_index].icount - 1;
342 /* set iptr to last instruction of BB */
343 iptr = m->basicblocks[b_index].iinstr + iindex;
345 bv_reset(sets->in, lifetimes);
347 for (;iindex >= 0; iindex--, iptr--) {
348 /* get source Stack for the current instruction */
349 /* destination stack is available as iptr->dst */
350 /* source stack is either the destination stack of the previos */
351 /* instruction, or the basicblock instack for the first instruction */
352 if (iindex) /* != 0 is > 0 here, since iindex ist always >= 0 */
355 src=m->basicblocks[b_index].instack;
357 /* Reset kill and gen bitvectors for use in */
358 /* liveness_scan_register_canditates */
360 bv_reset(sets->kill, lifetimes);
361 bv_reset(sets->gen, lifetimes);
363 /* get gen and kill set of instruction */
365 liveness_scan_registers_canditates(jd, b_index, iindex, src, sets);
367 /* tmp = out(instr) - kill(instr) */
369 bv_minus(sets->tmp, sets->out, sets->kill, lifetimes);
371 /* in = gen(instr) union tmp = gen union (out - kill) */
373 bv_union(sets->in, sets->gen, sets->tmp, lifetimes);
375 /* Set SAVEDVAR flag for locals */
377 if (op_needs_saved[iptr->opc])
378 for(i = ls->maxlifetimes; i < ls->lifetimecount; i++)
379 if (!ls->lifetime[i].savedvar)
380 if ( bv_get_bit(sets->in,i) && bv_get_bit(sets->out,i) )
381 ls->lifetime[i].savedvar = SAVEDVAR;
383 /* out(instr-1) = in(instr) (only one successor)*/
385 bv_copy(sets->out, sets->in, lifetimes);
387 /* create gen sets for incoming stackslots */
389 /* global instruction index for bb b_index */
391 iindex = ls->icount_block[ls->sorted_rev[b_index]];
392 bv_reset(sets->kill, lifetimes);
393 bv_reset(sets->gen, lifetimes);
394 src = m->basicblocks[b_index].instack;
395 if (m->basicblocks[b_index].type != BBTYPE_STD) {
396 liveness_set_stack(ls, b_index, iindex, src, sets, LV_KILL);
399 for (;src != NULL; src=src->prev) {
400 /* only TEMP or LOCALVAR by now possible */
401 /* liveness_set_stack redirects for LOCALVARS */
402 liveness_set_stack(ls, b_index, iindex, src, sets, LV_GEN);
403 _LV_ASSERT( ((src->varkind == LOCALVAR) || (src->varkind == TEMPVAR)) );
405 /* in = gen union (out - kill) */
406 bv_minus(sets->tmp, sets->out, sets->kill, lifetimes);
407 bv_union(sets->in, sets->gen, sets->tmp, lifetimes);
410 void liveness(jitdata *jd) {
423 #ifdef LV_DEBUG_CHECK
429 /***************************************************************************
431 - Exact Lifeness Information for intra Basic Blocks Stackslots are trivial
432 They should not be included in the gen, kill, in and out sets to improve
434 - Local Vars as represented in rd->locals "are quite sparse". An intermediate
435 representation for really used index/type pairs should be implemented.
436 ***************************************************************************/
442 if (ls->lifetimecount == 0)
444 ls->lifetime = DMNEW(struct lifetime, ls->lifetimecount);
445 for (i=0; i < ls->lifetimecount; i++) ls->lifetime[i].type = -1;
447 sets.gen = bv_new(ls->lifetimecount);
448 sets.kill = bv_new(ls->lifetimecount);
449 sets.tmp = bv_new(ls->lifetimecount);
450 sets.out = bv_new(ls->lifetimecount);
451 sets.in = bv_new(ls->lifetimecount);
453 params = bv_new(ls->lifetimecount);
455 visited = bv_new(m->basicblockcount);
456 buff = DMNEW(char, ls->lifetimecount+1);
458 out = DMNEW(bitvector, m->basicblockcount);
459 in = DMNEW(bitvector, m->basicblockcount);
460 for(i = 0; i < m->basicblockcount; i++) {
461 out[i] = bv_new(ls->lifetimecount);
462 in[i] = bv_new(ls->lifetimecount);
465 /* set in[0] to arguments */
466 /* <-> kill at 0, -1 */
468 for (p = 0, i = 0; p < md->paramcount; p++) {
469 t = md->paramtypes[p].type;
471 if (rd->locals[i][t].type >= 0)
472 /* Param to Local init happens before normal Code */
473 liveness_set_local(ls, 0, -1, i, t, &sets, LV_KILL);
475 if (IS_2_WORD_TYPE(t)) /* increment local counter a second time */
476 i++; /* for 2 word types */
478 bv_copy(params, sets.kill, ls->lifetimecount);
480 /* fill Worklist so that last node will be taken out first */
481 W = wl_new(m->basicblockcount);
482 for (i = 0; i < m->basicblockcount; i++)
483 if (ls->sorted[i] != -1)
484 wl_add(W, ls->sorted[i]);
486 /* Worklist algorithm*/
487 while (!wl_is_empty(W)) {
490 /* out[b_index] = for all s element of successors(b_index) union in[s]*/
491 for (succ = ls->succ[b_index]; succ != NULL; succ = succ->next)
492 bv_union(out[b_index], out[b_index], in[succ->value],
495 bv_copy(sets.out, out[b_index], ls->lifetimecount);
497 /* compute in[b_index] */
498 liveness_scan_basicblock(jd, b_index, &sets, ls->lifetimecount);
500 if (!bv_get_bit(visited, b_index)) {
501 liveness_join_lifetimes(jd, b_index);
502 bv_set_bit(visited, b_index);
505 if (!bv_equal(sets.in, in[b_index], ls->lifetimecount)) {
506 bv_copy(in[b_index], sets.in, ls->lifetimecount);
507 for(pred = ls->pred[b_index]; pred != NULL; pred = pred->next)
508 wl_add(W, pred->value);
512 #ifdef LV_DEBUG_CHECK
513 s = m->basicblocks[b_index].instack;
514 if ((s != NULL) && (m->basicblocks[b_index].flags != BBTYPE_STD))
516 for( ; s != NULL; s = s->prev) {
517 #ifdef LV_DEBUG_VERBOSE
518 if (!bv_get_bit(in[b_index], -s->varnum - 1)) {
519 log_text("liveness: Error In Stacklot not live!\n");
522 _LV_ASSERT( (bv_get_bit(in[b_index], -s->varnum - 1)) );
526 for (i = 0; i < m->basicblockcount; i++)
527 if ((b_index=ls->sorted[i]) != -1) {
528 for(t = 0; t < ls->lifetimecount; t++) {
529 if (ls->lifetime[t].type != -1) {
530 if (bv_get_bit(in[b_index], t)) {
531 p = ls->icount_block[ls->sorted_rev[b_index]];
532 if (p < ls->lifetime[t].i_first_def)
533 ls->lifetime[t].i_first_def = p;
535 if (bv_get_bit(out[b_index], t)) {
537 ls->icount_block[ls->sorted_rev[b_index]]+m->basicblocks[b_index].icount - 1;
538 if (p > ls->lifetime[t].i_last_use)
539 ls->lifetime[t].i_last_use = p;
547 struct lifetime *liveness_get_ss_lifetime(lsradata *ls, stackptr s) {
550 if (s->varnum >= 0) { /* new stackslot lifetime */
551 #ifdef LV_DEBUG_VERBOSE
552 if (-ls->v_index - 1 >= ls->maxlifetimes) {
553 printf("%i %i\n", -ls->v_index - 1, ls->maxlifetimes);
556 _LV_ASSERT(-ls->v_index - 1 < ls->maxlifetimes);
558 n = &(ls->lifetime[-ls->v_index - 1]);
560 n->v_index = ls->v_index--;
564 n->i_first_def = INT_MAX;
569 n = &(ls->lifetime[-s->varnum - 1]);
571 liveness_add_ss( n, s);
575 void liveness_set_stack(lsradata *ls, int block, int g_iindex, stackptr s,
580 if (s->varkind == LOCALVAR) {
581 liveness_set_local(ls, block, g_iindex, s->varnum, s->type, sets, op);
582 } else if (s->varkind == TEMPVAR) {
583 n = liveness_get_ss_lifetime(ls, s);
585 bv_set_bit(sets->kill, -s->varnum - 1);
586 if (n->i_first_def > g_iindex) {
587 n->i_first_def = g_iindex;
591 bv_set_bit(sets->gen, -s->varnum - 1);
592 if (n->i_last_use < g_iindex) {
593 n->i_last_use = g_iindex;
596 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
600 void liveness_set_local(lsradata *ls, int block, int g_iindex, s4 v_index,
601 int type, lv_sets *sets, int op) {
604 n = &(ls->lifetime[ ls->maxlifetimes + v_index * (TYPE_ADR+1) + type]);
606 if (n->type == -1) { /* new local lifetime */
610 /* TODO: Look if local really needs to be a savedvar */
611 n->savedvar = 0; /* SAVEDVAR; */
616 n->i_first_def = INT_MAX;
618 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
620 bv_set_bit(sets->kill, ls->maxlifetimes + v_index * (TYPE_ADR+1)+ type);
621 if (n->i_first_def > g_iindex) {
622 n->i_first_def = g_iindex;
626 bv_set_bit(sets->gen, ls->maxlifetimes + v_index * (TYPE_ADR+1) + type);
627 if (n->i_last_use < g_iindex) {
628 n->i_last_use = g_iindex;
633 void liveness_scan_registers_canditates(jitdata *jd, int b_index, int iindex,
634 stackptr src, lv_sets *sets)
636 /* methodinfo *lm; */
637 builtintable_entry *bte;
648 iptr = m->basicblocks[b_index].iinstr + iindex;
650 g_iindex = ls->icount_block[ls->sorted_rev[b_index]] + iindex;
654 /* local read (return adress) */
655 liveness_set_local(ls, b_index, g_iindex, iptr->op1, TYPE_ADR, sets, LV_GEN);
659 /* case ICMD_ELSE_ICONST: */
664 case ICMD_PUTSTATICCONST:
665 case ICMD_INLINE_START:
666 case ICMD_INLINE_END:
667 case ICMD_INLINE_GOTO:
671 /* local = local+<const> */
672 liveness_set_local(ls, b_index, g_iindex, iptr->op1, TYPE_INT, sets, LV_GEN);
673 liveness_set_local(ls, b_index, g_iindex, iptr->op1, TYPE_INT, sets, LV_KILL);
676 /* pop 0 push 1 const: const->stack */
683 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
686 /* pop 0 push 1 load: local->stack */
692 if (dst->varkind != LOCALVAR) {
693 /* local->value on stack */
694 liveness_set_local(ls, b_index, g_iindex, iptr->op1,
695 iptr->opc - ICMD_ILOAD, sets, LV_GEN);
697 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
698 } else /* if (dst->varnum != iptr->op1) */ {
700 liveness_set_local(ls, b_index, g_iindex, iptr->op1,
701 iptr->opc - ICMD_ILOAD, sets, LV_GEN);
702 liveness_set_local(ls, b_index, g_iindex, dst->varnum,
703 iptr->opc - ICMD_ILOAD, sets, LV_KILL);
708 /* Stack(arrayref,index)->stack */
719 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
720 /* stack->arrayref */
721 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
722 /* arrayref[index]->stack */
723 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
727 /* stack(arrayref,index,value)->arrayref[index]=value */
738 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
740 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
741 /* stack -> arrayref */
742 liveness_set_stack(ls, b_index, g_iindex, src->prev->prev, sets, LV_GEN);
745 /* pop 1 push 0 store: stack -> local */
751 if (src->varkind != LOCALVAR) {
753 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
754 liveness_set_local(ls, b_index, g_iindex, iptr->op1, iptr->opc - ICMD_ISTORE,
757 liveness_set_local(ls, b_index, g_iindex, src->varnum, iptr->opc-ICMD_ISTORE,
759 liveness_set_local(ls, b_index, g_iindex, iptr->op1, iptr->opc - ICMD_ISTORE,
765 case ICMD_POP: /* throw away a stackslot */
766 /* TODO: check if used anyway (DUP...) and change codegen to */
767 /* ignore this stackslot */
768 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
776 case ICMD_ARETURN: /* stack(value) -> [empty] */
778 case ICMD_ATHROW: /* stack(objref) -> undefined */
780 case ICMD_PUTSTATIC: /* stack(value) -> static_field */
781 case ICMD_PUTFIELDCONST:
783 /* pop 1 push 0 branch */
784 case ICMD_IFNULL: /* stack(value) -> branch? */
801 /* pop 1 push 0 table branch */
802 case ICMD_TABLESWITCH:
803 case ICMD_LOOKUPSWITCH:
805 case ICMD_MONITORENTER:
806 case ICMD_MONITOREXIT:
808 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
812 case ICMD_POP2: /* throw away 2 stackslots */
813 /* TODO: check if used anyway (DUP...) and change codegen to */
814 /* ignore this stackslot */
815 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
816 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
819 /* pop 2 push 0 branch */
821 case ICMD_IF_ICMPEQ: /* stack (v1,v2) -> branch(v1,v2) */
839 case ICMD_PUTFIELD: /* stack(objref,value) -> objref = value */
841 case ICMD_IASTORECONST:
842 case ICMD_LASTORECONST:
843 case ICMD_AASTORECONST:
844 case ICMD_BASTORECONST:
845 case ICMD_CASTORECONST:
846 case ICMD_SASTORECONST:
848 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
849 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
852 /* pop 0 push 1 dup */
854 /* src == dst->prev */
857 /* src and dst->prev are identical */
858 /* liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_KILL);
859 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_GEN);*/
861 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
865 /* pop 0 push 2 dup */
867 /* src == dst->prev->prev */
868 /* src->prev == dst->prev->prev->prev */
870 /* src->prev -> dst->prev-> */
872 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
873 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
876 /* pop 2 push 3 dup */
879 /* src->prev -> dst->prev */
880 /* src -> dst->prev->prev */
882 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
883 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
884 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
886 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
887 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
890 /* pop 3 push 4 dup */
893 /* src->prev -> dst->prev */
894 /* src->prev->prev -> dst->prev->prev */
895 /* dst (=src) -> dst->prev->prev->prev */
897 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
898 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
899 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
901 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev, sets,
903 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
904 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
905 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev, sets,
909 /* pop 3 push 5 dup */
912 /* src->prev -> dst->prev */
913 /* src->prev->prev -> dst->prev->prev */
914 /* dst (=src) -> dst->prev->prev->prev */
915 /* dst->prev (=src->prev) -> dst->prev->prev->prev->prev */
916 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
917 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
918 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
920 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev, sets,
922 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev->prev,
924 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
925 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
926 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev, sets,
930 /* pop 4 push 6 dup */
933 /* src->prev -> dst->prev */
934 /* src->prev->prev -> dst->prev->prev */
935 /* src->prev->prev->prev -> dst->prev->prev->prev */
936 /* dst (=src) -> dst->prev->prev->prev->prev */
937 /* dst->prev (=src->prev) -> dst->prev->prev->prev->prev->prev */
938 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
939 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
940 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
942 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev, sets,
944 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev->prev,
946 liveness_set_stack(ls, b_index, g_iindex,
947 dst->prev->prev->prev->prev->prev, sets, LV_KILL);
948 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
949 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
950 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev, sets,
952 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev->prev,
956 /* pop 2 push 2 swap */
958 /* src -> dst->prev */
959 /* src->prev -> dst */
960 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
961 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
962 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
963 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
1017 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1018 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1019 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
1023 case ICMD_LADDCONST:
1024 case ICMD_LSUBCONST:
1025 case ICMD_LMULCONST:
1029 case ICMD_LANDCONST:
1031 case ICMD_LXORCONST:
1032 case ICMD_LSHLCONST:
1033 case ICMD_LSHRCONST:
1034 case ICMD_LUSHRCONST:
1036 case ICMD_IADDCONST:
1037 case ICMD_ISUBCONST:
1038 case ICMD_IMULCONST:
1042 case ICMD_IANDCONST:
1044 case ICMD_IXORCONST:
1045 case ICMD_ISHLCONST:
1046 case ICMD_ISHRCONST:
1047 case ICMD_IUSHRCONST:
1049 /* case ICMD_IFEQ_ICONST: */
1050 /* case ICMD_IFNE_ICONST: */
1051 /* case ICMD_IFLT_ICONST: */
1052 /* case ICMD_IFGE_ICONST: */
1053 /* case ICMD_IFGT_ICONST: */
1054 /* case ICMD_IFLE_ICONST: */
1059 case ICMD_INT2SHORT:
1077 case ICMD_CHECKCAST:
1079 case ICMD_ARRAYLENGTH:
1080 case ICMD_INSTANCEOF:
1083 case ICMD_ANEWARRAY:
1086 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1087 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1091 case ICMD_GETSTATIC:
1094 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1097 /* pop many push any */
1099 case ICMD_INVOKESTATIC:
1100 case ICMD_INVOKESPECIAL:
1101 case ICMD_INVOKEVIRTUAL:
1102 case ICMD_INVOKEINTERFACE:
1103 INSTRUCTION_GET_METHODDESC(iptr,md);
1106 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1109 if (md->returntype.type != TYPE_VOID)
1110 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1118 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1121 if (md->returntype.type != TYPE_VOID)
1122 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1125 case ICMD_MULTIANEWARRAY:
1128 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1131 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1136 new_internalerror("Unknown ICMD %d during register allocation",
1143 * These are local overrides for various environment variables in Emacs.
1144 * Please do not remove this and leave it at the end of the file, where
1145 * Emacs will automagically detect them.
1146 * ---------------------------------------------------------------------
1149 * indent-tabs-mode: t
1153 * vim:noexpandtab:sw=4:ts=4: