diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-17 12:42:15 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-17 12:42:15 +0000 |
commit | c6e113f5680538a551f79df3ab19b69aed628521 (patch) | |
tree | 481bad0ddb13bebf28c6adf95a0f0dd778677085 | |
parent | 0b6ce4cffe977387b9d578c97d4bbe4fbbb00468 (diff) |
added 'pure' function attribute - fixed indirect function calls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4469 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | tcg/tcg.c | 65 | ||||
-rw-r--r-- | tcg/tcg.h | 4 |
2 files changed, 46 insertions, 23 deletions
@@ -946,32 +946,51 @@ void tcg_liveness_analysis(TCGContext *s) def = &tcg_op_defs[op]; switch(op) { case INDEX_op_call: - nb_args = args[-1]; - args -= nb_args; - nb_iargs = args[0] & 0xffff; - nb_oargs = args[0] >> 16; - args++; + { + int call_flags; - /* output args are dead */ - for(i = 0; i < nb_oargs; i++) { - arg = args[i]; - dead_temps[arg] = 1; - } - - /* globals are live (they may be used by the call) */ - memset(dead_temps, 0, s->nb_globals); + nb_args = args[-1]; + args -= nb_args; + nb_iargs = args[0] & 0xffff; + nb_oargs = args[0] >> 16; + args++; + call_flags = args[nb_oargs + nb_iargs]; + + /* pure functions can be removed if their result is not + used */ + if (call_flags & TCG_CALL_PURE) { + for(i = 0; i < nb_oargs; i++) { + arg = args[i]; + if (!dead_temps[arg]) + goto do_not_remove_call; + } + tcg_set_nop(s, gen_opc_buf + op_index, + args - 1, nb_args); + } else { + do_not_remove_call: - /* input args are live */ - dead_iargs = 0; - for(i = 0; i < nb_iargs; i++) { - arg = args[i + nb_oargs]; - if (dead_temps[arg]) { - dead_iargs |= (1 << i); + /* output args are dead */ + for(i = 0; i < nb_oargs; i++) { + arg = args[i]; + dead_temps[arg] = 1; + } + + /* globals are live (they may be used by the call) */ + memset(dead_temps, 0, s->nb_globals); + + /* input args are live */ + dead_iargs = 0; + for(i = 0; i < nb_iargs; i++) { + arg = args[i + nb_oargs]; + if (dead_temps[arg]) { + dead_iargs |= (1 << i); + } + dead_temps[arg] = 0; + } + s->op_dead_iargs[op_index] = dead_iargs; } - dead_temps[arg] = 0; + args--; } - s->op_dead_iargs[op_index] = dead_iargs; - args--; break; case INDEX_op_set_label: args--; @@ -1640,7 +1659,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, } /* mark dead temporaries and free the associated registers */ - for(i = 0; i < nb_params; i++) { + for(i = 0; i < nb_iargs; i++) { arg = args[nb_oargs + i]; if (IS_DEAD_IARG(i)) { ts = &s->temps[arg]; @@ -148,6 +148,10 @@ typedef int TCGv; #define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */ #define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */ #define TCG_CALL_TYPE_REGPARM 0x0003 /* i386 style regparm call (3 regs) */ +/* A pure function only reads its arguments and globals variables and + cannot raise exceptions. Hence a call to a pure function can be + safely suppressed if the return value is not used. */ +#define TCG_CALL_PURE 0x0010 typedef enum { TCG_COND_EQ, |