@samitouri / QOSamiQemu / commits / 744eb39667

tcg/optimize: possibly expand deposit into zero with shifts

Use tcg_op_imm_match to choose between expanding with AND+SHL vs SHL+SHR. Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-ID: <20260303010833.1115741-8-richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

Richard Henderson committed Feb 3, 2026 at 15:51 UTC 744eb39667b6d562fa68cd63c6600779f717df40
1 file changed +30 -6
tcg/optimize.c
+30 -6
@@ -1743,14 +1743,38 @@ static bool fold_deposit(OptContext *ctx, TCGOp *op)
1743 goto done;
1744 }
1745
1746 - /* Lower invalid deposit into zero as AND + SHL. */
1746 + /* Lower invalid deposit into zero as AND + SHL or SHL + SHR. */
1747 if (!valid) {
1748 - op2 = opt_insert_before(ctx, op, INDEX_op_and, 3);
1749 - op2->args[0] = ret;
1750 - op2->args[1] = arg2;
1751 - op2->args[2] = arg_new_constant(ctx, len_mask);
1752 - fold_and(ctx, op2);
1748 + if (TCG_TARGET_extract_valid(ctx->type, 0, len)) {
1749 + /* EXTRACT (at 0) + SHL */
1750 + op2 = opt_insert_before(ctx, op, INDEX_op_extract, 4);
1751 + op2->args[0] = ret;
1752 + op2->args[1] = arg2;
1753 + op2->args[2] = 0;
1754 + op2->args[3] = len;
1755 + } else if (tcg_op_imm_match(INDEX_op_and, ctx->type, len_mask)) {
1756 + /* AND + SHL */
1757 + op2 = opt_insert_before(ctx, op, INDEX_op_and, 3);
1758 + op2->args[0] = ret;
1759 + op2->args[1] = arg2;
1760 + op2->args[2] = arg_new_constant(ctx, len_mask);
1761 + } else {
1762 + /* SHL + SHR */
1763 + int shl = width - len;
1764 + int shr = width - len - ofs;
1765 +
1766 + op2 = opt_insert_before(ctx, op, INDEX_op_shl, 3);
1767 + op2->args[0] = ret;
1768 + op2->args[1] = arg2;
1769 + op2->args[2] = arg_new_constant(ctx, shl);
1770 +
1771 + op->opc = INDEX_op_shr;
1772 + op->args[1] = ret;
1773 + op->args[2] = arg_new_constant(ctx, shr);
1774 + goto done;
1775 + }
1776
1777 + /* Finish the (EXTRACT|AND) + SHL cases. */
1778 op->opc = INDEX_op_shl;
1779 op->args[1] = ret;
1780 op->args[2] = arg_new_constant(ctx, ofs);