5 #include "toolbox/bitvector.h"
6 #include "toolbox/set.h"
7 #include "toolbox/worklist.h"
10 #include "vm/jit/jit.h"
13 #define printf(...) do { if (getenv("VERB")) printf(__VA_ARGS__); } while (0)
14 #define show_method(...) do { if (getenv("VERB")) show_method(__VA_ARGS__); } while (0)
17 typedef struct phi_function {
22 typedef struct basicblock_info {
26 phi_function *phi_functions;
29 typedef struct var_info {
41 typedef struct ssa_info {
45 unsigned total_local_count;
48 static inline basicblock_info *bb_info(basicblock *bb) {
49 return (basicblock_info *)(bb->vp);
52 static ssa_info *ssa_init(jitdata *jd) {
58 ssa->vars_count = jd->localcount;
60 ssa->vars = DMNEW(var_info, ssa->vars_count);
61 MZERO(ssa->vars, var_info, ssa->vars_count);
62 for (i = 0; i < ssa->vars_count; ++i) {
63 ssa->vars[i].work = set_new(jd->basicblockcount);
69 static void ssa_place_phi_functions(ssa_info *ssa) {
71 basicblock *bptr, *Y, *n, **itdf;
77 for (bptr = ssa->jd->basicblocks; bptr; bptr = bptr->next) {
79 bbi = DNEW(basicblock_info);
80 bbi->defines = bv_new(ssa->vars_count);
81 bbi->phi = bv_new(ssa->vars_count);
86 for (iptr = bptr->iinstr; iptr != bptr->iinstr + bptr->icount; ++iptr) {
87 if (instruction_has_dst(iptr)) {
89 var_is_local(ssa->jd, iptr->dst.varindex)
92 bv_set_bit(bbi->defines, iptr->dst.varindex);
94 set_insert(ssa->vars[iptr->dst.varindex].work, bptr);
95 /* Accout definition */
96 ssa->vars[iptr->dst.varindex].num_defs += 1;
102 bptr = ssa->jd->basicblocks;
104 for (a = 0; a < ssa->vars_count; ++a) {
105 bv_set_bit(bbi->defines, a);
106 set_insert(ssa->vars[a].work, bptr);
107 ssa->vars[a].num_defs += 1;
110 for (a = 0; a < ssa->vars_count; ++a) {
111 work = ssa->vars[a].work;
112 while (! set_empty(work)) {
113 n = (basicblock *)set_pop(work);
115 itdf = n->domfrontier;
116 itdf != n->domfrontier + n->domfrontiercount;
120 if (! bv_get_bit(bb_info(Y)->phi, a)) {
121 bv_set_bit(bb_info(Y)->phi, a);
122 printf(" *** BB %d: phi for var %d\n", Y->nr, a);
123 bb_info(Y)->phi_count += 1;
124 ssa->vars[a].num_defs += 1;
125 if (! bv_get_bit(bb_info(Y)->defines, a)) {
134 static void ssa_create_phi_functions(ssa_info *ssa) {
136 basicblock_info *bbi;
140 for (bptr = ssa->jd->basicblocks; bptr; bptr = bptr->next) {
143 bbi->phi_functions = DMNEW(phi_function, bbi->phi_count);
144 itph = bbi->phi_functions;
146 for (i = 0; i < ssa->vars_count; ++i) {
147 if (bv_get_bit(bbi->phi, i)) {
149 itph->args = DMNEW(s4, bptr->predecessorcount);
150 for (j = 0; j < bptr->predecessorcount; ++j) {
159 static void ssa_calculate_offsets(ssa_info *ssa) {
161 unsigned cur_offset = ssa->jd->localcount;
163 ssa->total_local_count = 0;
165 for (i = 0; i < ssa->vars_count; ++i) {
167 ssa->vars[i].offset = cur_offset;
169 ssa->total_local_count += ssa->vars[i].num_defs;
171 if (ssa->vars[i].num_defs > 1) {
172 cur_offset += (ssa->vars[i].num_defs - 1);
178 static s4 ssa_rename_var(ssa_info *ssa, s4 var, unsigned index) {
181 if (var_is_local(ssa->jd, var)) {
182 assert(0 < index && index <= ssa->vars[var].num_defs);
186 return ssa->vars[var].offset + (index - 2);
188 assert(ret < ssa->total_local_count);
190 return ssa->total_local_count + (var - ssa->vars_count);
193 printf(" *** rename %c %d vers %d => %d\n", var_is_local(ssa->jd, var) ? 'L' : 'O', var, index, ret);
197 static void ssa_rename_uses(ssa_info *ssa, s4 *uses, unsigned uses_count) {
198 while (uses_count > 0) {
199 if (var_is_local(ssa->jd, *uses)) {
200 *uses = ssa_rename_var(ssa, *uses, *(ssa->vars[*uses].stack_top));
202 *uses = ssa_rename_var(ssa, *uses, 0);
209 static void ssa_rename_definition(ssa_info *ssa, s4 *pdef) {
213 if (var_is_local(ssa->jd, def)) {
214 ssa->vars[def].count += 1;
215 i = ssa->vars[def].count;
216 ssa->vars[def].stack_top += 1;
217 *(ssa->vars[def].stack_top) = i;
220 *pdef = ssa_rename_var(ssa, def, i);
223 static void ssa_rename_block(ssa_info *ssa, basicblock *bptr) {
225 basicblock_info *bbi = bb_info(bptr);
230 basicblock **itsucc, **itpred, **itdsucc, *Y;
238 orig_stack_top = DMNEW(s4 *, ssa->vars_count);
239 for (a = 0; a < ssa->vars_count; ++a) orig_stack_top[a] = ssa->vars[a].stack_top;
243 printf(" *** === %d ===========\n", bptr->nr);
245 ssa_rename_uses(ssa, bptr->invars, bptr->indepth);
247 /* Phi functions are the first instructions in the block */
248 printf(" *** --- phis ---------\n");
250 itph = bbi->phi_functions;
251 itph != bbi->phi_functions + bbi->phi_count;
254 ssa_rename_definition(ssa, &(itph->dst));
257 printf(" *** --- vars ---------\n");
259 if (bptr == ssa->jd->basicblocks) {
260 for (i = 0; i < ssa->jd->localcount; ++i) {
262 ssa_rename_definition(ssa, &tmp);
266 for (iptr = bptr->iinstr; iptr != bptr->iinstr + bptr->icount; ++iptr) {
272 switch (icmd_table[iptr->opc].dataflow) {
275 s[2] = iptr->sx.s23.s3.varindex;
280 s[1] = iptr->sx.s23.s2.varindex;
287 s[0] = iptr->s1.varindex;
297 uses = iptr->sx.s23.s2.args;
298 uses_count = iptr->s1.argcount;
303 printf(" *** %s uses ", icmd_table[iptr->opc].name);
304 for (jj = 0; jj < uses_count; ++jj) printf("%d ",uses[jj]);
307 if (uses_count > 0) {
308 /* Update uses, if there are any */
310 ssa_rename_uses(ssa, uses, uses_count);
312 /* If uses were s, then we need to update the instruction */
315 switch (uses_count) {
317 iptr->sx.s23.s3.varindex = s[2];
319 iptr->sx.s23.s2.varindex = s[1];
321 iptr->s1.varindex = s[0];
326 /* Rename definitions */
328 if (instruction_has_dst(iptr)) {
329 printf(" *** %s defines %d\n", icmd_table[iptr->opc].name, iptr->dst.varindex);
330 ssa_rename_definition(ssa, &(iptr->dst.varindex));
335 for (i = 0; i < bptr->outdepth; ++i) {
336 ssa_rename_definition(ssa, bptr->outvars + i);
341 printf(" *** succs %d\n", bptr->successorcount);
344 itsucc = bptr->successors;
345 itsucc != bptr->successors + bptr->successorcount;
351 itpred = Y->predecessors, j = 0;
352 itpred != Y->predecessors + Y->predecessorcount;
355 if (*itpred == bptr) break;
358 assert(j != Y->predecessorcount);
361 itph = bb_info(Y)->phi_functions;
362 itph != bb_info(Y)->phi_functions + bb_info(Y)->phi_count;
365 ssa_rename_uses(ssa, itph->args + j, 1);
372 itdsucc = bptr->domsuccessors;
373 itdsucc != bptr->domsuccessors + bptr->domsuccessorcount;
376 ssa_rename_block(ssa, *itdsucc);
379 /* For each definition of some variable a in the original S, pop stack */
382 for (a = 0; a < ssa->vars_count; ++a) ssa->vars[a].stack_top = orig_stack_top[a];
385 static void ssa_rename(ssa_info *ssa) {
388 for (i = 0; i < ssa->vars_count; ++i) {
389 ssa->vars[i].stack = DMNEW(unsigned, ssa->vars[i].num_defs + 1);
390 ssa->vars[i].stack[0] = 0;
391 ssa->vars[i].stack_top = ssa->vars[i].stack;
394 ssa_rename_block(ssa, ssa->jd->basicblocks);
397 static void ssa_export(ssa_info *ssa) {
399 jitdata *jd = ssa->jd;
400 methoddesc *md = jd->m->parseddesc;
404 vartop = ssa->total_local_count + jd->vartop - jd->localcount;
405 vars = DMNEW(varinfo, vartop);
407 printf(" *** vartop(%d) = ssa->total_local_count(%d) + jd->vartop(%d) - jd->localcount(%d)\n",
408 vartop , ssa->total_local_count , jd->vartop , jd->localcount);
412 /* Version 1 of each local */
414 for (i = 0; i < jd->localcount; ++i) {
415 *(it++) = jd->var[i];
418 /* Other versions of each local */
420 for (i = 0; i < jd->localcount; ++i) {
421 for (j = 1; j < ssa->vars[i].num_defs; ++j) {
422 *(it++) = jd->var[i];
428 for (i = jd->localcount; i < jd->vartop; ++i) {
429 *(it++) = jd->var[i];
433 jd->vartop = jd->varcount = vartop;
435 jd->local_map = DMREALLOC(jd->local_map, s4, 5 * jd->maxlocals, 5 * (jd->maxlocals + ssa->total_local_count - jd->localcount));
437 for (i = 0; i < ssa->total_local_count - jd->localcount; ++i) {
438 for (j = 0; j < 5; ++j) {
439 varindex = jd->localcount + i;
440 if (jd->var[varindex].type != j) {
443 jd->local_map[((jd->maxlocals + i) * 5) + j] = varindex;
447 jd->maxlocals += (ssa->total_local_count - jd->localcount);
448 jd->localcount = ssa->total_local_count;
450 printf(" *** jd->localcount %d, jd->maxlocals %d\n", jd->localcount , jd->maxlocals);
453 unsigned get_predecessor_index(basicblock *from, basicblock *to) {
457 for (itpred = to->predecessors; itpred != to->predecessors + to->predecessorcount; ++itpred) {
458 if (*itpred == from) break;
462 if (j == to->predecessorcount) {
463 printf(" *** %d => %d\n", from->nr, to->nr);
464 assert(j != to->predecessorcount);
470 basicblock *create_block(ssa_info *ssa, basicblock *from, basicblock *to) {
472 basicblock_info *toi;
475 unsigned j = get_predecessor_index(from, to);
477 mid = DNEW(basicblock);
478 MZERO(mid, basicblock, 1);
483 mid->nr = ssa->jd->basicblockcount;
484 ssa->jd->basicblockcount += 1;
487 mid->icount = toi->phi_count + 1;
488 iptr = mid->iinstr = DMNEW(instruction, mid->icount);
489 MZERO(mid->iinstr, instruction, mid->icount);
491 for (itph = toi->phi_functions; itph != toi->phi_functions + toi->phi_count; ++itph) {
492 iptr->opc = ICMD_COPY;
493 iptr->dst.varindex = itph->dst;
494 iptr->s1.varindex = itph->args[j];
495 assert(itph->dst < ssa->total_local_count);
496 assert(itph->args[j] < ssa->total_local_count);
500 iptr->opc = ICMD_GOTO;
501 iptr->dst.block = to;
512 void crate_fallthrough(ssa_info *ssa, basicblock *bptr) {
514 basicblock_info *toi;
518 if (bptr->next == NULL) return;
520 j = get_predecessor_index(bptr, bptr->next);
522 toi = bb_info(bptr->next);
525 bptr->iinstr = DMREALLOC(bptr->iinstr, instruction, bptr->icount, bptr->icount + toi->phi_count);
526 iptr = bptr->iinstr + bptr->icount;
527 bptr->icount += toi->phi_count;
529 for (itph = toi->phi_functions; itph != toi->phi_functions + toi->phi_count; ++itph) {
530 iptr->opc = ICMD_COPY;
531 iptr->dst.varindex = itph->dst;
532 iptr->s1.varindex = itph->args[j];
533 assert(itph->dst < ssa->total_local_count);
534 assert(itph->args[j] < ssa->total_local_count);
540 void ssa_create_phi_moves(ssa_info *ssa) {
545 branch_target_t *table;
546 lookup_target_t *lookup;
549 for (bptr = ssa->jd->basicblocks; bptr; bptr = bptr->next) {
550 if (bptr->type == 666) {
551 bptr->type = BBTYPE_STD;
554 if (! bptr->vp) continue;
555 if (! (bptr->flags >= BBREACHED)) continue;
557 for (iptr = bptr->iinstr; iptr != bptr->iinstr + bptr->icount; ++iptr) {
558 switch (icmd_table[iptr->opc].controlflow) {
562 iptr->dst.block = create_block(ssa, bptr, iptr->dst.block);
565 table = iptr->dst.table;
566 l = iptr->sx.s23.s2.tablelow;
567 i = iptr->sx.s23.s3.tablehigh;
569 i += 1; /* default */
571 table->block = create_block(ssa, bptr, table->block);
576 lookup = iptr->dst.lookup;
577 i = iptr->sx.s23.s2.lookupcount;
579 lookup->target.block = create_block(ssa, bptr, lookup->target.block);
582 iptr->sx.s23.s3.lookupdefault.block = create_block(ssa, bptr, iptr->sx.s23.s3.lookupdefault.block);
585 iptr->sx.s23.s3.jsrtarget.block = create_block(ssa, bptr, iptr->sx.s23.s3.jsrtarget.block);
588 if ((iptr->opc == ICMD_GOTO) || icmd_table[iptr->opc].controlflow == CF_END)
590 else if (iptr->opc != ICMD_NOP)
593 if (! bptr->next) continue;
594 if (! (bptr->next->flags >= BBREACHED)) continue;
595 if (bptr->next->type == 666) continue;
596 if (!gt) crate_fallthrough(ssa, bptr);
600 void xssa(jitdata *jd) {
601 ssa_info *ssa = ssa_init(jd);
603 printf("=============== [ before %s ] =========================\n", jd->m->name->text);
605 printf("=============== [ /before ] =========================\n");
607 ssa_place_phi_functions(ssa);
608 ssa_create_phi_functions(ssa);
609 ssa_calculate_offsets(ssa);
612 ssa_create_phi_moves(ssa);
614 printf("=============== [ after ] =========================\n");
616 printf("=============== [ /after ] =========================\n");