* Moved all files from vmcore/ to vm/.
[cacao.git] / src / vm / jit / optimizing / ssa.c
1 /* src/vm/jit/optimizing/ssa.c - static single-assignment form
2
3    Copyright (C) 2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
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.
12
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.
17
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
21    02111-1307, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #include "mm/memory.h"
32
33 #include "toolbox/bitvector.h"
34 #include "toolbox/worklist.h"
35
36 #include "vm/builtin.h"
37
38 #include "vm/jit/jit.h" /* icmd_table */
39
40 #include "vm/jit/ir/bytecode.h"
41
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"
46
47 #include "vm/jit/optimizing/ssa.h"
48 #include "vm/jit/optimizing/ssa_rename.h"
49 #include "vm/jit/optimizing/ssa_phi.h"
50
51 #include "vm/jit/python.h"
52
53 #if defined(SSA_DEBUG_VERBOSE)
54 #include "vm/options.h"   /* compileverbose */
55 #endif
56
57 /* function prototypes */
58 void ssa_set_local_def(lsradata *, int , int);
59 void ssa_set_interface(jitdata *, basicblock *, s4 *);
60
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 *,
64                                                 int , worklist *);
65
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 *);
70
71
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 *);
78 #endif
79
80 /* ssa ************************************************************************
81
82 SSA main procedure:
83
84 SSA Algorithms are based on "modern compiler implementation in C" from andrew 
85 w. appel, edition 2004
86
87 Corrections:
88 page 441 Algorithm 19.6. Inserting phi-functions:
89
90 ...
91     for each Y in DF[n]
92 -       if Y not element of A phi [n]
93 +       if a not element of A phi [n]
94             insert the statment a <- ...
95 ...
96 ...
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]
101            W <- W join {Y}
102
103 ******************************************************************************/
104 void xssa(jitdata *jd);
105 void yssa(jitdata *jd);
106 void ssa(jitdata *jd) {
107         struct dominatordata *dd;
108         lsradata *ls;
109         graphdata *gd;
110
111 #if defined(ENABLE_LOOPS)
112         /* Loop optimization "destroys" the basicblock array */
113         /* TODO: work with the basicblock list               */
114         if (opt_loops) {
115                 log_text("lsra not possible with loop optimization\n");
116                 exit(1);
117         }
118 #endif
119
120         cfg_add_root(jd);
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");*/
127         
128         /*if (getenv("XSSA")) {
129                 dominator_tree_build(jd);
130                 dominance_frontier_build(jd);
131                 xssa(jd);
132         } else */{
133                 yssa(jd);
134         }
135         /*pythonpass_run(jd, "foo", "after");*/
136         cfg_remove_root(jd);
137         return;
138
139         ls = jd->ls;
140
141     ssa_init(jd);
142         /* Generate the Control Flow Graph */
143         /* Add one for a Basic Block 0 to be inserted, so lateron */
144         /* with SSA Parameter initialization is handled right */
145
146         gd = graph_init(jd->basicblockcount + 1);
147         graph_make_cfg(jd, gd);
148
149         dd = compute_Dominators(gd, ls->basicblockcount);
150         computeDF(gd, dd, ls->basicblockcount, 0);
151
152         ssa_place_phi_functions(jd, gd, dd);
153         ssa_rename(jd, gd, dd);
154 #ifdef SSA_DEBUG_VERBOSE
155         if (compileverbose) {
156                 printf("Phi before Cleanup\n");
157                 ssa_print_phi(ls, gd);
158                 ssa_print_lt(ls);
159         }
160 #endif
161         lt_scanlifetimes(jd, gd, dd);
162 #ifdef SSA_DEBUG_VERBOSE
163         if (compileverbose) {
164                 ssa_print_lt(ls);
165         }
166 #endif
167         if (opt_ssa_dce) {
168                 dead_code_elimination(jd, gd); 
169 #ifdef SSA_DEBUG_VERBOSE
170                 if (compileverbose) {
171                         printf("Phi after dead code elemination\n");
172                         ssa_print_phi(ls, gd);
173                         ssa_print_lt(ls);
174                 }
175 #endif
176         }
177         if (opt_ssa_cp) {
178                 copy_propagation(jd, gd);
179 #ifdef SSA_DEBUG_VERBOSE
180                 if (compileverbose) {
181                         printf("Phi after copy propagation\n");
182                         ssa_print_phi(ls, gd);
183                         ssa_print_lt(ls);
184                 }
185 #endif
186         }
187
188         ssa_generate_phi_moves(jd, gd);
189         transform_BB(jd, gd);
190
191         lt_lifeness_analysis(jd, gd);
192
193 #ifdef SSA_DEBUG_CHECK
194         {
195                 int i, j, pred, in_d, out_d;
196                 graphiterator iter_pred;
197                 s4 *in, *out;
198                 bool phi_define;
199                 methodinfo *m;
200
201                 m = jd->m;
202
203                 for(i = 0; i < ls->basicblockcount; i++) {
204                         if (ls->basicblocks[i]->indepth != 0) {
205                                 pred = graph_get_first_predecessor(gd, i, &iter_pred);
206                                 for (; (pred != -1); pred = graph_get_next(&iter_pred)) {
207                                         in_d = ls->basicblocks[i]->indepth - 1;
208                                         in = ls->basicblocks[i]->invars;
209                                         for (; in_d >= 0; in_d--) {
210                                                 phi_define = false;
211                                                 for (j = 0; (!phi_define) && (j<ls->ssavarcount); j++) {
212                                                         if (ls->phi[i][j] != NULL)
213                                                                 if (ls->phi[i][j][0] == in[in_d])
214                                                                         phi_define = true;
215                                                 }
216                                                 if (!phi_define) {
217                                                         /* in not defined in phi function -> check with */
218                                                         /* outstack(s)  of predecessor(s) */
219                                                         out_d = ls->basicblocks[pred]->outdepth - 1;
220                                                         out = ls->basicblocks[pred]->outvars;
221                                                         _SSA_ASSERT(out_d >= in_d);
222                                                         for(; out_d > in_d; out_d--);
223                                                         if ((in[in_d] != out[out_d]) || 
224                                                         (VAR(in[in_d])->flags != VAR(out[out_d])->flags)) {
225                                                                 printf("Method: %s %s\n",
226                                                                            m->clazz->name->text, m->name->text);
227                                                                         printf("Error: Stack Varnum Mismatch BBin %3i BBout %3i Stackdepth %3i\n", i, pred, in_d);
228                                                                 if (compileverbose)
229                                                                         printf("Error: Stack Varnum Mismatch BBin %3i BBout %3i Stackdepth %3i\n", i, pred, in_d);
230 /*                                                              else */
231 /*                                                                      _SSA_ASSERT(0); */
232                                                         }
233                                                 }
234                                         }
235                                 }
236                         }
237                 }
238         }
239
240 #endif
241
242 #ifdef SSA_DEBUG_VERBOSE
243         if (compileverbose)
244                 ssa_print_trees(jd, gd, dd);
245 #endif
246
247 }
248
249 /* ssa_init *******************************************************************
250
251 Initialise data structures for ssa
252
253 IOVARS of same stackdepth and same type are coalesced:
254 interface_map[ 5 * stackdepth + type ] = new_varindex with
255 0 <= new_varindex < ls->ssavarcount
256
257 TODO: check if coalescing of IOVARS of same stackdepth and type only of adjacent
258 basic blocks could decrease the number of phi functions and so improve ssa 
259 analysis performance!
260
261 All LOCALVARS and IOVARS get a new unique varindex:
262 ls->new_varindex[0..jd->varcount[ = new_varindex with
263 0 <= new_varindex < ls->ssavarcount
264
265 The jd->varcount bits long bitvectors ls->var_def[0..jd->basicblockindex+1[
266  are set  to the definitions of LOCALVARS and IOVARS. (So the only the first 
267 ls->ssavarcount bits of each of these vectors contain valid data, but 
268 ls->ssavarcount is computed at the same time as the definitons are stored.)
269
270 The basic block number used as index for the bitvector array ls->var_def is 
271 already shifted by one to make space for the new basic block 0 for parameter
272 initialization.
273
274 ******************************************************************************/
275
276 void ssa_init(jitdata *jd) {
277         int         p, t, v;
278         methoddesc  *md;
279         int         i, l, b_index, len;
280         instruction *iptr;
281         basicblock  *bptr;
282         s4          *interface_map; /* holds an new unique index for every used  */
283                                     /* basic block inoutvar described by a dupel */
284                                 /*(depth,type). Used to coalesce the inoutvars*/
285         methodinfo   *m;
286         lsradata     *ls;
287         builtintable_entry *bte;
288
289         ls = jd->ls;
290         m = jd->m;
291         md = m->parseddesc;
292
293
294 #if defined(SSA_DEBUG_CHECK) || defined(SSA_DEBUG_VERBOSE)
295 # if defined(SSA_DEBUG_VERBOSE)
296         if (compileverbose) {
297                 printf("%s %s ",m->clazz->name->text, m->name->text);
298                 if (code_is_leafmethod(jd->code))
299                         printf("**Leafmethod**");
300                 printf("\n");
301         }
302 # endif
303         if (strcmp(m->clazz->name->text,"spec/benchmarks/_213_javac/Parser")==0)
304                 if (strcmp(m->name->text,"parseTerm")==0)
305 # if defined(SSA_DEBUG_VERBOSE)
306                         if (compileverbose) 
307                                 printf("12-------------------12\n");
308 # else
309                 { int dummy=1; dummy++; }
310 # endif
311 #endif
312
313 #ifdef SSA_DEBUG_VERBOSE
314     if (compileverbose) 
315                 printf("ssa_init: basicblockcount %3i localcount %3i\n",
316                            jd->basicblockcount, jd->localcount);
317 #endif
318
319         /* As first step all definitions of local variables and in/out vars are   */
320         /* gathered. in/outvars are coalesced for same type and depth             */
321         /* "normal" tempvars (just living within one basicblock are) ignored      */
322
323         ls->num_defs = DMNEW(int, jd->varcount);
324         ls->new_varindex = DMNEW(int , jd->varcount);
325
326         for(p = 0; p < jd->varcount; p++) {
327                 ls->num_defs[p] = 0;
328                 ls->new_varindex[p] = UNUSED;
329         }
330
331         /* init Var Definition bitvectors */
332
333         ls->var_def = DMNEW(int *, jd->basicblockcount + 1);
334         for(i = 0; i < jd->basicblockcount + 1; i++) {
335                 ls->var_def[i] =  bv_new(jd->varcount);
336         }
337
338         ls->ssavarcount = 0;
339
340         /* Add parameters first in right order, so the new local indices          */
341         /* 0..p will correspond to "their" parameters                             */
342         /* They get defined at the artificial Block 0, the real method bbs will   */
343         /* be ed to start at block 1                                              */
344
345         /* don't look at already eliminated (not used) parameters (locals) */
346
347         for (p = 0, l = 0; p < md->paramcount; p++) {
348                 t = md->paramtypes[p].type;
349                 i = jd->local_map[l * 5 + t];
350                 l++;
351                 if (IS_2_WORD_TYPE(t))    /* increment local counter a second time  */
352                         l++;                  /* for 2 word types */
353                 if (i == UNUSED)
354                         continue;
355                 ssa_set_local_def(ls, -1, i);
356         }
357
358         _SSA_ASSERT(ls->ssavarcount < jd->varcount);
359
360         /* coalesce bb in/out vars */
361
362         interface_map = DMNEW(s4, jd->stackcount * 5);
363         for(i = 0; i < jd->stackcount * 5; i++)
364                 interface_map[i] = UNUSED;
365
366         bptr = jd->basicblocks;
367
368         for(; bptr != NULL; bptr = bptr->next) {
369 #ifdef SSA_DEBUG_VERBOSE
370         if (compileverbose)
371                 printf("ssa_init: BB %3i flags %3x\n",bptr->nr, bptr->flags);
372 #endif
373                 if (bptr->flags >= BBREACHED) {
374
375                         /* 'valid' Basic Block */
376
377                         b_index = bptr->nr;
378
379                         len = bptr->icount;
380                         iptr = bptr->iinstr;
381                         ssa_set_interface(jd, bptr, interface_map);
382
383                         /* !!!!!!!!! not true for now !!!!!!!!! */
384                         /* All baseline optimizations from stack.c are turned off for */
385                         /* SSA! */
386
387                         for (; len > 0; len--, iptr++) {
388
389                                 /* Look for definitions (iptr->dst). INVOKE and BUILTIN have */
390                                 /* an optional dst - so they to be checked first */
391
392                                 v = UNUSED;
393                                 if (icmd_table[iptr->opc].dataflow == DF_INVOKE) {
394                                                 INSTRUCTION_GET_METHODDESC(iptr,md);
395                                                 if (md->returntype.type != TYPE_VOID)
396                                                         v = iptr->dst.varindex;
397                                 }
398                                 else if (icmd_table[iptr->opc].dataflow == DF_BUILTIN) {
399                                                 bte = iptr->sx.s23.s3.bte;
400                                                 md = bte->md;
401                                                 if (md->returntype.type != TYPE_VOID)
402                                                         v = iptr->dst.varindex;
403                                 }
404                                 else if (icmd_table[iptr->opc].dataflow >= DF_DST_BASE) {
405                                         v = iptr->dst.varindex;
406                                 }
407
408                                 if (v != UNUSED) {
409                                         if (( v < jd->localcount) || ( VAR(v)->flags & INOUT )) {
410
411                                   /* !IS_TEMPVAR && !IS_PREALLOC == (IS_LOCALVAR || IS_INOUT) */
412
413                                                 ssa_set_local_def(ls, b_index, v);
414                                         }
415                                 }
416                         }
417                 }
418         }
419         _SSA_ASSERT(ls->ssavarcount < jd->varcount);
420
421 #ifdef SSA_DEBUG_VERBOSE
422         if (compileverbose) {
423                 printf("ssa_init: Vars: Orig:%3i SSAVar: %3i\n", jd->varcount, 
424                            ls->ssavarcount);
425                 for(i = 0; i < jd->varcount; i++) {
426                         if ((i < jd->localcount) || ( VAR(i)->flags & INOUT)) {
427                                 printf("%3i(%3i,%3x) ",i,VAR(i)->type, VAR(i)->flags);
428                                 ssa_show_variable(jd, i, VAR(i),0);
429                                 if (i < ls->ssavarcount) {
430                                         printf(" -> %3i", ls->new_varindex[i]);
431                                 }
432                                 printf("\n");
433                         }
434                 }
435         }
436 #endif
437 }
438
439 /* ssa_set_def ****************************************************************
440
441 Helper for ssa_set_local_def and ssa_set_interface
442
443 The definition of a var is stored in the bitvector array ls->var_def.
444
445 The number of definitons of each var is counted, so the number of new vars with
446 SSA is known.
447
448 ******************************************************************************/
449
450 void ssa_set_def(lsradata *ls, int b_index, int varindex) {
451
452         /* b_index + 1 to leave space for the param init block 0 */
453
454         bv_set_bit(ls->var_def[b_index + 1], varindex);
455
456         /* count number of defs for every var since SSA */
457         /* will create a new var for every definition */
458
459         ls->num_defs[varindex]++;
460 }
461
462 /* ssa_set_local_def **********************************************************
463
464 Helper for ssa_init
465
466 Assigns a new unique index for the local var varindex (if not already done so)
467 and then calls ssa_set_def to remember the definition in the bitvector array
468 ls->var_def
469
470 ******************************************************************************/
471
472 void ssa_set_local_def(lsradata *ls, int b_index, int varindex) {
473
474         if (ls->new_varindex[varindex] == UNUSED) {
475                 ls->new_varindex[varindex] = ls->ssavarcount++;
476         }
477
478         ssa_set_def(ls, b_index, ls->new_varindex[varindex]);
479 }
480
481 /* ssa_set_local_def **********************************************************
482
483 Helper for ssa_set_interface
484
485 IN: ls              pointer to lsradata structure
486     iovar           varindex of INOUTVAR to process
487         map_index       stackdepth * 5 + type, used for coalescing IOVARS.
488
489 IN/OUT
490         interface_map   used for coalescing IOVARS. interface_map[map_index] == 
491                         UNUSED, if this map_index (==stackdepth,type tupel) did not
492                                         occur till now. Then interface_map[map_index] will be set
493                                         to a new unique index.
494         ls->new_varindex will be set to this new unique index to map the old
495                          varindizes to the new ones.
496
497 Assigns a new unique index for the local var varindex (if not already done so)
498 and then calls ssa_set_def to remember the definition in the bitvector array
499 ls->var_def
500
501 ******************************************************************************/
502
503 void ssa_set_iovar(lsradata *ls, s4 iovar, int map_index, s4 *interface_map) {
504                 if (interface_map[map_index] == UNUSED) 
505                         interface_map[map_index] = ls->ssavarcount++;
506
507                 ls->new_varindex[iovar] = interface_map[map_index];
508 }
509
510
511 /* ssa_set_interface ***********************************************************
512
513 Helper for ssa_init
514
515 IN: ls              pointer to lsradata structure
516     *bptr           pointer to the basic block to be processed
517
518 IN/OUT
519         interface_map   used for coalescing IOVARS. interface_map[map_index] == 
520                         UNUSED, if this map_index (==stackdepth,type tupel) did not
521                                         occur till now. Then interface_map[map_index] will be set
522                                         to a new unique index. (see ssa_set_iovar)
523
524 Searches the basic block given by *bptr for IN and OUTVARS and coalesces them
525 for each unique stackdepth,type dupel. For each OUTVAR with a different or no 
526 INVAR at the same stackdepth the definition of this OUTVAR in this basic block 
527 is remembered in ls->var_def. (see ssa_set_def)
528
529 ******************************************************************************/
530
531 void ssa_set_interface(jitdata *jd, basicblock *bptr, s4 *interface_map) {
532         s4 *out, *in;
533         int in_d, out_d;
534         int o_map_index, i_map_index;
535         lsradata *ls;
536
537         ls = jd->ls;
538
539         out = bptr->outvars;
540         in = bptr->invars;
541         in_d = bptr->indepth - 1;
542         out_d = bptr->outdepth - 1;
543
544         /* ignore top Stackelement of instack in case of EXH or SBR blocks */
545         /* These are no Interface stackslots! */
546         if ((bptr->type == BBTYPE_EXH) ||
547                 (bptr->type == BBTYPE_SBR)) {
548                 in_d--;
549         }
550
551         /* invars with no corresponding outvars are not defined here */
552         /* just set up the interface_map */
553
554         for(;(in_d > out_d); in_d--) {
555                 i_map_index = in_d * 5 + VAR(in[in_d])->type;
556                 ssa_set_iovar(ls, in[in_d], i_map_index, interface_map);
557         }
558
559         while((out_d >= 0)) {
560                 /* set up interface_map */
561
562                 o_map_index = out_d * 5 + VAR(out[out_d])->type;
563                 if (in_d >= 0) {
564                         i_map_index = in_d * 5 + VAR(in[in_d])->type;
565                         ssa_set_iovar(ls, in[in_d], i_map_index, interface_map);
566                 }
567                 ssa_set_iovar(ls, out[out_d], o_map_index, interface_map);
568                 if (in_d == out_d) {
569                         out_d--;
570                         in_d--;
571                 }
572                 else {
573                         out_d--;
574                 }
575         }
576 }
577
578 #ifdef SSA_DEBUG_VERBOSE
579 void ssa_print_trees(jitdata *jd, graphdata *gd, dominatordata *dd) {
580         int i,j;
581         lsradata *ls;
582
583         ls = jd->ls;
584
585         printf("ssa_printtrees: maxlocals %3i", jd->localcount);
586                 
587         printf("Dominator Tree: \n");
588         for(i = 0; i < ls->basicblockcount; i++) {
589                 printf("%3i:",i);
590                 for(j = 0; j < ls->basicblockcount; j++) {
591                         if (dd->idom[j] == i) {
592                                 printf(" %3i", j);
593                         }
594                 }
595                 printf("\n");
596         }
597
598         printf("Dominator Forest:\n");
599         for(i = 0; i < ls->basicblockcount; i++) {
600                 printf("%3i:",i);
601                 for(j = 0; j < dd->num_DF[i]; j++) {
602                                 printf(" %3i", dd->DF[i][j]);
603                 }
604                 printf("\n");
605         }
606 #if 0
607         if (ls->ssavarcount > 0) {
608         printf("Use Sites\n");
609         for(i = 0; i < ls->ssavarcount; i++) {
610                 printf("use_sites[%3i]=%p:",i,(void *)ls->use_sites[i]);
611                 for(j = 0; j < ls->basicblockcount; j++) {
612                         if ((j % 5) == 0) printf(" ");
613                         if (bv_get_bit(ls->use_sites[i], j))
614                                 printf("1");
615                         else
616                                 printf("0");
617                 }
618                 printf("\n");
619         }
620         }
621 #endif
622         printf("var Definitions:\n");
623         for(i = 0; i < jd->basicblockcount; i++) {
624                 printf("var_def[%3i]=%p:",i,(void *)ls->var_def[i]);
625                 for(j = 0; j < ls->ssavarcount; j++) {
626                         if ((j % 5) == 0) printf(" ");
627                         if (bv_get_bit(ls->var_def[i], j))
628                                 printf("1");
629                         else
630                                 printf("0");
631                 }
632                 printf(" (");
633                 for(j=0; j < ((((ls->ssavarcount * 5+7)/8) + sizeof(int) - 1)/sizeof(int));
634                         j++)
635                         printf("%8x",ls->var_def[i][j]);
636                 printf(")\n");
637         }
638 }
639 #endif
640
641
642 /****************************************************************************
643 Optimizations
644 ****************************************************************************/
645
646
647 /****************************************************************************
648 Dead Code Elimination
649 ****************************************************************************/
650 void dead_code_elimination(jitdata *jd, graphdata *gd) {
651         int a, i, source;
652         worklist *W;
653
654         instruction *iptr;
655         struct lifetime *lt, *s_lt;
656
657         bool remove_statement;
658         struct site *use;
659
660         lsradata *ls;
661 #ifdef SSA_DEBUG_VERBOSE
662         methodinfo *m;
663
664         m  = jd->m;
665 #endif
666         ls = jd->ls;
667
668         W = wl_new(ls->lifetimecount);
669         if (ls->lifetimecount > 0) {
670
671                 /* put all lifetimes into Worklist W */
672
673                 for(a = 0; a < ls->lifetimecount; a++) {
674                         if (ls->lifetime[a].type != UNUSED) {
675                                 wl_add(W, a);
676                         }
677                 }
678         }
679
680         /* Remove unused lifetimes */
681
682         while(!wl_is_empty(W)) {
683
684                 /* take a var out of Worklist */
685
686                 a = wl_get(W);
687
688                 lt = &(ls->lifetime[a]);
689                 if ((lt->def == NULL) || (lt->type == UNUSED))
690
691                         /* lifetime was already removed -> no defs anymore */
692
693                         continue;
694
695                 /* Remove lifetimes, which are only used in the phi function which */
696                 /* defines them! */
697
698                 remove_statement = (lt->use != NULL) && (lt->use->iindex < 0);
699                 for(use = lt->use; (remove_statement && (use != NULL)); 
700                         use = use->next)
701                 {
702                         remove_statement = remove_statement && 
703                                 (use->b_index == lt->def->b_index) &&
704                                 (use->iindex == lt->def->iindex);
705                 }
706
707                 if (remove_statement) {
708 #ifdef SSA_DEBUG_CHECK
709
710                         /* def == use can only happen in phi functions */
711
712                         if (remove_statement)
713                                 _SSA_ASSERT(lt->use->iindex < 0);
714 #endif
715
716                         /* give it free for removal */
717
718                         lt->use = NULL;
719                 }
720
721                 if (lt->use == NULL) {
722
723                         /* Look at statement of definition of a and remove it,           */
724                         /* if the Statement has no sideeffects other than the assignemnt */
725                         /* of a */
726
727                         if (lt->def->iindex < 0 ) {
728
729                                 /* phi function */
730                                 /* delete use of sources , delete phi functions  */
731
732                                 _SSA_ASSERT(ls->phi[lt->def->b_index][-lt->def->iindex-1] !=
733                                                         NULL);
734
735                                 for (i = 1;i <= graph_get_num_predecessor(gd, lt->def->b_index);
736                                          i++) {
737                                         source =
738                                                 ls->phi[lt->def->b_index][-lt->def->iindex-1][i];
739                                         if ((source != ls->varcount_with_indices) && 
740                                                 (source != lt->v_index) &&
741                                                 (source != UNUSED)) {
742
743                                                 /* phi Argument was not already removed (already in 
744                                                    because of "selfdefinition") */
745
746                                                 s_lt = &(ls->lifetime[source]);
747
748                                                 /* remove it */
749
750                                                 lt_remove_use_site(s_lt,lt->def->b_index,
751                                                                                    lt->def->iindex);
752
753                                                 /*  put it on the Worklist */
754
755                                                 wl_add(W, source);
756                                         }
757                                 }
758
759                                 /* now delete phi function itself */
760 #ifdef SSA_DEBUG_VERBOSE
761                                         if (compileverbose) {
762                                                 printf("dce: BB%3i phi for var %3i=%3i removed \n",
763                                                            lt->def->b_index, -lt->def->iindex - 1,
764                                                            lt->v_index);
765                                         }
766 #endif
767
768                                 ls->phi[lt->def->b_index][-lt->def->iindex-1] = NULL;
769                         }
770                         else {
771
772                                 /* "normal" Use by ICMD */
773
774                                 remove_statement = false;
775                                 if (lt->def->b_index != 0) {
776
777                                         /* do not look at artificial block 0 (parameter init) */
778
779                                         iptr = ls->basicblocks[lt->def->b_index]->iinstr + 
780                                                 lt->def->iindex;
781
782                                         if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
783
784                                                 /* if ICMD could throw an exception do not remove it! */
785
786                                                 remove_statement = false;
787 #ifdef SSA_DEBUG_VERBOSE
788                                                 if (compileverbose) {
789                                                         printf("dce: PEI: BB%3i II%3i %s not removed \n",
790                                                                    lt->def->b_index, lt->def->iindex,
791                                                                    bytecode[iptr->opc].mnemonic);
792                                                 }
793 #endif
794
795                                         }
796                                         else {
797                                                 remove_statement = true;
798
799                                                 switch (icmd_table[iptr->opc].dataflow) {
800                                                 case DF_3_TO_0:
801                                                 case DF_3_TO_1: /* icmd has s1, s2 and s3 */
802                                                         a = iptr->sx.s23.s3.varindex;
803                                                         s_lt = ls->lifetime + a;
804                                                         lt_remove_use_site(s_lt, lt->def->b_index,
805                                                                                            lt->def->iindex);
806                                                         wl_add(W, a);
807
808                                                         /* "fall through" for handling of s2 and s1 */
809
810                                                 case DF_2_TO_0:
811                                                 case DF_2_TO_1: /* icmd has s1 and s2 */
812                                                         a = iptr->sx.s23.s2.varindex;
813                                                         s_lt = ls->lifetime + a;
814                                                         lt_remove_use_site(s_lt, lt->def->b_index,
815                                                                                            lt->def->iindex);
816                                                         wl_add(W, a);
817
818                                                         /* "fall through" for handling of s1 */
819
820                                                         /* DF_{IINC,STORE,LOAD} are DF_{1_TO_1,MOVE,COPY} */
821
822                                                 case DF_1_TO_0:
823                                                 case DF_1_TO_1:
824                                                 case DF_MOVE:
825                                                 case DF_COPY:
826                                                         a = iptr->s1.varindex;
827                                                         s_lt = ls->lifetime + a;
828                                                         lt_remove_use_site(s_lt, lt->def->b_index,
829                                                                                            lt->def->iindex);
830                                                         wl_add(W, a);
831                                                 }
832 #ifdef SSA_DEBUG_VERBOSE
833                                                 if (compileverbose) {
834                                                         printf("dce: BB%3i II%3i %s removed \n",
835                                                                    lt->def->b_index, lt->def->iindex,
836                                                                    bytecode[iptr->opc].mnemonic);
837                                                 }
838 #endif
839                                         }
840
841                                         if (remove_statement) {
842
843                                                 /* remove statement */
844
845 #ifdef SSA_DEBUG_VERBOSE
846                                                 if (compileverbose)
847                                                         printf("dce: %s %s:at BB %3i II %3i NOP-<%s\n",
848                                                                    m->clazz->name->text, m->name->text, 
849                                                                    lt->def->b_index, lt->def->iindex, 
850                                                                    icmd_table[iptr->opc].name);
851 #endif
852                                                 iptr->opc = ICMD_NOP;
853                                         }
854                                 } /* (lt->def->b_index != 0) */
855                         } /* if (lt->def->iindex < 0 ) else */
856
857                         /* remove definition of a */
858
859 #ifdef SSA_DEBUG_VERBOSE
860                         if (compileverbose)
861                                 printf("dce: var %3i removed\n", lt->v_index);
862 #endif
863                         VAR(lt->v_index)->type = UNUSED;
864                         lt->type = UNUSED;
865                         lt->def = NULL;
866 /*                      jd->var */
867                 } /* if (lt->use == NULL) */
868         } /* while(!wl_is_empty(W)) */
869 } /* dead_code_elimination */
870
871 /****************************************************************************
872 Simple Constant Propagation
873 ****************************************************************************/
874
875 void simple_constant_propagation() {
876 }
877
878 /****************************************************************************
879 Optimization
880 *******************************************************************************/
881 void copy_propagation(jitdata *jd, graphdata *gd) {
882         int a, i, source;
883         int only_source;
884
885         worklist *W;
886
887         instruction *iptr;
888         struct lifetime *lt, *s_lt;
889
890         lsradata *ls;
891
892         ls = jd->ls;
893
894         W = wl_new(ls->lifetimecount);
895         if (ls->lifetimecount > 0) {
896                 /* put all lifetimes on Worklist */
897                 for(a = 0; a < ls->lifetimecount; a++) {
898                         if (ls->lifetime[a].type != UNUSED) {
899                                 wl_add(W, a);
900                         }
901                 }
902         }
903
904         while(!wl_is_empty(W)) {
905                 /* take a var out of Worklist */
906                 a = wl_get(W);
907
908                 lt = ls->lifetime + a;
909                 if (lt->type == UNUSED)
910                         continue;
911                 _SSA_ASSERT(lt->def != NULL);
912 #if 0
913                 _SSA_ASSERT(lt->use != NULL);
914 #endif
915                 if (lt->def->iindex < 0 ) {
916
917                         /* phi function */
918                         /* look, if phi function degenerated to a x = phi(y) */
919                         /* and if so, substitute y for every use of x */
920
921                         _SSA_ASSERT(ls->phi[lt->def->b_index][-lt->def->iindex-1] != NULL);
922
923                         only_source = ls->varcount_with_indices;
924                         for (i = 1; i <= graph_get_num_predecessor(gd, lt->def->b_index);
925                                  i++) {
926                                         source = ls->phi[lt->def->b_index][-lt->def->iindex-1][i];
927                                         if ((source != ls->varcount_with_indices) && 
928                                                 (source != UNUSED)) {   
929                                                 if (only_source == ls->varcount_with_indices) {
930
931                                                         /* first valid source argument of phi function */
932
933                                                         only_source = source;
934                                                 } else {
935
936                                                         /* second valid source argument of phi function */
937                                                         /* exit for loop */
938
939                                                         only_source = ls->varcount_with_indices;
940                                                         break;
941                                                 }
942                                         }
943                         }
944
945                         if (only_source != ls->varcount_with_indices) {
946                                 
947 #ifdef SSA_DEBUG_VERBOSE
948                                 if (compileverbose)
949                                         printf(
950                                                    "-- copy propagation phi-func: BB %3i II %3i: %3i -> %3i\n",
951                                                    lt->def->b_index, lt->def->iindex,
952                                                    only_source, lt->v_index);
953 #endif
954                                 s_lt = ls->lifetime + only_source;
955
956                                 /* replace all use sites of lt with the var_index only_source */
957
958                                 ssa_replace_use_sites( jd, gd, lt, only_source, W);
959
960                                 /* delete def of lt */
961
962                                 ls->phi[lt->def->b_index][-lt->def->iindex-1] = NULL;
963
964                                 /* remove this deleted use site of s_lt */
965
966                                 lt_remove_use_site(s_lt, lt->def->b_index, lt->def->iindex);
967
968                                 lt->def = NULL;
969
970                                 /* move use sites from lt to s_lt */
971
972                                 lt_move_use_sites(lt, s_lt);
973
974                                 /* invalidate lt */
975
976                                 lt->type = UNUSED;
977                                 VAR(lt->v_index)->type = UNUSED;
978
979                                 /* add s_lt again to Worklist W */
980
981                                 wl_add(W, s_lt->v_index);
982 #ifdef SSA_DEBUG_VERBOSE
983                                 if (compileverbose)
984                                         _ssa_print_lt(s_lt);
985 #endif
986                         } /* if (only_source != ls->varcount_with_indices) */
987                 }
988                 else { /* if (lt->def->iindex < 0 ) */  
989
990                         /* def in argument passing - no propagation possible */
991                         /* (there is no ICMD for this... */
992
993                         if (lt->def->b_index == 0)
994                                 continue;
995
996                         /* def in "normal" ICMD */
997
998                         iptr = ls->basicblocks[lt->def->b_index]->iinstr + 
999                                 lt->def->iindex;
1000                         
1001                         switch(iptr->opc) {
1002                         case ICMD_ISTORE:
1003                         case ICMD_LSTORE:
1004                         case ICMD_FSTORE:
1005                         case ICMD_DSTORE:
1006                         case ICMD_ASTORE:
1007                         case ICMD_ILOAD:
1008                         case ICMD_LLOAD:
1009                         case ICMD_FLOAD:
1010                         case ICMD_DLOAD:
1011                         case ICMD_ALOAD:
1012                         case ICMD_MOVE:
1013 #ifdef SSA_DEBUG_VERBOSE
1014                                 if (compileverbose)
1015                                         printf(
1016                                                    "-- copy propagation %3i %s: BB %3i II %3i: %3i -> %3i\n",
1017                                                    iptr->opc, bytecode[iptr->opc].mnemonic,
1018                                                    lt->def->b_index, lt->def->iindex,
1019                                                    iptr->s1.varindex, iptr->dst.varindex);
1020 #endif
1021                                 s_lt = ls->lifetime + iptr->s1.varindex;
1022                                 
1023                                 _SSA_ASSERT( lt->v_index == iptr->dst.varindex);
1024                                 
1025                                 /* replace all use sites of lt with the var_index */
1026                                 /* iptr->s1.varindex (==lt->v_index) */
1027                                 
1028                                 ssa_replace_use_sites(jd, gd, lt, iptr->s1.varindex, W);
1029                                 
1030                                 _SSA_ASSERT(lt->def->next == NULL);
1031                                 _SSA_ASSERT(s_lt->def != NULL);
1032                                 _SSA_ASSERT(s_lt->def->next == NULL);
1033
1034                                 /* this ICMD is not a PEI -> so no danger in deleting it!     */
1035                                 /* delete def of lt (ICMD_NOP) */
1036
1037                                 /* lt->def->iindex > 0 -> ICMD */
1038
1039                                 iptr->opc = ICMD_NOP;
1040
1041                                 /* remove this deleted use site of s_lt */
1042
1043                                 lt_remove_use_site(s_lt, lt->def->b_index, lt->def->iindex);
1044
1045                                 /* invalidate def site of lt */
1046                                 
1047                                 lt->def = NULL;
1048                                 
1049                                 /* move use sites from lt to s_lt */
1050                                 
1051                                 lt_move_use_sites(lt, s_lt);
1052
1053                                 /* invalidate lt */
1054
1055                                 lt->type = UNUSED;
1056                                 VAR(lt->v_index)->type = UNUSED;
1057
1058                                 /* add s_lt again to Worklist W */
1059                                 wl_add(W, s_lt->v_index);
1060 #ifdef SSA_DEBUG_VERBOSE
1061                                 if (compileverbose)
1062                                         _ssa_print_lt(s_lt);
1063 #endif
1064                                 break;
1065                         }
1066                 } /* if (lt->def->iindex < 0 ) */
1067         } /* while(!wl_is_empty(W)) */
1068 }
1069
1070 void ssa_replace_use_sites(jitdata *jd, graphdata *gd, struct lifetime *lt,
1071                                                    int new_v_index, worklist *W) {
1072         struct site *s;
1073         int i, source;
1074         instruction *iptr;
1075         s4 *argp;
1076
1077         methoddesc *md;
1078         builtintable_entry *bte;
1079         lsradata *ls;
1080
1081         ls = jd->ls;
1082         md = jd->m->parseddesc;
1083         
1084
1085         for(s = lt->use; s != NULL; s = s->next) {
1086                 if (s->iindex < 0) {
1087
1088                         /* Use in phi function */
1089
1090                         for (i = 1;i <= graph_get_num_predecessor(gd, s->b_index); i++) {
1091                                 source = ls->phi[s->b_index][-s->iindex-1][i];
1092                                 if (source == lt->v_index) {
1093
1094                                         /* check if this use in this phi function is a     */
1095                                         /* "selfdefinition" (x = phi(...,x,...))           */
1096                                         /* if so replace the use with -1 (x=phi(...,-1,...)*/
1097
1098                                         if (new_v_index == ls->phi[s->b_index][-s->iindex-1][0]) {
1099 #ifdef SSA_DEBUG_VERBOSE
1100                                                 if (W != NULL) {
1101                                                         if (compileverbose)
1102                                                                 printf(
1103                                                          "copy propagation phi: BB %3i I %3i: %3i -> %3i\n",
1104                                                          s->b_index, s->iindex, -1, source);
1105                                                 }
1106 #endif
1107                                                 ls->phi[s->b_index][-s->iindex-1][i] = -1;
1108
1109                                                 /* remove this use site of use site */
1110                                                 lt_remove_use_site(lt, s->b_index, s->iindex);
1111                                         }
1112                                         else {
1113 #ifdef SSA_DEBUG_VERBOSE
1114                                                 if (W != NULL) {
1115                                                         if (compileverbose)
1116                                                                 printf(
1117                                                          "copy propagation phi: BB %3i I %3i: %3i -> %3i\n",
1118                                                          s->b_index, s->iindex, new_v_index, source);
1119                                                 }
1120 #endif
1121                                                 ls->phi[s->b_index][-s->iindex-1][i] = new_v_index;
1122                                         }
1123                                 }
1124                         }
1125                         if (W != NULL) {
1126
1127                                 /* Add var, which is defined by this phi function to */
1128                                 /* the worklist */
1129
1130                                 source = ls->phi[s->b_index][-s->iindex-1][0];
1131                                 wl_add(W, source);
1132                         }
1133                 }
1134                 else { /* use in ICMD */
1135         
1136                         iptr = ls->basicblocks[s->b_index]->iinstr + 
1137                                 s->iindex;
1138
1139                 /* check for use (s1, s2, s3 or special (argp) ) */
1140
1141                         i = UNUSED;
1142                         switch (icmd_table[iptr->opc].dataflow) {
1143                         case DF_3_TO_0:
1144                         case DF_3_TO_1: /* icmd has s1, s2 and s3 */
1145                                 if (iptr->sx.s23.s3.varindex == lt->v_index) {
1146 #ifdef SSA_DEBUG_VERBOSE
1147                                         if (W != NULL) {
1148                                                 if (compileverbose)
1149                                                         printf("copy propagation loc3: BB %3i I %3i: %3i -> \
1150                                     %3i\n", s->b_index, s->iindex,
1151                                                                    new_v_index, iptr->sx.s23.s3.varindex);
1152                                         }
1153 #endif
1154                                         iptr->sx.s23.s3.varindex = new_v_index;
1155                                 }
1156
1157                                 /* now "fall through" for handling of s2 and s1 */
1158
1159                         case DF_2_TO_0:
1160                         case DF_2_TO_1: /* icmd has s1 and s2 */
1161                                 if (iptr->sx.s23.s2.varindex == lt->v_index) {
1162 #ifdef SSA_DEBUG_VERBOSE
1163                                         if (W != NULL) {
1164                                                 if (compileverbose)
1165                                                         printf("copy propagation loc2: BB %3i I %3i: %3i -> \
1166                                     %3i\n", s->b_index, s->iindex,
1167                                                                    new_v_index, iptr->sx.s23.s2.varindex);
1168                                         }
1169 #endif
1170                                         iptr->sx.s23.s2.varindex = new_v_index;
1171                                 }
1172
1173                                 /* now "fall through" for handling of s1 */
1174
1175                         case DF_1_TO_0:
1176                         case DF_1_TO_1:
1177                         case DF_MOVE:
1178                         case DF_COPY:
1179                                 if (iptr->s1.varindex == lt->v_index) {
1180 #ifdef SSA_DEBUG_VERBOSE
1181                                         if (W != NULL) {
1182                                                 if (compileverbose)
1183                                                         printf(
1184                                                         "copy propagation loc1: BB %3i I %3i: %3i -> %3i\n",
1185                                                         s->b_index, s->iindex, new_v_index,
1186                                                         iptr->s1.varindex);
1187                                         }
1188 #endif
1189                                         iptr->s1.varindex = new_v_index;
1190                                 }
1191                                 break;
1192
1193                                 /* TODO: */
1194                                 /* ? really look at md->paramcount or iptr->s1.argcount */
1195                                 /* has to be taken, so that pass-through stackslots get */
1196                                 /* renamed, too? */
1197
1198                         case DF_INVOKE:
1199                                 INSTRUCTION_GET_METHODDESC(iptr,md);
1200                                 i = md->paramcount;
1201                                 break;
1202                         case DF_BUILTIN:
1203                                 bte = iptr->sx.s23.s3.bte;
1204                                 md = bte->md;
1205                                 i = md->paramcount;
1206                                 break;
1207                         case DF_N_TO_1:
1208                                 i = iptr->s1.argcount;
1209                                 break;
1210                         }
1211                         if (i != UNUSED) {
1212                                 argp = iptr->sx.s23.s2.args;
1213                                 while (--i >= 0) {
1214                                         if (*argp == lt->v_index) {
1215 #ifdef SSA_DEBUG_VERBOSE
1216                                                 if (W != NULL) {
1217                                                         if (compileverbose)
1218                                                                 printf(
1219                                                                            "copy propagation locN: BB %3i I %3i: %3i -> %3i\n"
1220                                                                            , s->b_index, s->iindex, new_v_index, *argp);
1221                                                 }
1222 #endif
1223                                                 *argp = new_v_index;
1224                                                         
1225                                         }
1226                                         argp++;
1227                                 }
1228                         }
1229
1230                 } /* if (s->iindex < 0) */
1231         } /* for(s = lt->use; s != NULL; s = s->next) */
1232 }
1233
1234 #ifdef SSA_DEBUG_VERBOSE
1235 void ssa_print_lt(lsradata *ls) {
1236         int i;
1237         struct lifetime *lt;
1238
1239         printf("SSA LT Def/Use\n");
1240         for(i = 0; i < ls->lifetimecount; i++) {
1241                 lt = ls->lifetime + i;
1242                 _ssa_print_lt(lt);
1243         }
1244 }
1245
1246 void _ssa_print_lt(struct lifetime *lt) {
1247         struct site *use;
1248
1249         if (lt->type != UNUSED) {
1250                 printf("VI %3i Type %3i Def: ",lt->v_index, lt->type);
1251                 if (lt->def != NULL)
1252                         printf("%3i,%3i Use: ",lt->def->b_index, lt->def->iindex);
1253                 else
1254                         printf("%3i,%3i Use: ",0,0);
1255                 for(use = lt->use; use != NULL; use = use->next)
1256                         printf("%3i,%3i ",use->b_index, use->iindex);
1257                 printf("\n");
1258         }
1259 }
1260
1261 void ssa_show_variable(jitdata *jd, int index, varinfo *v, int stage)
1262 {
1263         char type;
1264         char kind;
1265
1266         switch (v->type) {
1267                 case TYPE_INT: type = 'i'; break;
1268                 case TYPE_LNG: type = 'l'; break;
1269                 case TYPE_FLT: type = 'f'; break;
1270                 case TYPE_DBL: type = 'd'; break;
1271                 case TYPE_ADR: type = 'a'; break;
1272                 case TYPE_RET: type = 'r'; break;
1273                 default:       type = '?';
1274         }
1275
1276         if (index < jd->localcount) {
1277                 kind = 'L';
1278                 if (v->flags & (PREALLOC | INOUT))
1279                                 printf("<INVALID FLAGS!>");
1280         }
1281         else {
1282                 if (v->flags & PREALLOC) {
1283                         kind = 'A';
1284                         if (v->flags & INOUT)
1285                                 printf("<INVALID FLAGS!>");
1286                 }
1287                 else if (v->flags & INOUT)
1288                         kind = 'I';
1289                 else
1290                         kind = 'T';
1291         }
1292
1293         printf("%c%c%3d", kind, type, index);
1294
1295         if (v->flags & SAVEDVAR)
1296                 putchar('!');
1297
1298         putchar(' ');
1299         fflush(stdout);
1300 }
1301 #endif
1302
1303 /****************************************************************************
1304 Optimization
1305 ****************************************************************************/
1306
1307 /*
1308  * These are local overrides for various environment variables in Emacs.
1309  * Please do not remove this and leave it at the end of the file, where
1310  * Emacs will automagically detect them.
1311  * ---------------------------------------------------------------------
1312  * Local variables:
1313  * mode: c
1314  * indent-tabs-mode: t
1315  * c-basic-offset: 4
1316  * tab-width: 4
1317  * End:
1318  */