[PATCH] tcg/optimize: Fix s_mask computation for shifts

Jacob Young <[email protected]> Tue, 04 Aug 2026 02:27:23 -0400
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
Previously, we would produce an incorrect smask in this case:

    t1.smask = 0xffffffff80000000
    shr_i32 t0,t1,$0x1
    t0.smask = 0xffffffffc0000000

because `do_constant_folding` would produce `smask = 0x40000000` which
was passed unchanged to `fold_masks_zos` which would then update with
`s_mask |= INT32_MIN;`, producing the incorrect result above.

Reproducer (i386 assembly):

        .text
        .globl  _start
    _start:
        movw    $0x4000, %ax
        addw    %ax, %ax
        cwtl
        shrl    %eax
        xorl    %ebx, %ebx
        cmpw    $-0x3fff, %ax
        setnl   %bl
        movl    $1, %eax
        int     $0x80

Signed-off-by: Jacob Young <[email protected]>
---
 tcg/optimize.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index fcdef25bee..96f7841afa 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -2658,6 +2658,14 @@ static bool fold_shift(OptContext *ctx, TCGOp *op)
         o_mask = do_constant_folding(op->opc, ctx->type, o_mask, sh);
         s_mask = do_constant_folding(op->opc, ctx->type, s_mask, sh);
 
+        /*
+         * If the bit shifted into the result sign was not in the
+         * input s_mask, then no bits are known to match it.
+         */
+        if ((int64_t)s_mask >= 0) {
+            s_mask = 0;
+        }
+
         return fold_masks_zos(ctx, op, z_mask, o_mask, s_mask);
     }
 

-- 
2.55.0