From: Florian Krohm Date: Thu, 31 Jul 2025 20:56:34 +0000 (+0000) Subject: x86 specific changes for BZ 507033 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=42bff04db954b8a214334ad67256c32e88ddc7cf;p=thirdparty%2Fvalgrind.git x86 specific changes for BZ 507033 Rework code to use Iop_ClzNat32 instead of the deprecated Iop_Clz32. Likewise for Iop_Ctz32. Part of fixing https://bugs.kde.org/show_bug.cgi?id=507033 --- diff --git a/VEX/priv/guest_x86_toIR.c b/VEX/priv/guest_x86_toIR.c index 7b31bd769..11617914d 100644 --- a/VEX/priv/guest_x86_toIR.c +++ b/VEX/priv/guest_x86_toIR.c @@ -3418,14 +3418,14 @@ static IRTemp gen_LZCNT ( IRType ty, IRTemp src ) binop(Iop_Shl32, mkexpr(src32), mkU8(32 - 8 * sizeofIRType(ty)))); - // Clz32 has undefined semantics when its input is zero, so - // special-case around that. + /* Guard against 0 input value. Use ClzNat32 operator for all other + values */ IRTemp res32 = newTemp(Ity_I32); assign(res32, IRExpr_ITE( binop(Iop_CmpEQ32, mkexpr(src32x), mkU32(0)), mkU32(8 * sizeofIRType(ty)), - unop(Iop_Clz32, mkexpr(src32x)) + unop(Iop_ClzNat32, mkexpr(src32x)) )); IRTemp res = newTemp(ty); @@ -6512,18 +6512,16 @@ UInt dis_bs_E_G ( UChar sorb, Int sz, Int delta, Bool fwds ) elimination of previous stores to this field work better. */ stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) )); - /* Result: iff source value is zero, we can't use - Iop_Clz32/Iop_Ctz32 as they have no defined result in that case. - But anyway, Intel x86 semantics say the result is undefined in - such situations. Hence handle the zero case specially. */ + /* Intel x86 semantics say the result is undefined iff source value is + zero. Hence handle the zero case specially. */ /* Bleh. What we compute: - bsf32: if src == 0 then 0 else Ctz32(src) - bsr32: if src == 0 then 0 else 31 - Clz32(src) + bsf32: if src == 0 then 0 else CtzNat32(src) + bsr32: if src == 0 then 0 else 31 - ClzNat32(src) - bsf16: if src == 0 then 0 else Ctz32(16Uto32(src)) - bsr16: if src == 0 then 0 else 31 - Clz32(16Uto32(src)) + bsf16: if src == 0 then 0 else CtzNat32(16Uto32(src)) + bsr16: if src == 0 then 0 else 31 - ClzNat32(16Uto32(src)) First, widen src to 32 bits if it is not already. @@ -6540,10 +6538,10 @@ UInt dis_bs_E_G ( UChar sorb, Int sz, Int delta, Bool fwds ) IRExpr_ITE( mkexpr(srcB), /* src != 0 */ - fwds ? unop(Iop_Ctz32, mkexpr(src32)) + fwds ? unop(Iop_CtzNat32, mkexpr(src32)) : binop(Iop_Sub32, mkU32(31), - unop(Iop_Clz32, mkexpr(src32))), + unop(Iop_ClzNat32, mkexpr(src32))), /* src == 0 -- leave dst unchanged */ widenUto32( getIReg( sz, gregOfRM(modrm) ) ) ) diff --git a/VEX/priv/host_x86_isel.c b/VEX/priv/host_x86_isel.c index e89b14532..d35df8fc4 100644 --- a/VEX/priv/host_x86_isel.c +++ b/VEX/priv/host_x86_isel.c @@ -1306,14 +1306,14 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, const IRExpr* e ) addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, dst)); return dst; } - case Iop_Ctz32: { + case Iop_CtzNat32: { /* Count trailing zeroes, implemented by x86 'bsfl' */ HReg dst = newVRegI(env); HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); addInstr(env, X86Instr_Bsfr32(True,src,dst)); return dst; } - case Iop_Clz32: { + case Iop_ClzNat32: { /* Count leading zeroes. Do 'bsrl' to establish the index of the highest set bit, and subtract that value from 31. */ diff --git a/memcheck/tests/vbit-test/irops.c b/memcheck/tests/vbit-test/irops.c index 1794191a7..e104c18ac 100644 --- a/memcheck/tests/vbit-test/irops.c +++ b/memcheck/tests/vbit-test/irops.c @@ -109,13 +109,13 @@ static irop_t irops[] = { { DEFOP(Iop_MullU32, UNDEF_LEFT), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 1, .ppc64 = 1, .ppc32 = 1, .mips32 =0, .mips64 = 1 }, // mips asserts { DEFOP(Iop_MullU64, UNDEF_LEFT), .s390x = 1, .amd64 = 1, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 0, .mips32 =0, .mips64 = 1 }, // ppc32, mips assert { DEFOP(Iop_Clz64, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 0, .mips32 =0, .mips64 = 1 }, // ppc32 asserts - { DEFOP(Iop_Clz32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 1, .arm = 1, .ppc64 = 1, .ppc32 = 1, .mips32 =1, .mips64 = 1 }, + { DEFOP(Iop_Clz32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 1, .ppc64 = 1, .ppc32 = 1, .mips32 =1, .mips64 = 1 }, { DEFOP(Iop_Ctz64, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 =0, .mips64 = 0 }, - { DEFOP(Iop_Ctz32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 =0, .mips64 = 0 }, + { DEFOP(Iop_Ctz32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 =0, .mips64 = 0 }, { DEFOP(Iop_ClzNat64, UNDEF_ALL), .s390x = 1, .amd64 = 1, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 0, .mips32 =0, .mips64 = 0 }, // ppc32 asserts - { DEFOP(Iop_ClzNat32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 =0, .mips64 = 0 }, + { DEFOP(Iop_ClzNat32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 1, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 =0, .mips64 = 0 }, { DEFOP(Iop_CtzNat64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 0, .mips32 =0, .mips64 = 0 }, - { DEFOP(Iop_CtzNat32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 1, .mips32 =0, .mips64 = 0 }, + { DEFOP(Iop_CtzNat32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 1, .mips32 =0, .mips64 = 0 }, { DEFOP(Iop_PopCount64, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 0, .mips32 =0, .mips64 = 0 }, { DEFOP(Iop_PopCount32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 =0, .mips64 = 0 }, { DEFOP(Iop_CmpLT32S, UNDEF_ALL), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 1, .ppc64 = 1, .ppc32 = 1, .mips32 =1, .mips64 = 1 },