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
41 #include "mm/memory.h"
43 #include "toolbox/logging.h"
44 #include "toolbox/worklist.h"
46 #include "vm/builtin.h"
47 #include "vm/exceptions.h"
48 #include "vm/global.h"
49 #include "vm/method.h"
50 #include "vm/resolve.h"
51 #include "vm/jit/codegen-common.h"
52 #include "vm/jit/jit.h"
53 #include "vm/jit/allocator/lsra.h"
54 #include "vm/jit/allocator/liveness.h"
57 /* function prototypes */
58 void liveness_scan_registers_canditates(jitdata *jd, int b_index, int iindex,
59 stackptr src, lv_sets *sets);
60 void liveness_set_stack(lsradata *ls, int block, int g_iindex, stackptr s,
61 lv_sets *sets, int op);
62 void liveness_set_local(lsradata *ls, int block, int g_iindex, s4 v_index,
63 int type, lv_sets *sets, int op);
65 void liveness_add_ss(struct lifetime *lt, stackptr s) {
67 /* Stackslot noch nicht eingetragen? */
69 if (s->varnum != lt->v_index) {
70 ss = DNEW(struct stackslot);
72 ss->s->varnum = lt->v_index;
73 ss->next = lt->local_ss;
75 if (s != NULL) lt->savedvar |= s->flags & SAVEDVAR;
76 if (s != NULL) lt->type = s->type;
80 void liveness_join_ss( struct lsradata *ls, struct stackelement *in,
81 struct stackelement *out) {
82 struct lifetime *lt, *lto;
83 struct stackslot *ss, *ss_last;
86 if (in->varnum != out->varnum) {
87 lt = &(ls->lifetime[-in->varnum - 1]);
91 #ifdef LV_DEBUG_VERBOSE
92 log_text("liveness_join_ss: lifetime for instack not found\n");
98 if (out->varnum >= 0) { /* no lifetime for this slot till now */
99 liveness_add_ss(lt, out);
101 lto = &(ls->lifetime[-out->varnum - 1]);
103 #ifdef LV_DEBUG_CHECK
104 if (lto->type == -1) {
105 #ifdef LV_DEBUG_VERBOSE
106 log_text("liveness_join_ss: lifetime for outstack not found\n");
111 #ifdef LV_DEBUG_CHECK
112 if (lto->type != lt->type) {
113 #ifdef LV_DEBUG_VERBOSE
114 log_text("liveness_join_ss: in/out stack type mismatch\n");
120 /* take Lifetime lto out of ls->lifetimes */
123 /* merge lto into lt of in */
125 /* change varnums of all lto->local_ss->s to lt->v_index */
126 ss_last = ss = lto->local_ss;
129 ss->s->varnum = lt->v_index;
132 /* link both lto->local_ss list to lt->local_ss */
133 if (ss_last != NULL) {
134 ss_last->next = lt->local_ss;
135 lt->local_ss = lto->local_ss;
138 lt->savedvar |= lto->savedvar;
139 lt->flags |= lto->flags;
140 lt->usagecount += lto->usagecount;
142 /*join of [bb|i]_first_def und [bb|i]_last_use */
143 if (lto->bb_first_def < lt->bb_first_def) {
144 lt->bb_first_def = lto->bb_first_def;
145 lt->i_first_def = lto->i_first_def;
146 } else if ((lto->bb_first_def == lt->bb_first_def) &&
147 ( lto->i_first_def < lt->i_first_def)) {
148 lt->i_first_def = lto->i_first_def;
150 if (lto->bb_last_use > lt->bb_last_use) {
151 lt->bb_last_use = lto->bb_last_use;
152 lt->i_last_use = lto->i_last_use;
153 } else if ((lto->bb_last_use == lt->bb_last_use) &&
154 ( lto->i_last_use > lt->i_last_use)) {
155 lt->i_last_use = lto->i_last_use;
161 /* join instack of Basic Block b_index with outstack of predecessors */
162 void liveness_join_lifetimes(jitdata *jd, int b_index) {
163 struct stackelement *in, *i, *out;
172 /* do not join instack of Exception Handler */
173 if (m->basicblocks[b_index].type == BBTYPE_EXH)
175 in=m->basicblocks[b_index].instack;
176 /* do not join first instack element of a subroutine header */
177 if (m->basicblocks[b_index].type == BBTYPE_SBR)
181 for (pred = ls->pred[b_index]; pred != NULL; pred = pred->next) {
182 out = m->basicblocks[pred->value].outstack;
183 for (i=in; (i != NULL); i = i->prev, out=out->prev) {
184 liveness_join_ss(ls, i, out);
190 void liveness_setup(jitdata *jd) {
191 int i, icount, b_index;
199 ls->icount_block = DMNEW(int, m->basicblockcount);
200 ls->icount_block[0] = icount = 0;
201 for(i = 0; i < m->basicblockcount; i++) {
203 /* create a global instruction index in icount_block */
204 if (ls->sorted[i-1] != -1)
205 icount += m->basicblocks[ ls->sorted[i-1] ].icount;
206 ls->icount_block[i] = icount;
209 if ((b_index = ls->sorted[i]) != -1) {
210 /* 'valid' Basic Block */
212 /* adapt in- and outstacks for LSRA */
213 src = m->basicblocks[b_index].instack;
214 if (m->basicblocks[b_index].type != BBTYPE_STD) {
215 #ifdef LV_DEBUG_CHECK
217 #ifdef LV_DEBUG_VERBOSE
218 log_text("No Incoming Stackslot for Exception/Subroutine BB\n");
223 if (src->varkind == STACKVAR)
224 src->varkind = TEMPVAR;
227 for (;src != NULL; src=src->prev) {
228 /* no ARGVAR possible at BB Boundaries with LSRA! */
229 /* -> change to TEMPVAR */
230 if (src->varkind == ARGVAR ) {
231 src->varkind = TEMPVAR;
232 /* On Architectures with own return registers a return
233 stackslot is marked as varkind=ARGVAR with varnum=-1
234 but for lsra a varkind==TEMPVAR, varnum=-1 would mean,
235 that already a lifetime was allocated! */
236 if (src->varnum < 0) src->varnum = 0;
238 else if (src->varkind == LOCALVAR ) {
239 /* only allowed for top most ss at sbr or exh entries! */
240 #ifdef LV_DEBUG_VERBOSE
241 log_text("LOCALVAR at basicblock instack\n");
245 if (src->varkind == STACKVAR )
246 /* no Interfaces at BB Boundaries with LSRA! */
247 /* -> change to TEMPVAR */
248 src->varkind = TEMPVAR;
252 src = m->basicblocks[b_index].outstack;
253 for (;src != NULL; src=src->prev) {
254 if (src->varkind == ARGVAR ) {
255 #ifdef LV_DEBUG_VERBOSE
256 log_text("ARGVAR at basicblock outstack\n");
259 } else if (src->varkind == LOCALVAR ) {
260 #ifdef LV_DEBUG_VERBOSE
261 log_text("LOCALVAR at basicblock outstack\n");
265 /* no Interfaces at BB Boundaries with LSRA! */
266 /* -> change to TEMPVAR */
267 if (src->varkind == STACKVAR )
268 src->varkind = TEMPVAR;
275 void liveness_init(jitdata *jd) {
288 for(i = 0; i < m->basicblockcount; i++) {
289 if ((b_index = ls->sorted[i]) != -1) {
290 /* 'valid' Basic Block */
292 /* Scan Number of Stack Lifetimes */
293 lifetimes += m->basicblocks[b_index].indepth;
295 dst = m->basicblocks[b_index].instack;
296 len = m->basicblocks[b_index].icount;
297 iptr = m->basicblocks[b_index].iinstr;
298 for (;len>0; len--, iptr++) {
321 if (( dst != NULL) && (src != dst))
327 ls->maxlifetimes = lifetimes;
328 ls->lifetimecount = lifetimes + jd->maxlocals * (TYPE_ADR+1);
331 void liveness_scan_basicblock(jitdata *jd, int b_index,
332 lv_sets *sets, int lifetimes) {
343 src = m->basicblocks[b_index].instack;
345 iindex = m->basicblocks[b_index].icount - 1;
346 /* set iptr to last instruction of BB */
347 iptr = m->basicblocks[b_index].iinstr + iindex;
349 bv_reset(sets->in, lifetimes);
351 for (;iindex >= 0; iindex--, iptr--) {
352 /* get source Stack for the current instruction */
353 /* destination stack is available as iptr->dst */
354 /* source stack is either the destination stack of the previos */
355 /* instruction, or the basicblock instack for the first instruction */
356 if (iindex) /* != 0 is > 0 here, since iindex ist always >= 0 */
359 src=m->basicblocks[b_index].instack;
361 /* Reset kill and gen bitvectors for use in */
362 /* liveness_scan_register_canditates */
364 bv_reset(sets->kill, lifetimes);
365 bv_reset(sets->gen, lifetimes);
367 /* get gen and kill set of instruction */
369 liveness_scan_registers_canditates(jd, b_index, iindex, src, sets);
371 /* tmp = out(instr) - kill(instr) */
373 bv_minus(sets->tmp, sets->out, sets->kill, lifetimes);
375 /* in = gen(instr) union tmp = gen union (out - kill) */
377 bv_union(sets->in, sets->gen, sets->tmp, lifetimes);
379 /* Set SAVEDVAR flag for locals */
381 if (op_needs_saved[iptr->opc])
382 for(i = ls->maxlifetimes; i < ls->lifetimecount; i++)
383 if (!ls->lifetime[i].savedvar)
384 if ( bv_get_bit(sets->in,i) && bv_get_bit(sets->out,i) )
385 ls->lifetime[i].savedvar = SAVEDVAR;
387 /* out(instr-1) = in(instr) (only one successor)*/
389 bv_copy(sets->out, sets->in, lifetimes);
391 /* create gen sets for incoming stackslots */
393 /* global instruction index for bb b_index */
395 iindex = ls->icount_block[ls->sorted_rev[b_index]];
396 bv_reset(sets->kill, lifetimes);
397 bv_reset(sets->gen, lifetimes);
398 src = m->basicblocks[b_index].instack;
399 if (m->basicblocks[b_index].type != BBTYPE_STD) {
400 liveness_set_stack(ls, b_index, iindex, src, sets, LV_KILL);
403 for (;src != NULL; src=src->prev) {
404 /* only TEMP or LOCALVAR by now possible */
405 /* liveness_set_stack redirects for LOCALVARS */
406 liveness_set_stack(ls, b_index, iindex, src, sets, LV_GEN);
407 _LV_ASSERT( ((src->varkind == LOCALVAR) || (src->varkind == TEMPVAR)) );
409 /* in = gen union (out - kill) */
410 bv_minus(sets->tmp, sets->out, sets->kill, lifetimes);
411 bv_union(sets->in, sets->gen, sets->tmp, lifetimes);
414 void liveness(jitdata *jd) {
427 #ifdef LV_DEBUG_CHECK
433 /***************************************************************************
435 - Exact Lifeness Information for intra Basic Blocks Stackslots are trivial
436 They should not be included in the gen, kill, in and out sets to improve
438 - Local Vars as represented in rd->locals "are quite sparse". An intermediate
439 representation for really used index/type pairs should be implemented.
440 ***************************************************************************/
446 if (ls->lifetimecount == 0)
448 ls->lifetime = DMNEW(struct lifetime, ls->lifetimecount);
449 for (i=0; i < ls->lifetimecount; i++) ls->lifetime[i].type = -1;
451 sets.gen = bv_new(ls->lifetimecount);
452 sets.kill = bv_new(ls->lifetimecount);
453 sets.tmp = bv_new(ls->lifetimecount);
454 sets.out = bv_new(ls->lifetimecount);
455 sets.in = bv_new(ls->lifetimecount);
457 params = bv_new(ls->lifetimecount);
459 visited = bv_new(m->basicblockcount);
460 buff = DMNEW(char, ls->lifetimecount+1);
462 out = DMNEW(bitvector, m->basicblockcount);
463 in = DMNEW(bitvector, m->basicblockcount);
464 for(i = 0; i < m->basicblockcount; i++) {
465 out[i] = bv_new(ls->lifetimecount);
466 in[i] = bv_new(ls->lifetimecount);
469 /* set in[0] to arguments */
470 /* <-> kill at 0, -1 */
472 for (p = 0, i = 0; p < md->paramcount; p++) {
473 t = md->paramtypes[p].type;
475 if (rd->locals[i][t].type >= 0)
476 /* Param to Local init happens before normal Code */
477 liveness_set_local(ls, 0, -1, i, t, &sets, LV_KILL);
479 if (IS_2_WORD_TYPE(t)) /* increment local counter a second time */
480 i++; /* for 2 word types */
482 bv_copy(params, sets.kill, ls->lifetimecount);
484 /* fill Worklist so that last node will be taken out first */
485 W = wl_new(m->basicblockcount);
486 for (i = 0; i < m->basicblockcount; i++)
487 if (ls->sorted[i] != -1)
488 wl_add(W, ls->sorted[i]);
490 /* Worklist algorithm*/
491 while (!wl_is_empty(W)) {
494 /* out[b_index] = for all s element of successors(b_index) union in[s]*/
495 for (succ = ls->succ[b_index]; succ != NULL; succ = succ->next)
496 bv_union(out[b_index], out[b_index], in[succ->value],
499 bv_copy(sets.out, out[b_index], ls->lifetimecount);
501 /* compute in[b_index] */
502 liveness_scan_basicblock(jd, b_index, &sets, ls->lifetimecount);
504 if (!bv_get_bit(visited, b_index)) {
505 liveness_join_lifetimes(jd, b_index);
506 bv_set_bit(visited, b_index);
509 if (!bv_equal(sets.in, in[b_index], ls->lifetimecount)) {
510 bv_copy(in[b_index], sets.in, ls->lifetimecount);
511 for(pred = ls->pred[b_index]; pred != NULL; pred = pred->next)
512 wl_add(W, pred->value);
516 #ifdef LV_DEBUG_CHECK
517 s = m->basicblocks[b_index].instack;
518 if ((s != NULL) && (m->basicblocks[b_index].flags != BBTYPE_STD))
520 for( ; s != NULL; s = s->prev) {
521 #ifdef LV_DEBUG_VERBOSE
522 if (!bv_get_bit(in[b_index], -s->varnum - 1)) {
523 log_text("liveness: Error In Stacklot not live!\n");
526 _LV_ASSERT( (bv_get_bit(in[b_index], -s->varnum - 1)) );
530 for (i = 0; i < m->basicblockcount; i++)
531 if ((b_index=ls->sorted[i]) != -1) {
532 for(t = 0; t < ls->lifetimecount; t++) {
533 if (ls->lifetime[t].type != -1) {
534 if (bv_get_bit(in[b_index], t)) {
535 p = ls->icount_block[ls->sorted_rev[b_index]];
536 if (p < ls->lifetime[t].i_first_def)
537 ls->lifetime[t].i_first_def = p;
539 if (bv_get_bit(out[b_index], t)) {
541 ls->icount_block[ls->sorted_rev[b_index]]+m->basicblocks[b_index].icount - 1;
542 if (p > ls->lifetime[t].i_last_use)
543 ls->lifetime[t].i_last_use = p;
551 struct lifetime *liveness_get_ss_lifetime(lsradata *ls, stackptr s) {
554 if (s->varnum >= 0) { /* new stackslot lifetime */
555 #ifdef LV_DEBUG_VERBOSE
556 if (-ls->v_index - 1 >= ls->maxlifetimes) {
557 printf("%i %i\n", -ls->v_index - 1, ls->maxlifetimes);
560 _LV_ASSERT(-ls->v_index - 1 < ls->maxlifetimes);
562 n = &(ls->lifetime[-ls->v_index - 1]);
564 n->v_index = ls->v_index--;
568 n->i_first_def = INT_MAX;
573 n = &(ls->lifetime[-s->varnum - 1]);
575 liveness_add_ss( n, s);
579 void liveness_set_stack(lsradata *ls, int block, int g_iindex, stackptr s,
584 if (s->varkind == LOCALVAR) {
585 liveness_set_local(ls, block, g_iindex, s->varnum, s->type, sets, op);
586 } else if (s->varkind == TEMPVAR) {
587 n = liveness_get_ss_lifetime(ls, s);
589 bv_set_bit(sets->kill, -s->varnum - 1);
590 if (n->i_first_def > g_iindex) {
591 n->i_first_def = g_iindex;
595 bv_set_bit(sets->gen, -s->varnum - 1);
596 if (n->i_last_use < g_iindex) {
597 n->i_last_use = g_iindex;
600 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
604 void liveness_set_local(lsradata *ls, int block, int g_iindex, s4 v_index,
605 int type, lv_sets *sets, int op) {
608 n = &(ls->lifetime[ ls->maxlifetimes + v_index * (TYPE_ADR+1) + type]);
610 if (n->type == -1) { /* new local lifetime */
614 /* TODO: Look if local really needs to be a savedvar */
615 n->savedvar = 0; /* SAVEDVAR; */
620 n->i_first_def = INT_MAX;
622 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
624 bv_set_bit(sets->kill, ls->maxlifetimes + v_index * (TYPE_ADR+1)+ type);
625 if (n->i_first_def > g_iindex) {
626 n->i_first_def = g_iindex;
630 bv_set_bit(sets->gen, ls->maxlifetimes + v_index * (TYPE_ADR+1) + type);
631 if (n->i_last_use < g_iindex) {
632 n->i_last_use = g_iindex;
637 void liveness_scan_registers_canditates(jitdata *jd, int b_index, int iindex,
638 stackptr src, lv_sets *sets)
640 /* methodinfo *lm; */
641 builtintable_entry *bte;
652 iptr = m->basicblocks[b_index].iinstr + iindex;
654 g_iindex = ls->icount_block[ls->sorted_rev[b_index]] + iindex;
658 /* local read (return adress) */
659 liveness_set_local(ls, b_index, g_iindex, iptr->op1, TYPE_ADR, sets, LV_GEN);
663 /* case ICMD_ELSE_ICONST: */
668 case ICMD_PUTSTATICCONST:
669 case ICMD_INLINE_START:
670 case ICMD_INLINE_END:
671 case ICMD_INLINE_GOTO:
675 /* local = local+<const> */
676 liveness_set_local(ls, b_index, g_iindex, iptr->op1, TYPE_INT, sets, LV_GEN);
677 liveness_set_local(ls, b_index, g_iindex, iptr->op1, TYPE_INT, sets, LV_KILL);
680 /* pop 0 push 1 const: const->stack */
687 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
690 /* pop 0 push 1 load: local->stack */
696 if (dst->varkind != LOCALVAR) {
697 /* local->value on stack */
698 liveness_set_local(ls, b_index, g_iindex, iptr->op1,
699 iptr->opc - ICMD_ILOAD, sets, LV_GEN);
701 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
702 } else /* if (dst->varnum != iptr->op1) */ {
704 liveness_set_local(ls, b_index, g_iindex, iptr->op1,
705 iptr->opc - ICMD_ILOAD, sets, LV_GEN);
706 liveness_set_local(ls, b_index, g_iindex, dst->varnum,
707 iptr->opc - ICMD_ILOAD, sets, LV_KILL);
712 /* Stack(arrayref,index)->stack */
723 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
724 /* stack->arrayref */
725 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
726 /* arrayref[index]->stack */
727 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
731 /* stack(arrayref,index,value)->arrayref[index]=value */
742 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
744 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
745 /* stack -> arrayref */
746 liveness_set_stack(ls, b_index, g_iindex, src->prev->prev, sets, LV_GEN);
749 /* pop 1 push 0 store: stack -> local */
755 if (src->varkind != LOCALVAR) {
757 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
758 liveness_set_local(ls, b_index, g_iindex, iptr->op1, iptr->opc - ICMD_ISTORE,
761 liveness_set_local(ls, b_index, g_iindex, src->varnum, iptr->opc-ICMD_ISTORE,
763 liveness_set_local(ls, b_index, g_iindex, iptr->op1, iptr->opc - ICMD_ISTORE,
769 case ICMD_POP: /* throw away a stackslot */
770 /* TODO: check if used anyway (DUP...) and change codegen to */
771 /* ignore this stackslot */
772 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
780 case ICMD_ARETURN: /* stack(value) -> [empty] */
782 case ICMD_ATHROW: /* stack(objref) -> undefined */
784 case ICMD_PUTSTATIC: /* stack(value) -> static_field */
785 case ICMD_PUTFIELDCONST:
787 /* pop 1 push 0 branch */
788 case ICMD_IFNULL: /* stack(value) -> branch? */
805 /* pop 1 push 0 table branch */
806 case ICMD_TABLESWITCH:
807 case ICMD_LOOKUPSWITCH:
809 case ICMD_MONITORENTER:
810 case ICMD_MONITOREXIT:
812 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
816 case ICMD_POP2: /* throw away 2 stackslots */
817 /* TODO: check if used anyway (DUP...) and change codegen to */
818 /* ignore this stackslot */
819 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
820 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
823 /* pop 2 push 0 branch */
825 case ICMD_IF_ICMPEQ: /* stack (v1,v2) -> branch(v1,v2) */
843 case ICMD_PUTFIELD: /* stack(objref,value) -> objref = value */
845 case ICMD_IASTORECONST:
846 case ICMD_LASTORECONST:
847 case ICMD_AASTORECONST:
848 case ICMD_BASTORECONST:
849 case ICMD_CASTORECONST:
850 case ICMD_SASTORECONST:
852 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
853 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
856 /* pop 0 push 1 dup */
858 /* src == dst->prev */
861 /* src and dst->prev are identical */
862 /* liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_KILL);
863 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_GEN);*/
865 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
869 /* pop 0 push 2 dup */
871 /* src == dst->prev->prev */
872 /* src->prev == dst->prev->prev->prev */
874 /* src->prev -> dst->prev-> */
876 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
877 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
880 /* pop 2 push 3 dup */
883 /* src->prev -> dst->prev */
884 /* src -> dst->prev->prev */
886 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
887 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
888 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
890 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
891 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
894 /* pop 3 push 4 dup */
897 /* src->prev -> dst->prev */
898 /* src->prev->prev -> dst->prev->prev */
899 /* dst (=src) -> dst->prev->prev->prev */
901 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
902 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
903 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
905 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev, sets,
907 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
908 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
909 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev, sets,
913 /* pop 3 push 5 dup */
916 /* src->prev -> dst->prev */
917 /* src->prev->prev -> dst->prev->prev */
918 /* dst (=src) -> dst->prev->prev->prev */
919 /* dst->prev (=src->prev) -> dst->prev->prev->prev->prev */
920 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
921 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
922 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
924 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev, sets,
926 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev->prev,
928 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
929 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
930 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev, sets,
934 /* pop 4 push 6 dup */
937 /* src->prev -> dst->prev */
938 /* src->prev->prev -> dst->prev->prev */
939 /* src->prev->prev->prev -> dst->prev->prev->prev */
940 /* dst (=src) -> dst->prev->prev->prev->prev */
941 /* dst->prev (=src->prev) -> dst->prev->prev->prev->prev->prev */
942 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
943 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
944 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev, sets,
946 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev, sets,
948 liveness_set_stack(ls, b_index, g_iindex, dst->prev->prev->prev->prev,
950 liveness_set_stack(ls, b_index, g_iindex,
951 dst->prev->prev->prev->prev->prev, sets, LV_KILL);
952 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
953 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
954 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev, sets,
956 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev->prev->prev,
960 /* pop 2 push 2 swap */
962 /* src -> dst->prev */
963 /* src->prev -> dst */
964 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
965 liveness_set_stack(ls, b_index, g_iindex, dst->prev, sets, LV_KILL);
966 liveness_set_stack(ls, b_index, g_iindex + 1, src, sets, LV_GEN);
967 liveness_set_stack(ls, b_index, g_iindex + 1, src->prev, sets, LV_GEN);
1021 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1022 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1023 liveness_set_stack(ls, b_index, g_iindex, src->prev, sets, LV_GEN);
1027 case ICMD_LADDCONST:
1028 case ICMD_LSUBCONST:
1029 case ICMD_LMULCONST:
1033 case ICMD_LANDCONST:
1035 case ICMD_LXORCONST:
1036 case ICMD_LSHLCONST:
1037 case ICMD_LSHRCONST:
1038 case ICMD_LUSHRCONST:
1040 case ICMD_IADDCONST:
1041 case ICMD_ISUBCONST:
1042 case ICMD_IMULCONST:
1046 case ICMD_IANDCONST:
1048 case ICMD_IXORCONST:
1049 case ICMD_ISHLCONST:
1050 case ICMD_ISHRCONST:
1051 case ICMD_IUSHRCONST:
1053 /* case ICMD_IFEQ_ICONST: */
1054 /* case ICMD_IFNE_ICONST: */
1055 /* case ICMD_IFLT_ICONST: */
1056 /* case ICMD_IFGE_ICONST: */
1057 /* case ICMD_IFGT_ICONST: */
1058 /* case ICMD_IFLE_ICONST: */
1063 case ICMD_INT2SHORT:
1081 case ICMD_CHECKCAST:
1083 case ICMD_ARRAYLENGTH:
1084 case ICMD_INSTANCEOF:
1087 case ICMD_ANEWARRAY:
1090 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1091 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1095 case ICMD_GETSTATIC:
1098 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1101 /* pop many push any */
1103 case ICMD_INVOKESTATIC:
1104 case ICMD_INVOKESPECIAL:
1105 case ICMD_INVOKEVIRTUAL:
1106 case ICMD_INVOKEINTERFACE:
1107 INSTRUCTION_GET_METHODDESC(iptr,md);
1110 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1113 if (md->returntype.type != TYPE_VOID)
1114 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1122 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1125 if (md->returntype.type != TYPE_VOID)
1126 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1129 case ICMD_MULTIANEWARRAY:
1132 liveness_set_stack(ls, b_index, g_iindex, src, sets, LV_GEN);
1135 liveness_set_stack(ls, b_index, g_iindex, dst, sets, LV_KILL);
1139 exceptions_throw_internalerror("Unknown ICMD %d during register allocation",
1146 * These are local overrides for various environment variables in Emacs.
1147 * Please do not remove this and leave it at the end of the file, where
1148 * Emacs will automagically detect them.
1149 * ---------------------------------------------------------------------
1152 * indent-tabs-mode: t
1156 * vim:noexpandtab:sw=4:ts=4: