CACAO
ssa3.cpp
Go to the documentation of this file.
1 /* src/vm/jit/optimizing/ssa3.cpp
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zu Foerderung der freien virtuellen Machine 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., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23  SSA transformation PROTOTYPE based on:
24 
25  Moessenboeck, H.,
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)
29 
30  TODO
31 
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.
39 */
40 
42 
43 #include "config.h"
44 
45 #include "vm/jit/jit.hpp"
47 #include "vm/global.hpp"
48 #include "mm/memory.hpp"
49 #include "mm/dumpmemory.hpp"
50 #include "toolbox/list.hpp"
51 
52 #include <limits.h>
53 #include <stdio.h>
54 
55 /*#define ELIMINATE_NOP_LOAD_STORE*/
56 #define FIXME(x) x
57 #define SSA_VERIFY
58 /*#define SSA_VERBOSE */
59 
60 /*
61 __attribute__((always_inline))
62 */
63 
64 /*** phi ********************************************************************/
65 
66 typedef enum {
70 } phi_flags_t;
71 
72 static inline void phi_set_flag(instruction *iptr, phi_flags_t flag) {
73  iptr->flags.bits |= (1 << flag);
74 }
75 
76 static inline void phi_clear_flag(instruction *iptr, phi_flags_t flag) {
77  iptr->flags.bits &= ~(1 << flag);
78 }
79 
80 static inline bool phi_has_flag(const instruction *iptr, phi_flags_t flag) {
81  return (iptr->flags.bits & (1 << flag)) != 0;
82 }
83 
84 static inline instruction *phi_get_subst(instruction *iptr) {
85  return iptr->sx.s23.s2.iargs[-1];
86 }
87 
88 static inline bool phi_has_subst(const instruction *iptr) {
89  return (iptr->sx.s23.s2.iargs[-1] != NULL);
90 }
91 
92 
93 static inline void phi_init(instruction *iptr, unsigned argcount, s4 index) {
94  unsigned i;
95 
96  iptr->opc = ICMD_PHI;
97  iptr->flags.bits = 0;
98  iptr->dst.varindex = 0;
99  iptr->s1.argcount = argcount;
100  iptr->sx.s23.s2.iargs = DMNEW(instruction *, argcount + 1);
101  iptr->sx.s23.s2.iargs += 1;
102  iptr->sx.s23.s3.javaindex = index;
103 
104  /* subst field - If non-null, the phi function shall be replaced by the
105  value produced by the subst instruction. */
106  iptr->sx.s23.s2.iargs[-1] = NULL;
107 
108 #if !defined(NDEBUG)
109  for (i = 0; i < argcount; ++i) {
110  iptr->sx.s23.s2.iargs[i] = (instruction *)0x7fffffff;
111  }
112 #endif
113 }
114 
115 #define phi_assert_opc(iptr) assert(iptr->opc == ICMD_PHI)
116 
117 #define phi_assert_arg(iptr, arg) assert(arg < iptr->s1.argcount)
118 
119 static inline s4 phi_arg_count(const instruction *iptr) {
120  phi_assert_opc(iptr);
121  return iptr->s1.argcount;
122 }
123 
124 static inline instruction *phi_get_arg(const instruction *iptr, unsigned arg) {
125  phi_assert_opc(iptr);
126  phi_assert_arg(iptr, arg);
127  return iptr->sx.s23.s2.iargs[arg];
128 }
129 
130 static inline s4 phi_get_arg_var(const instruction *iptr, unsigned arg) {
131  phi_assert_opc(iptr);
132  phi_assert_arg(iptr, arg);
133  return iptr->sx.s23.s2.iargs[arg]->dst.varindex;
134 }
135 
136 static inline void phi_set_all_args(instruction *iptr, instruction *value) {
137  unsigned i;
138  phi_assert_opc(iptr);
139  for (i = 0; i < iptr->s1.argcount; ++i) {
140  iptr->sx.s23.s2.iargs[i] = value;
141  }
142 }
143 
144 static inline s4 phi_get_index(const instruction *iptr) {
145  phi_assert_opc(iptr);
146  return iptr->sx.s23.s3.javaindex;
147 }
148 
149 static inline s4 phi_get_dst(const instruction *iptr) {
150  phi_assert_opc(iptr);
151  return iptr->dst.varindex;
152 }
153 
154 static inline void phi_set_dst(instruction *iptr, s4 dst) {
155  phi_assert_opc(iptr);
156  iptr->dst.varindex = dst;
157 }
158 
159 static inline bool phi_get_used(const instruction *iptr) {
160  phi_assert_opc(iptr);
161  return phi_has_flag(iptr, PHI_FLAG_USED);
162 }
163 
164 static void phi_set_used(instruction *iptr) {
165  phi_assert_opc(iptr);
166  if (! phi_has_flag(iptr, PHI_FLAG_USED)) {
168  /* TODO recurse into arguments */
169  }
170 }
171 
173  if (use != NULL) {
174  while (use->opc == ICMD_PHI) {
175  if (phi_has_subst(use)) {
176  use = phi_get_subst(use);
177  } else {
178  break;
179  }
180  }
181  }
182  return use;
183 }
184 
185 static inline void phi_set_arg(instruction *iptr, unsigned arg, instruction *value) {
186  phi_assert_opc(iptr);
187  phi_assert_arg(iptr, arg);
188  assert(value != NULL);
189  iptr->sx.s23.s2.iargs[arg] = value;
190 }
191 
192 static inline bool phi_is_redundant(const instruction *iptr) {
193  return (
196  );
197 }
198 
199 static inline void phi_create_copy(instruction *iptr, unsigned arg, instruction *copy) {
200  phi_assert_opc(iptr);
201  phi_assert_arg(iptr, arg);
202  copy->dst.varindex = phi_get_dst(iptr);
203  copy->s1.varindex = phi_resolve_use(phi_get_arg(iptr, arg))->dst.varindex;
204  if (copy->dst.varindex == copy->s1.varindex || phi_is_redundant(iptr)) {
205  copy->opc = ICMD_NOP;
206  } else {
207  copy->opc = ICMD_COPY;
208  }
209 }
210 
211 #if !defined(NDEBUG)
212 static void phi_print(const instruction *iptr) {
213  unsigned i;
214  instruction *use;
215  printf("%d = phi(", iptr->dst.varindex);
216  for (i = 0; i < iptr->s1.argcount; ++i) {
217  use = phi_resolve_use(iptr->sx.s23.s2.iargs[i]);
218  if (use) {
219  printf("%d, ", use->dst.varindex);
220  } else {
221  printf("null, ");
222  }
223  }
224  printf(")\n");
225 }
226 #endif
227 
228 #define FOR_EACH_PHI_USE_CAST(iptr, it, cast) \
229  for ( \
230  (it) = cast (iptr)->sx.s23.s2.iargs; \
231  (it) != cast (iptr)->sx.s23.s2.iargs + (iptr)->s1.argcount; \
232  ++(it) \
233  )
234 
235 #define FOR_EACH_PHI_USE(iptr, it) \
236  FOR_EACH_PHI_USE_CAST(iptr, it, )
237 
238 #define FOR_EACH_PHI_USE_CONST(iptr, it) \
239  FOR_EACH_PHI_USE_CAST(iptr, it, (const instruction *))
240 
242 
243  s4 dst = iptr->dst.varindex;
244  s4 use;
245  instruction *iuse;
246  instruction **ituse;
247  unsigned num_different = 0;
248  instruction *different;
249 
250  if (phi_is_redundant(iptr)) return; /* XXX */
251 
252  /* x = phi(x, y, x, x) ... PHI_FLAG_REDUNDANT_ONE
253  x = phi(x, x, x, x) ... PHI_FLAG_REDUNDANT_ALL */
254 
255  FOR_EACH_PHI_USE(iptr, ituse) {
256  iuse = phi_resolve_use(*ituse);
257  assert(iuse);
258 
259  use = iuse->dst.varindex;
260 
261  if (use != dst) {
262  different = *ituse;
263  num_different += 1;
264  if (num_different >= 2) {
267  }
268  }
269  }
270 
271  if (num_different == 1) {
272  /* Set the subst field of the instruction.
273  I.e. the instruction will be replaced by the value produced by y. */
274  iptr->sx.s23.s2.iargs[-1] = different;
275 
278  } else if (num_different == 0) {
279  assert(0);
280  /*iptr->sx.s23.s2.iargs[-1] = iptr->sx.s23.s2.iargs[0];*/
281 
284  /*assert(0);*/
285  }
286 }
287 
288 
289 /*** goto *******************************************************************/
290 
291 static inline void goto_init(instruction *iptr, basicblock *dst) {
292  iptr->opc = ICMD_GOTO;
293  iptr->dst.block = dst;
294 }
295 
296 /*** instruction ***********************************************************/
297 
298 static void instruction_get_uses(const instruction *iptr, s4 *buf, s4 **puses, unsigned *puses_count) {
299  unsigned uses_count = 0;
300 
301  switch (icmd_table[iptr->opc].dataflow) {
302  case DF_3_TO_0:
303  case DF_3_TO_1:
304  buf[2] = iptr->sx.s23.s3.varindex;
305  uses_count += 1;
306 
307  case DF_2_TO_0:
308  case DF_2_TO_1:
309  buf[1] = iptr->sx.s23.s2.varindex;
310  uses_count += 1;
311 
312  case DF_1_TO_0:
313  case DF_1_TO_1:
314  case DF_COPY:
315  case DF_MOVE:
316  buf[0] = iptr->s1.varindex;
317  uses_count += 1;
318 
319  *puses_count = uses_count;
320  *puses = buf;
321  break;
322 
323  case DF_N_TO_1:
324  case DF_INVOKE:
325  case DF_BUILTIN:
326 
327  *puses = iptr->sx.s23.s2.args;
328  *puses_count = iptr->s1.argcount;
329  break;
330 
331  default:
332 
333  *puses_count = 0;
334  break;
335  }
336 }
337 
338 static inline void instruction_set_uses(instruction *iptr, s4 *buf, s4 *uses, unsigned uses_count) {
339  if (uses == buf) {
340  switch (uses_count) {
341  case 3:
342  iptr->sx.s23.s3.varindex = buf[2];
343  case 2:
344  iptr->sx.s23.s2.varindex = buf[1];
345  case 1:
346  iptr->s1.varindex = buf[0];
347  }
348  }
349 }
350 
351 /*** vars *******************************************************************/
352 
353 #define VARS_CATEGORY_SHIFT 28
354 #define VARS_INDEX_MASK 0x0FFFFFFF
355 
356 #define VARS_CATEGORY_LOCAL 0
357 #define VARS_CATEGORY_STACK 1
358 #define VARS_CATEGORY_OTHERS 2
359 
360 #define VAR_TYPE_SUBSTITUED ((Type) 666)
361 
362 #define OLD_INDEX_UNUSED -2
363 
364 typedef struct {
367 } vars_item_t;
368 
369 typedef struct {
370  vars_item_t items[9000]; /* XXX hardcoded max */
371  unsigned max;
372  unsigned count;
373  unsigned category;
374 } vars_t;
375 
376 static inline unsigned vars_add_item(vars_t *vs, const varinfo *item) {
377  unsigned i = vs->count;
378  assert(i < vs->max);
379  vs->count += 1;
380  vs->items[i].v = *item;
382  return (vs->category << VARS_CATEGORY_SHIFT) | i;
383 }
384 
385 static inline unsigned vars_add(vars_t *vs) {
386  unsigned i = vs->count;
387  assert(i < vs->max);
388  vs->count += 1;
389  return (vs->category << VARS_CATEGORY_SHIFT) | i;
390 }
391 
392 static inline varinfo *vars_back(vars_t *vs) {
393  assert(vs->count > 0);
394  return &(vs->items[vs->count - 1].v);
395 }
396 
397 static inline void vars_init(vars_t *vs, unsigned category) {
398  vs->max = sizeof(vs->items) / sizeof(vs->items[0]);
399  vs->count = 0;
400  assert((category & 0x3) == category);
401  vs->category = category;
402 }
403 
404 static inline unsigned vars_get_category(unsigned varindex) {
405  return (varindex >> VARS_CATEGORY_SHIFT);
406 }
407 
408 static inline unsigned vars_get_index(unsigned varindex) {
409  return (varindex & VARS_INDEX_MASK);
410 }
411 
412 static void vars_subst(vars_t *vs, unsigned varindex, unsigned replacementindex) {
413  varindex = vars_get_index(varindex);
414  replacementindex = vars_get_index(replacementindex);
415 
416  vs->items[varindex].v.type = VAR_TYPE_SUBSTITUED;
417  vs->items[varindex].v.vv.ii[1] = replacementindex;
418 }
419 
420 static unsigned vars_resolve_subst(const vars_t *vs, unsigned varindex) {
421 #if !defined(NDEBUG)
422  unsigned loop_ctr = 0;
423 #endif
424  varindex = vars_get_index(varindex);
425 
426  if (vs->items[varindex].v.type == VAR_TYPE_SUBSTITUED) /*fprintf(stderr, "*")*/;
427 
428  while (vs->items[varindex].v.type == VAR_TYPE_SUBSTITUED) {
429  assert(loop_ctr++ != vs->count);
430  varindex = vs->items[varindex].v.vv.ii[1];
431  }
432 
433  return (vs->category << VARS_CATEGORY_SHIFT) | varindex ;
434 }
435 
436 static void vars_copy_to_final(vars_t *vs, varinfo *dst) {
437  const vars_item_t *it;
438  unsigned subst;
439 
440  for (it = vs->items; it != vs->items + vs->count; ++it, ++dst) {
441 
442  /* Copy variable. */
443 
444  *dst = it->v;
445 
446  /* Eliminate VAR_TYPE_SUBSTITUED as it leads to problems. */
447 
448  if (dst->type == VAR_TYPE_SUBSTITUED) {
449  subst = vars_get_index(vars_resolve_subst(vs, it - vs->items));
450  dst->type = vs->items[subst].v.type;
451 
452  }
453  }
454 }
455 
456 static void vars_import(vars_t *vs, varinfo *v, unsigned count, s4 old_index) {
457  vars_item_t *it;
458 
459  assert((vs->count + count) <= vs->max);
460 
461  it = vs->items + vs->count;
462  vs->count += count;
463 
464  while (count-- > 0) {
465  it->v = *v;
466  it->old_index = old_index;
467  it += 1;
468  v += 1;
469  old_index += 1;
470  }
471 }
472 
473 static inline void vars_record_old_index(vars_t *vs, unsigned varindex, s4 old_index) {
474  vars_item_t *item;
475  varindex = vars_get_index(varindex);
476 
477  assert(varindex < vs->count);
478 
479  item = vs->items + varindex;
480 
481  assert(
482  item->old_index == OLD_INDEX_UNUSED ||
483  item->old_index == old_index
484  );
485 
486  item->old_index = old_index;
487 }
488 
489 static inline s4 vars_get_old_index(vars_t *vs, unsigned varindex) {
490  s4 old;
491 
492  varindex = vars_get_index(varindex);
493 
494  assert(varindex < vs->count);
495  old = vs->items[varindex].old_index;
496  assert(old != OLD_INDEX_UNUSED);
497 
498  return old;
499 }
500 
501 /*** phis *******************************************************************/
502 
503 typedef struct {
505  unsigned max;
506  unsigned count;
507 } phis_t;
508 
509 static inline void phis_init(phis_t *ps, unsigned max) {
510  ps->max = max;
511  ps->count = 0;
512  ps->items = DMNEW(instruction, max);
513 }
514 
515 static inline instruction *phis_add(phis_t *ps) {
516  unsigned i = ps->count;
517  assert(i < ps->max);
518  ps->count += 1;
519  return ps->items + i;
520 }
521 
522 static inline instruction *phis_get(const phis_t *ps, unsigned i) {
523  assert(i < ps->count);
524  return ps->items + i;
525 }
526 
527 static inline bool phis_contains(const phis_t *ps, const instruction *phi) {
528  return (ps->items <= phi) && (phi < (ps->items + ps->max));
529 }
530 
531 #define FOR_EACH_PHI_FUNCTION_(ps, it) \
532  for ((it) = (ps)->items; (it) != (ps)->items + (ps)->count; ++(it)) \
533 
534 #define FOR_EACH_PHI_FUNCTION(ps, it) \
535  FOR_EACH_PHI_FUNCTION_(ps, it) if (!phi_is_redundant((it)))
536 
537 #if !defined(NDEBUG)
538 FIXME() inline void phis_print(const phis_t *ps) {
539  const instruction *iptr;
540  FOR_EACH_PHI_FUNCTION(ps, iptr) {
541  phi_print(iptr);
542  }
543 }
544 #endif
545 
546 static inline unsigned phis_copy_to(const phis_t *ps, instruction *dst) {
547  instruction *it;
548  instruction *out = dst;
549 
550  FOR_EACH_PHI_FUNCTION(ps, it) {
551  *(out++) = *it;
552  }
553 
554  return (out - dst);
555 }
556 
557 /*** state_array ************************************************************/
558 
559 typedef struct {
561  unsigned count;
562 } state_array_t;
563 
564 static inline void state_array_init(state_array_t *sa, unsigned count) {
565  sa->items = NULL;
566  sa->count = count;
567 }
568 
569 static inline bool state_array_has_items(const state_array_t *sa) {
570  return (sa->items != NULL);
571 }
572 
573 static inline s4 state_array_get_var(const state_array_t *sa, unsigned index) {
574  assert(index < sa->count);
575  assert(sa->items[index]);
576  return sa->items[index]->dst.varindex;
577 }
578 
579 static inline instruction *state_array_get(const state_array_t *sa, unsigned index) {
580  assert(index < sa->count);
581  return sa->items[index];
582 }
583 
584 static inline void state_array_set(const state_array_t *sa, unsigned index, instruction *value) {
585  assert(index < sa->count);
586  sa->items[index] = value;
587 }
588 
589 static inline void state_array_copy(state_array_t *sa, state_array_t *other) {
590  assert(sa->count == other->count);
591  MCOPY(sa->items, other->items, instruction *, sa->count);
592 }
593 
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))
596 
597 static inline void state_array_allocate_items(state_array_t *sa) {
598  sa->items = DMNEW(instruction *, sa->count);
599  MZERO(sa->items, instruction *, sa->count);
600 }
601 
602 /*** basicblock_chain *******************************************************/
603 
604 typedef struct {
608 
610  bbc->first = NULL;
611  bbc->last = NULL;
612 }
613 
614 #define basicblock_chain_clear basicblock_chain_init
615 
617  if (bbc->first == NULL) {
618  assert(bbc->last == NULL);
619  assert(bb->next == NULL);
620  bbc->first = bb;
621  bbc->last = bb;
622  } else {
623  assert(bbc->last->next == NULL);
624  bbc->last->next = bb;
625  bbc->last = bb;
626  }
627 }
628 
630  assert(bbc->first);
631  return bbc->first;
632 }
633 
635  assert(bbc->last);
636  return bbc->last;
637 }
638 
639 static inline bool basicblock_chain_empty(const basicblock_chain_t *bbc) {
640  return bbc->first == NULL;
641 }
642 
643 /*** exception_entry_chain ***************************************************/
644 
645 typedef struct {
649 
651  eec->first = NULL;
652  eec->last = NULL;
653 }
654 
655 #define exception_entry_chain_clear exception_entry_chain_init
656 
658  if (eec->first == NULL) {
659  eec->first = ee;
660  eec->last = ee;
661  } else {
662  eec->last->next = ee;
663  eec->last->down = ee;
664  eec->last = ee;
665  }
666 }
667 
668 static inline bool exception_entry_chain_empty(const exception_entry_chain_t *eec) {
669  return eec->first == NULL;
670 }
671 
673  assert(eec->last);
674  return eec->last;
675 }
676 
678  assert(eec->first);
679  return eec->first;
680 }
681 
682 /*** traversal **************************************************************/
683 
684 typedef struct {
685  unsigned (*var_num_to_index)(void *vp, s4 var);
686  varinfo *(*index_to_initial_var)(void *vp, unsigned index);
687  varinfo *(*var_num_to_varinfo)(void *vp, s4 var);
688  unsigned (*variables_count)(void *vp);
690 
691 typedef struct {
694  void *ops_vp;
696 } traversal_t;
697 
698 /*** basicblock_info ********************************************************/
699 
700 typedef struct basicblock_info {
701  bool visited;
702  bool active;
703  bool traversed;
705 
708 
710 
712 
713 #if defined(SSA_VERIFY)
715 #endif
716 
718 
719 /*** traversal **************************************************************/
720 
721 void traversal_init(traversal_t *t, unsigned count, void *ops_vp, traversal_ops_t *ops) {
722  t->phis = DNEW(phis_t);
723  phis_init(t->phis, count);
724 
726  state_array_init(t->state_array, count);
727 
728  t->ops_vp = ops_vp;
729  t->ops = ops;
730 }
731 
733  instruction *phi = phis_add(t->phis);
734  s4 dst;
735 
736  phi_init(phi, argcount, index);
737  dst = vars_add_item(v, t->ops->index_to_initial_var(t->ops_vp, index));
738  phi_set_dst(phi, dst);
739 
740  state_array_set(t->state_array, index, phi);
741 
742  vars_record_old_index(v, phi->dst.varindex, index);
743 
744  return phi;
745 }
746 
747 static void traversal_rename_def(traversal_t *t, vars_t *vars, instruction *iptr) {
748  const varinfo *v;
749  unsigned index;
750  s4 old;
751 
753 
754  v = t->ops->var_num_to_varinfo(t->ops_vp, iptr->dst.varindex);
755  index = t->ops->var_num_to_index(t->ops_vp, iptr->dst.varindex);
756 
757  old = iptr->dst.varindex;
758  iptr->dst.varindex = vars_add_item(vars, v);
759  state_array_set(t->state_array, index, iptr);
760 
761  vars_record_old_index(vars, iptr->dst.varindex, index);
762 }
763 
764 static void traversal_rename_use(traversal_t *t, vars_t *vars, s4 *puse) {
765  unsigned index;
766  s4 old;
767 
769 
770  index = t->ops->var_num_to_index(t->ops_vp, *puse);
771 
772  assert(state_array_get(t->state_array, index));
773  old = *puse;
774  *puse = state_array_get_var(t->state_array, index);
775 
776  vars_record_old_index(vars, *puse, index);
777 }
778 
779 static inline unsigned traversal_variables_count(traversal_t *t) {
780  return t->ops->variables_count(t->ops_vp);
781 }
782 
783 unsigned local_var_num_to_index(void *vp, s4 var) {
784  return (unsigned)var;
785 }
786 
788  jitdata *jd = (jitdata *)vp;
789  return jd->var + index;
790 }
791 
793  jitdata *jd = (jitdata *)vp;
794  return jd->var + var;
795 }
796 
797 unsigned local_variables_count(void *vp) {
798  jitdata *jd = (jitdata *)vp;
799  return jd->localcount;
800 }
801 
807 };
808 
809 unsigned inout_var_num_to_index(void *vp, s4 var) {
810  basicblock *bb = (basicblock *)vp;
811  unsigned i;
812 
813  for (i = 0; i < bb->indepth; ++i) {
814  if (bb->invars[i] == var) {
815  return i;
816  }
817  }
818 
819  for (i = 0; i < bb->outdepth; ++i) {
820  if (bb->outvars[i] == var) {
821  return i;
822  }
823  }
824 
825  assert(0);
826 }
827 
829  basicblock *bb = (basicblock *)vp;
830  jitdata *jd = (jitdata *)(((basicblock_info_t *)bb->vp)->locals->ops_vp); /* evil hack */
831  assert(index < bb->indepth);
832  return jd->var + bb->invars[index];
833 }
834 
836  basicblock *bb = (basicblock *)vp;
837  jitdata *jd = (jitdata *)(((basicblock_info_t *)bb->vp)->locals->ops_vp); /* evil hack */
838  return jd->var + var;
839 }
840 
841 unsigned inout_variables_count(void *vp) {
842  basicblock *bb = (basicblock *)vp;
843  return bb->indepth;
844 }
845 
851 };
852 
853 /*** basicblock_info ********************************************************/
854 
856  MZERO(bbi, basicblock_info_t, 1);
857 
858  bbi->locals = DNEW(traversal_t);
859  traversal_init(bbi->locals, jd->localcount, jd, &traversal_local_ops);
860 
861  bbi->stack = DNEW(traversal_t);
862  traversal_init(bbi->stack, jd->maxinterfaces, bb, &traversal_inout_ops);
863 
866 }
867 
868 /*** basicblock *************************************************************/
869 
871  return (basicblock_info_t *)(bb->vp);
872 }
873 
874 #define bb_info basicblock_info
875 
877  unsigned ret;
878  basicblock **itpred;
879 
880  ret = bb->predecessorcount;
881 
882  FOR_EACH_EXPREDECESSOR(bb, itpred) {
883  ret += (*itpred)->exouts;
884  }
885 
886  return ret;
887 }
888 
890  basicblock **itpred;
891  unsigned j = 0;
892 
893  FOR_EACH_PREDECESSOR(to, itpred) {
894  if (*itpred == from) break;
895  j++;
896  }
897 
898  assert(j != to->predecessorcount);
899 
900  return j;
901 }
902 
903 static unsigned basicblock_get_ex_predecessor_index(basicblock *from, unsigned pei, basicblock *to) {
904  unsigned j;
905  basicblock **itpred;
906 
907  j = to->predecessorcount;
908 
909  FOR_EACH_EXPREDECESSOR(to, itpred) {
910  if ((*itpred)->nr == from->nr) {
911  j += pei;
912  return j;
913  } else {
914  j += (*itpred)->exouts;
915  }
916  }
917 
918  assert(0);
919 }
920 
921 /*** ssa_info ***************************************************************/
922 
923 typedef struct ssa_info {
924  jitdata *jd;
925 
929 
930  s4 s_buf[3];
931 
933 
934  struct {
942  } original;
943 
944  unsigned keep_in_out:1;
945 
947 
948 void ssa_info_init(ssa_info_t *ssa, jitdata *jd) {
949  ssa->jd = jd;
950 
951  ssa->locals = DNEW(vars_t);
953 
954  /* Initialize first version of locals, that is always available. */
955  vars_import(ssa->locals, jd->var, jd->localcount, 0);
956 
957  ssa->stack = DNEW(vars_t);
959 
960  ssa->others = DNEW(vars_t);
962 
965 
966  ssa->original.maxlocals = jd->maxlocals;
968  ssa->original.local_map = jd->local_map;
969  ssa->original.var = jd->var;
970  ssa->original.vartop = jd->vartop;
971  ssa->original.varcount = jd->varcount;
972  ssa->original.localcount = jd->localcount;
973 
974  ssa->keep_in_out = false;
975 }
976 
977 /*** others_mapping *********************************************************/
978 
979 static inline void others_mapping_set(ssa_info *ssa, s4 var, s4 new_var) {
980  ssa->jd->var[var].vv.ii[1] = new_var;
981 }
982 
983 static inline s4 others_mapping_get(const ssa_info *ssa, s4 var) {
984  return ssa->jd->var[var].vv.ii[1];
985 }
986 
987 /*** code *******************************************************************/
988 
990  basicblock *bptr;
991  basicblock *exh = NULL;
992  instruction *iptr;
993  exception_entry *ee;
994  size_t add_vars;
995  size_t avail_vars;
996  s4 v;
997  basicblock_chain_t chain;
998  basicblock *last = NULL;
999  basicblock *marker = NULL;
1000  s4 vartop;
1001  unsigned i;
1002 
1003  if (jd->exceptiontablelength == 0) {
1004  return;
1005  }
1006 
1007  basicblock_chain_init(&chain);
1008 
1009  /* Remember, where we started adding IO variables. */
1010 
1011  vartop = jd->vartop;
1012 
1013  /* For each exception handler block, create one block with a prologue block */
1014 
1015  FOR_EACH_BASICBLOCK(jd, bptr) {
1016  if (bptr->type == basicblock::TYPE_EXH) {
1017 
1018  /*
1019 
1020  +---- EXH (exh)-------+
1021  | in0 in1 in2 exc |
1022  | ..... |
1023  +---------------------+
1024 
1025  === TRANSFORMED TO ===>
1026 
1027  +---- PROL (exh) -------+
1028  | in0 in1 in2 |
1029  | GETEXECEPTION => OU3 |
1030  | GOTO REAL_EXH |
1031  | in0 in1 in2 OU3 |
1032  +-----------------------+
1033 
1034  +---- REAL_EXH (std) -+
1035  | in0 in1 in2 exc |
1036  | ...... |
1037  +---------------------+
1038 
1039  */
1040 
1041  bptr->type = basicblock::TYPE_STD;
1042  bptr->predecessorcount = 0; /* legacy */
1043 
1044  /* Create basicblock with 2 instructions */
1045 
1046  exh = DNEW(basicblock);
1047  MZERO(exh, basicblock, 1);
1048 
1049  iptr = DMNEW(instruction, 2);
1050  MZERO(iptr, instruction, 2);
1051 
1052  /* Create outvars */
1053 
1054  exh->outdepth = bptr->indepth;
1055 
1056  if (exh->outdepth > 0) {
1057  exh->outvars = DMNEW(s4, exh->outdepth);
1058  for (i = 0; i < exh->outdepth; ++i) {
1059  exh->outvars[i] = vartop++;
1060  }
1061  }
1062 
1063  /* Create invars */
1064 
1065  exh->indepth = exh->outdepth - 1;
1066  exh->invars = exh->outvars;
1067 
1068 #if 0
1069  /* Create new outvar */
1070 
1071  assert(jd->vartop < jd->varcount);
1072  v = jd->vartop;
1073  jd->vartop += 1;
1074  jd->var[v].type = TYPE_ADR;
1075  jd->var[v].flags = INOUT;
1076 #endif
1077 
1078  exh->nr = jd->basicblockcount;
1079  jd->basicblockcount += 1;
1080  exh->mpc = -1;
1081  exh->type = basicblock::TYPE_EXH;
1082  exh->icount = 2;
1083  exh->iinstr = iptr;
1084 /*
1085  exh->outdepth = 1;
1086  exh->outvars = DNEW(s4);
1087  exh->outvars[0] = v;
1088 */
1089  exh->predecessorcount = -1; /* legacy */
1090  exh->state = basicblock::FINISHED;
1091  exh->method = jd->m;
1092 
1093  basicblock_chain_add(&chain, exh);
1094 
1095  /* Get exception */
1096 
1097  iptr->opc = ICMD_GETEXCEPTION;
1098  iptr->dst.varindex = exh->outvars[exh->outdepth - 1];
1099  iptr += 1;
1100 
1101  /* Goto real exception handler */
1102 
1103  goto_init(iptr, bptr);
1104 
1105  bptr->vp = exh;
1106  } else {
1107  bptr->vp = NULL;
1108  }
1109 
1110  if (bptr->next == NULL) {
1111  marker = bptr;
1112  } else {
1113  last = bptr;
1114  }
1115  }
1116 
1117  /* We need to allocate the new iovars in the var array */
1118 
1119  avail_vars = (jd->varcount - jd->vartop);
1120  add_vars = (vartop - jd->vartop);
1121 
1122  if (add_vars > avail_vars) {
1123  add_vars -= avail_vars;
1124  jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, jd->varcount + add_vars);
1125  jd->varcount += add_vars;
1126  }
1127 
1128  jd->vartop = vartop;
1129 
1130  /* Put the chain of exception handlers between just before the last
1131  basic block (end marker). */
1132 
1133  if (! basicblock_chain_empty(&chain)) {
1134  marker->nr = jd->basicblockcount;
1135  basicblock_chain_back(&chain)->next = marker;
1136  last->next = basicblock_chain_front(&chain);
1137 
1138  assert(last->nr + 1 == basicblock_chain_front(&chain)->nr);
1139  assert(marker->nr == jd->basicblockcount);
1140  }
1141 
1142  /* Replace all exception handlers in exception table with their respective
1143  prologue blocks. */
1144 
1145  for (ee = jd->exceptiontable; ee; ee = ee->down) {
1146  assert(ee->handler->vp);
1147 
1148  bptr = ee->handler;
1149  exh = (basicblock *)ee->handler->vp;
1150 
1151  ee->handler = exh;
1152 
1153  /* Set up IO variables in newly craeted exception handlers. */
1154 
1155  for (i = 0; i < exh->outdepth; ++i) {
1156  v = exh->outvars[i];
1157 
1158  jd->var[v].flags = INOUT;
1159  jd->var[v].type = jd->var[ bptr->invars[i] ].type;
1160  }
1161  }
1162 
1163 }
1164 
1166  basicblock *bptr, *exh;
1167  unsigned i;
1168  exception_entry *ee;
1169 #if !defined(NDEBUG)
1170  bool found = false;
1171 #endif
1172 
1173  FOR_EACH_BASICBLOCK(jd, bptr) {
1174  if (bptr->type == basicblock::TYPE_EXH) {
1175  assert(bptr->iinstr[1].opc == ICMD_GOTO);
1176  exh = bptr->iinstr[1].dst.block;
1177 
1178  bptr->state = basicblock::DELETED;
1179  bptr->icount = 0;
1180  bptr->indepth = 0;
1181  bptr->outdepth = 0;
1182  exh->type = basicblock::TYPE_EXH;
1183  bptr->vp = exh;
1184 
1185  /* bptr is no more a predecessor of exh */
1186 
1187  for (i = 0; i < exh->predecessorcount; ++i) {
1188  if (exh->predecessors[i] == bptr) {
1189  exh->predecessors[i] = exh->predecessors[exh->predecessorcount - 1];
1190  exh->predecessorcount -= 1;
1191 #if !defined(NDEBUG)
1192  found = true;
1193 #endif
1194  break;
1195  }
1196  }
1197 
1198  assert(found);
1199 
1200  } else {
1201  bptr->vp = NULL;
1202  }
1203  }
1204 
1205  for (ee = jd->exceptiontable; ee; ee = ee->down) {
1206  assert(ee->handler->vp);
1207  ee->handler = (basicblock*) ee->handler->vp;
1208  }
1209 }
1210 
1211 /*** ssa_enter ***************************************************************/
1212 
1213 static void ssa_enter_mark_loops_intern(basicblock *bb, unsigned num_branches) {
1214  basicblock_info_t *bbi = bb_info(bb);
1215  basicblock **itsucc;
1216 
1217  if (! bbi->visited) {
1218  bbi->visited = true;
1219  bbi->active = true;
1220  FOR_EACH_SUCCESSOR(bb, itsucc) {
1221  /* There is a single branch from bb into the successor. */
1222  ssa_enter_mark_loops_intern(*itsucc, 1);
1223  }
1224  FOR_EACH_EXHANDLER(bb, itsucc) {
1225  /* For exception handler type successors,
1226  we count a branch into the exception handler from every PEI. */
1227  ssa_enter_mark_loops_intern(*itsucc, bb->exouts);
1228  }
1229  bbi->active = false;
1230  } else if (bbi->active) {
1231  bbi->backward_branches += num_branches;
1232  }
1233 }
1234 
1235 static inline void ssa_enter_mark_loops(basicblock *bb) {
1237 }
1238 
1239 static void ssa_enter_merge(
1240  traversal_t *src,
1241  traversal_t *dst,
1242  basicblock *bdst,
1243  unsigned predecessor_index,
1244  vars_t *vdst
1245 ) {
1246 
1247  basicblock_info_t *dsti = bb_info(bdst);
1248  unsigned predecessor_count = basicblock_get_predecessor_count(bdst);
1249  instruction *phi;
1250  instruction *old;
1251  s4 i;
1252 
1253  /* We are merging for the first time into this block. */
1254 
1255  if (! state_array_has_items(dst->state_array)) {
1256 
1258 
1259  if (dsti->backward_branches > 0) {
1260  /* Loop header, create phi functions for all variables. */
1261  for (i = 0; i < traversal_variables_count(dst); ++i) {
1262  phi = traversal_create_phi(dst, vdst, predecessor_count, i);
1263  /* No need to init, they will only be filled in later. */
1264  }
1265  } else {
1267  return;
1268  }
1269  }
1270 
1271  /* We are merging another block. */
1272 
1273  /* Process every variable. */
1274 
1275  for (i = 0; i < traversal_variables_count(dst); ++i) {
1276  if (dsti->traversed) {
1277 
1278  /* Back edge, all phi functions are already created.
1279  We only need to set their arguments. */
1280 
1281  phi_set_arg(
1282  phis_get(dst->phis, i),
1283  predecessor_index,
1284  state_array_get(src->state_array, i)
1285  );
1286 
1287  } else if (state_array_get(dst->state_array, i) != state_array_get(src->state_array, i)) {
1288 
1289  /* A different definition of this var reaches the block.
1290  We need to create a phi function. */
1291 
1292  if (phis_contains(dst->phis, state_array_get(dst->state_array, i))) {
1293  /* There is already a phi function created for this var.
1294  No need to create one. */
1295  } else {
1296  /* Create a new phi function.
1297  Set all arguments to old value in state array. */
1298  old = state_array_get(dst->state_array, i);
1299  phi = traversal_create_phi(dst, vdst, predecessor_count, i);
1300  phi_set_all_args(phi, old);
1301  }
1302 
1303  /* Set argument of phi function. */
1304 
1305  phi_set_arg(
1306  state_array_get(dst->state_array, i),
1307  predecessor_index,
1308  state_array_get(src->state_array, i)
1309  );
1310  }
1311  }
1312 }
1313 
1314 static void ssa_enter_process_block(ssa_info *ssa, basicblock *bb);
1316 
1317 #if defined(SSA_VERIFY)
1318 static void ssa_enter_verify_no_redundant_phis(ssa_info_t *ssa) {
1319  basicblock *bptr;
1320  basicblock_info_t *bbi;
1321  instruction *itph;
1322 
1323  /* XXX */
1324  return;
1325 
1326  FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
1327  if (basicblock_reached(bptr)) {
1328  bbi = bb_info(bptr);
1329  FOR_EACH_PHI_FUNCTION(bbi->locals->phis, itph) {
1330  if (! phi_is_redundant(itph)) {
1332  assert(! phi_is_redundant(itph));
1333  }
1334  }
1335  FOR_EACH_PHI_FUNCTION(bbi->stack->phis, itph) {
1336  if (! phi_is_redundant(itph)) {
1338  assert(! phi_is_redundant(itph));
1339  }
1340  }
1341  }
1342  }
1343 }
1344 #endif
1345 
1346 static void ssa_enter_traverse(ssa_info_t *ssa, basicblock *bb) {
1347  basicblock **itsucc;
1348  basicblock_info_t *succi;
1349  basicblock_info_t *bbi = bb_info(bb);
1350  unsigned predecessor_count;
1351 
1352  /* Process block */
1353 
1354  ssa_enter_process_block(ssa, bb);
1355 
1356  /* Recurse */
1357 
1358  FOR_EACH_SUCCESSOR(bb, itsucc) {
1359 
1360  succi = bb_info(*itsucc);
1361 
1363  bbi->locals,
1364  succi->locals,
1365  *itsucc,
1366  basicblock_get_predecessor_index(bb, *itsucc),
1367  ssa->locals
1368  );
1369 
1371  bbi->stack,
1372  succi->stack,
1373  *itsucc,
1374  basicblock_get_predecessor_index(bb, *itsucc),
1375  ssa->stack
1376  );
1377 
1378  succi->complete_predecessors += 1;
1379 
1380  predecessor_count = basicblock_get_predecessor_count(*itsucc);
1381 
1382  if (
1383  succi->complete_predecessors ==
1384  (predecessor_count - succi->backward_branches)
1385  ) {
1386  ssa_enter_traverse(ssa, *itsucc);
1387  }
1388 
1389  if (
1390  (succi->complete_predecessors == predecessor_count) &&
1391  (succi->backward_branches > 0)
1392  ) {
1393 #if defined(SSA_VERIFY)
1394  assert(succi->num_phi_elimination < 2);
1395  succi->num_phi_elimination += 1;
1396 #endif
1397  ssa_enter_eliminate_redundant_phis(succi->locals, ssa->locals, succi);
1398  ssa_enter_eliminate_redundant_phis(succi->stack, ssa->stack, succi);
1399  }
1400  }
1401 
1402  FOR_EACH_EXHANDLER(bb, itsucc) {
1403 
1404  succi = bb_info(*itsucc);
1405 
1406  succi->complete_predecessors += bb->exouts; /* XXX this might be 0 */
1407 
1408  predecessor_count = basicblock_get_predecessor_count(*itsucc);
1409 
1410  if (
1411  succi->complete_predecessors ==
1412  (predecessor_count - succi->backward_branches)
1413  ) {
1414  ssa_enter_traverse(ssa, *itsucc);
1415  }
1416 
1417  if (
1418  (succi->complete_predecessors == predecessor_count) &&
1419  (succi->backward_branches > 0)
1420  ) {
1421 #if defined(SSA_VERIFY)
1422  assert(succi->num_phi_elimination < 2);
1423  succi->num_phi_elimination += 1;
1424 #endif
1425  ssa_enter_eliminate_redundant_phis(succi->locals, ssa->locals, succi);
1426  ssa_enter_eliminate_redundant_phis(succi->stack, ssa->stack, succi);
1427  }
1428 
1429  }
1430 
1431 }
1432 
1433 static void ssa_enter_process_pei(ssa_info *ssa, basicblock *bb, unsigned pei) {
1434  basicblock_info_t *bbi = bb_info(bb);
1435  basicblock_info_t *succi;
1436  basicblock **itsucc;
1437 
1438  FOR_EACH_EXHANDLER(bb, itsucc) {
1439  succi = bb_info(*itsucc);
1440 
1442  bbi->locals,
1443  succi->locals,
1444  *itsucc,
1445  basicblock_get_ex_predecessor_index(bb, pei, *itsucc),
1446  ssa->locals
1447  );
1448 
1450  bbi->stack,
1451  succi->stack,
1452  *itsucc,
1453  basicblock_get_ex_predecessor_index(bb, pei, *itsucc),
1454  ssa->stack
1455  );
1456  }
1457 }
1458 
1460 
1461  instruction *itph;
1462  bool ret = false;
1463 
1464  /* XXX */
1465  assert(false);
1466  return false;
1467 
1468  FOR_EACH_PHI_FUNCTION(t->phis, itph) {
1469 
1471 
1472  /* If the phi function is redundant,
1473  make the variable it defines point to the value defined by the substituing
1474  instruction. */
1475 
1476  if (phi_is_redundant(itph)) {
1477  vars_subst(vs, itph->dst.varindex, phi_get_subst(itph)->dst.varindex);
1478  assert(bbi->backward_branches > 0);
1479  ret = true;
1480  }
1481  }
1482 
1483  return ret;
1484 }
1485 
1486 #if 0
1487 static void ssa_enter_post_eliminate_redundand_phi(
1488  ssa_info_t *ssa,
1489  instruction *phi,
1490  state_array *sa,
1491  basicblock *bptr
1492 ) {
1494  phi_set_flag(PHI_FLAG_REDUNDANCY_CHECKED);
1495 
1496  /* if redundancy changed and phi function escapes block */
1497 
1498  /* for each successor */
1499 }
1500 
1501 static void ssa_enter_post_eliminate_redundant_phis(ssa_info_t *ssa) {
1502  basicblock *bptr;
1503  basicblock_info_t *bbi;
1504  instruction *itph;
1505 
1506  FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
1507  bbi = bb_info(bptr);
1508 
1509  if (bbi->backward_branches > 0) {
1510  /* Redundant phi functions have the left hand side as operand.
1511  This can happen by definition only in loop headers. */
1512 
1513  FOR_EACH_PHI_FUNCTION(bbi->locals, itph) {
1514  if (! phi_has_flag(PHI_FLAG_REDUNDANCY_CHECKED)) {
1515  /* Calculate redundancy? */
1516  /* Changed? */
1517  /* If yes recurse? */
1518  }
1519  }
1520 
1521  FOR_EACH_PHI_FUNCTION(bbi->stack, itph) {
1522  }
1523  }
1524  }
1525 }
1526 #endif
1527 
1529  unsigned i;
1530  instruction *iptr;
1531 
1532  for (i = 0; i < sa->count; ++i) {
1533  iptr = DNEW(instruction);
1534  iptr->opc = ICMD_NOP;
1535  iptr->dst.varindex = i;
1536  state_array_set(sa, i, iptr);
1537  }
1538 }
1539 
1541  basicblock_info_t *bbi = bb_info(bb);
1542  instruction *iptr;
1543  unsigned pei = 0;
1544  s4 *ituse;
1545  s4 *uses;
1546  unsigned uses_count;
1547  s4 old;
1548 
1549  /* Every basic block can be traversed only once. */
1550 
1551  assert(! bbi->traversed);
1552  bbi->traversed = true;
1553 
1554  /* The root basicblock needs special treatment. */
1555 
1556  if (bb->predecessorcount == 0 && bb->type != basicblock::TYPE_EXH) {
1560 
1563  }
1564 
1565 #if 0
1566  /* Exception handlers have a clean stack. */
1567 
1568  /* Not true with inlining. */
1569 
1570  if (bb->type == basicblock::TYPE_EXH) {
1573  }
1574 #endif
1575 
1576  /* Some in/out vars get marked as INOUT in simplereg,
1577  and are not marked at this point.
1578  Mark them manually. */
1579 
1580  for (ituse = bb->invars; ituse != bb->invars + bb->indepth; ++ituse) {
1581  if (ssa->keep_in_out && ssa->jd->var[*ituse].type == TYPE_RET) {
1582  continue;
1583  }
1584  ssa->jd->var[*ituse].flags |= INOUT;
1585  ssa->jd->var[*ituse].flags &= ~PREALLOC;
1586  }
1587 
1588  for (ituse = bb->outvars; ituse != bb->outvars + bb->outdepth; ++ituse) {
1589  if (ssa->keep_in_out && ssa->jd->var[*ituse].type == TYPE_RET) {
1590  continue;
1591  }
1592  ssa->jd->var[*ituse].flags |= INOUT;
1593  ssa->jd->var[*ituse].flags &= ~PREALLOC;
1594  }
1595 
1596  /* Process instructions */
1597 
1599 
1600  FOR_EACH_INSTRUCTION(bb, iptr) {
1601 
1602 #if defined(ELIMINATE_NOP_LOAD_STORE)
1603 
1604  /* Kill NOP instructions of the form:
1605  LOAD foo => foo
1606  STORE foo => foo
1607  As they create a lot of unnecessary definitions.
1608  For performance, definitely eliminate them. However, keeping them is a
1609  good stress test.
1610  */
1611 
1612  if (
1613  (icmd_table[iptr->opc].dataflow == DF_LOAD) ||
1614  (icmd_table[iptr->opc].dataflow == DF_STORE)
1615  ) {
1616  if (iptr->dst.varindex == iptr->s1.varindex) {
1617  iptr->opc = ICMD_NOP;
1618  continue;
1619  }
1620  }
1621 #endif
1622 
1623  if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
1624  ssa_enter_process_pei(ssa, bb, pei++);
1625  }
1626 
1627  instruction_get_uses(iptr, ssa->s_buf, &uses, &uses_count);
1628 
1629  for (ituse = uses; ituse != uses + uses_count; ++ituse) {
1630  if (var_is_local(ssa->jd, *ituse)) {
1632  bbi->locals,
1633  ssa->locals,
1634  ituse
1635  );
1636  } else if (var_is_inout(ssa->jd, *ituse)) {
1638  bbi->stack,
1639  ssa->stack,
1640  ituse
1641  );
1642  } else {
1643  *ituse = others_mapping_get(ssa, *ituse);
1644  }
1645  }
1646 
1647  instruction_set_uses(iptr, ssa->s_buf, uses, uses_count);
1648 
1649  if (instruction_has_dst(iptr)) {
1650  if (var_is_local(ssa->jd, iptr->dst.varindex)) {
1652  bbi->locals,
1653  ssa->locals,
1654  iptr
1655  );
1656  } else if (var_is_inout(ssa->jd, iptr->dst.varindex)) {
1658  bbi->stack,
1659  ssa->stack,
1660  iptr
1661  );
1662  } else {
1663  old = iptr->dst.varindex;
1664  iptr->dst.varindex = vars_add_item(
1665  ssa->others,
1666  ssa->jd->var + iptr->dst.varindex
1667  );
1668  vars_record_old_index(ssa->others, iptr->dst.varindex, old);
1669  others_mapping_set(ssa, old, iptr->dst.varindex);
1670  }
1671  }
1672  }
1673 }
1674 
1675 /*
1676 
1677  [locals.........................][interaces][others]
1678  [original locals][version > 1 ]
1679  <--------------- new locals --------------->
1680 */
1681 
1683  s4 vartop;
1684  varinfo *vars;
1685  s4 *it;
1686  unsigned i, j;
1687  jitdata *jd = ssa->jd;
1688  s4 *local_map;
1689 
1690  vartop = ssa->locals->count + ssa->stack->count + ssa->others->count;
1691  vars = DMNEW(varinfo, vartop);
1692 
1693  vars_copy_to_final(ssa->locals, vars);
1694  vars_copy_to_final(ssa->stack, vars + ssa->locals->count);
1695  vars_copy_to_final(ssa->others, vars + ssa->locals->count + ssa->stack->count);
1696 
1697  jd->var = vars;
1698  jd->vartop = jd->varcount = vartop;
1699 
1700  /* Grow local map to accomodate all new locals and iovars.
1701  But keep the local map for version 1 of locals, that contains the holes. */
1702 
1703  local_map = DMNEW(
1704  s4,
1705  5 * (jd->maxlocals + ssa->locals->count + ssa->stack->count - jd->localcount)
1706  );
1707 
1708  MCOPY(local_map, jd->local_map, s4, 5 * jd->maxlocals);
1709 
1710  jd->local_map = local_map;
1711 
1712  it = jd->local_map + (jd->maxlocals * 5); /* start adding entries here */
1713 
1714  /* Add version > 1 of all locals */
1715 
1716  for (i = jd->localcount; i < ssa->locals->count; ++i) {
1717  for (j = 0; j < 5; ++j) {
1718  if (jd->var[i].type != j) {
1719  *it = jitdata::UNUSED;
1720  } else {
1721  *it = i;
1722  }
1723  it += 1;
1724  }
1725  }
1726 
1727  /* Add all io vars. */
1728 
1729  for (i = ssa->locals->count; i < ssa->locals->count + ssa->stack->count; ++i) {
1730  for (j = 0; j < 5; ++j) {
1731  if (jd->var[i].type != j) {
1732  *it = jitdata::UNUSED;
1733  } else {
1734  *it = i;
1735  }
1736  it += 1;
1737  }
1738  }
1739 
1740  /* Add locals. */
1741 
1742  jd->maxlocals += (ssa->locals->count + ssa->stack->count - jd->localcount);
1743  jd->localcount = ssa->locals->count + ssa->stack->count;
1744 
1745  /* Eliminate interfaces. */
1746 
1747  jd->maxinterfaces = 0;
1748 
1749 }
1750 
1751 static void ssa_enter_export_phis(ssa_info_t *ssa) {
1752  basicblock *bptr;
1753  basicblock_info_t *bbi;
1754  instruction *dst;
1755 
1756  FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
1757  bbi = bb_info(bptr);
1758  if (bbi != NULL) {
1759  bptr->phis = DMNEW(instruction, bbi->locals->phis->count + bbi->stack->phis->count);
1760 
1761  dst = bptr->phis;
1762 
1763  dst += phis_copy_to(bbi->locals->phis, dst);
1764 
1765  dst += phis_copy_to(bbi->stack->phis, dst);
1766 
1767  bptr->phicount = dst - bptr->phis;
1768  }
1769  }
1770 }
1771 
1772 /* TODO rename */
1773 static inline void ssa_enter_eliminate_category(ssa_info_t *ssa, s4 *pvar) {
1774  switch (vars_get_category(*pvar)) {
1775  case VARS_CATEGORY_LOCAL:
1776  *pvar = vars_get_index(vars_resolve_subst(ssa->locals, *pvar));
1777  break;
1778  case VARS_CATEGORY_STACK:
1779  *pvar = vars_get_index(vars_resolve_subst(ssa->stack, *pvar)) + ssa->locals->count;
1780  break;
1781  case VARS_CATEGORY_OTHERS:
1782  *pvar = vars_get_index(*pvar) + ssa->locals->count + ssa->stack->count;
1783  break;
1784  }
1785 }
1786 
1787 /* TODO rename */
1788 void ssa_enter_eliminate_categories(ssa_info_t *ssa) {
1789  basicblock *bb;
1790  instruction *iptr;
1791  s4 *ituse, *uses;
1792  unsigned uses_count;
1793  basicblock_info_t *bbi;
1794  instruction *itph;
1795 
1796  FOR_EACH_BASICBLOCK(ssa->jd, bb) {
1797 
1798  bbi = bb_info(bb);
1799 
1800  if (! ssa->keep_in_out) {
1801  bb->indepth = 0;
1802  bb->outdepth = 0;
1803  }
1804 
1805  if (bbi != NULL) {
1806  FOR_EACH_PHI_FUNCTION(bbi->locals->phis, itph) {
1807  ssa_enter_eliminate_category(ssa, &(itph->dst.varindex));
1808  }
1809 
1810  FOR_EACH_PHI_FUNCTION(bbi->stack->phis, itph) {
1811  ssa_enter_eliminate_category(ssa, &(itph->dst.varindex));
1812  }
1813  }
1814 
1815  FOR_EACH_INSTRUCTION(bb, iptr) {
1816  if (instruction_has_dst(iptr)) {
1817  ssa_enter_eliminate_category(ssa, &(iptr->dst.varindex));
1818  }
1819  instruction_get_uses(iptr, ssa->s_buf, &uses, &uses_count);
1820  for (ituse = uses; ituse != uses + uses_count; ++ituse) {
1821  ssa_enter_eliminate_category(ssa, ituse);
1822  }
1823  instruction_set_uses(iptr, ssa->s_buf, uses, uses_count);
1824  }
1825  }
1826 }
1827 
1829  basicblock *bptr;
1830  basicblock_info_t *bbi;
1831  instruction *itph;
1832  instruction **ituse;
1833  unsigned i;
1834  char path[PATH_MAX], *ppath;
1835  FILE *f;
1836 
1837  snprintf(path, PATH_MAX, "|tmp|graphs|%s.%s.dot", ssa->jd->m->clazz->name.begin(), ssa->jd->m->name.begin());
1838  for (ppath = path; *ppath; ++ppath) {
1839  if (*ppath == '|') *ppath = '/';
1840  else if (*ppath == '/') *ppath = '.';
1841  }
1842 
1843  f = fopen(path, "w");
1844 
1845  if (f == NULL) return;
1846 
1847  fprintf(f, "digraph G {\n");
1848 
1849  FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
1850  bbi = bb_info(bptr);
1851  if (bbi != NULL) {
1852  FOR_EACH_PHI_FUNCTION(bbi->locals->phis, itph) {
1853  i = 0;
1854  FOR_EACH_PHI_USE(itph, ituse) {
1855  if ((*ituse)->opc == ICMD_PHI) {
1856  fprintf(f, "%d -> %d;\n", (*ituse)->dst.varindex, itph->dst.varindex);
1857  }
1858  i += 1;
1859  }
1860  }
1861  }
1862  }
1863 
1864  fprintf(f, "};\n");
1865 
1866  fclose(f);
1867 }
1868 
1870  ssa_info *ssa,
1871  basicblock *from,
1872  basicblock *to,
1873  unsigned predecessor_index,
1874  unsigned reserved_insns
1875 ) {
1876  basicblock *bb;
1877  instruction *iptr;
1878  instruction *itph;
1879  basicblock_info_t *toi;
1880 
1881  toi = bb_info(to);
1882 
1883  /* Create basicblock and instruction array. */
1884 
1885  bb = DNEW(basicblock);
1886  MZERO(bb, basicblock, 1);
1887 
1888  bb->nr = ssa->jd->basicblockcount;
1889  ssa->jd->basicblockcount += 1;
1890  bb->mpc = -1;
1891  bb->method = ssa->jd->m;
1892  bb->type = basicblock::TYPE_STD;
1893  bb->icount = reserved_insns
1894  + toi->locals->phis->count
1895  + toi->stack->phis->count
1896  + 1;
1897  bb->iinstr = DMNEW(instruction, bb->icount);
1898  MZERO(bb->iinstr, instruction, bb->icount);
1899 
1900  /* Populate instruction array. */
1901 
1902  iptr = bb->iinstr + reserved_insns;
1903 
1904  /* Add phi moves. */
1905 
1906  FOR_EACH_PHI_FUNCTION(toi->locals->phis, itph) {
1907  phi_create_copy(itph, predecessor_index, iptr++);
1908  }
1909 
1910  FOR_EACH_PHI_FUNCTION(toi->stack->phis, itph) {
1911  phi_create_copy(itph, predecessor_index, iptr++);
1912  }
1913 
1914  /* Add goto to real block. */
1915 
1916  goto_init(iptr, to);
1917 
1918  /* Add basicblock to chain of newly created basicblocks. */
1919 
1920  basicblock_chain_add(ssa->new_blocks, bb);
1921 
1922  return bb;
1923 }
1924 
1926  ssa_info *ssa,
1927  basicblock *from,
1928  basicblock *to
1929 ) {
1931  ssa,
1932  from,
1933  to,
1935  0
1936  );
1937 }
1938 
1940  unsigned predecessor_index;
1941  basicblock_info_t *toi;
1942  instruction *iptr;
1943  instruction *itph;
1944  unsigned icount;
1945 
1946  if (bptr->next == NULL) {
1947  /* No fallthrough. */
1948  return;
1949  }
1950 
1951  predecessor_index = basicblock_get_predecessor_index(bptr, bptr->next);
1952  toi = bb_info(bptr->next);
1953 
1954  assert(toi);
1955 
1956  /* Resize instruction array to accomodate all phi moves. */
1957 
1958  icount = bptr->icount + toi->locals->phis->count + toi->stack->phis->count;
1959 
1960  bptr->iinstr = DMREALLOC(
1961  bptr->iinstr,
1962  instruction,
1963  bptr->icount,
1964  icount
1965  );
1966 
1967  iptr = bptr->iinstr + bptr->icount;
1968  bptr->icount = icount;
1969 
1970  /* Create phi moves. */
1971 
1972  FOR_EACH_PHI_FUNCTION(toi->locals->phis, itph) {
1973  phi_create_copy(itph, predecessor_index, iptr++);
1974  }
1975 
1976  FOR_EACH_PHI_FUNCTION(toi->stack->phis, itph) {
1977  phi_create_copy(itph, predecessor_index, iptr++);
1978  }
1979 }
1980 
1982  basicblock *bptr;
1983  instruction *iptr;
1984  basicblock *last = NULL;
1985 
1986  s4 i, l;
1987  branch_target_t *table;
1988  lookup_target_t *lookup;
1989  bool has_fallthrough;
1990 
1991  FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
1992 
1993  if (bptr->next == NULL) {
1994  last = bptr;
1995  }
1996 
1997  if (bptr->vp == NULL) {
1998  continue;
1999  }
2000 
2001  if (! basicblock_reached(bptr)) {
2002  continue;
2003  }
2004 
2005  has_fallthrough = true;
2006 
2007  for (iptr = bptr->iinstr; iptr != bptr->iinstr + bptr->icount; ++iptr) {
2008  switch (icmd_table[iptr->opc].controlflow) {
2009  case CF_IF:
2010  case CF_RET:
2011  case CF_GOTO:
2012  iptr->dst.block =
2013  ssa_leave_create_transition_block(ssa, bptr, iptr->dst.block);
2014  break;
2015  case CF_TABLE:
2016  table = iptr->dst.table;
2017  l = iptr->sx.s23.s2.tablelow;
2018  i = iptr->sx.s23.s3.tablehigh;
2019  i = i - l + 1;
2020  i += 1; /* default */
2021  while (--i >= 0) {
2022  table->block =
2023  ssa_leave_create_transition_block(ssa, bptr, table->block);
2024  ++table;
2025  }
2026  break;
2027  case CF_LOOKUP:
2028  lookup = iptr->dst.lookup;
2029  i = iptr->sx.s23.s2.lookupcount;
2030  while (--i >= 0) {
2031  lookup->target.block =
2032  ssa_leave_create_transition_block(ssa, bptr, lookup->target.block);
2033  lookup++;
2034  }
2035  iptr->sx.s23.s3.lookupdefault.block =
2036  ssa_leave_create_transition_block(ssa, bptr, iptr->sx.s23.s3.lookupdefault.block);
2037  break;
2038  case CF_JSR:
2039  iptr->sx.s23.s3.jsrtarget.block =
2040  ssa_leave_create_transition_block(ssa, bptr, iptr->sx.s23.s3.jsrtarget.block);
2041  break;
2042  }
2043 
2044  if (
2045  (iptr->opc == ICMD_GOTO) ||
2046  (iptr->opc == ICMD_JSR) ||
2047  (iptr->opc == ICMD_RET) ||
2048  icmd_table[iptr->opc].controlflow == CF_END ||
2049  (iptr->opc == ICMD_TABLESWITCH) ||
2050  (iptr->opc == ICMD_LOOKUPSWITCH)
2051  ) {
2052  has_fallthrough = false;
2053  } else if (iptr->opc != ICMD_NOP) {
2054  has_fallthrough = true;
2055  }
2056 
2057  }
2058 
2059  if (bptr->next == NULL) {
2060  continue;
2061  }
2062 
2063  if (! basicblock_reached(bptr->next)) {
2064  continue;
2065  }
2066 
2067  if (has_fallthrough) {
2068  ssa_leave_create_fallthrough(ssa, bptr);
2069  }
2070  }
2071 
2072  /* Add chain of new basic blocks */
2073 
2074  if (last != NULL && ! basicblock_chain_empty(ssa->new_blocks)) {
2075  last->next = basicblock_chain_front(ssa->new_blocks);
2076  }
2077 
2078 }
2079 
2081 
2082  basicblock_info_t *bbi = bb_info(bptr);
2083  unsigned iidx = iptr - bptr->iinstr;
2084  basicblock *newblock;
2085  basicblock *tosplit;
2086  unsigned ileft;
2087  unsigned pos;
2088 
2089  assert(iidx < bptr->icount);
2090  assert(bbi);
2091 
2092  /* If there are no subbasicblocks yet, we initialize the first one to be a
2093  copy of the original basicblock. */
2094 
2096  newblock = DNEW(basicblock);
2097  *newblock = *bptr;
2098  newblock->next = NULL;
2099  newblock->vp = NULL;
2100  basicblock_chain_add(bbi->subbasicblocks, newblock);
2101  }
2102 
2103  /* Find the subbasicblock that will be split:
2104  the one that cointains iptr. */
2105 
2106  tosplit = basicblock_chain_front(bbi->subbasicblocks);
2107  pos = 0;
2108 
2109  while (tosplit->next && (iidx >= (pos + tosplit->icount))) {
2110  assert(bptr->nr == tosplit->nr);
2111  pos += tosplit->icount;
2112  tosplit = tosplit->next;
2113  }
2114 
2115  assert(bptr->nr == tosplit->nr);
2116 
2117  /* Calculate number of instructions left in block to split. */
2118 
2119  ileft = iptr - tosplit->iinstr + 1;
2120  assert(ileft <= tosplit->icount);
2121 
2122  /* If there are any instructions left in the block to split, split */
2123 
2124  if (ileft < tosplit->icount) {
2125  newblock = DNEW(basicblock);
2126  *newblock = *tosplit;
2127 
2128  tosplit->next = newblock;
2129  tosplit->icount = ileft;
2130 
2131  newblock->icount -= ileft;
2132  newblock->iinstr += ileft;
2133 
2134  assert(tosplit->nr == bptr->nr);
2135  assert(newblock->nr == bptr->nr);
2136  assert(newblock->next == NULL);
2137 
2138  if (newblock->next == NULL) {
2139  bbi->subbasicblocks->last = newblock;
2140  }
2141  }
2142 
2143  /* We won't break pointers/references to bptr.
2144  So return bptr instread of the first fragment.
2145  Later, we will put the first fragment into the memory used by bptr.
2146  */
2147 
2148  if (tosplit == basicblock_chain_front(bbi->subbasicblocks)) {
2149  tosplit = bptr;
2150  }
2151 
2152  return tosplit;
2153 }
2154 
2156  ssa_info *ssa,
2157  basicblock *from,
2158  unsigned pei,
2159  basicblock *to
2160 ) {
2161  basicblock *exh;
2162 
2163  /* From is a try block, to is an exception handler prologue. */
2164 
2165  /* Remove old prologue. */
2166 
2167  to->state = basicblock::DELETED;
2168 
2169  /* Create new exception handler. */
2170 
2172  ssa,
2173  from,
2174  to,
2175  basicblock_get_ex_predecessor_index(from, pei, to),
2176  1
2177  );
2178  exh->type = basicblock::TYPE_EXH;
2179 
2180  /* Copy goto to real exception handler at the end of the exception handler
2181  prologue. */
2182 
2183  assert(to->iinstr[to->icount - 1].opc == ICMD_GOTO);
2184  assert(exh->iinstr[exh->icount - 1].opc == ICMD_GOTO);
2185  exh->iinstr[exh->icount - 1] = to->iinstr[to->icount - 1];
2186 
2187  /* Copy getexception from the old prologue. */
2188 
2189  assert(to->iinstr[0].opc == ICMD_GETEXCEPTION);
2190  exh->iinstr[0] = to->iinstr[0];
2191 
2192  return exh;
2193 }
2194 
2196  ssa_info_t *ssa,
2197  basicblock *from,
2198  basicblock *handler,
2199  classref_or_classinfo catchtype
2200 ) {
2201 
2203  basicblock_info_t *fromi = bb_info(from);
2204 
2205  ee->start = from;
2206 
2207  /* If the try block has subbasicblocks, the next block is the next fragment,
2208  not the successor block. */
2209 
2210  if (fromi != NULL) {
2212  } else {
2213  ee->end = from->next;
2214  }
2215  ee->handler = handler;
2216  ee->catchtype = catchtype;
2217  ee->next = NULL;
2218  ee->down = NULL;
2219 
2220  return ee;
2221 }
2222 
2224  basicblock *bptr;
2225  instruction *iptr;
2226  exception_entry *ite;
2228  classref_or_classinfo catchtype;
2229  basicblock *ittry;
2230  unsigned pei;
2231  basicblock *try_block;
2232  basicblock *exh;
2233  exception_entry *ee;
2234  basicblock *last = NULL;
2235 
2236  if (! basicblock_chain_empty(ssa->new_blocks)) {
2237  last = basicblock_chain_back(ssa->new_blocks);
2238  }
2239 
2241 
2242  for (ite = ssa->jd->exceptiontable; ite; ite = ite->down) {
2243  bptr = ite->handler;
2244  catchtype = ite->catchtype;
2246  for (ittry = ite->start; ittry != ite->end; ittry = ittry->next) {
2247  if (basicblock_reached(ittry)) {
2248  /* Dead code does not have a basicblock_info_t associated. */
2249  pei = 0;
2250  FOR_EACH_INSTRUCTION(ittry, iptr) {
2251  if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
2252  /* try is basicblock fragment till (including) the pei */
2253  try_block = ssa_leave_split_basicblock_at(ssa, ittry, iptr);
2254  /* ee is handler for try */
2256  ssa, try_block, pei, bptr
2257  );
2259  ssa, try_block, exh, catchtype
2260  );
2261  exception_entry_chain_add(&chain, ee);
2262  pei += 1;
2263  ssa->jd->exceptiontablelength += 1;
2264  }
2265  }
2266  }
2267  }
2268  if (! exception_entry_chain_empty(&chain)) {
2269  exception_entry_chain_back(&chain)->down = ite->down;
2270  exception_entry_chain_back(&chain)->next = ite->next;
2271  /* Replace original exception entry by first new one. */
2272  *ite = *exception_entry_chain_front(&chain);
2273  /* Set current iteration position to last newly created one. */
2274  ite = exception_entry_chain_back(&chain);
2275  }
2276  }
2277 
2278  if (last == NULL) {
2279  for (last = ssa->jd->basicblocks; last->next != NULL; last = last->next);
2280  }
2281 
2282  if (last != NULL && ! basicblock_chain_empty(ssa->new_blocks)) {
2283  last->next = basicblock_chain_front(ssa->new_blocks);
2284  }
2285 }
2286 
2287 void ssa_simple_leave_restore(ssa_info_t *ssa, basicblock *bptr, s4 *pvar) {
2288  s4 var = *pvar;
2289  s4 index;
2290  basicblock_info_t *bbi;
2291 
2292  if (var < ssa->locals->count) {
2293  *pvar = vars_get_old_index(ssa->locals, var);
2294  } else if (var < ssa->locals->count + ssa->stack->count) {
2295 
2296  index = vars_get_old_index(
2297  ssa->stack,
2298  var - ssa->locals->count
2299  );
2300 
2301  bbi = bb_info(bptr);
2302 
2303  /* We have to determine whether to take an invar or an outvar for
2304  the stack depth ``index''.
2305  The state array contains the last definition of the stack element
2306  at the given depth.
2307  */
2308 
2309  if (state_array_get_var(bbi->stack->state_array, index) == var) {
2310  /* The last definition of a stack depth inside the basicblock.
2311  This is the outvar at the given depth.
2312  If there is no outvar at the given depth, it must be an invar.
2313  */
2314  if (index < bptr->outdepth) {
2315  *pvar = bptr->outvars[index];
2316  } else if (index < bptr->indepth) {
2317  *pvar = bptr->invars[index];
2318  } else {
2319  assert(0);
2320  }
2321  } else {
2322  /* A different than the last definition of a stack depth.
2323  This must be an invar.
2324  */
2325  assert(index < bptr->indepth);
2326  *pvar = bptr->invars[index];
2327  }
2328  } else {
2329  *pvar = vars_get_old_index(
2330  ssa->others,
2331  var - ssa->locals->count - ssa->stack->count
2332  );
2333  }
2334 }
2335 
2336 void ssa_simple_leave(ssa_info_t *ssa) {
2337  basicblock *bptr;
2338  instruction *iptr;
2339  s4 *ituse, *uses;
2340  unsigned uses_count;
2341 
2342  FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
2343  if (bptr->type == basicblock::TYPE_EXH) {
2344  /* (Aritifical) exception handler blocks will be eliminated. */
2345  continue;
2346  }
2347  /* In reverse order. We need to rename the definition after any use! */
2348  FOR_EACH_INSTRUCTION_REV(bptr, iptr) {
2349  if (instruction_has_dst(iptr)) {
2350  ssa_simple_leave_restore(ssa, bptr, &(iptr->dst.varindex));
2351  }
2352  instruction_get_uses(iptr, ssa->s_buf, &uses, &uses_count);
2353  for (ituse = uses; ituse != uses + uses_count; ++ituse) {
2354  ssa_simple_leave_restore(ssa, bptr, ituse);
2355  }
2356  instruction_set_uses(iptr, ssa->s_buf, uses, uses_count);
2357  }
2358  bptr->phicount = 0;
2359  }
2360 
2362 
2363  ssa->jd->maxlocals = ssa->original.maxlocals;
2364  ssa->jd->maxinterfaces = ssa->original.maxinterfaces;
2365  ssa->jd->local_map =ssa->original.local_map;
2366  ssa->jd->var = ssa->original.var;
2367  ssa->jd->vartop = ssa->original.vartop;
2368  ssa->jd->varcount = ssa->original.varcount;
2369  ssa->jd->localcount = ssa->original.localcount;
2370 }
2371 
2372 #include "vm/rt-timing.hpp"
2373 
2374 void yssa(jitdata *jd) {
2375  basicblock *it;
2376  basicblock_info_t *iti;
2377  ssa_info *ssa;
2378 
2379  struct timespec bs, es, be, ee;
2380 
2381 /* TODO port to new rt-timing */
2382 #if 0
2383  RT_TIMING_GET_TIME(bs);
2384 #endif
2385 
2386 #ifdef SSA_VERBOSE
2387  bool verb = true;
2388  if (verb) {
2389  printf("=============== [ before %s ] =========================\n", jd->m->name.begin());
2390  show_method(jd, 3);
2391  printf("=============== [ /before ] =========================\n");
2392  }
2393 #endif
2394 
2395  ssa = DNEW(ssa_info);
2396 
2397  ssa_info_init(ssa, jd);
2398  ssa->keep_in_out = true;
2399 
2400  FOR_EACH_BASICBLOCK(jd, it) {
2401  if (basicblock_reached(it)) {
2402  iti = DNEW(basicblock_info_t);
2403  basicblock_info_init(iti, it, jd);
2404  it->vp = iti;
2405  } else {
2406  it->vp = NULL;
2407  }
2408  }
2409 
2411 
2412  ssa_enter_traverse(ssa, jd->basicblocks);
2413 
2415 
2417 
2418  ssa_enter_export_phis(ssa);
2419 
2421 
2422  /*ssa_enter_create_phi_graph(ssa);*/
2423 
2424 /* TODO port to new rt-timing */
2425 #if 0
2426  RT_TIMING_GET_TIME(be);
2427 #endif
2429 /* TODO port to new rt-timing */
2430 #if 0
2431  RT_TIMING_GET_TIME(ee);
2432 #endif
2433 
2434  /*
2435  ssa_leave_create_phi_moves(ssa);
2436 
2437  ssa_leave_create_exceptional_phi_moves(ssa);
2438  */
2439 
2440 #ifdef SSA_VERBOSE
2441  if (verb) {
2442  printf("=============== [ mid ] =========================\n");
2443  show_method(jd, 3);
2444  printf("=============== [ /mid ] =========================\n");
2445  }
2446 #endif
2447 
2448  ssa_simple_leave(ssa);
2449 
2450 #ifdef SSA_VERBOSE
2451  if (verb) {
2452  printf("=============== [ after ] =========================\n");
2453  show_method(jd, 3);
2454  printf("=============== [ /after ] =========================\n");
2455  }
2456 #endif
2457 
2458 /* TODO port to new rt-timing */
2459 #if 0
2460  RT_TIMING_GET_TIME(es);
2461 
2462  RT_TIMING_TIME_DIFF(bs, es, RT_TIMING_1);
2463  RT_TIMING_TIME_DIFF(be, ee, RT_TIMING_2);
2464 #endif
2465 }
2466 
2468  basicblock *bptr, *next;
2469  basicblock_info_t *bbi;
2470 
2471  FOR_EACH_BASICBLOCK(jd, bptr) {
2472  bbi = bb_info(bptr);
2473  if (bbi != NULL) {
2474  if (! basicblock_chain_empty(bbi->subbasicblocks)) {
2475  next = bptr->next;
2476  /* Copy first subblock, to keep pointers intact. */
2477  *bptr = *basicblock_chain_front(bbi->subbasicblocks);
2479  bptr->next = next;
2480  }
2481  }
2482  }
2483 
2484 #ifdef SSA_VERBOSE
2485  printf("=============== [ elim ] =========================\n");
2486  show_method(jd, 3);
2487  printf("=============== [ /elim ] =========================\n");
2488 #endif
2489 }
2490 
2491 /*
2492  * These are local overrides for various environment variables in Emacs.
2493  * Please do not remove this and leave it at the end of the file, where
2494  * Emacs will automagically detect them.
2495  * ---------------------------------------------------------------------
2496  * Local variables:
2497  * mode: c++
2498  * indent-tabs-mode: t
2499  * c-basic-offset: 4
2500  * tab-width: 4
2501  * End:
2502  * vim:noexpandtab:sw=4:ts=4:
2503  */
static void ssa_enter_mark_loops(basicblock *bb)
Definition: ssa3.cpp:1235
s4 vartop
Definition: ssa3.cpp:939
static basicblock * ssa_leave_split_basicblock_at(ssa_info *ssa, basicblock *bptr, instruction *iptr)
Definition: ssa3.cpp:2080
static void state_array_set(const state_array_t *sa, unsigned index, instruction *value)
Definition: ssa3.cpp:584
Utf8String name
Definition: method.hpp:71
static void basicblock_chain_init(basicblock_chain_t *bbc)
Definition: ssa3.cpp:609
std::size_t index
basicblock * block
union varinfo::@19 vv
exception_entry * last
Definition: ssa3.cpp:647
struct basicblock_info basicblock_info_t
s4 exceptiontablelength
Definition: jit.hpp:167
static void phi_set_flag(instruction *iptr, phi_flags_t flag)
Definition: ssa3.cpp:72
#define DF_1_TO_0
Definition: icmd.hpp:335
static void instruction_get_uses(const instruction *iptr, s4 *buf, s4 **puses, unsigned *puses_count)
Definition: ssa3.cpp:298
static bool state_array_has_items(const state_array_t *sa)
Definition: ssa3.cpp:569
static unsigned vars_resolve_subst(const vars_t *vs, unsigned varindex)
Definition: ssa3.cpp:420
#define CF_GOTO
Definition: icmd.hpp:376
basicblock * basicblocks
Definition: jit.hpp:141
static void ssa_enter_merge(traversal_t *src, traversal_t *dst, basicblock *bdst, unsigned predecessor_index, vars_t *vdst)
Definition: ssa3.cpp:1239
Definition: jit.hpp:126
#define DF_2_TO_0
Definition: icmd.hpp:336
Definition: stack.hpp:46
static void phis_init(phis_t *ps, unsigned max)
Definition: ssa3.cpp:509
static void ssa_enter_mark_loops_intern(basicblock *bb, unsigned num_branches)
Definition: ssa3.cpp:1213
#define DF_1_TO_1
Definition: icmd.hpp:342
static bool instruction_has_dst(const instruction *iptr)
#define max(a, b)
Definition: lsra.hpp:80
varinfo * inout_var_num_to_varinfo(void *vp, s4 var)
Definition: ssa3.cpp:835
#define basicblock_chain_clear
Definition: ssa3.cpp:614
s4 localcount
Definition: jit.hpp:152
static void state_array_init(state_array_t *sa, unsigned count)
Definition: ssa3.cpp:564
exception_entry * exceptiontable
Definition: jit.hpp:168
static exception_entry * exception_entry_chain_back(exception_entry_chain_t *eec)
Definition: ssa3.cpp:672
unsigned keep_in_out
Definition: ssa3.cpp:944
#define CF_RET
Definition: icmd.hpp:380
traversal_ops_t traversal_local_ops
Definition: ssa3.cpp:802
argument_type from
void traversal_init(traversal_t *t, unsigned count, void *ops_vp, traversal_ops_t *ops)
Definition: ssa3.cpp:721
static void phi_set_used(instruction *iptr)
Definition: ssa3.cpp:164
#define phi_assert_arg(iptr, arg)
Definition: ssa3.cpp:117
static bool basicblock_chain_empty(const basicblock_chain_t *bbc)
Definition: ssa3.cpp:639
static void ssa_enter_process_block(ssa_info *ssa, basicblock *bb)
Definition: ssa3.cpp:1540
#define VARS_CATEGORY_STACK
Definition: ssa3.cpp:357
State state
Definition: jit.hpp:320
varinfo * local_index_to_initial_var(void *vp, unsigned index)
Definition: ssa3.cpp:787
void ssa_simple_leave(ssa_info_t *ssa)
Definition: ssa3.cpp:2336
#define DMREALLOC(ptr, type, num1, num2)
Definition: dumpmemory.hpp:372
static void traversal_rename_use(traversal_t *t, vars_t *vars, s4 *puse)
Definition: ssa3.cpp:764
s4 maxlocals
Definition: jit.hpp:162
s4 * invars
Definition: jit.hpp:330
basicblock * next
Definition: jit.hpp:344
#define bb_info
Definition: ssa3.cpp:874
s4 s_buf[3]
Definition: ssa3.cpp:930
#define DF_STORE
Definition: icmd.hpp:363
bool traversed
Definition: ssa3.cpp:703
#define VARS_CATEGORY_OTHERS
Definition: ssa3.cpp:358
static void traversal_rename_def(traversal_t *t, vars_t *vars, instruction *iptr)
Definition: ssa3.cpp:747
void unfix_exception_handlers(jitdata *jd)
Definition: ssa3.cpp:1165
static unsigned vars_add_item(vars_t *vs, const varinfo *item)
Definition: ssa3.cpp:376
static void vars_subst(vars_t *vs, unsigned varindex, unsigned replacementindex)
Definition: ssa3.cpp:412
unsigned inout_variables_count(void *vp)
Definition: ssa3.cpp:841
unsigned local_variables_count(void *vp)
Definition: ssa3.cpp:797
s4 outdepth
Definition: jit.hpp:333
int32_t argcount
Definition: instruction.hpp:64
varinfo * var
Definition: jit.hpp:148
#define show_method(...)
Definition: ssa2.cpp:41
#define CF_JSR
Definition: icmd.hpp:379
static instruction * phi_get_subst(instruction *iptr)
Definition: ssa3.cpp:84
s4 ii[2]
Definition: reg.hpp:53
static void phi_set_all_args(instruction *iptr, instruction *value)
Definition: ssa3.cpp:136
s4 mpc
Definition: jit.hpp:352
int32_t varindex
Definition: instruction.hpp:63
unsigned max
Definition: ssa3.cpp:505
s4 vartop
Definition: jit.hpp:149
varinfo * var
Definition: ssa3.cpp:938
#define CF_TABLE
Definition: icmd.hpp:377
static basicblock * basicblock_chain_front(basicblock_chain_t *bbc)
Definition: ssa3.cpp:629
#define CF_END
Definition: icmd.hpp:375
traversal_ops_t traversal_inout_ops
Definition: ssa3.cpp:846
static void phi_init(instruction *iptr, unsigned argcount, s4 index)
Definition: ssa3.cpp:93
static unsigned basicblock_get_ex_predecessor_index(basicblock *from, unsigned pei, basicblock *to)
Definition: ssa3.cpp:903
#define DF_3_TO_0
Definition: icmd.hpp:337
static unsigned basicblock_get_predecessor_count(basicblock *bb)
Definition: ssa3.cpp:876
#define FOR_EACH_PHI_USE(iptr, it)
Definition: ssa3.cpp:235
void escape_analysis_perform(jitdata *jd)
Definition: escape.cpp:1277
Type type
Definition: reg.hpp:44
static instruction * phi_resolve_use(instruction *use)
Definition: ssa3.cpp:172
jitdata * jd
Definition: ssa2.cpp:69
bool visited
Definition: ssa3.cpp:701
unsigned count
Definition: ssa3.cpp:561
#define DF_3_TO_1
Definition: icmd.hpp:344
lookup_target_t * lookup
static void ssa_leave_create_exceptional_phi_moves(ssa_info *ssa)
Definition: ssa3.cpp:2223
instruction * iinstr
Definition: jit.hpp:326
instruction * traversal_create_phi(traversal_t *t, vars_t *v, unsigned argcount, s4 index)
Definition: ssa3.cpp:732
Definition: reg.hpp:43
s4 icount
Definition: jit.hpp:325
static s4 phi_get_arg_var(const instruction *iptr, unsigned arg)
Definition: ssa3.cpp:130
unsigned inout_var_num_to_index(void *vp, s4 var)
Definition: ssa3.cpp:809
#define FOR_EACH_SUCCESSOR(bptr, it)
Definition: jit.hpp:381
static bool var_is_local(const jitdata *jd, s4 i)
Definition: jit.hpp:261
#define DNEW(type)
Definition: dumpmemory.hpp:370
static unsigned vars_add(vars_t *vs)
Definition: ssa3.cpp:385
s4 varcount
Definition: jit.hpp:151
varinfo *(* var_num_to_varinfo)(void *vp, s4 var)
Definition: ssa3.cpp:687
#define state_array_assert_items(sa)
Definition: ssa3.cpp:594
#define MCOPY(dest, src, type, num)
Definition: memory.hpp:103
static void ssa_enter_export_phis(ssa_info_t *ssa)
Definition: ssa3.cpp:1751
vars_item_t items[9000]
Definition: ssa3.cpp:370
JNIEnv void * arg
Definition: jvmti.h:405
instruction ** items
Definition: ssa3.cpp:560
#define DF_N_TO_1
Definition: icmd.hpp:345
instruction * items
Definition: ssa3.cpp:504
varinfo * local_var_num_to_varinfo(void *vp, s4 var)
Definition: ssa3.cpp:792
static void phi_set_dst(instruction *iptr, s4 dst)
Definition: ssa3.cpp:154
static void vars_import(vars_t *vs, varinfo *v, unsigned count, s4 old_index)
Definition: ssa3.cpp:456
basicblock_chain_t * subbasicblocks
Definition: ssa3.cpp:709
#define ICMDTABLE_PEI
Definition: icmd.hpp:384
static void ssa_enter_eliminate_category(ssa_info_t *ssa, s4 *pvar)
Definition: ssa3.cpp:1773
void basicblock_info_init(basicblock_info_t *bbi, basicblock *bb, jitdata *jd)
Definition: ssa3.cpp:855
branch_target_t target
Definition: instruction.hpp:57
dst_operand_t dst
flags_operand_t flags
phi_flags_t
Definition: ssa3.cpp:66
Definition: ssa3.cpp:645
varinfo * inout_index_to_initial_var(void *vp, unsigned index)
Definition: ssa3.cpp:828
static bool phi_has_flag(const instruction *iptr, phi_flags_t flag)
Definition: ssa3.cpp:80
static basicblock * ssa_leave_create_transition_block_intern(ssa_info *ssa, basicblock *from, basicblock *to, unsigned predecessor_index, unsigned reserved_insns)
Definition: ssa3.cpp:1869
traversal_t * stack
Definition: ssa3.cpp:707
basicblock ** predecessors
Definition: jit.hpp:339
#define VAR_TYPE_SUBSTITUED
Definition: ssa3.cpp:360
static unsigned vars_get_category(unsigned varindex)
Definition: ssa3.cpp:404
classinfo * clazz
Definition: method.hpp:80
int32_t dataflow
Definition: icmd.hpp:395
basicblock * start
Definition: jit.hpp:241
s4 * local_map
Definition: ssa3.cpp:937
static void state_array_allocate_items(state_array_t *sa)
Definition: ssa3.cpp:597
#define FOR_EACH_INSTRUCTION_REV(bptr, it)
Definition: jit.hpp:394
static void phi_create_copy(instruction *iptr, unsigned arg, instruction *copy)
Definition: ssa3.cpp:199
s4 predecessorcount
Definition: jit.hpp:337
Utf8String name
Definition: class.hpp:91
static void phi_clear_flag(instruction *iptr, phi_flags_t flag)
Definition: ssa3.cpp:76
static void basicblock_chain_add(basicblock_chain_t *bbc, basicblock *bb)
Definition: ssa3.cpp:616
basicblock * handler
Definition: jit.hpp:243
vars_t * others
Definition: ssa3.cpp:928
static basicblock * basicblock_chain_back(basicblock_chain_t *bbc)
Definition: ssa3.cpp:634
#define CF_IF
Definition: icmd.hpp:371
#define DF_COPY
Definition: icmd.hpp:350
static void phi_calculate_redundancy(instruction *iptr)
Definition: ssa3.cpp:241
#define MZERO(ptr, type, num)
Definition: memory.hpp:105
#define VARS_CATEGORY_LOCAL
Definition: ssa3.cpp:356
exception_entry * next
Definition: jit.hpp:245
static basicblock * ssa_leave_create_transition_exception_handler(ssa_info *ssa, basicblock *from, unsigned pei, basicblock *to)
Definition: ssa3.cpp:2155
static void others_mapping_set(ssa_info *ssa, s4 var, s4 new_var)
Definition: ssa3.cpp:979
static void instruction_set_uses(instruction *iptr, s4 *buf, s4 *uses, unsigned uses_count)
Definition: ssa3.cpp:338
basicblock * first
Definition: ssa3.cpp:605
classref_or_classinfo catchtype
Definition: jit.hpp:244
static bool phi_has_subst(const instruction *iptr)
Definition: ssa3.cpp:88
static void goto_init(instruction *iptr, basicblock *dst)
Definition: ssa3.cpp:291
s4 indepth
Definition: jit.hpp:332
static unsigned traversal_variables_count(traversal_t *t)
Definition: ssa3.cpp:779
s4 old_index
Definition: ssa3.cpp:366
s4 maxlocals
Definition: ssa3.cpp:935
s4 * local_map
Definition: jit.hpp:153
unsigned(* var_num_to_index)(void *vp, s4 var)
Definition: ssa3.cpp:685
s4 maxinterfaces
Definition: ssa3.cpp:936
static void phi_print(const instruction *iptr)
Definition: ssa3.cpp:212
static instruction * phis_add(phis_t *ps)
Definition: ssa3.cpp:515
MIIterator i
#define FOR_EACH_BASICBLOCK(jd, it)
Definition: jit.hpp:181
int32_t s4
Definition: types.hpp:45
MIIterator pos
static s4 others_mapping_get(const ssa_info *ssa, s4 var)
Definition: ssa3.cpp:983
static unsigned phis_copy_to(const phis_t *ps, instruction *dst)
Definition: ssa3.cpp:546
#define VARS_CATEGORY_SHIFT
Definition: ssa3.cpp:353
#define FOR_EACH_PREDECESSOR(bptr, it)
Definition: jit.hpp:384
static void exception_entry_chain_add(exception_entry_chain_t *eec, exception_entry *ee)
Definition: ssa3.cpp:657
static bool exception_entry_chain_empty(const exception_entry_chain_t *eec)
Definition: ssa3.cpp:668
static instruction * phi_get_arg(const instruction *iptr, unsigned arg)
Definition: ssa3.cpp:124
static bool phi_is_redundant(const instruction *iptr)
Definition: ssa3.cpp:192
#define DF_MOVE
Definition: icmd.hpp:351
unsigned count
Definition: ssa3.cpp:372
s4 * outvars
Definition: jit.hpp:331
static void ssa_leave_create_phi_moves(ssa_info *ssa)
Definition: ssa3.cpp:1981
static exception_entry * ssa_leave_create_transition_exception_entry(ssa_info_t *ssa, basicblock *from, basicblock *handler, classref_or_classinfo catchtype)
Definition: ssa3.cpp:2195
union instruction::@12 sx
#define OLD_INDEX_UNUSED
Definition: ssa3.cpp:362
struct ssa_info ssa_info
#define FIXME(x)
Definition: ssa3.cpp:56
exception_entry * down
Definition: jit.hpp:247
static unsigned basicblock_get_predecessor_index(basicblock *from, basicblock *to)
Definition: ssa3.cpp:889
#define CF_LOOKUP
Definition: icmd.hpp:378
unsigned num_phi_elimination
Definition: ssa3.cpp:714
static s4 state_array_get_var(const state_array_t *sa, unsigned index)
Definition: ssa3.cpp:573
basicblock * last
Definition: ssa3.cpp:606
int32_t varindex
struct ssa_info::@16 original
unsigned(* variables_count)(void *vp)
Definition: ssa3.cpp:688
s4 localcount
Definition: ssa3.cpp:941
static void phi_set_arg(instruction *iptr, unsigned arg, instruction *value)
Definition: ssa3.cpp:185
static void vars_init(vars_t *vs, unsigned category)
Definition: ssa3.cpp:397
traversal_ops_t * ops
Definition: ssa3.cpp:695
icmdtable_entry_t icmd_table[256]
Definition: icmd.cpp:60
state_array_t * state_array
Definition: ssa3.cpp:693
void yssa(jitdata *jd)
Definition: ssa3.cpp:2374
This file contains the real-time timing utilities.
s1_operand_t s1
Definition: ssa3.cpp:503
basicblock * block
Definition: instruction.hpp:50
void ssa_simple_leave_restore(ssa_info_t *ssa, basicblock *bptr, s4 *pvar)
Definition: ssa3.cpp:2287
int32_t controlflow
Definition: icmd.hpp:396
static void vars_copy_to_final(vars_t *vs, varinfo *dst)
Definition: ssa3.cpp:436
unsigned max
Definition: ssa3.cpp:371
void * ops_vp
Definition: ssa3.cpp:694
traversal_t * locals
Definition: ssa3.cpp:706
byte_iterator begin() const
Definition: utf8.hpp:106
static bool phi_get_used(const instruction *iptr)
Definition: ssa3.cpp:159
void eliminate_subbasicblocks(jitdata *jd)
Definition: ssa3.cpp:2467
static void ssa_enter_export_variables(ssa_info *ssa)
Definition: ssa3.cpp:1682
void ssa_enter_eliminate_categories(ssa_info_t *ssa)
Definition: ssa3.cpp:1788
static exception_entry * exception_entry_chain_front(exception_entry_chain_t *eec)
Definition: ssa3.cpp:677
vars_t * locals
Definition: ssa3.cpp:926
methodinfo * m
Definition: jit.hpp:127
static void vars_record_old_index(vars_t *vs, unsigned varindex, s4 old_index)
Definition: ssa3.cpp:473
static void ssa_enter_create_phi_graph(ssa_info *ssa)
Definition: ssa3.cpp:1828
unsigned local_var_num_to_index(void *vp, s4 var)
Definition: ssa3.cpp:783
s4 maxinterfaces
Definition: jit.hpp:165
basicblock * end
Definition: jit.hpp:242
static void exception_entry_chain_init(exception_entry_chain_t *eec)
Definition: ssa3.cpp:650
methodinfo * method
Definition: jit.hpp:349
static bool var_is_inout(const jitdata *jd, s4 i)
Definition: jit.hpp:269
static varinfo * vars_back(vars_t *vs)
Definition: ssa3.cpp:392
static void state_array_copy(state_array_t *sa, state_array_t *other)
Definition: ssa3.cpp:589
s4 flags
Definition: reg.hpp:45
#define DF_LOAD
Definition: icmd.hpp:362
static bool phis_contains(const phis_t *ps, const instruction *phi)
Definition: ssa3.cpp:527
#define DF_INVOKE
Definition: icmd.hpp:347
unsigned category
Definition: ssa3.cpp:373
#define FOR_EACH_INSTRUCTION(bptr, it)
Definition: jit.hpp:391
s4 nr
Definition: jit.hpp:319
unsigned complete_predecessors
Definition: ssa3.cpp:711
static void ssa_enter_process_pei(ssa_info *ssa, basicblock *bb, unsigned pei)
Definition: ssa3.cpp:1433
static bool basicblock_reached(const basicblock *bptr)
Definition: jit.hpp:438
s4 basicblockcount
Definition: jit.hpp:144
#define DMNEW(type, num)
Definition: dumpmemory.hpp:371
exception_entry * first
Definition: ssa3.cpp:646
OStream & out()
Definition: OStream.cpp:39
struct instruction::@12::@13 s23
static s4 vars_get_old_index(vars_t *vs, unsigned varindex)
Definition: ssa3.cpp:489
basicblock_chain_t * new_blocks
Definition: ssa3.cpp:932
static struct @5 ops[]
void ssa(jitdata *jd)
Definition: ssa.cpp:105
static instruction * phis_get(const phis_t *ps, unsigned i)
Definition: ssa3.cpp:522
static void ssa_leave_create_fallthrough(ssa_info *ssa, basicblock *bptr)
Definition: ssa3.cpp:1939
varinfo v
Definition: ssa3.cpp:365
void fix_exception_handlers(jitdata *jd)
Definition: ssa3.cpp:989
static java_object_t * next
Definition: copy.c:43
static bool ssa_enter_eliminate_redundant_phis(traversal_t *t, vars_t *vs, basicblock_info_t *bbi)
s4 varcount
Definition: ssa3.cpp:940
static vars_t * vs
Definition: ssa3.cpp:1459
#define state_array_assert_no_items(sa)
Definition: ssa3.cpp:595
Definition: ssa3.cpp:369
static basicblock * ssa_leave_create_transition_block(ssa_info *ssa, basicblock *from, basicblock *to)
Definition: ssa3.cpp:1925
static s4 phi_arg_count(const instruction *iptr)
Definition: ssa3.cpp:119
static void ssa_enter_verify_no_redundant_phis(ssa_info_t *ssa)
Definition: ssa3.cpp:1318
Definition: jit.hpp:240
vars_t * stack
Definition: ssa3.cpp:927
static instruction * state_array_get(const state_array_t *sa, unsigned index)
Definition: ssa3.cpp:579
#define FOR_EACH_PHI_FUNCTION(ps, it)
Definition: ssa3.cpp:534
static unsigned vars_get_index(unsigned varindex)
Definition: ssa3.cpp:408
#define DF_BUILTIN
Definition: icmd.hpp:348
phis_t * phis
Definition: ssa3.cpp:692
static s4 phi_get_dst(const instruction *iptr)
Definition: ssa3.cpp:149
Type type
Definition: jit.hpp:322
static void ssa_enter_traverse(ssa_info_t *ssa, basicblock *bb)
Definition: ssa3.cpp:1346
struct ssa_info ssa_info_t
#define printf(...)
Definition: ssa2.cpp:40
struct basicblock_info basicblock_info
Definition: dominators.cpp:280
#define DF_2_TO_1
Definition: icmd.hpp:343
branch_target_t * table
#define phi_assert_opc(iptr)
Definition: ssa3.cpp:115
unsigned count
Definition: ssa3.cpp:506
int32_t flags
Definition: icmd.hpp:397
static void ssa_enter_init_locals(state_array_t *sa)
Definition: ssa3.cpp:1528
void ssa_info_init(ssa_info_t *ssa, jitdata *jd)
Definition: ssa3.cpp:948
#define VARS_INDEX_MASK
Definition: ssa3.cpp:354
varinfo *(* index_to_initial_var)(void *vp, unsigned index)
Definition: ssa3.cpp:686
unsigned backward_branches
Definition: ssa3.cpp:704
static s4 phi_get_index(const instruction *iptr)
Definition: ssa3.cpp:144