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