Reviewed-by: Matt Turner <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
---
tcg/optimize.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 65 insertions(+), 1 deletion(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 1e4d2a0a425..a7f45bdd541 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -2106,6 +2106,68 @@ static bool fold_extu(OptContext *ctx, TCGOp *op)
return fold_masks_zo(ctx, op, z_mask, o_mask);
}
+static bool fold_shift(OptContext *ctx, TCGOp *op);
+static bool fold_lea(OptContext *ctx, TCGOp *op)
+{
+ TCGArg sh = op->args[3];
+ TCGArg imm = op->args[4];
+ int var_mask = 0;
+
+ if (arg_is_const(op->args[1])) {
+ imm += arg_const_val(op->args[1]);
+ } else {
+ var_mask |= 1;
+ }
+ if (arg_is_const(op->args[2])) {
+ imm += arg_const_val(op->args[2]) << sh;
+ } else {
+ var_mask |= 2;
+ }
+
+ switch (var_mask) {
+ case 0:
+ return tcg_opt_gen_movi(ctx, op, op->args[0], imm);
+
+ case 1:
+ if (imm == 0) {
+ return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[1]);
+ }
+ op->opc = INDEX_op_add;
+ op->args[2] = arg_new_constant(ctx, imm);
+ break;
+
+ case 2:
+ if (sh == 0) {
+ if (imm == 0) {
+ return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[2]);
+ }
+ op->opc = INDEX_op_add;
+ op->args[1] = op->args[2];
+ op->args[2] = arg_new_constant(ctx, imm);
+ break;
+ }
+ if (imm == 0) {
+ op->opc = INDEX_op_shl;
+ op->args[1] = op->args[2];
+ op->args[2] = arg_new_constant(ctx, sh);
+ return fold_shift(ctx, op);
+ }
+
+ /* If arg1 was not already 0, fold the immediates. */
+ if (arg_const_val(op->args[1]) != 0) {
+ if (TCG_TARGET_lea_imm_valid(ctx->type, imm)) {
+ op->args[1] = arg_new_constant(ctx, 0);
+ op->args[4] = imm;
+ } else {
+ op->args[1] = arg_new_constant(ctx, imm);
+ op->args[4] = 0;
+ }
+ }
+ break;
+ }
+ return finish_folding(ctx, op);
+}
+
static bool fold_mb(OptContext *ctx, TCGOp *op)
{
/* Eliminate duplicate and redundant fence instructions. */
@@ -2218,7 +2280,6 @@ static bool fold_mul_highpart(OptContext *ctx, TCGOp *op)
return finish_folding(ctx, op);
}
-static bool fold_shift(OptContext *ctx, TCGOp *op);
static bool fold_multiply2(OptContext *ctx, TCGOp *op)
{
swap_commutative(op->args[0], &op->args[2], &op->args[3]);
@@ -3211,6 +3272,9 @@ void tcg_optimize(TCGContext *s)
case INDEX_op_st_vec:
done = fold_tcg_st_memcopy(&ctx, op);
break;
+ case INDEX_op_lea:
+ done = fold_lea(&ctx, op);
+ break;
case INDEX_op_mb:
done = fold_mb(&ctx, op);
break;
--
2.53.0