aboutsummaryrefslogtreecommitdiff
path: root/tcg/optimize.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-08-04 23:24:04 +0000
committerRichard Henderson <richard.henderson@linaro.org>2023-08-24 11:22:42 -0700
commit3635502dd00bcfee3a6ab790d950c2fc4ace607b (patch)
treed3a3f2e187d586a23b33af696d3c24dd11a8a114 /tcg/optimize.c
parent13d885b0ad4ada4d216b0341de5ae4a9ce3f5abb (diff)
tcg: Introduce negsetcond opcodes
Introduce a new opcode for negative setcond. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'tcg/optimize.c')
-rw-r--r--tcg/optimize.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/tcg/optimize.c b/tcg/optimize.c
index bbd9bb64c6..3013eb04e6 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -1567,14 +1567,22 @@ static bool fold_movcond(OptContext *ctx, TCGOp *op)
if (arg_is_const(op->args[3]) && arg_is_const(op->args[4])) {
uint64_t tv = arg_info(op->args[3])->val;
uint64_t fv = arg_info(op->args[4])->val;
- TCGOpcode opc;
+ TCGOpcode opc, negopc = 0;
switch (ctx->type) {
case TCG_TYPE_I32:
opc = INDEX_op_setcond_i32;
+ if (TCG_TARGET_HAS_negsetcond_i32) {
+ negopc = INDEX_op_negsetcond_i32;
+ }
+ tv = (int32_t)tv;
+ fv = (int32_t)fv;
break;
case TCG_TYPE_I64:
opc = INDEX_op_setcond_i64;
+ if (TCG_TARGET_HAS_negsetcond_i64) {
+ negopc = INDEX_op_negsetcond_i64;
+ }
break;
default:
g_assert_not_reached();
@@ -1586,6 +1594,14 @@ static bool fold_movcond(OptContext *ctx, TCGOp *op)
} else if (fv == 1 && tv == 0) {
op->opc = opc;
op->args[3] = tcg_invert_cond(cond);
+ } else if (negopc) {
+ if (tv == -1 && fv == 0) {
+ op->opc = negopc;
+ op->args[3] = cond;
+ } else if (fv == -1 && tv == 0) {
+ op->opc = negopc;
+ op->args[3] = tcg_invert_cond(cond);
+ }
}
}
return false;
@@ -1796,6 +1812,26 @@ static bool fold_setcond(OptContext *ctx, TCGOp *op)
return false;
}
+static bool fold_negsetcond(OptContext *ctx, TCGOp *op)
+{
+ TCGCond cond = op->args[3];
+ 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);
+ }
+
+ /* Value is {0,-1} so all bits are repetitions of the sign. */
+ ctx->s_mask = -1;
+ return false;
+}
+
+
static bool fold_setcond2(OptContext *ctx, TCGOp *op)
{
TCGCond cond = op->args[5];
@@ -2253,6 +2289,9 @@ void tcg_optimize(TCGContext *s)
CASE_OP_32_64(setcond):
done = fold_setcond(&ctx, op);
break;
+ CASE_OP_32_64(negsetcond):
+ done = fold_negsetcond(&ctx, op);
+ break;
case INDEX_op_setcond2_i32:
done = fold_setcond2(&ctx, op);
break;