tcg/optimize: Sink commutative operand swapping into fold functions
Most of these are handled by creating a fold_const2_commutative to handle all of the binary operators. The rest were already handled on a case-by-case basis in the switch, and have their own fold function in which to place the call. We now have only one major switch on TCGOpcode. Introduce NO_DEST and a block comment for swap_commutative in order to make the handling of brcond and movcond opcodes cleaner. Reviewed-by: Luis Pires <luis.pires@eldorado.org.br> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
9531c078ff
commit
7a2f708452
142
tcg/optimize.c
142
tcg/optimize.c
@ -577,6 +577,19 @@ static int do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* swap_commutative:
|
||||
* @dest: TCGArg of the destination argument, or NO_DEST.
|
||||
* @p1: first paired argument
|
||||
* @p2: second paired argument
|
||||
*
|
||||
* If *@p1 is a constant and *@p2 is not, swap.
|
||||
* If *@p2 matches @dest, swap.
|
||||
* Return true if a swap was performed.
|
||||
*/
|
||||
|
||||
#define NO_DEST temp_arg(NULL)
|
||||
|
||||
static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2)
|
||||
{
|
||||
TCGArg a1 = *p1, a2 = *p2;
|
||||
@ -696,6 +709,12 @@ static bool fold_const2(OptContext *ctx, TCGOp *op)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool fold_const2_commutative(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
swap_commutative(op->args[0], &op->args[1], &op->args[2]);
|
||||
return fold_const2(ctx, op);
|
||||
}
|
||||
|
||||
static bool fold_masks(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
uint64_t a_mask = ctx->a_mask;
|
||||
@ -832,7 +851,7 @@ static bool fold_xx_to_x(OptContext *ctx, TCGOp *op)
|
||||
|
||||
static bool fold_add(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
if (fold_const2(ctx, op) ||
|
||||
if (fold_const2_commutative(ctx, op) ||
|
||||
fold_xi_to_x(ctx, op, 0)) {
|
||||
return true;
|
||||
}
|
||||
@ -891,6 +910,10 @@ static bool fold_addsub2(OptContext *ctx, TCGOp *op, bool add)
|
||||
|
||||
static bool fold_add2(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
/* Note that the high and low parts may be independently swapped. */
|
||||
swap_commutative(op->args[0], &op->args[2], &op->args[4]);
|
||||
swap_commutative(op->args[1], &op->args[3], &op->args[5]);
|
||||
|
||||
return fold_addsub2(ctx, op, true);
|
||||
}
|
||||
|
||||
@ -898,7 +921,7 @@ static bool fold_and(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
uint64_t z1, z2;
|
||||
|
||||
if (fold_const2(ctx, op) ||
|
||||
if (fold_const2_commutative(ctx, op) ||
|
||||
fold_xi_to_i(ctx, op, 0) ||
|
||||
fold_xi_to_x(ctx, op, -1) ||
|
||||
fold_xx_to_x(ctx, op)) {
|
||||
@ -950,8 +973,13 @@ static bool fold_andc(OptContext *ctx, TCGOp *op)
|
||||
static bool fold_brcond(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
TCGCond cond = op->args[2];
|
||||
int i = do_constant_folding_cond(ctx->type, op->args[0], op->args[1], cond);
|
||||
int i;
|
||||
|
||||
if (swap_commutative(NO_DEST, &op->args[0], &op->args[1])) {
|
||||
op->args[2] = cond = tcg_swap_cond(cond);
|
||||
}
|
||||
|
||||
i = do_constant_folding_cond(ctx->type, op->args[0], op->args[1], cond);
|
||||
if (i == 0) {
|
||||
tcg_op_remove(ctx->tcg, op);
|
||||
return true;
|
||||
@ -966,10 +994,14 @@ static bool fold_brcond(OptContext *ctx, TCGOp *op)
|
||||
static bool fold_brcond2(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
TCGCond cond = op->args[4];
|
||||
int i = do_constant_folding_cond2(&op->args[0], &op->args[2], cond);
|
||||
TCGArg label = op->args[5];
|
||||
int inv = 0;
|
||||
int i, inv = 0;
|
||||
|
||||
if (swap_commutative2(&op->args[0], &op->args[2])) {
|
||||
op->args[4] = cond = tcg_swap_cond(cond);
|
||||
}
|
||||
|
||||
i = do_constant_folding_cond2(&op->args[0], &op->args[2], cond);
|
||||
if (i >= 0) {
|
||||
goto do_brcond_const;
|
||||
}
|
||||
@ -1219,7 +1251,7 @@ static bool fold_dup2(OptContext *ctx, TCGOp *op)
|
||||
|
||||
static bool fold_eqv(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
if (fold_const2(ctx, op) ||
|
||||
if (fold_const2_commutative(ctx, op) ||
|
||||
fold_xi_to_x(ctx, op, -1) ||
|
||||
fold_xi_to_not(ctx, op, 0)) {
|
||||
return true;
|
||||
@ -1381,8 +1413,20 @@ static bool fold_mov(OptContext *ctx, TCGOp *op)
|
||||
static bool fold_movcond(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
TCGCond cond = op->args[5];
|
||||
int i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond);
|
||||
int i;
|
||||
|
||||
if (swap_commutative(NO_DEST, &op->args[1], &op->args[2])) {
|
||||
op->args[5] = cond = tcg_swap_cond(cond);
|
||||
}
|
||||
/*
|
||||
* Canonicalize the "false" input reg to match the destination reg so
|
||||
* that the tcg backend can implement a "move if true" operation.
|
||||
*/
|
||||
if (swap_commutative(op->args[0], &op->args[4], &op->args[3])) {
|
||||
op->args[5] = cond = tcg_invert_cond(cond);
|
||||
}
|
||||
|
||||
i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond);
|
||||
if (i >= 0) {
|
||||
return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[4 - i]);
|
||||
}
|
||||
@ -1428,7 +1472,7 @@ static bool fold_mul(OptContext *ctx, TCGOp *op)
|
||||
|
||||
static bool fold_mul_highpart(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
if (fold_const2(ctx, op) ||
|
||||
if (fold_const2_commutative(ctx, op) ||
|
||||
fold_xi_to_i(ctx, op, 0)) {
|
||||
return true;
|
||||
}
|
||||
@ -1437,6 +1481,8 @@ static bool fold_mul_highpart(OptContext *ctx, TCGOp *op)
|
||||
|
||||
static bool fold_multiply2(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
swap_commutative(op->args[0], &op->args[2], &op->args[3]);
|
||||
|
||||
if (arg_is_const(op->args[2]) && arg_is_const(op->args[3])) {
|
||||
uint64_t a = arg_info(op->args[2])->val;
|
||||
uint64_t b = arg_info(op->args[3])->val;
|
||||
@ -1480,7 +1526,7 @@ static bool fold_multiply2(OptContext *ctx, TCGOp *op)
|
||||
|
||||
static bool fold_nand(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
if (fold_const2(ctx, op) ||
|
||||
if (fold_const2_commutative(ctx, op) ||
|
||||
fold_xi_to_not(ctx, op, -1)) {
|
||||
return true;
|
||||
}
|
||||
@ -1509,7 +1555,7 @@ static bool fold_neg(OptContext *ctx, TCGOp *op)
|
||||
|
||||
static bool fold_nor(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
if (fold_const2(ctx, op) ||
|
||||
if (fold_const2_commutative(ctx, op) ||
|
||||
fold_xi_to_not(ctx, op, 0)) {
|
||||
return true;
|
||||
}
|
||||
@ -1529,7 +1575,7 @@ static bool fold_not(OptContext *ctx, TCGOp *op)
|
||||
|
||||
static bool fold_or(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
if (fold_const2(ctx, op) ||
|
||||
if (fold_const2_commutative(ctx, op) ||
|
||||
fold_xi_to_x(ctx, op, 0) ||
|
||||
fold_xx_to_x(ctx, op)) {
|
||||
return true;
|
||||
@ -1581,8 +1627,13 @@ static bool fold_remainder(OptContext *ctx, TCGOp *op)
|
||||
static bool fold_setcond(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
TCGCond cond = op->args[3];
|
||||
int i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond);
|
||||
int i;
|
||||
|
||||
if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) {
|
||||
op->args[3] = cond = tcg_swap_cond(cond);
|
||||
}
|
||||
|
||||
i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond);
|
||||
if (i >= 0) {
|
||||
return tcg_opt_gen_movi(ctx, op, op->args[0], i);
|
||||
}
|
||||
@ -1594,9 +1645,13 @@ static bool fold_setcond(OptContext *ctx, TCGOp *op)
|
||||
static bool fold_setcond2(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
TCGCond cond = op->args[5];
|
||||
int i = do_constant_folding_cond2(&op->args[1], &op->args[3], cond);
|
||||
int inv = 0;
|
||||
int i, inv = 0;
|
||||
|
||||
if (swap_commutative2(&op->args[1], &op->args[3])) {
|
||||
op->args[5] = cond = tcg_swap_cond(cond);
|
||||
}
|
||||
|
||||
i = do_constant_folding_cond2(&op->args[1], &op->args[3], cond);
|
||||
if (i >= 0) {
|
||||
goto do_setcond_const;
|
||||
}
|
||||
@ -1774,7 +1829,7 @@ static bool fold_tcg_ld(OptContext *ctx, TCGOp *op)
|
||||
|
||||
static bool fold_xor(OptContext *ctx, TCGOp *op)
|
||||
{
|
||||
if (fold_const2(ctx, op) ||
|
||||
if (fold_const2_commutative(ctx, op) ||
|
||||
fold_xx_to_i(ctx, op, 0) ||
|
||||
fold_xi_to_x(ctx, op, 0) ||
|
||||
fold_xi_to_not(ctx, op, -1)) {
|
||||
@ -1827,63 +1882,6 @@ void tcg_optimize(TCGContext *s)
|
||||
ctx.type = TCG_TYPE_I32;
|
||||
}
|
||||
|
||||
/* For commutative operations make constant second argument */
|
||||
switch (opc) {
|
||||
CASE_OP_32_64_VEC(add):
|
||||
CASE_OP_32_64_VEC(mul):
|
||||
CASE_OP_32_64_VEC(and):
|
||||
CASE_OP_32_64_VEC(or):
|
||||
CASE_OP_32_64_VEC(xor):
|
||||
CASE_OP_32_64(eqv):
|
||||
CASE_OP_32_64(nand):
|
||||
CASE_OP_32_64(nor):
|
||||
CASE_OP_32_64(muluh):
|
||||
CASE_OP_32_64(mulsh):
|
||||
swap_commutative(op->args[0], &op->args[1], &op->args[2]);
|
||||
break;
|
||||
CASE_OP_32_64(brcond):
|
||||
if (swap_commutative(-1, &op->args[0], &op->args[1])) {
|
||||
op->args[2] = tcg_swap_cond(op->args[2]);
|
||||
}
|
||||
break;
|
||||
CASE_OP_32_64(setcond):
|
||||
if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) {
|
||||
op->args[3] = tcg_swap_cond(op->args[3]);
|
||||
}
|
||||
break;
|
||||
CASE_OP_32_64(movcond):
|
||||
if (swap_commutative(-1, &op->args[1], &op->args[2])) {
|
||||
op->args[5] = tcg_swap_cond(op->args[5]);
|
||||
}
|
||||
/* For movcond, we canonicalize the "false" input reg to match
|
||||
the destination reg so that the tcg backend can implement
|
||||
a "move if true" operation. */
|
||||
if (swap_commutative(op->args[0], &op->args[4], &op->args[3])) {
|
||||
op->args[5] = tcg_invert_cond(op->args[5]);
|
||||
}
|
||||
break;
|
||||
CASE_OP_32_64(add2):
|
||||
swap_commutative(op->args[0], &op->args[2], &op->args[4]);
|
||||
swap_commutative(op->args[1], &op->args[3], &op->args[5]);
|
||||
break;
|
||||
CASE_OP_32_64(mulu2):
|
||||
CASE_OP_32_64(muls2):
|
||||
swap_commutative(op->args[0], &op->args[2], &op->args[3]);
|
||||
break;
|
||||
case INDEX_op_brcond2_i32:
|
||||
if (swap_commutative2(&op->args[0], &op->args[2])) {
|
||||
op->args[4] = tcg_swap_cond(op->args[4]);
|
||||
}
|
||||
break;
|
||||
case INDEX_op_setcond2_i32:
|
||||
if (swap_commutative2(&op->args[1], &op->args[3])) {
|
||||
op->args[5] = tcg_swap_cond(op->args[5]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Assume all bits affected, and no bits known zero. */
|
||||
ctx.a_mask = -1;
|
||||
ctx.z_mask = -1;
|
||||
|
Loading…
Reference in New Issue
Block a user