1 /* src/vm/jit/allocator/liveness.c - liveness analysis for lsra
3 Copyright (C) 2005, 2006, 2007 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
40 #include "mm/memory.h"
42 #include "toolbox/logging.h"
43 #include "toolbox/worklist.h"
45 #include "vm/builtin.h"
46 #include "vm/exceptions.h"
47 #include "vm/global.h"
48 #include "vm/method.h"
49 #include "vm/resolve.h"
50 #include "vm/jit/codegen-common.h"
51 #include "vm/jit/jit.h"
52 #include "vm/jit/allocator/lsra.h"
53 #include "vm/jit/allocator/liveness.h"
56 /* function prototypes */
57 void liveness_scan_registers_canditates(jitdata *jd, int b_index, int iindex,
58 stackptr src, lv_sets *sets);
59 void liveness_set_stack(lsradata *ls, int block, int g_iindex, stackptr s,
60 lv_sets *sets, int op);
61 void liveness_set_local(lsradata *ls, int block, int g_iindex, s4 v_index,
62 int type, lv_sets *sets, int op);
64 void liveness_add_ss(struct lifetime *lt, stackptr s) {
66 /* Stackslot noch nicht eingetragen? */
68 if (s->varnum != lt->v_index) {
69 ss = DNEW(struct stackslot);
71 ss->s->varnum = lt->v_index;
72 ss->next = lt->local_ss;
74 if (s != NULL) lt->savedvar |= s->flags & SAVEDVAR;
75 if (s != NULL) lt->type = s->type;
79 void liveness_join_ss( struct lsradata *ls, struct stackelement *in,
80 struct stackelement *out) {
81 struct lifetime *lt, *lto;
82 struct stackslot *ss, *ss_last;
85 if (in->varnum != out->varnum) {
86 lt = &(ls->lifetime[-in->varnum - 1]);
90 #ifdef LV_DEBUG_VERBOSE
91 log_text("liveness_join_ss: lifetime for instack not found\n");
97 if (out->varnum >= 0) { /* no lifetime for this slot till now */
98 liveness_add_ss(lt, out);
100 lto = &(ls->lifetime[-out->varnum - 1]);
102 #ifdef LV_DEBUG_CHECK
103 if (lto->type == -1) {
104 #ifdef LV_DEBUG_VERBOSE
105 log_text("liveness_join_ss: lifetime for outstack not found\n");
110 #ifdef LV_DEBUG_CHECK
111 if (lto->type != lt->type) {
112 #ifdef LV_DEBUG_VERBOSE
113 log_text("liveness_join_ss: in/out stack type mismatch\n");
119 /* take Lifetime lto out of ls->lifetimes */
122 /* merge lto into lt of in */
124 /* change varnums of all lto->local_ss->s to lt->v_index */
125 ss_last = ss = lto->local_ss;
128 ss->s->varnum = lt->v_index;
131 /* link both lto->local_ss list to lt->local_ss */
132 if (ss_last != NULL) {
133 ss_last->next = lt->local_ss;
134 lt->local_ss = lto->local_ss;
137 lt->savedvar |= lto->savedvar;
138 lt->flags |= lto->flags;
139 lt->usagecount += lto->usagecount;
141 /*join of [bb|i]_first_def und [bb|i]_last_use */
142 if (lto->bb_first_def < lt->bb_first_def) {
143 lt->bb_first_def = lto->bb_first_def;
144 lt->i_first_def = lto->i_first_def;
145 } else if ((lto->bb_first_def == lt->bb_first_def) &&
146 ( lto->i_first_def < lt->i_first_def)) {
147 lt->i_first_def = lto->i_first_def;
149 if (lto->bb_last_use > lt->bb_last_use) {
150 lt->bb_last_use = lto->bb_last_use;
151 lt->i_last_use = lto->i_last_use;
152 } else if ((lto->bb_last_use == lt->bb_last_use) &&
153 ( lto->i_last_use > lt->i_last_use)) {
154 lt->i_last_use = lto->i_last_use;
160 /* join instack of Basic Block b_index with outstack of predecessors */
161 void liveness_join_lifetimes(jitdata *jd, int b_index) {
162 struct stackelement *in, *i, *out;
171 /* do not join instack of Exception Handler */
172 if (m->basicblocks[b_index].type == BBTYPE_EXH)
174 in=m->basicblocks[b_index].instack;
175 /* do not join first instack element of a subroutine header */
176 if (m->basicblocks[b_index].type == BBTYPE_SBR)
180 for (pred = ls->pred[b_index]; pred != NULL; pred = pred->next) {
181 out = m->basicblocks[pred->value].outstack;
182 for (i=in; (i != NULL); i = i->prev, out=out->prev) {
183 liveness_join_ss(ls, i, out);
189 void liveness_setup(jitdata *jd) {
190 int i, icount, b_index;
198 ls->icount_block = DMNEW(int, m->basicblockcount);
199 ls->icount_block[0] = icount = 0;
200 for(i = 0; i < m->basicblockcount; i++) {
202 /* create a global instruction index in icount_block */
203 if (ls->sorted[i-1] != -1)
204 icount += m->basicblocks[ ls->sorted[i-1] ].icount;
205 ls->icount_block[i] = icount;
208 if ((b_index = ls->sorted[i]) != -1) {
209 /* 'valid' Basic Block */
211 /* adapt in- and outstacks for LSRA */
212 src = m->basicblocks[b_index].instack;
213 if (m->basicblocks[b_index].type != BBTYPE_STD) {
214 #ifdef LV_DEBUG_CHECK
216 #ifdef LV_DEBUG_VERBOSE
217 log_text("No Incoming Stackslot for Exception/Subroutine BB\n");
222 if (src->varkind == STACKVAR)
223 src->varkind = TEMPVAR;
226 for (;src != NULL; src=src->prev) {
227 /* no ARGVAR possible at BB Boundaries with LSRA! */
228 /* -> change to TEMPVAR */
229 if (src->varkind == ARGVAR ) {
230 src->varkind = TEMPVAR;
231 /* On Architectures with own return registers a return
232 stackslot is marked as varkind=ARGVAR with varnum=-1
233 but for lsra a varkind==TEMPVAR, varnum=-1 would mean,
234 that already a lifetime was allocated! */
235 if (src->varnum < 0) src->varnum = 0;
237 else if (src->varkind == LOCALVAR ) {
238 /* only allowed for top most ss at sbr or exh entries! */
239 #ifdef LV_DEBUG_VERBOSE
240 log_text("LOCALVAR at basicblock instack\n");
244 if (src->varkind == STACKVAR )
245 /* no Interfaces at BB Boundaries with LSRA! */
246 /* -> change to TEMPVAR */
247 src->varkind = TEMPVAR;
251 src = m->basicblocks[b_index].outstack;
252 for (;src != NULL; src=src->prev) {
253 if (src->varkind == ARGVAR ) {
254 #ifdef LV_DEBUG_VERBOSE
255 log_text("ARGVAR at basicblock outstack\n");
258 } else if (src->varkind == LOCALVAR ) {
259 #ifdef LV_DEBUG_VERBOSE
260 log_text("LOCALVAR at basicblock outstack\n");
264 /* no Interfaces at BB Boundaries with LSRA! */
265 /* -> change to TEMPVAR */
266 if (src->varkind == STACKVAR )
267 src->varkind = TEMPVAR;
274 void liveness_init(jitdata *jd) {
287 for(i = 0; i < m->basicblockcount; i++) {
288 if ((b_index = ls->sorted[i]) != -1) {
289 /* 'valid' Basic Block */
291 /* Scan Number of Stack Lifetimes */
292 lifetimes += m->basicblocks[b_index].indepth;
294 dst = m->basicblocks[b_index].instack;
295 len = m->basicblocks[b_index].icount;
296 iptr = m->basicblocks[b_index].iinstr;
297 for (;len>0; len--, iptr++) {
320 if (( dst != NULL) && (src != dst))
326 ls->maxlifetimes = lifetimes;
327 ls->lifetimecount = lifetimes + jd->maxlocals * (TYPE_ADR+1);
330 void liveness_scan_basicblock(jitdata *jd, int b_index,
331 lv_sets *sets, int lifetimes) {
342 src = m->basicblocks[b_index].instack;
344 iindex = m->basicblocks[b_index].icount - 1;
345 /* set iptr to last instruction of BB */
346 iptr = m->basicblocks[b_index].iinstr + iindex;
348 bv_reset(sets->in, lifetimes);
350 for (;iindex >= 0; iindex--, iptr--) {
351 /* get source Stack for the current instruction */
352 /* destination stack is available as iptr->dst */
353 /* source stack is either the destination stack of the previos */
354 /* instruction, or the basicblock instack for the first instruction */
355 if (iindex) /* != 0 is > 0 here, since iindex ist always >= 0 */
358 src=m->basicblocks[b_index].instack;
360 /* Reset kill and gen bitvectors for use in */
361 /* liveness_scan_register_canditates */
363 bv_reset(sets->kill, lifetimes);
364 bv_reset(sets->gen, lifetimes);
366 /* get gen and kill set of instruction */
368 liveness_scan_registers_canditates(jd, b_index, iindex, src, sets);
370 /* tmp = out(instr) - kill(instr) */
372 bv_minus(sets->tmp, sets->out, sets->kill, lifetimes);
374 /* in = gen(instr) union tmp = gen union (out - kill) */
376 bv_union(sets->in, sets->gen, sets->tmp, lifetimes);
378 /* Set SAVEDVAR flag for locals */
380 if (op_needs_saved[iptr->opc])
381 for(i = ls->maxlifetimes; i < ls->lifetimecount; i++)
382 if (!ls->lifetime[i].savedvar)
383 if ( bv_get_bit(sets->in,i) && bv_get_bit(sets->out,i) )
384 ls->lifetime[i].savedvar = SAVEDVAR;
386 /* out(instr-1) = in(instr) (only one successor)*/
388 bv_copy(sets->out, sets->in, lifetimes);
390 /* create gen sets for incoming stackslots */
392 /* global instruction index for bb b_index */
394 iindex = ls->icount_block[ls->sorted_rev[b_index]];
395 bv_reset(sets->kill, lifetimes);
396 bv_reset(sets->gen, lifetimes);
397 src = m->basicblocks[b_index].instack;
398 if (m->basicblocks[b_index].type != BBTYPE_STD) {
399 liveness_set_stack(ls, b_index, iindex, src, sets, LV_KILL);
402 for (;src != NULL; src=src->prev) {
403 /* only TEMP or LOCALVAR by now possible */
404 /* liveness_set_stack redirects for LOCALVARS */
405 liveness_set_stack(ls, b_index, iindex, src, sets, LV_GEN);
406 _LV_ASSERT( ((src->varkind == LOCALVAR) || (src->varkind == TEMPVAR)) );
408 /* in = gen union (out - kill) */
409 bv_minus(sets->tmp, sets->out, sets->kill, lifetimes);
410 bv_union(sets->in, sets->gen, sets->tmp, lifetimes);
413 void liveness(jitdata *jd) {
426 #ifdef LV_DEBUG_CHECK
432 /***************************************************************************
434 - Exact Lifeness Information for intra Basic Blocks Stackslots are trivial
435 They should not be included in the gen, kill, in and out sets to improve
437 - Local Vars as represented in rd->locals "are quite sparse". An intermediate
438 representation for really used index/type pairs should be implemented.
439 ***************************************************************************/
445 if (ls->lifetimecount == 0)
447 ls->lifetime = DMNEW(struct lifetime, ls->lifetimecount);
448 for (i=0; i < ls->lifetimecount; i++) ls->lifetime[i].type = -1;
450 sets.gen = bv_new(ls->lifetimecount);
451 sets.kill = bv_new(ls->lifetimecount);
452 sets.tmp = bv_new(ls->lifetimecount);
453 sets.out = bv_new(ls->lifetimecount);
454 sets.in = bv_new(ls->lifetimecount);
456 params = bv_new(ls->lifetimecount);
458 visited = bv_new(m->basicblockcount);
459 buff = DMNEW(char, ls->lifetimecount+1);
461 out = DMNEW(bitvector, m->basicblockcount);
462 in = DMNEW(bitvector, m->basicblockcount);
463 for(i = 0; i < m->basicblockcount; i++) {
464 out[i] = bv_new(ls->lifetimecount);
465 in[i] = bv_new(ls->lifetimecount);
468 /* set in[0] to arguments */
469 /* <-> kill at 0, -1 */
471 for (p = 0, i = 0; p < md->paramcount; p++) {
472 t = md->paramtypes[p].type;
474 if (rd->locals[i][t].type >= 0)
475 /* Param to Local init happens before normal Code */
476 liveness_set_local(ls, 0, -1, i, t, &sets, LV_KILL);
478 if (IS_2_WORD_TYPE(t)) /* increment local counter a second time */
479 i++; /* for 2 word types */
481 bv_copy(params, sets.kill, ls->lifetimecount);
483 /* fill Worklist so that last node will be taken out first */
484 W = wl_new(m->basicblockcount);
485 for (i = 0; i < m->basicblockcount; i++)
486 if (ls->sorted[i] != -1)
487 wl_add(W, ls->sorted[i]);
489 /* Worklist algorithm*/
490 while (!wl_is_empty(W)) {
493 /* out[b_index] = for all s element of successors(b_index) union in[s]*/
494 for (succ = ls->succ[b_index]; succ != NULL; succ = succ->next)
495 bv_union(out[b_index], out[b_index], in[succ->value],
498 bv_copy(sets.out, out[b_index], ls->lifetimecount);
500 /* compute in[b_index] */
501 liveness_scan_basicblock(jd, b_index, &sets, ls->lifetimecount);
503 if (!bv_get_bit(visited, b_index)) {
504 liveness_join_lifetimes(jd, b_index);
505 bv_set_bit(visited, b_index);
508 if (!bv_equal(sets.in, in[b_index], ls->lifetimecount)) {
509 bv_copy(in[b_index], sets.in, ls->lifetimecount);
510 for(pred = ls->pred[b_index]; pred != NULL; pred = pred->next)
511 wl_add(W, pred->value);
515 #ifdef LV_DEBUG_CHECK
516 s = m->basicblocks[b_index].instack;
517 if ((s != NULL) && (m->basicblocks[b_index].flags != BBTYPE_STD))
519 for( ; s != NULL; s = s->prev) {
520 #ifdef LV_DEBUG_VERBOSE
521 if (!bv_get_bit(in[b_index], -s->varnum - 1)) {
522 log_text("liveness: Error In Stacklot not live!\n");
525 _LV_ASSERT( (bv_get_bit(in[b_index], -s->varnum - 1)) );
529 for (i = 0; i < m->basicblockcount; i++)
530 if ((b_index=ls->sorted[i]) != -1) {
531 for(t = 0; t < ls->lifetimecount; t++) {
532 if (ls->lifetime[t].type != -1) {
533 if (bv_get_bit(in[b_index], t)) {
534 p = ls->icount_block[ls->sorted_rev[b_index]];
535 if (p < ls->lifetime[t].i_first_def)
536 ls->lifetime[t].i_first_def = p;
538 if (bv_get_bit(out[b_index], t)) {
540 ls->icount_block[ls->sorted_rev[b_index]]+m->basicblocks[b_index].icount - 1;
541 if (p > ls->lifetime[t].i_last_use)
542 ls->lifetime[t].i_last_use = p;
550 struct lifetime *liveness_get_ss_lifetime(lsradata *ls, stackptr s) {
553 if (s->varnum >= 0) { /* new stackslot lifetime */
554 #ifdef LV_DEBUG_VERBOSE
555 if (-ls->v_index - 1 >= ls->maxlifetimes) {
556 printf("%i %i\n", -ls->v_index - 1, ls->maxlifetimes);
559 _LV_ASSERT(-ls->v_index - 1 < ls->maxlifetimes);
561 n = &(ls->lifetime[-ls->v_index - 1]);
563 n->v_index = ls->v_index--;
567 n->i_first_def = INT_MAX;
572 n = &(ls->lifetime[-s->varnum - 1]);
574 liveness_add_ss( n, s);
578 void liveness_set_stack(lsradata *ls, int block, int g_iindex, stackptr s,
583 if (s->varkind == LOCALVAR) {
584 liveness_set_local(ls, block, g_iindex, s->varnum, s->type, sets, op);
585 } else if (s->varkind == TEMPVAR) {
586 n = liveness_get_ss_lifetime(ls, s);
588 bv_set_bit(sets->kill, -s->varnum - 1);
589 if (n->i_first_def > g_iindex) {
590 n->i_first_def = g_iindex;
594 bv_set_bit(sets->gen, -s->varnum - 1);
595 if (n->i_last_use < g_iindex) {
596 n->i_last_use = g_iindex;
599 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
603 void liveness_set_local(lsradata *ls, int block, int g_iindex, s4 v_index,
604 int type, lv_sets *sets, int op) {
607 n = &(ls->lifetime[ ls->maxlifetimes + v_index * (TYPE_ADR+1) + type]);
609 if (n->type == -1) { /* new local lifetime */
613 /* TODO: Look if local really needs to be a savedvar */
614 n->savedvar = 0; /* SAVEDVAR; */
619 n->i_first_def = INT_MAX;
621 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
623 bv_set_bit(sets->kill, ls->maxlifetimes + v_index * (TYPE_ADR+1)+ type);
624 if (n->i_first_def > g_iindex) {
625 n->i_first_def = g_iindex;
629 bv_set_bit(sets->gen, ls->maxlifetimes + v_index * (TYPE_ADR+1) + type);
630 if (n->i_last_use < g_iindex) {
631 n->i_last_use = g_iindex;
636 void liveness_scan_registers_canditates(jitdata *jd, int b_index, int iindex,
637 stackptr src, lv_sets *sets)
639 /* methodinfo *lm; */
640 builtintable_entry *bte;
651 iptr = m->basicblocks[b_index].iinstr + iindex;
653 g_iindex = ls->icount_block[ls->sorted_rev[b_index]] + iindex;
657 /* local read (return adress) */
658 liveness_set_local(ls, b_index, g_iindex, iptr->op1, TYPE_ADR, sets, LV_GEN);
662 /* case ICMD_ELSE_ICONST: */
667 case ICMD_PUTSTATICCONST:
668 case ICMD_INLINE_START:
669 case ICMD_INLINE_END:
670 case ICMD_INLINE_GOTO:
674 /* local = local+<const> */
675 liveness_set_local(ls, b_index, g_iindex, iptr->op1, TYPE_INT, sets, LV_GEN);
676 liveness_set_local(ls, b_index, g_iindex, iptr->op1, TYPE_INT, sets, LV_KILL);
679 /* pop 0 push 1 const: const->stack */
686 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
689 /* pop 0 push 1 load: local->stack */
695 if (dst->varkind != LOCALVAR) {
696 /* local->value on stack */
697 liveness_set_local(ls, b_index, g_iindex, iptr->op1,
698 iptr->opc - ICMD_ILOAD, sets, LV_GEN);
700 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
701 } else /* if (dst->varnum != iptr->op1) */ {
703 liveness_set_local(ls, b_index, g_iindex, iptr->op1,
704 iptr->opc - ICMD_ILOAD, sets, LV_GEN);
705 liveness_set_local(ls, b_index, g_iindex, dst->varnum,
706 iptr->opc - ICMD_ILOAD, sets, LV_KILL);
711 /* Stack(arrayref,index)->stack */
722 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
723 /* stack->arrayref */
724 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
725 /* arrayref[index]->stack */
726 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
730 /* stack(arrayref,index,value)->arrayref[index]=value */
741 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
743 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
744 /* stack -> arrayref */
745 liveness_set_stack(ls, b_index, g_iindex, src->prev->prev, sets, LV_GEN);
748 /* pop 1 push 0 store: stack -> local */
754 if (src->varkind != LOCALVAR) {
756 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
757 liveness_set_local(ls, b_index, g_iindex, iptr->op1, iptr->opc - ICMD_ISTORE,
760 liveness_set_local(ls, b_index, g_iindex, src->varnum, iptr->opc-ICMD_ISTORE,
762 liveness_set_local(ls, b_index, g_iindex, iptr->op1, iptr->opc - ICMD_ISTORE,
768 case ICMD_POP: /* throw away a stackslot */
769 /* TODO: check if used anyway (DUP...) and change codegen to */
770 /* ignore this stackslot */
771 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
779 case ICMD_ARETURN: /* stack(value) -> [empty] */
781 case ICMD_ATHROW: /* stack(objref) -> undefined */
783 case ICMD_PUTSTATIC: /* stack(value) -> static_field */
784 case ICMD_PUTFIELDCONST:
786 /* pop 1 push 0 branch */
787 case ICMD_IFNULL: /* stack(value) -> branch? */
804 /* pop 1 push 0 table branch */
805 case ICMD_TABLESWITCH:
806 case ICMD_LOOKUPSWITCH:
808 case ICMD_MONITORENTER:
809 case ICMD_MONITOREXIT:
811 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
815 case ICMD_POP2: /* throw away 2 stackslots */
816 /* TODO: check if used anyway (DUP...) and change codegen to */
817 /* ignore this stackslot */
818 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
819 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
822 /* pop 2 push 0 branch */
824 case ICMD_IF_ICMPEQ: /* stack (v1,v2) -> branch(v1,v2) */
842 case ICMD_PUTFIELD: /* stack(objref,value) -> objref = value */
844 case ICMD_IASTORECONST:
845 case ICMD_LASTORECONST:
846 case ICMD_AASTORECONST:
847 case ICMD_BASTORECONST:
848 case ICMD_CASTORECONST:
849 case ICMD_SASTORECONST:
851 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
852 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
855 /* pop 0 push 1 dup */
857 /* src == dst->prev */
860 /* src and dst->prev are identical */
861 /* liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_KILL);
862 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_GEN);*/
864 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
868 /* pop 0 push 2 dup */
870 /* src == dst->prev->prev */
871 /* src->prev == dst->prev->prev->prev */
873 /* src->prev -> dst->prev-> */
875 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
876 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
879 /* pop 2 push 3 dup */
882 /* src->prev -> dst->prev */
883 /* src -> dst->prev->prev */
885 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
886 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
887 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
889 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
890 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
893 /* pop 3 push 4 dup */
896 /* src->prev -> dst->prev */
897 /* src->prev->prev -> dst->prev->prev */
898 /* dst (=src) -> dst->prev->prev->prev */
900 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
901 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
902 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
904 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev, sets,
906 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
907 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
908 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev, sets,
912 /* pop 3 push 5 dup */
915 /* src->prev -> dst->prev */
916 /* src->prev->prev -> dst->prev->prev */
917 /* dst (=src) -> dst->prev->prev->prev */
918 /* dst->prev (=src->prev) -> dst->prev->prev->prev->prev */
919 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
920 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
921 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
923 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev, sets,
925 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev->prev,
927 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
928 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
929 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev, sets,
933 /* pop 4 push 6 dup */
936 /* src->prev -> dst->prev */
937 /* src->prev->prev -> dst->prev->prev */
938 /* src->prev->prev->prev -> dst->prev->prev->prev */
939 /* dst (=src) -> dst->prev->prev->prev->prev */
940 /* dst->prev (=src->prev) -> dst->prev->prev->prev->prev->prev */
941 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
942 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
943 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
945 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev, sets,
947 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev->prev,
949 liveness_set_stack(ls, b_index, g_iindex,
950 dst->prev->prev->prev->prev->prev, sets, LV_KILL);
951 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
952 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
953 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev, sets,
955 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev->prev,
959 /* pop 2 push 2 swap */
961 /* src -> dst->prev */
962 /* src->prev -> dst */
963 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
964 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
965 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
966 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
1020 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1021 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1022 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
1026 case ICMD_LADDCONST:
1027 case ICMD_LSUBCONST:
1028 case ICMD_LMULCONST:
1032 case ICMD_LANDCONST:
1034 case ICMD_LXORCONST:
1035 case ICMD_LSHLCONST:
1036 case ICMD_LSHRCONST:
1037 case ICMD_LUSHRCONST:
1039 case ICMD_IADDCONST:
1040 case ICMD_ISUBCONST:
1041 case ICMD_IMULCONST:
1045 case ICMD_IANDCONST:
1047 case ICMD_IXORCONST:
1048 case ICMD_ISHLCONST:
1049 case ICMD_ISHRCONST:
1050 case ICMD_IUSHRCONST:
1052 /* case ICMD_IFEQ_ICONST: */
1053 /* case ICMD_IFNE_ICONST: */
1054 /* case ICMD_IFLT_ICONST: */
1055 /* case ICMD_IFGE_ICONST: */
1056 /* case ICMD_IFGT_ICONST: */
1057 /* case ICMD_IFLE_ICONST: */
1062 case ICMD_INT2SHORT:
1080 case ICMD_CHECKCAST:
1082 case ICMD_ARRAYLENGTH:
1083 case ICMD_INSTANCEOF:
1086 case ICMD_ANEWARRAY:
1089 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1090 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1094 case ICMD_GETSTATIC:
1097 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1100 /* pop many push any */
1102 case ICMD_INVOKESTATIC:
1103 case ICMD_INVOKESPECIAL:
1104 case ICMD_INVOKEVIRTUAL:
1105 case ICMD_INVOKEINTERFACE:
1106 INSTRUCTION_GET_METHODDESC(iptr,md);
1109 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1112 if (md->returntype.type != TYPE_VOID)
1113 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1121 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1124 if (md->returntype.type != TYPE_VOID)
1125 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1128 case ICMD_MULTIANEWARRAY:
1131 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1134 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1138 exceptions_throw_internalerror("Unknown ICMD %d during register allocation",
1145 * These are local overrides for various environment variables in Emacs.
1146 * Please do not remove this and leave it at the end of the file, where
1147 * Emacs will automagically detect them.
1148 * ---------------------------------------------------------------------
1151 * indent-tabs-mode: t
1155 * vim:noexpandtab:sw=4:ts=4: