Commit 0bc331d1c7 for qemu.org

commit 0bc331d1c7d5cedc1dbe0bf21dc5f6be13c58fa4
Author: Richard Henderson <richard.henderson@linaro.org>
Date:   Wed Sep 16 01:47:05 2026 -1000

    tcg/optimize: Fix expansion/simplification of deposit

    When we computed z_mask/o_mask for the deposit, we may accidentally
    prove that the result is a constant.

    If we let the rest of the code expand as-is, when can we get to the
    end we'll see the constant, note that it's the same as the current
    value, remove what we think is "the opcode" that computes this same
    value.  But in this case we've been expanding deposit to multiple
    opcodes and the removal of only the last opcode breaks the expansion.

    Fix this by noting the constant result early, before expanding,
    allowing the entire operation to be removed.

    Cc: qemu-stable@nongnu.org
    Fixes: 5f747705a4 ("tcg/optimize: Lower unsupported deposit during optimize")
    Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4449
    Reviewed-by: Jim MacArthur <jim.macarthur@linaro.org>
    Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

diff --git a/tcg/optimize.c b/tcg/optimize.c
index bd91220650..1e4d2a0a42 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -1708,6 +1708,23 @@ static bool fold_deposit(OptContext *ctx, TCGOp *op)
     type_mask = MAKE_64BIT_MASK(0, width);
     len_mask = MAKE_64BIT_MASK(0, len);

+    /*
+     * Compute result masks before calling other fold_* subroutines
+     * which could modify the masks of our inputs.
+     */
+    z_mask = deposit64(t1->z_mask, ofs, len, t2->z_mask);
+    o_mask = deposit64(t1->o_mask, ofs, len, t2->o_mask);
+    if (ofs + len < width) {
+        s_mask = t1->s_mask & ~MAKE_64BIT_MASK(0, ofs + len);
+    } else {
+        s_mask = t2->s_mask << ofs;
+    }
+
+    /* Sometimes we prove a constant from non-constants. */
+    if (z_mask == o_mask) {
+        return tcg_opt_gen_movi(ctx, op, op->args[0], z_mask);
+    }
+
     /* Inserting all-zero into a value. */
     if ((t2->z_mask & len_mask) == 0) {
         op->opc = INDEX_op_and;
@@ -1740,18 +1757,6 @@ static bool fold_deposit(OptContext *ctx, TCGOp *op)
         return fold_or(ctx, op);
     }

-    /*
-     * Compute result masks before calling other fold_* subroutines
-     * which could modify the masks of our inputs.
-     */
-    z_mask = deposit64(t1->z_mask, ofs, len, t2->z_mask);
-    o_mask = deposit64(t1->o_mask, ofs, len, t2->o_mask);
-    if (ofs + len < width) {
-        s_mask = t1->s_mask & ~MAKE_64BIT_MASK(0, ofs + len);
-    } else {
-        s_mask = t2->s_mask << ofs;
-    }
-
     /* Inserting a value into zero. */
     if (ti_is_const_val(t1, 0)) {
         uint64_t need_mask;