81 return (iptr->
flags.
bits & (1 << flag)) != 0;
85 return iptr->
sx.
s23.s2.iargs[-1];
89 return (iptr->
sx.
s23.s2.iargs[-1] != NULL);
101 iptr->
sx.
s23.s2.iargs += 1;
106 iptr->
sx.
s23.s2.iargs[-1] = NULL;
109 for (i = 0; i < argcount; ++
i) {
115 #define phi_assert_opc(iptr) assert(iptr->opc == ICMD_PHI)
117 #define phi_assert_arg(iptr, arg) assert(arg < iptr->s1.argcount)
133 return iptr->
sx.
s23.s2.iargs[
arg]->dst.varindex;
140 iptr->
sx.
s23.s2.iargs[
i] = value;
146 return iptr->
sx.
s23.s3.javaindex;
188 assert(value != NULL);
228 #define FOR_EACH_PHI_USE_CAST(iptr, it, cast) \
230 (it) = cast (iptr)->sx.s23.s2.iargs; \
231 (it) != cast (iptr)->sx.s23.s2.iargs + (iptr)->s1.argcount; \
235 #define FOR_EACH_PHI_USE(iptr, it) \
236 FOR_EACH_PHI_USE_CAST(iptr, it, )
238 #define FOR_EACH_PHI_USE_CONST(iptr, it) \
239 FOR_EACH_PHI_USE_CAST(iptr, it, (const instruction *))
247 unsigned num_different = 0;
264 if (num_different >= 2) {
271 if (num_different == 1) {
274 iptr->
sx.
s23.s2.iargs[-1] = different;
278 }
else if (num_different == 0) {
299 unsigned uses_count = 0;
304 buf[2] = iptr->
sx.
s23.s3.varindex;
309 buf[1] = iptr->
sx.
s23.s2.varindex;
319 *puses_count = uses_count;
327 *puses = iptr->
sx.
s23.s2.args;
340 switch (uses_count) {
342 iptr->
sx.
s23.s3.varindex = buf[2];
344 iptr->
sx.
s23.s2.varindex = buf[1];
353 #define VARS_CATEGORY_SHIFT 28
354 #define VARS_INDEX_MASK 0x0FFFFFFF
356 #define VARS_CATEGORY_LOCAL 0
357 #define VARS_CATEGORY_STACK 1
358 #define VARS_CATEGORY_OTHERS 2
360 #define VAR_TYPE_SUBSTITUED ((Type) 666)
362 #define OLD_INDEX_UNUSED -2
393 assert(vs->
count > 0);
400 assert((category & 0x3) == category);
417 vs->
items[varindex].
v.
vv.
ii[1] = replacementindex;
422 unsigned loop_ctr = 0;
429 assert(loop_ctr++ != vs->
count);
459 assert((vs->
count + count) <= vs->
max);
464 while (count-- > 0) {
477 assert(varindex < vs->count);
479 item = vs->
items + varindex;
494 assert(varindex < vs->count);
523 assert(i < ps->count);
531 #define FOR_EACH_PHI_FUNCTION_(ps, it) \
532 for ((it) = (ps)->items; (it) != (ps)->items + (ps)->count; ++(it)) \
534 #define FOR_EACH_PHI_FUNCTION(ps, it) \
535 FOR_EACH_PHI_FUNCTION_(ps, it) if (!phi_is_redundant((it)))
570 return (sa->
items != NULL);
574 assert(index < sa->count);
575 assert(sa->
items[index]);
580 assert(index < sa->count);
585 assert(index < sa->count);
594 #define state_array_assert_items(sa) assert(state_array_has_items(sa) || (sa->count == 0))
595 #define state_array_assert_no_items(sa) assert(! state_array_has_items(sa))
614 #define basicblock_chain_clear basicblock_chain_init
617 if (bbc->
first == NULL) {
618 assert(bbc->
last == NULL);
619 assert(bb->
next == NULL);
640 return bbc->
first == NULL;
655 #define exception_entry_chain_clear exception_entry_chain_init
658 if (eec->
first == NULL) {
669 return eec->
first == NULL;
685 unsigned (*var_num_to_index)(
void *vp,
s4 var);
688 unsigned (*variables_count)(
void *vp);
713 #if defined(SSA_VERIFY)
784 return (
unsigned)var;
794 return jd->
var + var;
814 if (bb->
invars[i] == var) {
831 assert(index < bb->indepth);
838 return jd->
var + var;
874 #define bb_info basicblock_info
882 FOR_EACH_EXPREDECESSOR(bb, itpred) {
883 ret += (*itpred)->exouts;
894 if (*itpred == from)
break;
909 FOR_EACH_EXPREDECESSOR(to, itpred) {
910 if ((*itpred)->nr == from->
nr) {
914 j += (*itpred)->exouts;
1110 if (bptr->
next == NULL) {
1120 add_vars = (vartop - jd->
vartop);
1122 if (add_vars > avail_vars) {
1123 add_vars -= avail_vars;
1169 #if !defined(NDEBUG)
1191 #if !defined(NDEBUG)
1224 FOR_EACH_EXHANDLER(bb, itsucc) {
1230 }
else if (bbi->
active) {
1243 unsigned predecessor_index,
1317 #if defined(SSA_VERIFY)
1350 unsigned predecessor_count;
1393 #if defined(SSA_VERIFY)
1402 FOR_EACH_EXHANDLER(bb, itsucc) {
1421 #if defined(SSA_VERIFY)
1438 FOR_EACH_EXHANDLER(bb, itsucc) {
1478 assert(bbi->backward_branches > 0);
1487 static void ssa_enter_post_eliminate_redundand_phi(
1501 static void ssa_enter_post_eliminate_redundant_phis(ssa_info_t *
ssa) {
1532 for (i = 0; i < sa->
count; ++
i) {
1546 unsigned uses_count;
1602 #if defined(ELIMINATE_NOP_LOAD_STORE)
1629 for (ituse = uses; ituse != uses + uses_count; ++ituse) {
1716 for (i = jd->
localcount; i < ssa->locals->count; ++i) {
1717 for (j = 0; j < 5; ++j) {
1730 for (j = 0; j < 5; ++j) {
1767 bptr->phicount = dst - bptr->phis;
1792 unsigned uses_count;
1820 for (ituse = uses; ituse != uses + uses_count; ++ituse) {
1834 char path[PATH_MAX], *ppath;
1838 for (ppath = path; *ppath; ++ppath) {
1839 if (*ppath ==
'|') *ppath =
'/';
1840 else if (*ppath ==
'/') *ppath =
'.';
1843 f = fopen(path,
"w");
1845 if (f == NULL)
return;
1847 fprintf(f,
"digraph G {\n");
1856 fprintf(f,
"%d -> %d;\n", (*ituse)->dst.varindex, itph->
dst.
varindex);
1873 unsigned predecessor_index,
1874 unsigned reserved_insns
1893 bb->
icount = reserved_insns
1902 iptr = bb->
iinstr + reserved_insns;
1940 unsigned predecessor_index;
1946 if (bptr->
next == NULL) {
1989 bool has_fallthrough;
1993 if (bptr->
next == NULL) {
1997 if (bptr->vp == NULL) {
2005 has_fallthrough =
true;
2017 l = iptr->
sx.
s23.s2.tablelow;
2018 i = iptr->
sx.
s23.s3.tablehigh;
2029 i = iptr->
sx.
s23.s2.lookupcount;
2035 iptr->
sx.
s23.s3.lookupdefault.block =
2039 iptr->
sx.
s23.s3.jsrtarget.block =
2052 has_fallthrough =
false;
2054 has_fallthrough =
true;
2059 if (bptr->
next == NULL) {
2067 if (has_fallthrough) {
2083 unsigned iidx = iptr - bptr->
iinstr;
2089 assert(iidx < bptr->icount);
2098 newblock->
next = NULL;
2099 newblock->vp = NULL;
2109 while (tosplit->
next && (iidx >= (pos + tosplit->
icount))) {
2110 assert(bptr->
nr == tosplit->
nr);
2112 tosplit = tosplit->
next;
2115 assert(bptr->
nr == tosplit->
nr);
2119 ileft = iptr - tosplit->
iinstr + 1;
2120 assert(ileft <= tosplit->icount);
2124 if (ileft < tosplit->icount) {
2126 *newblock = *tosplit;
2128 tosplit->
next = newblock;
2131 newblock->
icount -= ileft;
2132 newblock->
iinstr += ileft;
2134 assert(tosplit->
nr == bptr->
nr);
2135 assert(newblock->
nr == bptr->
nr);
2136 assert(newblock->
next == NULL);
2138 if (newblock->
next == NULL) {
2210 if (fromi != NULL) {
2246 for (ittry = ite->
start; ittry != ite->
end; ittry = ittry->
next) {
2256 ssa, try_block, pei, bptr
2259 ssa, try_block, exh, catchtype
2292 if (var < ssa->locals->count) {
2294 }
else if (var < ssa->locals->count + ssa->
stack->
count) {
2314 if (index < bptr->outdepth) {
2316 }
else if (index < bptr->indepth) {
2325 assert(index < bptr->indepth);
2340 unsigned uses_count;
2353 for (ituse = uses; ituse != uses + uses_count; ++ituse) {
2379 struct timespec bs, es, be, ee;
2383 RT_TIMING_GET_TIME(bs);
2389 printf(
"=============== [ before %s ] =========================\n", jd->
m->
name.
begin());
2391 printf(
"=============== [ /before ] =========================\n");
2426 RT_TIMING_GET_TIME(be);
2431 RT_TIMING_GET_TIME(ee);
2442 printf(
"=============== [ mid ] =========================\n");
2444 printf(
"=============== [ /mid ] =========================\n");
2452 printf(
"=============== [ after ] =========================\n");
2454 printf(
"=============== [ /after ] =========================\n");
2460 RT_TIMING_GET_TIME(es);
2462 RT_TIMING_TIME_DIFF(bs, es, RT_TIMING_1);
2463 RT_TIMING_TIME_DIFF(be, ee, RT_TIMING_2);
2485 printf(
"=============== [ elim ] =========================\n");
2487 printf(
"=============== [ /elim ] =========================\n");
static void ssa_enter_mark_loops(basicblock *bb)
static basicblock * ssa_leave_split_basicblock_at(ssa_info *ssa, basicblock *bptr, instruction *iptr)
static void state_array_set(const state_array_t *sa, unsigned index, instruction *value)
static void basicblock_chain_init(basicblock_chain_t *bbc)
struct basicblock_info basicblock_info_t
static void phi_set_flag(instruction *iptr, phi_flags_t flag)
static void instruction_get_uses(const instruction *iptr, s4 *buf, s4 **puses, unsigned *puses_count)
static bool state_array_has_items(const state_array_t *sa)
static unsigned vars_resolve_subst(const vars_t *vs, unsigned varindex)
static void ssa_enter_merge(traversal_t *src, traversal_t *dst, basicblock *bdst, unsigned predecessor_index, vars_t *vdst)
static void phis_init(phis_t *ps, unsigned max)
static void ssa_enter_mark_loops_intern(basicblock *bb, unsigned num_branches)
static bool instruction_has_dst(const instruction *iptr)
varinfo * inout_var_num_to_varinfo(void *vp, s4 var)
#define basicblock_chain_clear
static void state_array_init(state_array_t *sa, unsigned count)
exception_entry * exceptiontable
static exception_entry * exception_entry_chain_back(exception_entry_chain_t *eec)
traversal_ops_t traversal_local_ops
void traversal_init(traversal_t *t, unsigned count, void *ops_vp, traversal_ops_t *ops)
static void phi_set_used(instruction *iptr)
#define phi_assert_arg(iptr, arg)
static bool basicblock_chain_empty(const basicblock_chain_t *bbc)
static void ssa_enter_process_block(ssa_info *ssa, basicblock *bb)
#define VARS_CATEGORY_STACK
varinfo * local_index_to_initial_var(void *vp, unsigned index)
void ssa_simple_leave(ssa_info_t *ssa)
#define DMREALLOC(ptr, type, num1, num2)
static void traversal_rename_use(traversal_t *t, vars_t *vars, s4 *puse)
#define VARS_CATEGORY_OTHERS
static void traversal_rename_def(traversal_t *t, vars_t *vars, instruction *iptr)
void unfix_exception_handlers(jitdata *jd)
static unsigned vars_add_item(vars_t *vs, const varinfo *item)
static void vars_subst(vars_t *vs, unsigned varindex, unsigned replacementindex)
unsigned inout_variables_count(void *vp)
unsigned local_variables_count(void *vp)
static instruction * phi_get_subst(instruction *iptr)
static void phi_set_all_args(instruction *iptr, instruction *value)
static basicblock * basicblock_chain_front(basicblock_chain_t *bbc)
traversal_ops_t traversal_inout_ops
static void phi_init(instruction *iptr, unsigned argcount, s4 index)
static unsigned basicblock_get_ex_predecessor_index(basicblock *from, unsigned pei, basicblock *to)
static unsigned basicblock_get_predecessor_count(basicblock *bb)
#define FOR_EACH_PHI_USE(iptr, it)
void escape_analysis_perform(jitdata *jd)
static instruction * phi_resolve_use(instruction *use)
static void ssa_leave_create_exceptional_phi_moves(ssa_info *ssa)
instruction * traversal_create_phi(traversal_t *t, vars_t *v, unsigned argcount, s4 index)
static s4 phi_get_arg_var(const instruction *iptr, unsigned arg)
unsigned inout_var_num_to_index(void *vp, s4 var)
#define FOR_EACH_SUCCESSOR(bptr, it)
static bool var_is_local(const jitdata *jd, s4 i)
static unsigned vars_add(vars_t *vs)
varinfo *(* var_num_to_varinfo)(void *vp, s4 var)
#define state_array_assert_items(sa)
#define MCOPY(dest, src, type, num)
static void ssa_enter_export_phis(ssa_info_t *ssa)
varinfo * local_var_num_to_varinfo(void *vp, s4 var)
static void phi_set_dst(instruction *iptr, s4 dst)
static void vars_import(vars_t *vs, varinfo *v, unsigned count, s4 old_index)
basicblock_chain_t * subbasicblocks
static void ssa_enter_eliminate_category(ssa_info_t *ssa, s4 *pvar)
void basicblock_info_init(basicblock_info_t *bbi, basicblock *bb, jitdata *jd)
varinfo * inout_index_to_initial_var(void *vp, unsigned index)
static bool phi_has_flag(const instruction *iptr, phi_flags_t flag)
static basicblock * ssa_leave_create_transition_block_intern(ssa_info *ssa, basicblock *from, basicblock *to, unsigned predecessor_index, unsigned reserved_insns)
basicblock ** predecessors
#define VAR_TYPE_SUBSTITUED
static unsigned vars_get_category(unsigned varindex)
static void state_array_allocate_items(state_array_t *sa)
#define FOR_EACH_INSTRUCTION_REV(bptr, it)
static void phi_create_copy(instruction *iptr, unsigned arg, instruction *copy)
static void phi_clear_flag(instruction *iptr, phi_flags_t flag)
static void basicblock_chain_add(basicblock_chain_t *bbc, basicblock *bb)
static basicblock * basicblock_chain_back(basicblock_chain_t *bbc)
static void phi_calculate_redundancy(instruction *iptr)
#define MZERO(ptr, type, num)
#define VARS_CATEGORY_LOCAL
static basicblock * ssa_leave_create_transition_exception_handler(ssa_info *ssa, basicblock *from, unsigned pei, basicblock *to)
static void others_mapping_set(ssa_info *ssa, s4 var, s4 new_var)
static void instruction_set_uses(instruction *iptr, s4 *buf, s4 *uses, unsigned uses_count)
classref_or_classinfo catchtype
static bool phi_has_subst(const instruction *iptr)
static void goto_init(instruction *iptr, basicblock *dst)
static unsigned traversal_variables_count(traversal_t *t)
unsigned(* var_num_to_index)(void *vp, s4 var)
static void phi_print(const instruction *iptr)
static instruction * phis_add(phis_t *ps)
#define FOR_EACH_BASICBLOCK(jd, it)
static s4 others_mapping_get(const ssa_info *ssa, s4 var)
static unsigned phis_copy_to(const phis_t *ps, instruction *dst)
#define VARS_CATEGORY_SHIFT
#define FOR_EACH_PREDECESSOR(bptr, it)
static void exception_entry_chain_add(exception_entry_chain_t *eec, exception_entry *ee)
static bool exception_entry_chain_empty(const exception_entry_chain_t *eec)
static instruction * phi_get_arg(const instruction *iptr, unsigned arg)
static bool phi_is_redundant(const instruction *iptr)
static void ssa_leave_create_phi_moves(ssa_info *ssa)
static exception_entry * ssa_leave_create_transition_exception_entry(ssa_info_t *ssa, basicblock *from, basicblock *handler, classref_or_classinfo catchtype)
union instruction::@12 sx
static unsigned basicblock_get_predecessor_index(basicblock *from, basicblock *to)
unsigned num_phi_elimination
static s4 state_array_get_var(const state_array_t *sa, unsigned index)
struct ssa_info::@16 original
unsigned(* variables_count)(void *vp)
static void phi_set_arg(instruction *iptr, unsigned arg, instruction *value)
static void vars_init(vars_t *vs, unsigned category)
icmdtable_entry_t icmd_table[256]
state_array_t * state_array
This file contains the real-time timing utilities.
void ssa_simple_leave_restore(ssa_info_t *ssa, basicblock *bptr, s4 *pvar)
static void vars_copy_to_final(vars_t *vs, varinfo *dst)
byte_iterator begin() const
static bool phi_get_used(const instruction *iptr)
void eliminate_subbasicblocks(jitdata *jd)
static void ssa_enter_export_variables(ssa_info *ssa)
void ssa_enter_eliminate_categories(ssa_info_t *ssa)
static exception_entry * exception_entry_chain_front(exception_entry_chain_t *eec)
static void vars_record_old_index(vars_t *vs, unsigned varindex, s4 old_index)
static void ssa_enter_create_phi_graph(ssa_info *ssa)
unsigned local_var_num_to_index(void *vp, s4 var)
static void exception_entry_chain_init(exception_entry_chain_t *eec)
static bool var_is_inout(const jitdata *jd, s4 i)
static varinfo * vars_back(vars_t *vs)
static void state_array_copy(state_array_t *sa, state_array_t *other)
static bool phis_contains(const phis_t *ps, const instruction *phi)
#define FOR_EACH_INSTRUCTION(bptr, it)
unsigned complete_predecessors
static void ssa_enter_process_pei(ssa_info *ssa, basicblock *bb, unsigned pei)
static bool basicblock_reached(const basicblock *bptr)
struct instruction::@12::@13 s23
static s4 vars_get_old_index(vars_t *vs, unsigned varindex)
basicblock_chain_t * new_blocks
static instruction * phis_get(const phis_t *ps, unsigned i)
static void ssa_leave_create_fallthrough(ssa_info *ssa, basicblock *bptr)
void fix_exception_handlers(jitdata *jd)
static java_object_t * next
static bool ssa_enter_eliminate_redundant_phis(traversal_t *t, vars_t *vs, basicblock_info_t *bbi)
#define state_array_assert_no_items(sa)
static basicblock * ssa_leave_create_transition_block(ssa_info *ssa, basicblock *from, basicblock *to)
static s4 phi_arg_count(const instruction *iptr)
static void ssa_enter_verify_no_redundant_phis(ssa_info_t *ssa)
static instruction * state_array_get(const state_array_t *sa, unsigned index)
#define FOR_EACH_PHI_FUNCTION(ps, it)
static unsigned vars_get_index(unsigned varindex)
static s4 phi_get_dst(const instruction *iptr)
static void ssa_enter_traverse(ssa_info_t *ssa, basicblock *bb)
struct ssa_info ssa_info_t
struct basicblock_info basicblock_info
#define phi_assert_opc(iptr)
static void ssa_enter_init_locals(state_array_t *sa)
void ssa_info_init(ssa_info_t *ssa, jitdata *jd)
varinfo *(* index_to_initial_var)(void *vp, unsigned index)
unsigned backward_branches
static s4 phi_get_index(const instruction *iptr)