Do constant folding for basic arithmetic operations.
Perform actual constant folding for ADD, SUB and MUL operations. Signed-off-by: Kirill Batuzov <batuzovk@ispras.ru> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
22613af4a6
commit
53108fb574
125
tcg/optimize.c
125
tcg/optimize.c
@ -96,9 +96,15 @@ static int op_bits(int op)
|
|||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case INDEX_op_mov_i32:
|
case INDEX_op_mov_i32:
|
||||||
|
case INDEX_op_add_i32:
|
||||||
|
case INDEX_op_sub_i32:
|
||||||
|
case INDEX_op_mul_i32:
|
||||||
return 32;
|
return 32;
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
case INDEX_op_mov_i64:
|
case INDEX_op_mov_i64:
|
||||||
|
case INDEX_op_add_i64:
|
||||||
|
case INDEX_op_sub_i64:
|
||||||
|
case INDEX_op_mul_i64:
|
||||||
return 64;
|
return 64;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
@ -156,6 +162,52 @@ static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val,
|
|||||||
gen_args[1] = val;
|
gen_args[1] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int op_to_mov(int op)
|
||||||
|
{
|
||||||
|
switch (op_bits(op)) {
|
||||||
|
case 32:
|
||||||
|
return INDEX_op_mov_i32;
|
||||||
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
|
case 64:
|
||||||
|
return INDEX_op_mov_i64;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "op_to_mov: unexpected return value of "
|
||||||
|
"function op_bits.\n");
|
||||||
|
tcg_abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
CASE_OP_32_64(add):
|
||||||
|
return x + y;
|
||||||
|
|
||||||
|
CASE_OP_32_64(sub):
|
||||||
|
return x - y;
|
||||||
|
|
||||||
|
CASE_OP_32_64(mul):
|
||||||
|
return x * y;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr,
|
||||||
|
"Unrecognized operation %d in do_constant_folding.\n", op);
|
||||||
|
tcg_abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static TCGArg do_constant_folding(int op, TCGArg x, TCGArg y)
|
||||||
|
{
|
||||||
|
TCGArg res = do_constant_folding_2(op, x, y);
|
||||||
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
|
if (op_bits(op) == 32) {
|
||||||
|
res &= 0xffffffff;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* Propagate constants and copies, fold constant expressions. */
|
/* Propagate constants and copies, fold constant expressions. */
|
||||||
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||||
TCGArg *args, TCGOpDef *tcg_op_defs)
|
TCGArg *args, TCGOpDef *tcg_op_defs)
|
||||||
@ -163,6 +215,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
|||||||
int i, nb_ops, op_index, op, nb_temps, nb_globals, nb_call_args;
|
int i, nb_ops, op_index, op, nb_temps, nb_globals, nb_call_args;
|
||||||
const TCGOpDef *def;
|
const TCGOpDef *def;
|
||||||
TCGArg *gen_args;
|
TCGArg *gen_args;
|
||||||
|
TCGArg tmp;
|
||||||
/* Array VALS has an element for each temp.
|
/* Array VALS has an element for each temp.
|
||||||
If this temp holds a constant then its value is kept in VALS' element.
|
If this temp holds a constant then its value is kept in VALS' element.
|
||||||
If this temp is a copy of other ones then this equivalence class'
|
If this temp is a copy of other ones then this equivalence class'
|
||||||
@ -189,6 +242,57 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For commutative operations make constant second argument */
|
||||||
|
switch (op) {
|
||||||
|
CASE_OP_32_64(add):
|
||||||
|
CASE_OP_32_64(mul):
|
||||||
|
if (temps[args[1]].state == TCG_TEMP_CONST) {
|
||||||
|
tmp = args[1];
|
||||||
|
args[1] = args[2];
|
||||||
|
args[2] = tmp;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simplify expression if possible. */
|
||||||
|
switch (op) {
|
||||||
|
CASE_OP_32_64(add):
|
||||||
|
CASE_OP_32_64(sub):
|
||||||
|
if (temps[args[1]].state == TCG_TEMP_CONST) {
|
||||||
|
/* Proceed with possible constant folding. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (temps[args[2]].state == TCG_TEMP_CONST
|
||||||
|
&& temps[args[2]].val == 0) {
|
||||||
|
if ((temps[args[0]].state == TCG_TEMP_COPY
|
||||||
|
&& temps[args[0]].val == args[1])
|
||||||
|
|| args[0] == args[1]) {
|
||||||
|
args += 3;
|
||||||
|
gen_opc_buf[op_index] = INDEX_op_nop;
|
||||||
|
} else {
|
||||||
|
gen_opc_buf[op_index] = op_to_mov(op);
|
||||||
|
tcg_opt_gen_mov(gen_args, args[0], args[1],
|
||||||
|
nb_temps, nb_globals);
|
||||||
|
gen_args += 2;
|
||||||
|
args += 3;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
CASE_OP_32_64(mul):
|
||||||
|
if ((temps[args[2]].state == TCG_TEMP_CONST
|
||||||
|
&& temps[args[2]].val == 0)) {
|
||||||
|
gen_opc_buf[op_index] = op_to_movi(op);
|
||||||
|
tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals);
|
||||||
|
args += 3;
|
||||||
|
gen_args += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Propagate constants through copy operations and do constant
|
/* Propagate constants through copy operations and do constant
|
||||||
folding. Constants will be substituted to arguments by register
|
folding. Constants will be substituted to arguments by register
|
||||||
allocator where needed and possible. Also detect copies. */
|
allocator where needed and possible. Also detect copies. */
|
||||||
@ -219,6 +323,27 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
|||||||
gen_args += 2;
|
gen_args += 2;
|
||||||
args += 2;
|
args += 2;
|
||||||
break;
|
break;
|
||||||
|
CASE_OP_32_64(add):
|
||||||
|
CASE_OP_32_64(sub):
|
||||||
|
CASE_OP_32_64(mul):
|
||||||
|
if (temps[args[1]].state == TCG_TEMP_CONST
|
||||||
|
&& temps[args[2]].state == TCG_TEMP_CONST) {
|
||||||
|
gen_opc_buf[op_index] = op_to_movi(op);
|
||||||
|
tmp = do_constant_folding(op, temps[args[1]].val,
|
||||||
|
temps[args[2]].val);
|
||||||
|
tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
|
||||||
|
gen_args += 2;
|
||||||
|
args += 3;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
reset_temp(args[0], nb_temps, nb_globals);
|
||||||
|
gen_args[0] = args[0];
|
||||||
|
gen_args[1] = args[1];
|
||||||
|
gen_args[2] = args[2];
|
||||||
|
gen_args += 3;
|
||||||
|
args += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case INDEX_op_call:
|
case INDEX_op_call:
|
||||||
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
|
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
|
||||||
if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
|
if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user