1
0
Fork 0

optimizer: finished building of basic blocks

git-svn-id: svn://svn.lighttpd.net/xcache/trunk@312 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
3.0
Xuefer 2006-12-09 16:28:25 +00:00
parent 4af40759f6
commit f0453a11dc
1 changed files with 118 additions and 39 deletions

View File

@ -1,4 +1,4 @@
#if 1
#if 0
#define DEBUG
#endif
@ -28,7 +28,7 @@ typedef struct _bb_t {
bbid_t jmpout_op1;
bbid_t jmpout_op2;
bbid_t jmpout_ext;
bbid_t follow;
bbid_t fall;
} bb_t;
/* }}} */
@ -101,21 +101,21 @@ static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */
return SUCCESS;
}
/* }}} */
static int op_get_jmpout(bb_t *bb, zend_op *opcodes, zend_op *opline) /* {{{ */
static int op_get_jmpout(int *jmpout_op1, int *jmpout_op2, int *jmpout_ext, zend_bool *fall, zend_op *opline) /* {{{ */
{
/* break=have follow */
/* break=will fall */
switch (opline->opcode) {
case ZEND_RETURN:
case ZEND_EXIT:
break;
return SUCCESS; /* no fall */
case ZEND_JMP:
bb->jmpout_op1 = opline->op1.u.opline_num;
return SUCCESS; /* no follow */
*jmpout_op1 = opline->op1.u.opline_num;
return SUCCESS; /* no fall */
case ZEND_JMPZNZ:
bb->jmpout_ext = opline->extended_value;
bb->jmpout_op2 = opline->op2.u.opline_num;
*jmpout_ext = opline->extended_value;
*jmpout_op2 = opline->op2.u.opline_num;
break;
case ZEND_JMPZ:
@ -130,13 +130,14 @@ static int op_get_jmpout(bb_t *bb, zend_op *opcodes, zend_op *opline) /* {{{ */
case ZEND_FE_RESET:
#endif
case ZEND_FE_FETCH:
bb->jmpout_op2 = opline->op2.u.opline_num;
*jmpout_op2 = opline->op2.u.opline_num;
break;
default:
return FAILURE;
}
*fall = 1;
return SUCCESS;
}
/* }}} */
@ -152,7 +153,7 @@ static bb_t *bb_new_ex(zend_op *opcodes, int count) /* {{{ */
bb->jmpout_op1 = BBID_INVALID;
bb->jmpout_op2 = BBID_INVALID;
bb->jmpout_ext = BBID_INVALID;
bb->follow = BBID_INVALID;
bb->fall = BBID_INVALID;
if (opcodes) {
bb->alloc = 0;
@ -177,6 +178,21 @@ static void bb_destroy(bb_t *bb) /* {{{ */
efree(bb);
}
/* }}} */
#ifdef DEBUG
static void bb_print(bb_t *bb, zend_op *opcodes) /* {{{ */
{
fprintf(stderr,
"%3d %3d %3d"
" %c%c"
" %3d %3d %3d %3d\r\n"
, bb->id, bb->count, bb->opcodes - opcodes
, bb->used ? 'U' : ' ', bb->alloc ? 'A' : ' '
, bb->jmpout_op1, bb->jmpout_op2, bb->jmpout_ext, bb->fall
);
}
/* }}} */
#endif
#define bbs_get(bbs, n) xc_stack_get(bbs, n)
static void bbs_destroy(bbs_t *bbs) /* {{{ */
{
@ -187,6 +203,16 @@ static void bbs_destroy(bbs_t *bbs) /* {{{ */
}
}
/* }}} */
#ifdef DEBUG
static void bbs_print(bbs_t *bbs, zend_op *opcodes) /* {{{ */
{
int i;
for (i = 0; i < xc_stack_count(bbs); i ++) {
bb_print(bbs_get(bbs, i), opcodes);
}
}
/* }}} */
#endif
#define bbs_init(bbs) xc_stack_init_ex(bbs, 16)
static bb_t *bbs_add_bb(bbs_t *bbs, bb_t *bb) /* {{{ */
{
@ -203,51 +229,97 @@ static bb_t *bbs_new_bb_ex(bbs_t *bbs, zend_op *opcodes, int count) /* {{{ */
static int bbs_build_from(bbs_t *bbs, zend_op *opcodes, int count) /* {{{ */
{
int i, prev;
bb_t bb, *pbb;
zend_bool *markjmpins = do_alloca(count);
zend_bool *markjmpouts = do_alloca(count);
bb_t *pbb;
bbid_t id;
int jmpout_op1, jmpout_op2, jmpout_ext;
zend_bool fall;
bbid_t *bbids = do_alloca(count * sizeof(bbid_t));
zend_bool *markjmpins = do_alloca(count * sizeof(zend_bool));
zend_bool *markjmpouts = do_alloca(count * sizeof(zend_bool));
memset(markjmpins, 0, sizeof(zend_bool));
memset(markjmpouts, 0, sizeof(zend_bool));
/* {{{ mark jmpin/jumpout */
memset(markjmpins, 0, count * sizeof(zend_bool));
memset(markjmpouts, 0, count * sizeof(zend_bool));
for (i = 0; i < count; i ++) {
/* BBID_INVALID=invalidate line
* bb.jmpout_op1 bb.jmpout_op2 bb.jmpout_ext bb.follow means opline number here, not basicblock id
*/
bb.jmpout_op1 = bb.jmpout_op2 = BBID_INVALID;
bb.jmpout_ext = bb.follow = BBID_INVALID;
if (op_get_jmpout(&bb, opcodes, &opcodes[i]) == SUCCESS) {
jmpout_op1 = jmpout_op2 = jmpout_ext = -1;
fall = 0;
if (op_get_jmpout(&jmpout_op1, &jmpout_op2, &jmpout_ext, &fall, &opcodes[i]) == SUCCESS) {
markjmpouts[i] = 1;
if (bb.jmpout_op1 != BBID_INVALID) {
markjmpins[bb.jmpout_op1] = 1;
if (jmpout_op1 != -1) {
markjmpins[jmpout_op1] = 1;
}
if (bb.jmpout_op2 != BBID_INVALID) {
markjmpins[bb.jmpout_op2] = 1;
if (jmpout_op2 != -1) {
markjmpins[jmpout_op2] = 1;
}
if (bb.jmpout_ext != BBID_INVALID) {
markjmpins[bb.jmpout_ext] = 1;
}
if (i < count && bb.follow != BBID_INVALID) {
markjmpins[i + 1] = 1;
if (jmpout_ext != -1) {
markjmpins[jmpout_ext] = 1;
}
}
}
/* }}} */
/* {{{ fill opcodes with newly allocated id */
for (i = 0; i < count; i ++) {
bbids[i] = BBID_INVALID;
}
prev = 0;
id = 0;
for (i = 1; i < count; i ++) {
if (markjmpins[i]) {
pbb = bbs_new_bb_ex(bbs, opcodes + prev, i - prev);
op_get_jmpout(pbb, opcodes, &opcodes[prev]);
if (markjmpins[i] || markjmpouts[i - 1]) {
for (; prev < i; prev ++) {
bbids[prev] = id;
}
id ++;
prev = i;
}
}
if (prev != count - 1) {
pbb = bbs_new_bb_ex(bbs, opcodes + prev, count - prev);
if (prev < count) {
for (; prev < i; prev ++) {
bbids[prev] = id;
}
}
/* }}} */
/* {{{ create basic blocks */
prev = 0;
id = 0;
for (i = 1; i < count; i ++) {
if (id == bbids[i]) {
continue;
}
id = bbids[i];
pbb = bbs_new_bb_ex(bbs, opcodes + prev, i - prev);
jmpout_op1 = jmpout_op2 = jmpout_ext = -1;
fall = 0;
if (op_get_jmpout(&jmpout_op1, &jmpout_op2, &jmpout_ext, &fall, &opcodes[prev]) == SUCCESS) {
if (jmpout_op1 != -1) {
pbb->jmpout_op1 = bbids[jmpout_op1];
assert(pbb->jmpout_op1 != BBID_INVALID);
}
if (jmpout_op2 != -1) {
pbb->jmpout_op2 = bbids[jmpout_op2];
assert(pbb->jmpout_op2 != BBID_INVALID);
}
if (jmpout_ext != -1) {
pbb->jmpout_ext = bbids[jmpout_ext];
assert(pbb->jmpout_ext != BBID_INVALID);
}
if (fall && i + 1 < count) {
pbb->fall = bbids[i + 1];
assert(pbb->fall != BBID_INVALID);
}
}
prev = i + 1;
}
assert(prev == count);
/* }}} */
free_alloca(bbids);
free_alloca(markjmpins);
free_alloca(markjmpouts);
return SUCCESS;
}
/* }}} */
@ -264,20 +336,27 @@ static int xc_optimize_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */
}
xc_undo_pass_two(op_array TSRMLS_CC);
#ifdef DEBUG
# if 0
TRACE("optimize file: %s", op_array->filename);
xc_dprint_zend_op_array(op_array, 0 TSRMLS_CC);
# endif
#endif
if (op_array_convert_switch(op_array)) {
if (op_array_convert_switch(op_array) == SUCCESS) {
bbs_init(&bbs);
if (bbs_build_from(&bbs, op_array->opcodes, op_array->last)) {
if (bbs_build_from(&bbs, op_array->opcodes, op_array->last) == SUCCESS) {
#ifdef DEBUG
bbs_print(&bbs, op_array->opcodes);
#endif
}
bbs_destroy(&bbs);
}
#ifdef DEBUG
# if 0
TRACE("%s", "after compiles");
xc_dprint_zend_op_array(op_array, 0 TSRMLS_CC);
# endif
#endif
xc_redo_pass_two(op_array TSRMLS_CC);
return 0;