Revision 866cb6cb tcg/tcg.c
b/tcg/tcg.c | ||
---|---|---|
1193 | 1193 |
} |
1194 | 1194 |
} |
1195 | 1195 |
|
1196 |
/* Liveness analysis : update the opc_dead_iargs array to tell if a
|
|
1196 |
/* Liveness analysis : update the opc_dead_args array to tell if a |
|
1197 | 1197 |
given input arguments is dead. Instructions updating dead |
1198 | 1198 |
temporaries are removed. */ |
1199 | 1199 |
static void tcg_liveness_analysis(TCGContext *s) |
... | ... | |
1203 | 1203 |
TCGArg *args; |
1204 | 1204 |
const TCGOpDef *def; |
1205 | 1205 |
uint8_t *dead_temps; |
1206 |
unsigned int dead_iargs;
|
|
1206 |
unsigned int dead_args; |
|
1207 | 1207 |
|
1208 | 1208 |
gen_opc_ptr++; /* skip end */ |
1209 | 1209 |
|
1210 | 1210 |
nb_ops = gen_opc_ptr - gen_opc_buf; |
1211 | 1211 |
|
1212 |
s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
|
|
1212 |
s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t)); |
|
1213 | 1213 |
|
1214 | 1214 |
dead_temps = tcg_malloc(s->nb_temps); |
1215 | 1215 |
memset(dead_temps, 1, s->nb_temps); |
... | ... | |
1256 | 1256 |
} |
1257 | 1257 |
|
1258 | 1258 |
/* input args are live */ |
1259 |
dead_iargs = 0;
|
|
1260 |
for(i = 0; i < nb_iargs; i++) {
|
|
1261 |
arg = args[i + nb_oargs];
|
|
1259 |
dead_args = 0; |
|
1260 |
for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
|
|
1261 |
arg = args[i]; |
|
1262 | 1262 |
if (arg != TCG_CALL_DUMMY_ARG) { |
1263 | 1263 |
if (dead_temps[arg]) { |
1264 |
dead_iargs |= (1 << i);
|
|
1264 |
dead_args |= (1 << i); |
|
1265 | 1265 |
} |
1266 | 1266 |
dead_temps[arg] = 0; |
1267 | 1267 |
} |
1268 | 1268 |
} |
1269 |
s->op_dead_iargs[op_index] = dead_iargs;
|
|
1269 |
s->op_dead_args[op_index] = dead_args;
|
|
1270 | 1270 |
} |
1271 | 1271 |
args--; |
1272 | 1272 |
} |
... | ... | |
1327 | 1327 |
} |
1328 | 1328 |
|
1329 | 1329 |
/* input args are live */ |
1330 |
dead_iargs = 0;
|
|
1331 |
for(i = 0; i < nb_iargs; i++) {
|
|
1332 |
arg = args[i + nb_oargs];
|
|
1330 |
dead_args = 0; |
|
1331 |
for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
|
|
1332 |
arg = args[i]; |
|
1333 | 1333 |
if (dead_temps[arg]) { |
1334 |
dead_iargs |= (1 << i);
|
|
1334 |
dead_args |= (1 << i); |
|
1335 | 1335 |
} |
1336 | 1336 |
dead_temps[arg] = 0; |
1337 | 1337 |
} |
1338 |
s->op_dead_iargs[op_index] = dead_iargs;
|
|
1338 |
s->op_dead_args[op_index] = dead_args;
|
|
1339 | 1339 |
} |
1340 | 1340 |
break; |
1341 | 1341 |
} |
... | ... | |
1352 | 1352 |
int nb_ops; |
1353 | 1353 |
nb_ops = gen_opc_ptr - gen_opc_buf; |
1354 | 1354 |
|
1355 |
s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
|
|
1356 |
memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
|
|
1355 |
s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t)); |
|
1356 |
memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t)); |
|
1357 | 1357 |
} |
1358 | 1358 |
#endif |
1359 | 1359 |
|
... | ... | |
1557 | 1557 |
save_globals(s, allocated_regs); |
1558 | 1558 |
} |
1559 | 1559 |
|
1560 |
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
|
|
1560 |
#define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
|
|
1561 | 1561 |
|
1562 | 1562 |
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args) |
1563 | 1563 |
{ |
... | ... | |
1582 | 1582 |
|
1583 | 1583 |
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, |
1584 | 1584 |
const TCGArg *args, |
1585 |
unsigned int dead_iargs)
|
|
1585 |
unsigned int dead_args) |
|
1586 | 1586 |
{ |
1587 | 1587 |
TCGTemp *ts, *ots; |
1588 | 1588 |
int reg; |
... | ... | |
1592 | 1592 |
ts = &s->temps[args[1]]; |
1593 | 1593 |
arg_ct = &def->args_ct[0]; |
1594 | 1594 |
|
1595 |
/* XXX: always mark arg dead if IS_DEAD_IARG(0) */
|
|
1595 |
/* XXX: always mark arg dead if IS_DEAD_ARG(1) */
|
|
1596 | 1596 |
if (ts->val_type == TEMP_VAL_REG) { |
1597 |
if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
|
|
1597 |
if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
|
|
1598 | 1598 |
/* the mov can be suppressed */ |
1599 | 1599 |
if (ots->val_type == TEMP_VAL_REG) |
1600 | 1600 |
s->reg_to_temp[ots->reg] = -1; |
... | ... | |
1642 | 1642 |
static void tcg_reg_alloc_op(TCGContext *s, |
1643 | 1643 |
const TCGOpDef *def, TCGOpcode opc, |
1644 | 1644 |
const TCGArg *args, |
1645 |
unsigned int dead_iargs)
|
|
1645 |
unsigned int dead_args) |
|
1646 | 1646 |
{ |
1647 | 1647 |
TCGRegSet allocated_regs; |
1648 | 1648 |
int i, k, nb_iargs, nb_oargs, reg; |
... | ... | |
1701 | 1701 |
/* if the input is aliased to an output and if it is |
1702 | 1702 |
not dead after the instruction, we must allocate |
1703 | 1703 |
a new register and move it */ |
1704 |
if (!IS_DEAD_IARG(i - nb_oargs))
|
|
1704 |
if (!IS_DEAD_ARG(i)) {
|
|
1705 | 1705 |
goto allocate_in_reg; |
1706 |
} |
|
1706 | 1707 |
} |
1707 | 1708 |
} |
1708 | 1709 |
reg = ts->reg; |
... | ... | |
1725 | 1726 |
tcg_reg_alloc_bb_end(s, allocated_regs); |
1726 | 1727 |
} else { |
1727 | 1728 |
/* mark dead temporaries and free the associated registers */ |
1728 |
for(i = 0; i < nb_iargs; i++) {
|
|
1729 |
arg = args[nb_oargs + i];
|
|
1730 |
if (IS_DEAD_IARG(i)) {
|
|
1729 |
for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
|
|
1730 |
arg = args[i]; |
|
1731 |
if (IS_DEAD_ARG(i)) { |
|
1731 | 1732 |
ts = &s->temps[arg]; |
1732 | 1733 |
if (!ts->fixed_reg) { |
1733 | 1734 |
if (ts->val_type == TEMP_VAL_REG) |
... | ... | |
1808 | 1809 |
|
1809 | 1810 |
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, |
1810 | 1811 |
TCGOpcode opc, const TCGArg *args, |
1811 |
unsigned int dead_iargs)
|
|
1812 |
unsigned int dead_args) |
|
1812 | 1813 |
{ |
1813 | 1814 |
int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params; |
1814 | 1815 |
TCGArg arg, func_arg; |
... | ... | |
1930 | 1931 |
|
1931 | 1932 |
|
1932 | 1933 |
/* mark dead temporaries and free the associated registers */ |
1933 |
for(i = 0; i < nb_iargs; i++) {
|
|
1934 |
arg = args[nb_oargs + i];
|
|
1935 |
if (IS_DEAD_IARG(i)) {
|
|
1934 |
for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
|
|
1935 |
arg = args[i]; |
|
1936 |
if (IS_DEAD_ARG(i)) { |
|
1936 | 1937 |
ts = &s->temps[arg]; |
1937 | 1938 |
if (!ts->fixed_reg) { |
1938 | 1939 |
if (ts->val_type == TEMP_VAL_REG) |
... | ... | |
2007 | 2008 |
TCGOpcode opc; |
2008 | 2009 |
int op_index; |
2009 | 2010 |
const TCGOpDef *def; |
2010 |
unsigned int dead_iargs;
|
|
2011 |
unsigned int dead_args; |
|
2011 | 2012 |
const TCGArg *args; |
2012 | 2013 |
|
2013 | 2014 |
#ifdef DEBUG_DISAS |
... | ... | |
2058 | 2059 |
#if TCG_TARGET_REG_BITS == 64 |
2059 | 2060 |
case INDEX_op_mov_i64: |
2060 | 2061 |
#endif |
2061 |
dead_iargs = s->op_dead_iargs[op_index];
|
|
2062 |
tcg_reg_alloc_mov(s, def, args, dead_iargs);
|
|
2062 |
dead_args = s->op_dead_args[op_index];
|
|
2063 |
tcg_reg_alloc_mov(s, def, args, dead_args); |
|
2063 | 2064 |
break; |
2064 | 2065 |
case INDEX_op_movi_i32: |
2065 | 2066 |
#if TCG_TARGET_REG_BITS == 64 |
... | ... | |
2095 | 2096 |
tcg_out_label(s, args[0], (long)s->code_ptr); |
2096 | 2097 |
break; |
2097 | 2098 |
case INDEX_op_call: |
2098 |
dead_iargs = s->op_dead_iargs[op_index];
|
|
2099 |
args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
|
|
2099 |
dead_args = s->op_dead_args[op_index];
|
|
2100 |
args += tcg_reg_alloc_call(s, def, opc, args, dead_args); |
|
2100 | 2101 |
goto next; |
2101 | 2102 |
case INDEX_op_end: |
2102 | 2103 |
goto the_end; |
... | ... | |
2104 | 2105 |
/* Note: in order to speed up the code, it would be much |
2105 | 2106 |
faster to have specialized register allocator functions for |
2106 | 2107 |
some common argument patterns */ |
2107 |
dead_iargs = s->op_dead_iargs[op_index];
|
|
2108 |
tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
|
|
2108 |
dead_args = s->op_dead_args[op_index];
|
|
2109 |
tcg_reg_alloc_op(s, def, opc, args, dead_args); |
|
2109 | 2110 |
break; |
2110 | 2111 |
} |
2111 | 2112 |
args += def->nb_args; |
Also available in: Unified diff