tcg/optimize: Handle min/max opcodes Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/tcg/optimize.c b/tcg/optimize.c index facf4c1..d291c84 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c
@@ -597,6 +597,30 @@ } return (uint64_t)x % ((uint64_t)y ? : 1); + case INDEX_op_smax: + if (type == TCG_TYPE_I32) { + return MAX((int32_t)x, (int32_t)y); + } + return MAX((int64_t)x, (int64_t)y); + + case INDEX_op_smin: + if (type == TCG_TYPE_I32) { + return MIN((int32_t)x, (int32_t)y); + } + return MIN((int64_t)x, (int64_t)y); + + case INDEX_op_umax: + if (type == TCG_TYPE_I32) { + return MAX((uint32_t)x, (uint32_t)y); + } + return MAX((uint64_t)x, (uint64_t)y); + + case INDEX_op_umin: + if (type == TCG_TYPE_I32) { + return MIN((uint32_t)x, (uint32_t)y); + } + return MIN((uint64_t)x, (uint64_t)y); + default: g_assert_not_reached(); } @@ -2101,6 +2125,16 @@ return true; } +static bool fold_minmax(OptContext *ctx, TCGOp *op, uint64_t bound) +{ + if (fold_const2_commutative(ctx, op) || + fold_xi_to_i(ctx, op, bound) || + fold_xx_to_x(ctx, op)) { + return true; + } + return finish_folding(ctx, op); +} + static bool fold_mov(OptContext *ctx, TCGOp *op) { return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[1]); @@ -3258,6 +3292,14 @@ case INDEX_op_sextract: done = fold_sextract(&ctx, op); break; + case INDEX_op_smax: + done = fold_minmax(&ctx, op, (ctx.type == TCG_TYPE_I32 + ? INT32_MAX : INT64_MAX)); + break; + case INDEX_op_smin: + done = fold_minmax(&ctx, op, (ctx.type == TCG_TYPE_I32 + ? INT32_MIN : INT64_MIN)); + break; case INDEX_op_sub: done = fold_sub(&ctx, op); break; @@ -3273,6 +3315,16 @@ case INDEX_op_sub_vec: done = fold_sub_vec(&ctx, op); break; + case INDEX_op_umax: + /* + * Note that 32-bit constants are stored sign extended, + * so (int32_t)UINT32_MAX == -1. + */ + done = fold_minmax(&ctx, op, -1); + break; + case INDEX_op_umin: + done = fold_minmax(&ctx, op, 0); + break; case INDEX_op_xor: case INDEX_op_xor_vec: done = fold_xor(&ctx, op);