1 /* src/vm/optimizing/ssa3.c
4 CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 SSA transformation PROTOTYPE based on:
26 Adding Static Single Assignment Form and a Graph Coloring Register
27 Allocator to the Java Hotspot Client Compiler, 2000
28 (http://www.ssw.uni-linz.ac.at/Research/Reports/Report15.html)
32 * Adapt for exception handling [done]
33 * Eliminiation of redundand PHI functions. [in progress]
34 * Handle also inout variables. [done]
35 * Create PHI functions lazyly, when they are used for the first time
36 (I suspect that currently PHIs are created that are never used).
37 * REWRITE. The code was never designed for producion. [done]
38 * Unify access to phi args.
41 #include "vm/jit/jit.h"
42 #include "vm/global.h"
43 #include "mm/memory.h"
44 #include "mm/dumpmemory.h"
45 #include "toolbox/list.h"
50 #define ELIMINATE_NOP_LOAD_STORE
53 /* #define SSA_VERBOSE */
56 __attribute__((always_inline))
59 /*** phi ********************************************************************/
63 PHI_FLAG_REDUNDANT_ALL,
64 PHI_FLAG_REDUNDANT_ONE
67 static inline void phi_set_flag(instruction *iptr, phi_flags_t flag) {
68 iptr->flags.bits |= (1 << flag);
71 static inline void phi_clear_flag(instruction *iptr, phi_flags_t flag) {
72 iptr->flags.bits &= ~(1 << flag);
75 static inline bool phi_has_flag(const instruction *iptr, phi_flags_t flag) {
76 return (iptr->flags.bits & (1 << flag)) != 0;
79 static inline instruction *phi_get_subst(instruction *iptr) {
80 return iptr->sx.s23.s2.iargs[-1];
83 static inline bool phi_has_subst(const instruction *iptr) {
84 return (iptr->sx.s23.s2.iargs[-1] != NULL);
88 static inline void phi_init(instruction *iptr, unsigned argcount, s4 index) {
93 iptr->dst.varindex = 0;
94 iptr->s1.argcount = argcount;
95 iptr->sx.s23.s2.iargs = DMNEW(instruction *, argcount + 1);
96 iptr->sx.s23.s2.iargs += 1;
97 iptr->sx.s23.s3.javaindex = index;
99 /* subst field - If non-null, the phi function shall be replaced by the
100 value produced by the subst instruction. */
101 iptr->sx.s23.s2.iargs[-1] = NULL;
104 for (i = 0; i < argcount; ++i) {
105 iptr->sx.s23.s2.iargs[i] = (instruction *)0x7fffffff;
110 #define phi_assert_opc(iptr) assert(iptr->opc == ICMD_PHI)
112 #define phi_assert_arg(iptr, arg) assert(arg < iptr->s1.argcount)
114 static inline s4 phi_arg_count(const instruction *iptr) {
115 phi_assert_opc(iptr);
116 return iptr->s1.argcount;
119 static inline instruction *phi_get_arg(const instruction *iptr, unsigned arg) {
120 phi_assert_opc(iptr);
121 phi_assert_arg(iptr, arg);
122 return iptr->sx.s23.s2.iargs[arg];
125 static inline s4 phi_get_arg_var(const instruction *iptr, unsigned arg) {
126 phi_assert_opc(iptr);
127 phi_assert_arg(iptr, arg);
128 return iptr->sx.s23.s2.iargs[arg]->dst.varindex;
131 static inline void phi_set_all_args(instruction *iptr, instruction *value) {
133 phi_assert_opc(iptr);
134 for (i = 0; i < iptr->s1.argcount; ++i) {
135 iptr->sx.s23.s2.iargs[i] = value;
139 static inline s4 phi_get_index(const instruction *iptr) {
140 phi_assert_opc(iptr);
141 return iptr->sx.s23.s3.javaindex;
144 static inline s4 phi_get_dst(const instruction *iptr) {
145 phi_assert_opc(iptr);
146 return iptr->dst.varindex;
149 static inline void phi_set_dst(instruction *iptr, s4 dst) {
150 phi_assert_opc(iptr);
151 iptr->dst.varindex = dst;
154 static inline bool phi_get_used(const instruction *iptr) {
155 phi_assert_opc(iptr);
156 return phi_has_flag(iptr, PHI_FLAG_USED);
159 static void phi_set_used(instruction *iptr) {
160 phi_assert_opc(iptr);
161 if (! phi_has_flag(iptr, PHI_FLAG_USED)) {
162 phi_set_flag(iptr, PHI_FLAG_USED);
163 /* TODO recurse into arguments */
167 static instruction *phi_resolve_use(instruction *use) {
169 while (use->opc == ICMD_PHI) {
170 if (phi_has_subst(use)) {
171 use = phi_get_subst(use);
180 static inline void phi_set_arg(instruction *iptr, unsigned arg, instruction *value) {
181 phi_assert_opc(iptr);
182 phi_assert_arg(iptr, arg);
183 assert(value != NULL);
184 iptr->sx.s23.s2.iargs[arg] = value;
187 static inline bool phi_is_redundant(const instruction *iptr) {
189 phi_has_flag(iptr, PHI_FLAG_REDUNDANT_ONE) ||
190 phi_has_flag(iptr, PHI_FLAG_REDUNDANT_ALL)
194 static inline void phi_create_copy(instruction *iptr, unsigned arg, instruction *copy) {
195 phi_assert_opc(iptr);
196 phi_assert_arg(iptr, arg);
197 copy->dst.varindex = phi_get_dst(iptr);
198 copy->s1.varindex = phi_resolve_use(phi_get_arg(iptr, arg))->dst.varindex;
199 if (copy->dst.varindex == copy->s1.varindex || phi_is_redundant(iptr)) {
200 copy->opc = ICMD_NOP;
202 copy->opc = ICMD_COPY;
207 static void phi_print(const instruction *iptr) {
210 printf("%d = phi(", iptr->dst.varindex);
211 for (i = 0; i < iptr->s1.argcount; ++i) {
212 use = phi_resolve_use(iptr->sx.s23.s2.iargs[i]);
214 printf("%d, ", use->dst.varindex);
223 #define FOR_EACH_PHI_USE_CAST(iptr, it, cast) \
225 (it) = cast (iptr)->sx.s23.s2.iargs; \
226 (it) != cast (iptr)->sx.s23.s2.iargs + (iptr)->s1.argcount; \
230 #define FOR_EACH_PHI_USE(iptr, it) \
231 FOR_EACH_PHI_USE_CAST(iptr, it, )
233 #define FOR_EACH_PHI_USE_CONST(iptr, it) \
234 FOR_EACH_PHI_USE_CAST(iptr, it, (const instruction *))
236 static void phi_calculate_redundancy(instruction *iptr) {
238 s4 dst = iptr->dst.varindex;
242 unsigned num_different = 0;
243 instruction *different;
245 if (phi_is_redundant(iptr)) return; /* XXX */
247 /* x = phi(x, y, x, x) ... PHI_FLAG_REDUNDANT_ONE
248 x = phi(x, x, x, x) ... PHI_FLAG_REDUNDANT_ALL */
250 FOR_EACH_PHI_USE(iptr, ituse) {
251 iuse = phi_resolve_use(*ituse);
254 use = iuse->dst.varindex;
259 if (num_different >= 2) {
260 phi_clear_flag(iptr, PHI_FLAG_REDUNDANT_ONE);
261 phi_clear_flag(iptr, PHI_FLAG_REDUNDANT_ALL);
266 if (num_different == 1) {
267 /* Set the subst field of the instruction.
268 I.e. the instruction will be replaced by the value produced by y. */
269 iptr->sx.s23.s2.iargs[-1] = different;
271 phi_set_flag(iptr, PHI_FLAG_REDUNDANT_ONE);
272 phi_clear_flag(iptr, PHI_FLAG_REDUNDANT_ALL);
273 } else if (num_different == 0) {
275 /*iptr->sx.s23.s2.iargs[-1] = iptr->sx.s23.s2.iargs[0];*/
277 phi_clear_flag(iptr, PHI_FLAG_REDUNDANT_ONE);
278 phi_clear_flag(iptr, PHI_FLAG_REDUNDANT_ALL);
284 /*** goto *******************************************************************/
286 static inline void goto_init(instruction *iptr, basicblock *dst) {
287 iptr->opc = ICMD_GOTO;
288 iptr->dst.block = dst;
291 /*** instruction ***********************************************************/
293 static void instruction_get_uses(const instruction *iptr, s4 *buf, s4 **puses, unsigned *puses_count) {
294 unsigned uses_count = 0;
296 switch (icmd_table[iptr->opc].dataflow) {
299 buf[2] = iptr->sx.s23.s3.varindex;
304 buf[1] = iptr->sx.s23.s2.varindex;
311 buf[0] = iptr->s1.varindex;
314 *puses_count = uses_count;
322 *puses = iptr->sx.s23.s2.args;
323 *puses_count = iptr->s1.argcount;
333 static inline void instruction_set_uses(instruction *iptr, s4 *buf, s4 *uses, unsigned uses_count) {
335 switch (uses_count) {
337 iptr->sx.s23.s3.varindex = buf[2];
339 iptr->sx.s23.s2.varindex = buf[1];
341 iptr->s1.varindex = buf[0];
346 /*** vars *******************************************************************/
348 #define VARS_CATEGORY_SHIFT 29
349 #define VARS_INDEX_MASK 0x1FFFFFFF
351 #define VARS_CATEGORY_LOCAL 0
352 #define VARS_CATEGORY_STACK 1
353 #define VARS_CATEGORY_OTHERS 2
355 #define VAR_TYPE_SUBSTITUED 666
358 varinfo items[9000]; /* XXX hardcoded max */
364 static inline unsigned vars_add_item(vars_t *vs, const varinfo *item) {
365 unsigned i = vs->count;
368 vs->items[i] = *item;
369 return (vs->category << VARS_CATEGORY_SHIFT) | i;
372 static inline unsigned vars_add(vars_t *vs) {
373 unsigned i = vs->count;
376 return (vs->category << VARS_CATEGORY_SHIFT) | i;
379 static inline varinfo *vars_back(vars_t *vs) {
380 assert(vs->count > 0);
381 return vs->items + (vs->count - 1);
384 static inline void vars_init(vars_t *vs, unsigned category) {
385 vs->max = sizeof(vs->items) / sizeof(vs->items[0]);
387 assert((category & 0x3) == category);
388 vs->category = category;
391 static inline unsigned vars_get_category(unsigned varindex) {
392 return (varindex >> VARS_CATEGORY_SHIFT);
395 static inline unsigned vars_get_index(unsigned varindex) {
396 return (varindex & VARS_INDEX_MASK);
399 static void vars_subst(vars_t *vs, unsigned varindex, unsigned replacementindex) {
400 varindex = vars_get_index(varindex);
401 replacementindex = vars_get_index(replacementindex);
403 vs->items[varindex].type = VAR_TYPE_SUBSTITUED;
404 vs->items[varindex].vv.regoff = replacementindex;
407 static unsigned vars_resolve_subst(const vars_t *vs, unsigned varindex) {
409 unsigned loop_ctr = 0;
411 varindex = vars_get_index(varindex);
413 if (vs->items[varindex].type == VAR_TYPE_SUBSTITUED) /*fprintf(stderr, "*")*/;
415 while (vs->items[varindex].type == VAR_TYPE_SUBSTITUED) {
416 assert(loop_ctr++ != vs->count);
417 varindex = vs->items[varindex].vv.regoff;
420 return (vs->category << VARS_CATEGORY_SHIFT) | varindex ;
423 static void vars_copy_to_final(vars_t *vs, varinfo *dst) {
427 for (it = vs->items; it != vs->items + vs->count; ++it, ++dst) {
433 /* Eliminate VAR_TYPE_SUBSTITUED as it leads to problems. */
435 if (dst->type == VAR_TYPE_SUBSTITUED) {
436 subst = vars_get_index(vars_resolve_subst(vs, it - vs->items));
437 dst->type = vs->items[subst].type;
444 /*** phis *******************************************************************/
452 static inline void phis_init(phis_t *ps, unsigned max) {
455 ps->items = DMNEW(instruction, max);
458 static inline instruction *phis_add(phis_t *ps) {
459 unsigned i = ps->count;
462 return ps->items + i;
465 static inline instruction *phis_get(const phis_t *ps, unsigned i) {
466 assert(i < ps->count);
467 return ps->items + i;
470 static inline bool phis_contains(const phis_t *ps, const instruction *phi) {
471 return (ps->items <= phi) && (phi < (ps->items + ps->max));
474 #define FOR_EACH_PHI_FUNCTION_(ps, it) \
475 for ((it) = (ps)->items; (it) != (ps)->items + (ps)->count; ++(it)) \
477 #define FOR_EACH_PHI_FUNCTION(ps, it) \
478 FOR_EACH_PHI_FUNCTION_(ps, it) if (!phi_is_redundant((it)))
481 FIXME() inline void phis_print(const phis_t *ps) {
482 const instruction *iptr;
483 FOR_EACH_PHI_FUNCTION(ps, iptr) {
489 static inline void phis_copy_to(const phis_t *ps, instruction *dst) {
498 /*** state_array ************************************************************/
505 static inline void state_array_init(state_array_t *sa, unsigned count) {
510 static inline bool state_array_has_items(const state_array_t *sa) {
511 return (sa->items != NULL);
514 static inline s4 state_array_get_var(const state_array_t *sa, unsigned index) {
515 assert(index < sa->count);
516 assert(sa->items[index]);
517 return sa->items[index]->dst.varindex;
520 static inline instruction *state_array_get(const state_array_t *sa, unsigned index) {
521 assert(index < sa->count);
522 return sa->items[index];
525 static inline void state_array_set(const state_array_t *sa, unsigned index, instruction *value) {
526 assert(index < sa->count);
527 sa->items[index] = value;
530 static inline void state_array_copy(state_array_t *sa, state_array_t *other) {
531 assert(sa->count == other->count);
532 MCOPY(sa->items, other->items, instruction *, sa->count);
535 #define state_array_assert_items(sa) assert(state_array_has_items(sa) || (sa->count == 0))
536 #define state_array_assert_no_items(sa) assert(! state_array_has_items(sa))
538 static inline void state_array_allocate_items(state_array_t *sa) {
539 sa->items = DMNEW(instruction *, sa->count);
540 MZERO(sa->items, instruction *, sa->count);
543 /*** basicblock_chain *******************************************************/
548 } basicblock_chain_t;
550 static void basicblock_chain_init(basicblock_chain_t *bbc) {
555 #define basicblock_chain_clear basicblock_chain_init
557 static void basicblock_chain_add(basicblock_chain_t *bbc, basicblock *bb) {
558 if (bbc->first == NULL) {
559 assert(bbc->last == NULL);
560 assert(bb->next == NULL);
564 assert(bbc->last->next == NULL);
565 bbc->last->next = bb;
570 static inline basicblock *basicblock_chain_front(basicblock_chain_t *bbc) {
575 static inline basicblock *basicblock_chain_back(basicblock_chain_t *bbc) {
580 static inline bool basicblock_chain_empty(const basicblock_chain_t *bbc) {
581 return bbc->first == NULL;
584 /*** exception_entry_chain ***************************************************/
587 exception_entry *first;
588 exception_entry *last;
589 } exception_entry_chain_t;
591 static void exception_entry_chain_init(exception_entry_chain_t *eec) {
596 #define exception_entry_chain_clear exception_entry_chain_init
598 static void exception_entry_chain_add(exception_entry_chain_t *eec, exception_entry *ee) {
599 if (eec->first == NULL) {
603 eec->last->next = ee;
604 eec->last->down = ee;
609 static inline bool exception_entry_chain_empty(const exception_entry_chain_t *eec) {
610 return eec->first == NULL;
613 static inline exception_entry *exception_entry_chain_back(exception_entry_chain_t *eec) {
618 static inline exception_entry *exception_entry_chain_front(exception_entry_chain_t *eec) {
623 /*** traversal **************************************************************/
626 unsigned (*var_num_to_index)(void *vp, s4 var);
627 varinfo *(*index_to_initial_var)(void *vp, unsigned index);
628 varinfo *(*var_num_to_varinfo)(void *vp, s4 var);
629 unsigned (*variables_count)(void *vp);
634 state_array_t *state_array;
636 traversal_ops_t *ops;
639 /*** basicblock_info ********************************************************/
641 typedef struct basicblock_info {
645 unsigned backward_branches;
650 basicblock_chain_t *subbasicblocks;
652 unsigned complete_predecessors;
654 #if defined(SSA_VERIFY)
655 unsigned num_phi_elimination;
660 /*** traversal **************************************************************/
662 void traversal_init(traversal_t *t, unsigned count, void *ops_vp, traversal_ops_t *ops) {
663 t->phis = DNEW(phis_t);
664 phis_init(t->phis, count);
666 t->state_array = DNEW(state_array_t);
667 state_array_init(t->state_array, count);
673 instruction *traversal_create_phi(traversal_t *t, vars_t *v, unsigned argcount, s4 index) {
674 instruction *phi = phis_add(t->phis);
677 phi_init(phi, argcount, index);
678 dst = vars_add_item(v, t->ops->index_to_initial_var(t->ops_vp, index));
679 phi_set_dst(phi, dst);
681 state_array_set(t->state_array, index, phi);
686 static void traversal_rename_def(traversal_t *t, vars_t *vars, instruction *iptr) {
690 state_array_assert_items(t->state_array);
692 v = t->ops->var_num_to_varinfo(t->ops_vp, iptr->dst.varindex);
693 index = t->ops->var_num_to_index(t->ops_vp, iptr->dst.varindex);
695 iptr->dst.varindex = vars_add_item(vars, v);
696 state_array_set(t->state_array, index, iptr);
699 static void traversal_rename_use(traversal_t *t, s4 *puse) {
702 state_array_assert_items(t->state_array);
704 index = t->ops->var_num_to_index(t->ops_vp, *puse);
706 assert(state_array_get(t->state_array, index));
707 *puse = state_array_get_var(t->state_array, index);
710 static inline unsigned traversal_variables_count(traversal_t *t) {
711 return t->ops->variables_count(t->ops_vp);
714 unsigned local_var_num_to_index(void *vp, s4 var) {
715 return (unsigned)var;
718 varinfo *local_index_to_initial_var(void *vp, unsigned index) {
719 jitdata *jd = (jitdata *)vp;
720 return jd->var + index;
723 varinfo *local_var_num_to_varinfo(void *vp, s4 var) {
724 jitdata *jd = (jitdata *)vp;
725 return jd->var + var;
728 unsigned local_variables_count(void *vp) {
729 jitdata *jd = (jitdata *)vp;
730 return jd->localcount;
733 traversal_ops_t traversal_local_ops = {
734 local_var_num_to_index,
735 local_index_to_initial_var,
736 local_var_num_to_varinfo,
737 local_variables_count
740 unsigned inout_var_num_to_index(void *vp, s4 var) {
741 basicblock *bb = (basicblock *)vp;
744 for (i = 0; i < bb->indepth; ++i) {
745 if (bb->invars[i] == var) {
750 for (i = 0; i < bb->outdepth; ++i) {
751 if (bb->outvars[i] == var) {
759 varinfo *inout_index_to_initial_var(void *vp, unsigned index) {
760 basicblock *bb = (basicblock *)vp;
761 jitdata *jd = (jitdata *)(((basicblock_info_t *)bb->vp)->locals->ops_vp); /* evil hack */
762 assert(index < bb->indepth);
763 return jd->var + bb->invars[index];
766 varinfo *inout_var_num_to_varinfo(void *vp, s4 var) {
767 basicblock *bb = (basicblock *)vp;
768 jitdata *jd = (jitdata *)(((basicblock_info_t *)bb->vp)->locals->ops_vp); /* evil hack */
769 return jd->var + var;
772 unsigned inout_variables_count(void *vp) {
773 basicblock *bb = (basicblock *)vp;
777 traversal_ops_t traversal_inout_ops = {
778 inout_var_num_to_index,
779 inout_index_to_initial_var,
780 inout_var_num_to_varinfo,
781 inout_variables_count
784 /*** basicblock_info ********************************************************/
786 void basicblock_info_init(basicblock_info_t *bbi, basicblock *bb, jitdata *jd) {
787 MZERO(bbi, basicblock_info_t, 1);
789 bbi->locals = DNEW(traversal_t);
790 traversal_init(bbi->locals, jd->localcount, jd, &traversal_local_ops);
792 bbi->stack = DNEW(traversal_t);
793 traversal_init(bbi->stack, jd->maxinterfaces, bb, &traversal_inout_ops);
795 bbi->subbasicblocks = DNEW(basicblock_chain_t);
796 basicblock_chain_init(bbi->subbasicblocks);
799 /*** basicblock *************************************************************/
801 static inline basicblock_info_t *basicblock_info(basicblock *bb) {
802 return (basicblock_info_t *)(bb->vp);
805 #define bb_info basicblock_info
807 static unsigned basicblock_get_predecessor_count(basicblock *bb) {
811 ret = bb->predecessorcount;
813 FOR_EACH_EXPREDECESSOR(bb, itpred) {
814 ret += (*itpred)->exouts;
820 static unsigned basicblock_get_predecessor_index(basicblock *from, basicblock *to) {
824 FOR_EACH_PREDECESSOR(to, itpred) {
825 if (*itpred == from) break;
829 assert(j != to->predecessorcount);
834 static unsigned basicblock_get_ex_predecessor_index(basicblock *from, unsigned pei, basicblock *to) {
838 j = to->predecessorcount;
840 FOR_EACH_EXPREDECESSOR(to, itpred) {
841 if ((*itpred)->nr == from->nr) {
845 j += (*itpred)->exouts;
852 /*** ssa_info ***************************************************************/
854 typedef struct ssa_info {
863 basicblock_chain_t *new_blocks;
865 } ssa_info, ssa_info_t;
867 void ssa_info_init(ssa_info_t *ssa, jitdata *jd) {
870 ssa->locals = DNEW(vars_t);
871 vars_init(ssa->locals, VARS_CATEGORY_LOCAL);
873 /* Initialize first version of locals, that is always available. */
874 MCOPY(ssa->locals->items, jd->var, varinfo, jd->localcount);
875 ssa->locals->count = jd->localcount;
877 ssa->stack = DNEW(vars_t);
878 vars_init(ssa->stack, VARS_CATEGORY_STACK);
880 ssa->others = DNEW(vars_t);
881 vars_init(ssa->others, VARS_CATEGORY_OTHERS);
883 ssa->new_blocks = DNEW(basicblock_chain_t);
884 basicblock_chain_init(ssa->new_blocks);
887 /*** others_mapping *********************************************************/
889 static inline void others_mapping_set(ssa_info *ssa, s4 var, s4 new_var) {
890 ssa->jd->var[var].vv.regoff = new_var;
893 static inline s4 others_mapping_get(const ssa_info *ssa, s4 var) {
894 return ssa->jd->var[var].vv.regoff;
897 /*** code *******************************************************************/
899 void fix_exception_handlers(jitdata *jd) {
901 basicblock *exh = NULL;
907 basicblock_chain_t chain;
908 basicblock *last = NULL;
909 basicblock *marker = NULL;
911 if (jd->exceptiontablelength == 0) {
915 basicblock_chain_init(&chain);
917 /* We need to allocate new iovars */
919 avail_vars = (jd->varcount - jd->vartop);
920 add_vars = jd->exceptiontablelength;
922 if (add_vars > avail_vars) {
923 add_vars -= avail_vars;
924 jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, jd->varcount + add_vars);
925 jd->varcount += add_vars;
928 /* For each exception handler block, create one block with a prologue block */
930 FOR_EACH_BASICBLOCK(jd, bptr) {
931 if (bptr->type == BBTYPE_EXH) {
933 bptr->type = BBTYPE_STD;
934 bptr->predecessorcount = 0; /* legacy */
936 /* Create basicblock with 2 instructions */
938 exh = DNEW(basicblock);
939 MZERO(exh, basicblock, 1);
941 iptr = DMNEW(instruction, 2);
942 MZERO(iptr, instruction, 2);
944 /* Create new outvar */
946 assert(jd->vartop < jd->varcount);
949 jd->var[v].type = TYPE_ADR;
950 jd->var[v].flags = INOUT;
952 exh->nr = jd->basicblockcount;
953 jd->basicblockcount += 1;
955 exh->type = BBTYPE_EXH;
959 exh->outvars = DNEW(s4);
961 exh->predecessorcount = -1; /* legacy */
962 exh->flags = BBFINISHED;
965 basicblock_chain_add(&chain, exh);
969 iptr->opc = ICMD_GETEXCEPTION;
970 iptr->dst.varindex = v;
973 /* Goto real exception handler */
975 goto_init(iptr, bptr);
982 if (bptr->next == NULL) {
989 /* Put the chain of exception handlers between just before the last
990 basic block (end marker). */
992 if (! basicblock_chain_empty(&chain)) {
993 marker->nr = jd->basicblockcount;
994 basicblock_chain_back(&chain)->next = marker;
995 last->next = basicblock_chain_front(&chain);
997 assert(last->nr + 1 == basicblock_chain_front(&chain)->nr);
998 assert(marker->nr == jd->basicblockcount);
1001 /* Replace all exception handlers in exception table with their respective
1004 for (ee = jd->exceptiontable; ee; ee = ee->down) {
1005 assert(ee->handler->vp);
1006 ee->handler = ee->handler->vp;
1011 /*** ssa_enter ***************************************************************/
1013 static void ssa_enter_mark_loops_intern(basicblock *bb, unsigned num_branches) {
1014 basicblock_info_t *bbi = bb_info(bb);
1015 basicblock **itsucc;
1017 if (! bbi->visited) {
1018 bbi->visited = true;
1020 FOR_EACH_SUCCESSOR(bb, itsucc) {
1021 /* There is a single branch from bb into the successor. */
1022 ssa_enter_mark_loops_intern(*itsucc, 1);
1024 FOR_EACH_EXHANDLER(bb, itsucc) {
1025 /* For exception handler type successors,
1026 we count a branch into the exception handler from every PEI. */
1027 ssa_enter_mark_loops_intern(*itsucc, bb->exouts);
1029 bbi->active = false;
1030 } else if (bbi->active) {
1031 bbi->backward_branches += num_branches;
1035 static inline void ssa_enter_mark_loops(basicblock *bb) {
1036 ssa_enter_mark_loops_intern(bb, 1);
1039 static void ssa_enter_merge(
1043 unsigned predecessor_index,
1047 basicblock_info_t *dsti = bb_info(bdst);
1048 unsigned predecessor_count = basicblock_get_predecessor_count(bdst);
1053 /* We are merging for the first time into this block. */
1055 if (! state_array_has_items(dst->state_array)) {
1057 state_array_allocate_items(dst->state_array);
1059 if (dsti->backward_branches > 0) {
1060 /* Loop header, create phi functions for all variables. */
1061 for (i = 0; i < traversal_variables_count(dst); ++i) {
1062 phi = traversal_create_phi(dst, vdst, predecessor_count, i);
1063 /* No need to init, they will only be filled in later. */
1066 state_array_copy(dst->state_array, src->state_array);
1071 /* We are merging another block. */
1073 /* Process every variable. */
1075 for (i = 0; i < traversal_variables_count(dst); ++i) {
1076 if (dsti->traversed) {
1078 /* Back edge, all phi functions are already created.
1079 We only need to set their arguments. */
1082 phis_get(dst->phis, i),
1084 state_array_get(src->state_array, i)
1087 } else if (state_array_get(dst->state_array, i) != state_array_get(src->state_array, i)) {
1089 /* A different definition of this var reaches the block.
1090 We need to create a phi function. */
1092 if (phis_contains(dst->phis, state_array_get(dst->state_array, i))) {
1093 /* There is already a phi function created for this var.
1094 No need to create one. */
1096 /* Create a new phi function.
1097 Set all arguments to old value in state array. */
1098 old = state_array_get(dst->state_array, i);
1099 phi = traversal_create_phi(dst, vdst, predecessor_count, i);
1100 phi_set_all_args(phi, old);
1103 /* Set argument of phi function. */
1106 state_array_get(dst->state_array, i),
1108 state_array_get(src->state_array, i)
1114 static void ssa_enter_process_block(ssa_info *ssa, basicblock *bb);
1115 static bool ssa_enter_eliminate_redundant_phis(traversal_t *t, vars_t *vs, basicblock_info_t *bbi);
1117 #if defined(SSA_VERIFY)
1118 static void ssa_enter_verify_no_redundant_phis(ssa_info_t *ssa) {
1120 basicblock_info_t *bbi;
1122 FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
1123 if (basicblock_reached(bptr)) {
1124 bbi = bb_info(bptr);
1125 FOR_EACH_PHI_FUNCTION(bbi->locals->phis, itph) {
1126 if (! phi_is_redundant(itph)) {
1127 phi_calculate_redundancy(itph);
1128 assert(! phi_is_redundant(itph));
1131 FOR_EACH_PHI_FUNCTION(bbi->stack->phis, itph) {
1132 if (! phi_is_redundant(itph)) {
1133 phi_calculate_redundancy(itph);
1134 assert(! phi_is_redundant(itph));
1142 static void ssa_enter_traverse(ssa_info_t *ssa, basicblock *bb) {
1143 basicblock **itsucc;
1144 basicblock_info_t *succi;
1145 basicblock_info_t *bbi = bb_info(bb);
1146 unsigned predecessor_count;
1150 ssa_enter_process_block(ssa, bb);
1154 FOR_EACH_SUCCESSOR(bb, itsucc) {
1156 succi = bb_info(*itsucc);
1162 basicblock_get_predecessor_index(bb, *itsucc),
1170 basicblock_get_predecessor_index(bb, *itsucc),
1174 succi->complete_predecessors += 1;
1176 predecessor_count = basicblock_get_predecessor_count(*itsucc);
1179 succi->complete_predecessors ==
1180 (predecessor_count - succi->backward_branches)
1182 ssa_enter_traverse(ssa, *itsucc);
1186 (succi->complete_predecessors == predecessor_count) &&
1187 (succi->backward_branches > 0)
1189 #if defined(SSA_VERIFY)
1190 assert(succi->num_phi_elimination < 2);
1191 succi->num_phi_elimination += 1;
1193 ssa_enter_eliminate_redundant_phis(succi->locals, ssa->locals, succi);
1194 ssa_enter_eliminate_redundant_phis(succi->stack, ssa->stack, succi);
1198 FOR_EACH_EXHANDLER(bb, itsucc) {
1200 succi = bb_info(*itsucc);
1202 succi->complete_predecessors += bb->exouts; /* XXX this might be 0 */
1204 predecessor_count = basicblock_get_predecessor_count(*itsucc);
1207 succi->complete_predecessors ==
1208 (predecessor_count - succi->backward_branches)
1210 ssa_enter_traverse(ssa, *itsucc);
1214 (succi->complete_predecessors == predecessor_count) &&
1215 (succi->backward_branches > 0)
1217 #if defined(SSA_VERIFY)
1218 assert(succi->num_phi_elimination < 2);
1219 succi->num_phi_elimination += 1;
1221 ssa_enter_eliminate_redundant_phis(succi->locals, ssa->locals, succi);
1222 ssa_enter_eliminate_redundant_phis(succi->stack, ssa->stack, succi);
1229 static void ssa_enter_process_pei(ssa_info *ssa, basicblock *bb, unsigned pei) {
1230 basicblock_info_t *bbi = bb_info(bb);
1231 basicblock_info_t *succi;
1232 basicblock **itsucc;
1234 FOR_EACH_EXHANDLER(bb, itsucc) {
1235 succi = bb_info(*itsucc);
1241 basicblock_get_ex_predecessor_index(bb, pei, *itsucc),
1247 static FIXME(bool) ssa_enter_eliminate_redundant_phis(traversal_t *t, vars_t *vs, basicblock_info_t *FIXME(bbi)) {
1252 FOR_EACH_PHI_FUNCTION(t->phis, itph) {
1254 phi_calculate_redundancy(itph);
1256 /* If the phi function is redundant,
1257 make the variable it defines point to the value defined by the substituing
1260 if (phi_is_redundant(itph)) {
1261 vars_subst(vs, itph->dst.varindex, phi_get_subst(itph)->dst.varindex);
1262 assert(bbi->backward_branches > 0);
1271 static void ssa_enter_post_eliminate_redundand_phi(
1277 phi_calculate_redundancy(phi);
1278 phi_set_flag(PHI_FLAG_REDUNDANCY_CHECKED);
1280 /* if redundancy changed and phi function escapes block */
1282 /* for each successor */
1285 static void ssa_enter_post_eliminate_redundant_phis(ssa_info_t *ssa) {
1287 basicblock_info_t *bbi;
1290 FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
1291 bbi = bb_info(bptr);
1293 if (bbi->backward_branches > 0) {
1294 /* Redundant phi functions have the left hand side as operand.
1295 This can happen by definition only in loop headers. */
1297 FOR_EACH_PHI_FUNCTION(bbi->locals, itph) {
1298 if (! phi_has_flag(PHI_FLAG_REDUNDANCY_CHECKED)) {
1299 /* Calculate redundancy? */
1301 /* If yes recurse? */
1305 FOR_EACH_PHI_FUNCTION(bbi->stack, itph) {
1312 static void ssa_enter_init_locals(state_array_t *sa) {
1316 for (i = 0; i < sa->count; ++i) {
1317 iptr = DNEW(instruction);
1318 iptr->opc = ICMD_NOP;
1319 iptr->dst.varindex = i;
1320 state_array_set(sa, i, iptr);
1324 static void ssa_enter_process_block(ssa_info *ssa, basicblock *bb) {
1325 basicblock_info_t *bbi = bb_info(bb);
1330 unsigned uses_count;
1333 /* Every basic block can be traversed only once. */
1335 assert(! bbi->traversed);
1336 bbi->traversed = true;
1338 /* The root basicblock needs special treatment. */
1340 if (bb->predecessorcount == 0 && bb->type != BBTYPE_EXH) {
1341 state_array_assert_no_items(bbi->locals->state_array);
1342 state_array_allocate_items(bbi->locals->state_array);
1343 ssa_enter_init_locals(bbi->locals->state_array);
1345 state_array_assert_no_items(bbi->stack->state_array);
1346 state_array_allocate_items(bbi->stack->state_array);
1349 /* Exception handlers have a clean stack. */
1351 if (bb->type == BBTYPE_EXH) {
1352 state_array_assert_no_items(bbi->stack->state_array);
1353 state_array_allocate_items(bbi->stack->state_array);
1356 /* Some in/out vars get marked as INOUT in simplereg,
1357 and are not marked at this point.
1358 Mark them manually. */
1360 for (ituse = bb->invars; ituse != bb->invars + bb->indepth; ++ituse) {
1361 ssa->jd->var[*ituse].flags |= INOUT;
1362 ssa->jd->var[*ituse].flags &= ~PREALLOC;
1365 for (ituse = bb->outvars; ituse != bb->outvars + bb->outdepth; ++ituse) {
1366 ssa->jd->var[*ituse].flags |= INOUT;
1367 ssa->jd->var[*ituse].flags &= ~PREALLOC;
1370 /* Process instructions */
1372 state_array_assert_items(bbi->locals->state_array);
1374 FOR_EACH_INSTRUCTION(bb, iptr) {
1376 #if defined(ELIMINATE_NOP_LOAD_STORE)
1378 /* Kill NOP instructions of the form:
1381 As they create a lot of unnecessary definitions.
1382 For performance, definitely eliminate them. However, keeping them is a
1387 (icmd_table[iptr->opc].dataflow == DF_LOAD) ||
1388 (icmd_table[iptr->opc].dataflow == DF_STORE)
1390 if (iptr->dst.varindex == iptr->s1.varindex) {
1391 iptr->opc = ICMD_NOP;
1397 if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
1398 ssa_enter_process_pei(ssa, bb, pei++);
1401 instruction_get_uses(iptr, ssa->s_buf, &uses, &uses_count);
1403 for (ituse = uses; ituse != uses + uses_count; ++ituse) {
1404 if (var_is_local(ssa->jd, *ituse)) {
1405 traversal_rename_use(
1409 } else if (var_is_inout(ssa->jd, *ituse)) {
1410 traversal_rename_use(
1415 *ituse = others_mapping_get(ssa, *ituse);
1419 instruction_set_uses(iptr, ssa->s_buf, uses, uses_count);
1421 if (instruction_has_dst(iptr)) {
1422 if (var_is_local(ssa->jd, iptr->dst.varindex)) {
1423 traversal_rename_def(
1428 } else if (var_is_inout(ssa->jd, iptr->dst.varindex)) {
1429 traversal_rename_def(
1435 old = iptr->dst.varindex;
1436 iptr->dst.varindex = vars_add_item(
1438 ssa->jd->var + iptr->dst.varindex
1440 others_mapping_set(ssa, old, iptr->dst.varindex);
1448 [locals.........................][interaces][others]
1449 [original locals][version > 1 ]
1450 <--------------- new locals --------------->
1453 static void ssa_enter_export_variables(ssa_info *ssa) {
1458 jitdata *jd = ssa->jd;
1460 vartop = ssa->locals->count + ssa->stack->count + ssa->others->count;
1461 vars = DMNEW(varinfo, vartop);
1463 vars_copy_to_final(ssa->locals, vars);
1464 vars_copy_to_final(ssa->stack, vars + ssa->locals->count);
1465 vars_copy_to_final(ssa->others, vars + ssa->locals->count + ssa->stack->count);
1468 jd->vartop = jd->varcount = vartop;
1470 /* Grow local map to accomodate all new locals and iovars.
1471 But keep the local map for version 1 of locals, that contains the holes. */
1473 jd->local_map = DMREALLOC(
1477 5 * (jd->maxlocals + ssa->locals->count + ssa->stack->count - jd->localcount)
1480 it = jd->local_map + (jd->maxlocals * 5); /* start adding entries here */
1482 /* Add version > 1 of all locals */
1484 for (i = jd->localcount; i < ssa->locals->count; ++i) {
1485 for (j = 0; j < 5; ++j) {
1486 if (jd->var[i].type != j) {
1495 /* Add all io vars. */
1497 for (i = ssa->locals->count; i < ssa->locals->count + ssa->stack->count; ++i) {
1498 for (j = 0; j < 5; ++j) {
1499 if (jd->var[i].type != j) {
1510 jd->maxlocals += (ssa->locals->count + ssa->stack->count - jd->localcount);
1511 jd->localcount = ssa->locals->count + ssa->stack->count;
1513 /* Eliminate interfaces. */
1515 jd->maxinterfaces = 0;
1519 static void ssa_enter_export_phis(ssa_info_t *ssa) {
1521 basicblock_info_t *bbi;
1524 FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
1525 bbi = bb_info(bptr);
1528 bbi->locals->phis->count +
1529 bbi->stack->phis->count;
1531 bptr->phis = DMNEW(instruction, bptr->phicount);
1535 phis_copy_to(bbi->locals->phis, dst);
1537 dst += bbi->locals->phis->count;
1539 phis_copy_to(bbi->stack->phis, dst);
1545 static inline void ssa_enter_eliminate_category(ssa_info_t *ssa, s4 *pvar) {
1546 switch (vars_get_category(*pvar)) {
1547 case VARS_CATEGORY_LOCAL:
1548 *pvar = vars_get_index(vars_resolve_subst(ssa->locals, *pvar));
1550 case VARS_CATEGORY_STACK:
1551 *pvar = vars_get_index(vars_resolve_subst(ssa->stack, *pvar)) + ssa->locals->count;
1553 case VARS_CATEGORY_OTHERS:
1554 *pvar = vars_get_index(*pvar) + ssa->locals->count + ssa->stack->count;
1560 void ssa_enter_eliminate_categories(ssa_info_t *ssa) {
1564 unsigned uses_count;
1565 basicblock_info_t *bbi;
1568 FOR_EACH_BASICBLOCK(ssa->jd, bb) {
1576 FOR_EACH_PHI_FUNCTION(bbi->locals->phis, itph) {
1577 ssa_enter_eliminate_category(ssa, &(itph->dst.varindex));
1580 FOR_EACH_PHI_FUNCTION(bbi->stack->phis, itph) {
1581 ssa_enter_eliminate_category(ssa, &(itph->dst.varindex));
1585 FOR_EACH_INSTRUCTION(bb, iptr) {
1586 if (instruction_has_dst(iptr)) {
1587 ssa_enter_eliminate_category(ssa, &(iptr->dst.varindex));
1589 instruction_get_uses(iptr, ssa->s_buf, &uses, &uses_count);
1590 for (ituse = uses; ituse != uses + uses_count; ++ituse) {
1591 ssa_enter_eliminate_category(ssa, ituse);
1593 instruction_set_uses(iptr, ssa->s_buf, uses, uses_count);
1598 static void ssa_enter_create_phi_graph(ssa_info *ssa) {
1600 basicblock_info_t *bbi;
1602 instruction **ituse;
1604 char path[PATH_MAX], *ppath;
1607 snprintf(path, PATH_MAX, "|tmp|graphs|%s.%s.dot", ssa->jd->m->clazz->name->text, ssa->jd->m->name->text);
1608 for (ppath = path; *ppath; ++ppath) {
1609 if (*ppath == '|') *ppath = '/';
1610 else if (*ppath == '/') *ppath = '.';
1613 f = fopen(path, "w");
1615 if (f == NULL) return;
1617 fprintf(f, "digraph G {\n");
1619 FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
1620 bbi = bb_info(bptr);
1622 FOR_EACH_PHI_FUNCTION(bbi->locals->phis, itph) {
1624 FOR_EACH_PHI_USE(itph, ituse) {
1625 if ((*ituse)->opc == ICMD_PHI) {
1626 fprintf(f, "%d -> %d;\n", (*ituse)->dst.varindex, itph->dst.varindex);
1639 static basicblock *ssa_leave_create_transition_block_intern(
1643 unsigned predecessor_index,
1644 unsigned reserved_insns
1649 basicblock_info_t *toi;
1653 /* Create basicblock and instruction array. */
1655 bb = DNEW(basicblock);
1656 MZERO(bb, basicblock, 1);
1658 bb->nr = ssa->jd->basicblockcount;
1659 ssa->jd->basicblockcount += 1;
1661 bb->method = ssa->jd->m;
1662 bb->type = BBTYPE_STD;
1665 toi->locals->phis->count +
1666 toi->stack->phis->count +
1668 bb->iinstr = DMNEW(instruction, bb->icount);
1669 MZERO(bb->iinstr, instruction, bb->icount);
1671 /* Populate instruction array. */
1673 iptr = bb->iinstr + reserved_insns;
1675 /* Add phi moves. */
1677 FOR_EACH_PHI_FUNCTION(toi->locals->phis, itph) {
1678 phi_create_copy(itph, predecessor_index, iptr++);
1681 FOR_EACH_PHI_FUNCTION(toi->stack->phis, itph) {
1682 phi_create_copy(itph, predecessor_index, iptr++);
1685 /* Add goto to real block. */
1687 goto_init(iptr, to);
1689 /* Add basicblock to chain of newly created basicblocks. */
1691 basicblock_chain_add(ssa->new_blocks, bb);
1696 static inline basicblock *ssa_leave_create_transition_block(
1701 return ssa_leave_create_transition_block_intern(
1705 basicblock_get_predecessor_index(from, to),
1710 static void ssa_leave_create_fallthrough(ssa_info *ssa, basicblock *bptr) {
1711 unsigned predecessor_index;
1712 basicblock_info_t *toi;
1717 if (bptr->next == NULL) {
1718 /* No fallthrough. */
1722 predecessor_index = basicblock_get_predecessor_index(bptr, bptr->next);
1723 toi = bb_info(bptr->next);
1727 /* Resize instruction array to accomodate all phi moves. */
1729 icount = bptr->icount + toi->locals->phis->count + toi->stack->phis->count;
1731 bptr->iinstr = DMREALLOC(
1738 iptr = bptr->iinstr + bptr->icount;
1739 bptr->icount = icount;
1741 /* Create phi moves. */
1743 FOR_EACH_PHI_FUNCTION(toi->locals->phis, itph) {
1744 phi_create_copy(itph, predecessor_index, iptr++);
1747 FOR_EACH_PHI_FUNCTION(toi->stack->phis, itph) {
1748 phi_create_copy(itph, predecessor_index, iptr++);
1752 static void ssa_leave_create_phi_moves(ssa_info *ssa) {
1755 basicblock *last = NULL;
1758 branch_target_t *table;
1759 lookup_target_t *lookup;
1760 bool has_fallthrough;
1762 FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
1764 if (bptr->next == NULL) {
1768 if (bptr->vp == NULL) {
1772 if (! basicblock_reached(bptr)) {
1776 has_fallthrough = true;
1778 for (iptr = bptr->iinstr; iptr != bptr->iinstr + bptr->icount; ++iptr) {
1779 switch (icmd_table[iptr->opc].controlflow) {
1784 ssa_leave_create_transition_block(ssa, bptr, iptr->dst.block);
1787 table = iptr->dst.table;
1788 l = iptr->sx.s23.s2.tablelow;
1789 i = iptr->sx.s23.s3.tablehigh;
1791 i += 1; /* default */
1794 ssa_leave_create_transition_block(ssa, bptr, table->block);
1799 lookup = iptr->dst.lookup;
1800 i = iptr->sx.s23.s2.lookupcount;
1802 lookup->target.block =
1803 ssa_leave_create_transition_block(ssa, bptr, lookup->target.block);
1806 iptr->sx.s23.s3.lookupdefault.block =
1807 ssa_leave_create_transition_block(ssa, bptr, iptr->sx.s23.s3.lookupdefault.block);
1810 iptr->sx.s23.s3.jsrtarget.block =
1811 ssa_leave_create_transition_block(ssa, bptr, iptr->sx.s23.s3.jsrtarget.block);
1816 (iptr->opc == ICMD_GOTO) ||
1817 (iptr->opc == ICMD_JSR) ||
1818 (iptr->opc == ICMD_RET) ||
1819 icmd_table[iptr->opc].controlflow == CF_END ||
1820 (iptr->opc == ICMD_TABLESWITCH) ||
1821 (iptr->opc == ICMD_LOOKUPSWITCH)
1823 has_fallthrough = false;
1824 } else if (iptr->opc != ICMD_NOP) {
1825 has_fallthrough = true;
1830 if (bptr->next == NULL) {
1834 if (! basicblock_reached(bptr->next)) {
1838 if (has_fallthrough) {
1839 ssa_leave_create_fallthrough(ssa, bptr);
1843 /* Add chain of new basic blocks */
1845 if (last != NULL && ! basicblock_chain_empty(ssa->new_blocks)) {
1846 last->next = basicblock_chain_front(ssa->new_blocks);
1851 static basicblock *ssa_leave_split_basicblock_at(ssa_info *ssa, basicblock *bptr, instruction *iptr) {
1853 basicblock_info_t *bbi = bb_info(bptr);
1854 unsigned iidx = iptr - bptr->iinstr;
1855 basicblock *newblock;
1856 basicblock *tosplit;
1860 assert(iidx < bptr->icount);
1863 /* If there are no subbasicblocks yet, we initialize the first one to be a
1864 copy of the original basicblock. */
1866 if (basicblock_chain_empty(bbi->subbasicblocks)) {
1867 newblock = DNEW(basicblock);
1869 newblock->next = NULL;
1870 newblock->vp = NULL;
1871 basicblock_chain_add(bbi->subbasicblocks, newblock);
1874 /* Find the subbasicblock that will be split:
1875 the one that cointains iptr. */
1877 tosplit = basicblock_chain_front(bbi->subbasicblocks);
1880 while (tosplit->next && (iidx >= (pos + tosplit->icount))) {
1881 assert(bptr->nr == tosplit->nr);
1882 pos += tosplit->icount;
1883 tosplit = tosplit->next;
1886 assert(bptr->nr == tosplit->nr);
1888 /* Calculate number of instructions left in block to split. */
1890 ileft = iptr - tosplit->iinstr + 1;
1891 assert(ileft <= tosplit->icount);
1893 /* If there are any instructions left in the block to split, split */
1895 if (ileft < tosplit->icount) {
1896 newblock = DNEW(basicblock);
1897 *newblock = *tosplit;
1899 tosplit->next = newblock;
1900 tosplit->icount = ileft;
1902 newblock->icount -= ileft;
1903 newblock->iinstr += ileft;
1905 assert(tosplit->nr == bptr->nr);
1906 assert(newblock->nr == bptr->nr);
1907 assert(newblock->next == NULL);
1909 if (newblock->next == NULL) {
1910 bbi->subbasicblocks->last = newblock;
1914 /* We won't break pointers/references to bptr.
1915 So return bptr instread of the first fragment.
1916 Later, we will put the first fragment into the memory used by bptr.
1919 if (tosplit == basicblock_chain_front(bbi->subbasicblocks)) {
1926 static basicblock *ssa_leave_create_transition_exception_handler(
1934 /* From is a try block, to is an exception handler prologue. */
1936 /* Remove old prologue. */
1938 to->flags = BBDELETED;
1940 /* Create new exception handler. */
1942 exh = ssa_leave_create_transition_block_intern(
1946 basicblock_get_ex_predecessor_index(from, pei, to),
1949 exh->type = BBTYPE_EXH;
1951 /* Copy goto to real exception handler at the end of the exception handler
1954 assert(to->iinstr[to->icount - 1].opc == ICMD_GOTO);
1955 assert(exh->iinstr[exh->icount - 1].opc == ICMD_GOTO);
1956 exh->iinstr[exh->icount - 1] = to->iinstr[to->icount - 1];
1958 /* Copy getexception from the old prologue. */
1960 assert(to->iinstr[0].opc == ICMD_GETEXCEPTION);
1961 exh->iinstr[0] = to->iinstr[0];
1966 static exception_entry *ssa_leave_create_transition_exception_entry(
1969 basicblock *handler,
1970 classref_or_classinfo catchtype
1973 exception_entry *ee = DNEW(exception_entry);
1974 basicblock_info_t *fromi = bb_info(from);
1978 /* If the try block has subbasicblocks, the next block is the next fragment,
1979 not the successor block. */
1981 if (fromi != NULL) {
1982 ee->end = basicblock_chain_front(fromi->subbasicblocks)->next;
1984 ee->end = from->next;
1986 ee->handler = handler;
1987 ee->catchtype = catchtype;
1994 static void ssa_leave_create_exceptional_phi_moves(ssa_info *ssa) {
1997 exception_entry *ite;
1998 exception_entry_chain_t chain;
1999 classref_or_classinfo catchtype;
2004 exception_entry *ee;
2005 basicblock *last = NULL;
2007 if (! basicblock_chain_empty(ssa->new_blocks)) {
2008 last = basicblock_chain_back(ssa->new_blocks);
2011 basicblock_chain_clear(ssa->new_blocks);
2013 for (ite = ssa->jd->exceptiontable; ite; ite = ite->down) {
2014 bptr = ite->handler;
2015 catchtype = ite->catchtype;
2016 exception_entry_chain_init(&chain);
2017 for (ittry = ite->start; ittry != ite->end; ittry = ittry->next) {
2018 if (basicblock_reached(ittry)) {
2019 /* Dead code does not have a basicblock_info_t associated. */
2021 FOR_EACH_INSTRUCTION(ittry, iptr) {
2022 if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
2023 /* try is basicblock fragment till (including) the pei */
2024 try = ssa_leave_split_basicblock_at(ssa, ittry, iptr);
2025 /* ee is handler for try */
2026 exh = ssa_leave_create_transition_exception_handler(
2029 ee = ssa_leave_create_transition_exception_entry(
2030 ssa, try, exh, catchtype
2032 exception_entry_chain_add(&chain, ee);
2034 ssa->jd->exceptiontablelength += 1;
2039 if (! exception_entry_chain_empty(&chain)) {
2040 exception_entry_chain_back(&chain)->down = ite->down;
2041 exception_entry_chain_back(&chain)->next = ite->next;
2042 /* Replace original exception entry by first new one. */
2043 *ite = *exception_entry_chain_front(&chain);
2044 /* Set current iteration position to last newly created one. */
2045 ite = exception_entry_chain_back(&chain);
2050 for (last = ssa->jd->basicblocks; last->next != NULL; last = last->next);
2053 if (last != NULL && ! basicblock_chain_empty(ssa->new_blocks)) {
2054 last->next = basicblock_chain_front(ssa->new_blocks);
2058 void yssa(jitdata *jd) {
2060 basicblock_info_t *iti;
2064 printf("=============== [ before %s ] =========================\n", jd->m->name->text);
2066 printf("=============== [ /before ] =========================\n");
2069 ssa = DNEW(ssa_info);
2071 ssa_info_init(ssa, jd);
2073 FOR_EACH_BASICBLOCK(jd, it) {
2074 if (basicblock_reached(it)) {
2075 iti = DNEW(basicblock_info_t);
2076 basicblock_info_init(iti, it, jd);
2083 ssa_enter_mark_loops(jd->basicblocks);
2085 ssa_enter_traverse(ssa, jd->basicblocks);
2087 ssa_enter_eliminate_categories(ssa);
2089 ssa_enter_export_variables(ssa);
2091 ssa_enter_export_phis(ssa);
2093 ssa_enter_verify_no_redundant_phis(ssa);
2095 /*ssa_enter_create_phi_graph(ssa);*/
2097 escape_analysis_perform(ssa->jd);
2099 ssa_leave_create_phi_moves(ssa);
2101 ssa_leave_create_exceptional_phi_moves(ssa);
2104 printf("=============== [ after ] =========================\n");
2106 printf("=============== [ /after ] =========================\n");
2111 void eliminate_subbasicblocks(jitdata *jd) {
2112 basicblock *bptr, *next;
2113 basicblock_info_t *bbi;
2115 FOR_EACH_BASICBLOCK(jd, bptr) {
2116 bbi = bb_info(bptr);
2118 if (! basicblock_chain_empty(bbi->subbasicblocks)) {
2120 /* Copy first subblock, to keep pointers intact. */
2121 *bptr = *basicblock_chain_front(bbi->subbasicblocks);
2122 bptr = basicblock_chain_back(bbi->subbasicblocks);
2129 printf("=============== [ elim ] =========================\n");
2131 printf("=============== [ /elim ] =========================\n");
2136 * These are local overrides for various environment variables in Emacs.
2137 * Please do not remove this and leave it at the end of the file, where
2138 * Emacs will automagically detect them.
2139 * ---------------------------------------------------------------------
2142 * indent-tabs-mode: t
2146 * vim:noexpandtab:sw=4:ts=4: