1 /* src/vm/jit/optimizing/ssa.c - static single-assignment form
3 Copyright (C) 2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
31 #include "mm/memory.h"
33 #include "toolbox/bitvector.h"
34 #include "toolbox/worklist.h"
36 #include "vm/builtin.h"
38 #include "vm/jit/jit.h" /* icmd_table */
40 #include "vm/jit/ir/bytecode.h"
42 #include "vm/jit/optimizing/dominators.h"
43 #include "vm/jit/optimizing/graph.h"
44 #include "vm/jit/optimizing/lifetimes.h"
45 #include "vm/jit/optimizing/lsra.h"
47 #include "vm/jit/optimizing/ssa.h"
48 #include "vm/jit/optimizing/ssa_rename.h"
49 #include "vm/jit/optimizing/ssa_phi.h"
51 #include "vm/jit/python.h"
53 #if defined(SSA_DEBUG_VERBOSE)
54 #include "vmcore/options.h" /* compileverbose */
57 /* function prototypes */
58 void ssa_set_local_def(lsradata *, int , int);
59 void ssa_set_interface(jitdata *, basicblock *, s4 *);
61 void dead_code_elimination(jitdata *jd, graphdata *gd);
62 void copy_propagation(jitdata *jd, graphdata *gd);
63 void ssa_replace_use_sites(jitdata *, graphdata *, struct lifetime *,
66 void ssa_set_def(lsradata *, int , int );
67 void ssa_set_local_def(lsradata *, int , int );
68 void ssa_set_iovar(lsradata *, s4 , int , s4 *);
69 void ssa_set_interface(jitdata *, basicblock *, s4 *);
72 #ifdef SSA_DEBUG_VERBOSE
73 void ssa_print_trees(jitdata *jd, graphdata *gd, dominatordata *dd);
74 void ssa_print_lt(lsradata *ls);
75 void _ssa_print_lt(struct lifetime *lt);
76 void ssa_show_variable(jitdata *jd, int index, varinfo *v, int stage);
77 void ssa_print_phi(lsradata *, graphdata *);
80 /* ssa ************************************************************************
84 SSA Algorithms are based on "modern compiler implementation in C" from andrew
85 w. appel, edition 2004
88 page 441 Algorithm 19.6. Inserting phi-functions:
92 - if Y not element of A phi [n]
93 + if a not element of A phi [n]
94 insert the statment a <- ...
97 - A phi [n] <- A phi [n] join {Y}
98 + A phi [n] <- A phi [n] join {a}
99 - if Y not element of A orig [n]
100 + if a not element of A orig [Y]
103 ******************************************************************************/
104 void xssa(jitdata *jd);
105 void yssa(jitdata *jd);
106 void ssa(jitdata *jd) {
107 struct dominatordata *dd;
111 #if defined(ENABLE_LOOPS)
112 /* Loop optimization "destroys" the basicblock array */
113 /* TODO: work with the basicblock list */
115 log_text("lsra not possible with loop optimization\n");
121 cfg_add_exceptional_edges(jd);
122 /*pythonpass_run(jd, "foo", "cfg_print");*/
123 /*dominator_tree_validate(jd, dd);*/
124 /*pythonpass_run(jd, "ssa2", "main");*/
125 /*pythonpass_run(jd, "alt_ssa", "main");*/
126 /*pythonpass_run(jd, "foo", "before");*/
128 /*if (getenv("XSSA")) {
129 dominator_tree_build(jd);
130 dominance_frontier_build(jd);
135 /*pythonpass_run(jd, "foo", "after");*/
141 /* Generate the Control Flow Graph */
142 /* Add one for a Basic Block 0 to be inserted, so lateron */
143 /* with SSA Parameter initialization is handled right */
145 gd = graph_init(jd->basicblockcount + 1);
146 graph_make_cfg(jd, gd);
148 dd = compute_Dominators(gd, ls->basicblockcount);
149 computeDF(gd, dd, ls->basicblockcount, 0);
151 ssa_place_phi_functions(jd, gd, dd);
152 ssa_rename(jd, gd, dd);
153 #ifdef SSA_DEBUG_VERBOSE
154 if (compileverbose) {
155 printf("Phi before Cleanup\n");
156 ssa_print_phi(ls, gd);
160 lt_scanlifetimes(jd, gd, dd);
161 #ifdef SSA_DEBUG_VERBOSE
162 if (compileverbose) {
167 dead_code_elimination(jd, gd);
168 #ifdef SSA_DEBUG_VERBOSE
169 if (compileverbose) {
170 printf("Phi after dead code elemination\n");
171 ssa_print_phi(ls, gd);
177 copy_propagation(jd, gd);
178 #ifdef SSA_DEBUG_VERBOSE
179 if (compileverbose) {
180 printf("Phi after copy propagation\n");
181 ssa_print_phi(ls, gd);
187 ssa_generate_phi_moves(jd, gd);
188 transform_BB(jd, gd);
190 lt_lifeness_analysis(jd, gd);
192 #ifdef SSA_DEBUG_CHECK
194 int i, j, pred, in_d, out_d;
195 graphiterator iter_pred;
202 for(i = 0; i < ls->basicblockcount; i++) {
203 if (ls->basicblocks[i]->indepth != 0) {
204 pred = graph_get_first_predecessor(gd, i, &iter_pred);
205 for (; (pred != -1); pred = graph_get_next(&iter_pred)) {
206 in_d = ls->basicblocks[i]->indepth - 1;
207 in = ls->basicblocks[i]->invars;
208 for (; in_d >= 0; in_d--) {
210 for (j = 0; (!phi_define) && (j<ls->ssavarcount); j++) {
211 if (ls->phi[i][j] != NULL)
212 if (ls->phi[i][j][0] == in[in_d])
216 /* in not defined in phi function -> check with */
217 /* outstack(s) of predecessor(s) */
218 out_d = ls->basicblocks[pred]->outdepth - 1;
219 out = ls->basicblocks[pred]->outvars;
220 _SSA_ASSERT(out_d >= in_d);
221 for(; out_d > in_d; out_d--);
222 if ((in[in_d] != out[out_d]) ||
223 (VAR(in[in_d])->flags != VAR(out[out_d])->flags)) {
224 printf("Method: %s %s\n",
225 m->clazz->name->text, m->name->text);
226 printf("Error: Stack Varnum Mismatch BBin %3i BBout %3i Stackdepth %3i\n", i, pred, in_d);
228 printf("Error: Stack Varnum Mismatch BBin %3i BBout %3i Stackdepth %3i\n", i, pred, in_d);
230 /* _SSA_ASSERT(0); */
241 #ifdef SSA_DEBUG_VERBOSE
243 ssa_print_trees(jd, gd, dd);
248 /* ssa_init *******************************************************************
250 Initialise data structures for ssa
252 IOVARS of same stackdepth and same type are coalesced:
253 interface_map[ 5 * stackdepth + type ] = new_varindex with
254 0 <= new_varindex < ls->ssavarcount
256 TODO: check if coalescing of IOVARS of same stackdepth and type only of adjacent
257 basic blocks could decrease the number of phi functions and so improve ssa
258 analysis performance!
260 All LOCALVARS and IOVARS get a new unique varindex:
261 ls->new_varindex[0..jd->varcount[ = new_varindex with
262 0 <= new_varindex < ls->ssavarcount
264 The jd->varcount bits long bitvectors ls->var_def[0..jd->basicblockindex+1[
265 are set to the definitions of LOCALVARS and IOVARS. (So the only the first
266 ls->ssavarcount bits of each of these vectors contain valid data, but
267 ls->ssavarcount is computed at the same time as the definitons are stored.)
269 The basic block number used as index for the bitvector array ls->var_def is
270 already shifted by one to make space for the new basic block 0 for parameter
273 ******************************************************************************/
275 void ssa_init(jitdata *jd) {
278 int i, l, b_index, len;
281 s4 *interface_map; /* holds an new unique index for every used */
282 /* basic block inoutvar described by a dupel */
283 /*(depth,type). Used to coalesce the inoutvars*/
286 builtintable_entry *bte;
293 #if defined(SSA_DEBUG_CHECK) || defined(SSA_DEBUG_VERBOSE)
294 # if defined(SSA_DEBUG_VERBOSE)
295 if (compileverbose) {
296 printf("%s %s ",m->clazz->name->text, m->name->text);
297 if (code_is_leafmethod(jd->code))
298 printf("**Leafmethod**");
302 if (strcmp(m->clazz->name->text,"spec/benchmarks/_213_javac/Parser")==0)
303 if (strcmp(m->name->text,"parseTerm")==0)
304 # if defined(SSA_DEBUG_VERBOSE)
306 printf("12-------------------12\n");
308 { int dummy=1; dummy++; }
312 #ifdef SSA_DEBUG_VERBOSE
314 printf("ssa_init: basicblockcount %3i localcount %3i\n",
315 jd->basicblockcount, jd->localcount);
318 /* As first step all definitions of local variables and in/out vars are */
319 /* gathered. in/outvars are coalesced for same type and depth */
320 /* "normal" tempvars (just living within one basicblock are) ignored */
322 ls->num_defs = DMNEW(int, jd->varcount);
323 ls->new_varindex = DMNEW(int , jd->varcount);
325 for(p = 0; p < jd->varcount; p++) {
327 ls->new_varindex[p] = UNUSED;
330 /* init Var Definition bitvectors */
332 ls->var_def = DMNEW(int *, jd->basicblockcount + 1);
333 for(i = 0; i < jd->basicblockcount + 1; i++) {
334 ls->var_def[i] = bv_new(jd->varcount);
339 /* Add parameters first in right order, so the new local indices */
340 /* 0..p will correspond to "their" parameters */
341 /* They get defined at the artificial Block 0, the real method bbs will */
342 /* be ed to start at block 1 */
344 /* don't look at already eliminated (not used) parameters (locals) */
346 for (p = 0, l = 0; p < md->paramcount; p++) {
347 t = md->paramtypes[p].type;
348 i = jd->local_map[l * 5 + t];
350 if (IS_2_WORD_TYPE(t)) /* increment local counter a second time */
351 l++; /* for 2 word types */
354 ssa_set_local_def(ls, -1, i);
357 _SSA_ASSERT(ls->ssavarcount < jd->varcount);
359 /* coalesce bb in/out vars */
361 interface_map = DMNEW(s4, jd->stackcount * 5);
362 for(i = 0; i < jd->stackcount * 5; i++)
363 interface_map[i] = UNUSED;
365 bptr = jd->basicblocks;
367 for(; bptr != NULL; bptr = bptr->next) {
368 #ifdef SSA_DEBUG_VERBOSE
370 printf("ssa_init: BB %3i flags %3x\n",bptr->nr, bptr->flags);
372 if (bptr->flags >= BBREACHED) {
374 /* 'valid' Basic Block */
380 ssa_set_interface(jd, bptr, interface_map);
382 /* !!!!!!!!! not true for now !!!!!!!!! */
383 /* All baseline optimizations from stack.c are turned off for */
386 for (; len > 0; len--, iptr++) {
388 /* Look for definitions (iptr->dst). INVOKE and BUILTIN have */
389 /* an optional dst - so they to be checked first */
392 if (icmd_table[iptr->opc].dataflow == DF_INVOKE) {
393 INSTRUCTION_GET_METHODDESC(iptr,md);
394 if (md->returntype.type != TYPE_VOID)
395 v = iptr->dst.varindex;
397 else if (icmd_table[iptr->opc].dataflow == DF_BUILTIN) {
398 bte = iptr->sx.s23.s3.bte;
400 if (md->returntype.type != TYPE_VOID)
401 v = iptr->dst.varindex;
403 else if (icmd_table[iptr->opc].dataflow >= DF_DST_BASE) {
404 v = iptr->dst.varindex;
408 if (( v < jd->localcount) || ( VAR(v)->flags & INOUT )) {
410 /* !IS_TEMPVAR && !IS_PREALLOC == (IS_LOCALVAR || IS_INOUT) */
412 ssa_set_local_def(ls, b_index, v);
418 _SSA_ASSERT(ls->ssavarcount < jd->varcount);
420 #ifdef SSA_DEBUG_VERBOSE
421 if (compileverbose) {
422 printf("ssa_init: Vars: Orig:%3i SSAVar: %3i\n", jd->varcount,
424 for(i = 0; i < jd->varcount; i++) {
425 if ((i < jd->localcount) || ( VAR(i)->flags & INOUT)) {
426 printf("%3i(%3i,%3x) ",i,VAR(i)->type, VAR(i)->flags);
427 ssa_show_variable(jd, i, VAR(i),0);
428 if (i < ls->ssavarcount) {
429 printf(" -> %3i", ls->new_varindex[i]);
438 /* ssa_set_def ****************************************************************
440 Helper for ssa_set_local_def and ssa_set_interface
442 The definition of a var is stored in the bitvector array ls->var_def.
444 The number of definitons of each var is counted, so the number of new vars with
447 ******************************************************************************/
449 void ssa_set_def(lsradata *ls, int b_index, int varindex) {
451 /* b_index + 1 to leave space for the param init block 0 */
453 bv_set_bit(ls->var_def[b_index + 1], varindex);
455 /* count number of defs for every var since SSA */
456 /* will create a new var for every definition */
458 ls->num_defs[varindex]++;
461 /* ssa_set_local_def **********************************************************
465 Assigns a new unique index for the local var varindex (if not already done so)
466 and then calls ssa_set_def to remember the definition in the bitvector array
469 ******************************************************************************/
471 void ssa_set_local_def(lsradata *ls, int b_index, int varindex) {
473 if (ls->new_varindex[varindex] == UNUSED) {
474 ls->new_varindex[varindex] = ls->ssavarcount++;
477 ssa_set_def(ls, b_index, ls->new_varindex[varindex]);
480 /* ssa_set_local_def **********************************************************
482 Helper for ssa_set_interface
484 IN: ls pointer to lsradata structure
485 iovar varindex of INOUTVAR to process
486 map_index stackdepth * 5 + type, used for coalescing IOVARS.
489 interface_map used for coalescing IOVARS. interface_map[map_index] ==
490 UNUSED, if this map_index (==stackdepth,type tupel) did not
491 occur till now. Then interface_map[map_index] will be set
492 to a new unique index.
493 ls->new_varindex will be set to this new unique index to map the old
494 varindizes to the new ones.
496 Assigns a new unique index for the local var varindex (if not already done so)
497 and then calls ssa_set_def to remember the definition in the bitvector array
500 ******************************************************************************/
502 void ssa_set_iovar(lsradata *ls, s4 iovar, int map_index, s4 *interface_map) {
503 if (interface_map[map_index] == UNUSED)
504 interface_map[map_index] = ls->ssavarcount++;
506 ls->new_varindex[iovar] = interface_map[map_index];
510 /* ssa_set_interface ***********************************************************
514 IN: ls pointer to lsradata structure
515 *bptr pointer to the basic block to be processed
518 interface_map used for coalescing IOVARS. interface_map[map_index] ==
519 UNUSED, if this map_index (==stackdepth,type tupel) did not
520 occur till now. Then interface_map[map_index] will be set
521 to a new unique index. (see ssa_set_iovar)
523 Searches the basic block given by *bptr for IN and OUTVARS and coalesces them
524 for each unique stackdepth,type dupel. For each OUTVAR with a different or no
525 INVAR at the same stackdepth the definition of this OUTVAR in this basic block
526 is remembered in ls->var_def. (see ssa_set_def)
528 ******************************************************************************/
530 void ssa_set_interface(jitdata *jd, basicblock *bptr, s4 *interface_map) {
533 int o_map_index, i_map_index;
540 in_d = bptr->indepth - 1;
541 out_d = bptr->outdepth - 1;
543 /* ignore top Stackelement of instack in case of EXH or SBR blocks */
544 /* These are no Interface stackslots! */
545 if ((bptr->type == BBTYPE_EXH) ||
546 (bptr->type == BBTYPE_SBR)) {
550 /* invars with no corresponding outvars are not defined here */
551 /* just set up the interface_map */
553 for(;(in_d > out_d); in_d--) {
554 i_map_index = in_d * 5 + VAR(in[in_d])->type;
555 ssa_set_iovar(ls, in[in_d], i_map_index, interface_map);
558 while((out_d >= 0)) {
559 /* set up interface_map */
561 o_map_index = out_d * 5 + VAR(out[out_d])->type;
563 i_map_index = in_d * 5 + VAR(in[in_d])->type;
564 ssa_set_iovar(ls, in[in_d], i_map_index, interface_map);
566 ssa_set_iovar(ls, out[out_d], o_map_index, interface_map);
577 #ifdef SSA_DEBUG_VERBOSE
578 void ssa_print_trees(jitdata *jd, graphdata *gd, dominatordata *dd) {
584 printf("ssa_printtrees: maxlocals %3i", jd->localcount);
586 printf("Dominator Tree: \n");
587 for(i = 0; i < ls->basicblockcount; i++) {
589 for(j = 0; j < ls->basicblockcount; j++) {
590 if (dd->idom[j] == i) {
597 printf("Dominator Forest:\n");
598 for(i = 0; i < ls->basicblockcount; i++) {
600 for(j = 0; j < dd->num_DF[i]; j++) {
601 printf(" %3i", dd->DF[i][j]);
606 if (ls->ssavarcount > 0) {
607 printf("Use Sites\n");
608 for(i = 0; i < ls->ssavarcount; i++) {
609 printf("use_sites[%3i]=%p:",i,(void *)ls->use_sites[i]);
610 for(j = 0; j < ls->basicblockcount; j++) {
611 if ((j % 5) == 0) printf(" ");
612 if (bv_get_bit(ls->use_sites[i], j))
621 printf("var Definitions:\n");
622 for(i = 0; i < jd->basicblockcount; i++) {
623 printf("var_def[%3i]=%p:",i,(void *)ls->var_def[i]);
624 for(j = 0; j < ls->ssavarcount; j++) {
625 if ((j % 5) == 0) printf(" ");
626 if (bv_get_bit(ls->var_def[i], j))
632 for(j=0; j < ((((ls->ssavarcount * 5+7)/8) + sizeof(int) - 1)/sizeof(int));
634 printf("%8x",ls->var_def[i][j]);
641 /****************************************************************************
643 ****************************************************************************/
646 /****************************************************************************
647 Dead Code Elimination
648 ****************************************************************************/
649 void dead_code_elimination(jitdata *jd, graphdata *gd) {
654 struct lifetime *lt, *s_lt;
656 bool remove_statement;
660 #ifdef SSA_DEBUG_VERBOSE
667 W = wl_new(ls->lifetimecount);
668 if (ls->lifetimecount > 0) {
670 /* put all lifetimes into Worklist W */
672 for(a = 0; a < ls->lifetimecount; a++) {
673 if (ls->lifetime[a].type != UNUSED) {
679 /* Remove unused lifetimes */
681 while(!wl_is_empty(W)) {
683 /* take a var out of Worklist */
687 lt = &(ls->lifetime[a]);
688 if ((lt->def == NULL) || (lt->type == UNUSED))
690 /* lifetime was already removed -> no defs anymore */
694 /* Remove lifetimes, which are only used in the phi function which */
697 remove_statement = (lt->use != NULL) && (lt->use->iindex < 0);
698 for(use = lt->use; (remove_statement && (use != NULL));
701 remove_statement = remove_statement &&
702 (use->b_index == lt->def->b_index) &&
703 (use->iindex == lt->def->iindex);
706 if (remove_statement) {
707 #ifdef SSA_DEBUG_CHECK
709 /* def == use can only happen in phi functions */
711 if (remove_statement)
712 _SSA_ASSERT(lt->use->iindex < 0);
715 /* give it free for removal */
720 if (lt->use == NULL) {
722 /* Look at statement of definition of a and remove it, */
723 /* if the Statement has no sideeffects other than the assignemnt */
726 if (lt->def->iindex < 0 ) {
729 /* delete use of sources , delete phi functions */
731 _SSA_ASSERT(ls->phi[lt->def->b_index][-lt->def->iindex-1] !=
734 for (i = 1;i <= graph_get_num_predecessor(gd, lt->def->b_index);
737 ls->phi[lt->def->b_index][-lt->def->iindex-1][i];
738 if ((source != ls->varcount_with_indices) &&
739 (source != lt->v_index) &&
740 (source != UNUSED)) {
742 /* phi Argument was not already removed (already in
743 because of "selfdefinition") */
745 s_lt = &(ls->lifetime[source]);
749 lt_remove_use_site(s_lt,lt->def->b_index,
752 /* put it on the Worklist */
758 /* now delete phi function itself */
759 #ifdef SSA_DEBUG_VERBOSE
760 if (compileverbose) {
761 printf("dce: BB%3i phi for var %3i=%3i removed \n",
762 lt->def->b_index, -lt->def->iindex - 1,
767 ls->phi[lt->def->b_index][-lt->def->iindex-1] = NULL;
771 /* "normal" Use by ICMD */
773 remove_statement = false;
774 if (lt->def->b_index != 0) {
776 /* do not look at artificial block 0 (parameter init) */
778 iptr = ls->basicblocks[lt->def->b_index]->iinstr +
781 if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
783 /* if ICMD could throw an exception do not remove it! */
785 remove_statement = false;
786 #ifdef SSA_DEBUG_VERBOSE
787 if (compileverbose) {
788 printf("dce: PEI: BB%3i II%3i %s not removed \n",
789 lt->def->b_index, lt->def->iindex,
790 bytecode[iptr->opc].mnemonic);
796 remove_statement = true;
798 switch (icmd_table[iptr->opc].dataflow) {
800 case DF_3_TO_1: /* icmd has s1, s2 and s3 */
801 a = iptr->sx.s23.s3.varindex;
802 s_lt = ls->lifetime + a;
803 lt_remove_use_site(s_lt, lt->def->b_index,
807 /* "fall through" for handling of s2 and s1 */
810 case DF_2_TO_1: /* icmd has s1 and s2 */
811 a = iptr->sx.s23.s2.varindex;
812 s_lt = ls->lifetime + a;
813 lt_remove_use_site(s_lt, lt->def->b_index,
817 /* "fall through" for handling of s1 */
819 /* DF_{IINC,STORE,LOAD} are DF_{1_TO_1,MOVE,COPY} */
825 a = iptr->s1.varindex;
826 s_lt = ls->lifetime + a;
827 lt_remove_use_site(s_lt, lt->def->b_index,
831 #ifdef SSA_DEBUG_VERBOSE
832 if (compileverbose) {
833 printf("dce: BB%3i II%3i %s removed \n",
834 lt->def->b_index, lt->def->iindex,
835 bytecode[iptr->opc].mnemonic);
840 if (remove_statement) {
842 /* remove statement */
844 #ifdef SSA_DEBUG_VERBOSE
846 printf("dce: %s %s:at BB %3i II %3i NOP-<%s\n",
847 m->clazz->name->text, m->name->text,
848 lt->def->b_index, lt->def->iindex,
849 icmd_table[iptr->opc].name);
851 iptr->opc = ICMD_NOP;
853 } /* (lt->def->b_index != 0) */
854 } /* if (lt->def->iindex < 0 ) else */
856 /* remove definition of a */
858 #ifdef SSA_DEBUG_VERBOSE
860 printf("dce: var %3i removed\n", lt->v_index);
862 VAR(lt->v_index)->type = UNUSED;
866 } /* if (lt->use == NULL) */
867 } /* while(!wl_is_empty(W)) */
868 } /* dead_code_elimination */
870 /****************************************************************************
871 Simple Constant Propagation
872 ****************************************************************************/
874 void simple_constant_propagation() {
877 /****************************************************************************
879 *******************************************************************************/
880 void copy_propagation(jitdata *jd, graphdata *gd) {
887 struct lifetime *lt, *s_lt;
893 W = wl_new(ls->lifetimecount);
894 if (ls->lifetimecount > 0) {
895 /* put all lifetimes on Worklist */
896 for(a = 0; a < ls->lifetimecount; a++) {
897 if (ls->lifetime[a].type != UNUSED) {
903 while(!wl_is_empty(W)) {
904 /* take a var out of Worklist */
907 lt = ls->lifetime + a;
908 if (lt->type == UNUSED)
910 _SSA_ASSERT(lt->def != NULL);
912 _SSA_ASSERT(lt->use != NULL);
914 if (lt->def->iindex < 0 ) {
917 /* look, if phi function degenerated to a x = phi(y) */
918 /* and if so, substitute y for every use of x */
920 _SSA_ASSERT(ls->phi[lt->def->b_index][-lt->def->iindex-1] != NULL);
922 only_source = ls->varcount_with_indices;
923 for (i = 1; i <= graph_get_num_predecessor(gd, lt->def->b_index);
925 source = ls->phi[lt->def->b_index][-lt->def->iindex-1][i];
926 if ((source != ls->varcount_with_indices) &&
927 (source != UNUSED)) {
928 if (only_source == ls->varcount_with_indices) {
930 /* first valid source argument of phi function */
932 only_source = source;
935 /* second valid source argument of phi function */
938 only_source = ls->varcount_with_indices;
944 if (only_source != ls->varcount_with_indices) {
946 #ifdef SSA_DEBUG_VERBOSE
949 "-- copy propagation phi-func: BB %3i II %3i: %3i -> %3i\n",
950 lt->def->b_index, lt->def->iindex,
951 only_source, lt->v_index);
953 s_lt = ls->lifetime + only_source;
955 /* replace all use sites of lt with the var_index only_source */
957 ssa_replace_use_sites( jd, gd, lt, only_source, W);
959 /* delete def of lt */
961 ls->phi[lt->def->b_index][-lt->def->iindex-1] = NULL;
963 /* remove this deleted use site of s_lt */
965 lt_remove_use_site(s_lt, lt->def->b_index, lt->def->iindex);
969 /* move use sites from lt to s_lt */
971 lt_move_use_sites(lt, s_lt);
976 VAR(lt->v_index)->type = UNUSED;
978 /* add s_lt again to Worklist W */
980 wl_add(W, s_lt->v_index);
981 #ifdef SSA_DEBUG_VERBOSE
985 } /* if (only_source != ls->varcount_with_indices) */
987 else { /* if (lt->def->iindex < 0 ) */
989 /* def in argument passing - no propagation possible */
990 /* (there is no ICMD for this... */
992 if (lt->def->b_index == 0)
995 /* def in "normal" ICMD */
997 iptr = ls->basicblocks[lt->def->b_index]->iinstr +
1012 #ifdef SSA_DEBUG_VERBOSE
1015 "-- copy propagation %3i %s: BB %3i II %3i: %3i -> %3i\n",
1016 iptr->opc, bytecode[iptr->opc].mnemonic,
1017 lt->def->b_index, lt->def->iindex,
1018 iptr->s1.varindex, iptr->dst.varindex);
1020 s_lt = ls->lifetime + iptr->s1.varindex;
1022 _SSA_ASSERT( lt->v_index == iptr->dst.varindex);
1024 /* replace all use sites of lt with the var_index */
1025 /* iptr->s1.varindex (==lt->v_index) */
1027 ssa_replace_use_sites(jd, gd, lt, iptr->s1.varindex, W);
1029 _SSA_ASSERT(lt->def->next == NULL);
1030 _SSA_ASSERT(s_lt->def != NULL);
1031 _SSA_ASSERT(s_lt->def->next == NULL);
1033 /* this ICMD is not a PEI -> so no danger in deleting it! */
1034 /* delete def of lt (ICMD_NOP) */
1036 /* lt->def->iindex > 0 -> ICMD */
1038 iptr->opc = ICMD_NOP;
1040 /* remove this deleted use site of s_lt */
1042 lt_remove_use_site(s_lt, lt->def->b_index, lt->def->iindex);
1044 /* invalidate def site of lt */
1048 /* move use sites from lt to s_lt */
1050 lt_move_use_sites(lt, s_lt);
1055 VAR(lt->v_index)->type = UNUSED;
1057 /* add s_lt again to Worklist W */
1058 wl_add(W, s_lt->v_index);
1059 #ifdef SSA_DEBUG_VERBOSE
1061 _ssa_print_lt(s_lt);
1065 } /* if (lt->def->iindex < 0 ) */
1066 } /* while(!wl_is_empty(W)) */
1069 void ssa_replace_use_sites(jitdata *jd, graphdata *gd, struct lifetime *lt,
1070 int new_v_index, worklist *W) {
1077 builtintable_entry *bte;
1081 md = jd->m->parseddesc;
1084 for(s = lt->use; s != NULL; s = s->next) {
1085 if (s->iindex < 0) {
1087 /* Use in phi function */
1089 for (i = 1;i <= graph_get_num_predecessor(gd, s->b_index); i++) {
1090 source = ls->phi[s->b_index][-s->iindex-1][i];
1091 if (source == lt->v_index) {
1093 /* check if this use in this phi function is a */
1094 /* "selfdefinition" (x = phi(...,x,...)) */
1095 /* if so replace the use with -1 (x=phi(...,-1,...)*/
1097 if (new_v_index == ls->phi[s->b_index][-s->iindex-1][0]) {
1098 #ifdef SSA_DEBUG_VERBOSE
1102 "copy propagation phi: BB %3i I %3i: %3i -> %3i\n",
1103 s->b_index, s->iindex, -1, source);
1106 ls->phi[s->b_index][-s->iindex-1][i] = -1;
1108 /* remove this use site of use site */
1109 lt_remove_use_site(lt, s->b_index, s->iindex);
1112 #ifdef SSA_DEBUG_VERBOSE
1116 "copy propagation phi: BB %3i I %3i: %3i -> %3i\n",
1117 s->b_index, s->iindex, new_v_index, source);
1120 ls->phi[s->b_index][-s->iindex-1][i] = new_v_index;
1126 /* Add var, which is defined by this phi function to */
1129 source = ls->phi[s->b_index][-s->iindex-1][0];
1133 else { /* use in ICMD */
1135 iptr = ls->basicblocks[s->b_index]->iinstr +
1138 /* check for use (s1, s2, s3 or special (argp) ) */
1141 switch (icmd_table[iptr->opc].dataflow) {
1143 case DF_3_TO_1: /* icmd has s1, s2 and s3 */
1144 if (iptr->sx.s23.s3.varindex == lt->v_index) {
1145 #ifdef SSA_DEBUG_VERBOSE
1148 printf("copy propagation loc3: BB %3i I %3i: %3i -> \
1149 %3i\n", s->b_index, s->iindex,
1150 new_v_index, iptr->sx.s23.s3.varindex);
1153 iptr->sx.s23.s3.varindex = new_v_index;
1156 /* now "fall through" for handling of s2 and s1 */
1159 case DF_2_TO_1: /* icmd has s1 and s2 */
1160 if (iptr->sx.s23.s2.varindex == lt->v_index) {
1161 #ifdef SSA_DEBUG_VERBOSE
1164 printf("copy propagation loc2: BB %3i I %3i: %3i -> \
1165 %3i\n", s->b_index, s->iindex,
1166 new_v_index, iptr->sx.s23.s2.varindex);
1169 iptr->sx.s23.s2.varindex = new_v_index;
1172 /* now "fall through" for handling of s1 */
1178 if (iptr->s1.varindex == lt->v_index) {
1179 #ifdef SSA_DEBUG_VERBOSE
1183 "copy propagation loc1: BB %3i I %3i: %3i -> %3i\n",
1184 s->b_index, s->iindex, new_v_index,
1188 iptr->s1.varindex = new_v_index;
1193 /* ? really look at md->paramcount or iptr->s1.argcount */
1194 /* has to be taken, so that pass-through stackslots get */
1198 INSTRUCTION_GET_METHODDESC(iptr,md);
1202 bte = iptr->sx.s23.s3.bte;
1207 i = iptr->s1.argcount;
1211 argp = iptr->sx.s23.s2.args;
1213 if (*argp == lt->v_index) {
1214 #ifdef SSA_DEBUG_VERBOSE
1218 "copy propagation locN: BB %3i I %3i: %3i -> %3i\n"
1219 , s->b_index, s->iindex, new_v_index, *argp);
1222 *argp = new_v_index;
1229 } /* if (s->iindex < 0) */
1230 } /* for(s = lt->use; s != NULL; s = s->next) */
1233 #ifdef SSA_DEBUG_VERBOSE
1234 void ssa_print_lt(lsradata *ls) {
1236 struct lifetime *lt;
1238 printf("SSA LT Def/Use\n");
1239 for(i = 0; i < ls->lifetimecount; i++) {
1240 lt = ls->lifetime + i;
1245 void _ssa_print_lt(struct lifetime *lt) {
1248 if (lt->type != UNUSED) {
1249 printf("VI %3i Type %3i Def: ",lt->v_index, lt->type);
1250 if (lt->def != NULL)
1251 printf("%3i,%3i Use: ",lt->def->b_index, lt->def->iindex);
1253 printf("%3i,%3i Use: ",0,0);
1254 for(use = lt->use; use != NULL; use = use->next)
1255 printf("%3i,%3i ",use->b_index, use->iindex);
1260 void ssa_show_variable(jitdata *jd, int index, varinfo *v, int stage)
1266 case TYPE_INT: type = 'i'; break;
1267 case TYPE_LNG: type = 'l'; break;
1268 case TYPE_FLT: type = 'f'; break;
1269 case TYPE_DBL: type = 'd'; break;
1270 case TYPE_ADR: type = 'a'; break;
1271 case TYPE_RET: type = 'r'; break;
1272 default: type = '?';
1275 if (index < jd->localcount) {
1277 if (v->flags & (PREALLOC | INOUT))
1278 printf("<INVALID FLAGS!>");
1281 if (v->flags & PREALLOC) {
1283 if (v->flags & INOUT)
1284 printf("<INVALID FLAGS!>");
1286 else if (v->flags & INOUT)
1292 printf("%c%c%3d", kind, type, index);
1294 if (v->flags & SAVEDVAR)
1302 /****************************************************************************
1304 ****************************************************************************/
1307 * These are local overrides for various environment variables in Emacs.
1308 * Please do not remove this and leave it at the end of the file, where
1309 * Emacs will automagically detect them.
1310 * ---------------------------------------------------------------------
1313 * indent-tabs-mode: t