mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 03:43:37 +08:00
added 'pure' function attribute - fixed indirect function calls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4469 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
0b6ce4cffe
commit
c6e113f568
65
tcg/tcg.c
65
tcg/tcg.c
@ -946,32 +946,51 @@ void tcg_liveness_analysis(TCGContext *s)
|
|||||||
def = &tcg_op_defs[op];
|
def = &tcg_op_defs[op];
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case INDEX_op_call:
|
case INDEX_op_call:
|
||||||
nb_args = args[-1];
|
{
|
||||||
args -= nb_args;
|
int call_flags;
|
||||||
nb_iargs = args[0] & 0xffff;
|
|
||||||
nb_oargs = args[0] >> 16;
|
|
||||||
args++;
|
|
||||||
|
|
||||||
/* output args are dead */
|
nb_args = args[-1];
|
||||||
for(i = 0; i < nb_oargs; i++) {
|
args -= nb_args;
|
||||||
arg = args[i];
|
nb_iargs = args[0] & 0xffff;
|
||||||
dead_temps[arg] = 1;
|
nb_oargs = args[0] >> 16;
|
||||||
}
|
args++;
|
||||||
|
call_flags = args[nb_oargs + nb_iargs];
|
||||||
/* globals are live (they may be used by the call) */
|
|
||||||
memset(dead_temps, 0, s->nb_globals);
|
|
||||||
|
|
||||||
/* input args are live */
|
/* pure functions can be removed if their result is not
|
||||||
dead_iargs = 0;
|
used */
|
||||||
for(i = 0; i < nb_iargs; i++) {
|
if (call_flags & TCG_CALL_PURE) {
|
||||||
arg = args[i + nb_oargs];
|
for(i = 0; i < nb_oargs; i++) {
|
||||||
if (dead_temps[arg]) {
|
arg = args[i];
|
||||||
dead_iargs |= (1 << 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:
|
||||||
|
|
||||||
|
/* 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;
|
break;
|
||||||
case INDEX_op_set_label:
|
case INDEX_op_set_label:
|
||||||
args--;
|
args--;
|
||||||
@ -1640,7 +1659,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mark dead temporaries and free the associated registers */
|
/* 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];
|
arg = args[nb_oargs + i];
|
||||||
if (IS_DEAD_IARG(i)) {
|
if (IS_DEAD_IARG(i)) {
|
||||||
ts = &s->temps[arg];
|
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_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_2 0x0002 /* i386 style regparm call (2 regs) */
|
||||||
#define TCG_CALL_TYPE_REGPARM 0x0003 /* i386 style regparm call (3 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 {
|
typedef enum {
|
||||||
TCG_COND_EQ,
|
TCG_COND_EQ,
|
||||||
|
Loading…
Reference in New Issue
Block a user