From: Florian Krohm Date: Sat, 30 Aug 2025 11:28:03 +0000 (+0000) Subject: iropt-test: Constant folding for DivModU32to32 and DivModS32to32 X-Git-Tag: VALGRIND_3_26_0~180 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=773544211c10a81773200864ba2b57cea7886e9e;p=thirdparty%2Fvalgrind.git iropt-test: Constant folding for DivModU32to32 and DivModS32to32 Needed for Mips. Mips is still disabled in iropt-test because there are miscompares between the folded the result and the result computed by the insn sequence that implements the IROp. Several IRops are affected. Part of fixing https://bugs.kde.org/show_bug.cgi?id=506211 --- diff --git a/VEX/priv/ir_opt.c b/VEX/priv/ir_opt.c index 5056b677b..925524e15 100644 --- a/VEX/priv/ir_opt.c +++ b/VEX/priv/ir_opt.c @@ -2193,6 +2193,31 @@ static IRExpr* fold_Expr_WRK ( IRExpr** env, IRExpr* e ) } break; } + case Iop_DivModU32to32: { + UInt u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32; + UInt u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; + if (u32b != 0) { + UInt q = u32a / u32b; + UInt r = u32a % u32b; + e2 = IRExpr_Const(IRConst_U64(((ULong)r << 32) | q)); + } + break; + } + case Iop_DivModS32to32: { + Int s32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32; + Int s32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; + if (s32b != 0) { + /* Division may trap when result overflows i.e. when + attempting: INT32_MAX / -1 */ + if (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32 == (1UL << 31) + && s32b == -1) + break; + Int q = s32a / s32b; + Int r = s32a % s32b; + e2 = IRExpr_Const(IRConst_U64(((ULong)(UInt)r << 32) | (UInt)q)); + } + break; + } /* -- Shl -- */ case Iop_Shl8: diff --git a/none/tests/iropt-test/binary.c b/none/tests/iropt-test/binary.c index 1fbe1341f..d8d3618b2 100644 --- a/none/tests/iropt-test/binary.c +++ b/none/tests/iropt-test/binary.c @@ -215,6 +215,20 @@ get_expected_value(const irop_t *op, const test_data_t *data) expected = (int64_t)(opnd_l << 32) / (int32_t)opnd_r; break; + case Iop_DivModU32to32: { + uint32_t q = opnd_l / opnd_r; + uint32_t r = opnd_l % opnd_r; + expected = ((uint64_t)r << 32) | q; + break; + } + + case Iop_DivModS32to32: { + int32_t q = (int32_t)opnd_l / (int32_t)opnd_r; + int32_t r = (int32_t)opnd_l % (int32_t)opnd_r; + expected = ((uint64_t)r << 32) | (uint32_t)q; + break; + } + case Iop_DivModU64to32: { uint64_t q = opnd_l / opnd_r; uint64_t r = opnd_l % opnd_r; @@ -424,6 +438,7 @@ ok_to_run(IROp op, uint64_t o1, uint64_t o2) case Iop_DivS32: case Iop_DivS64: case Iop_DivU32E: case Iop_DivS32E: + case Iop_DivModU32to32: return o2 != 0; /* Check that result can be represented */ @@ -448,6 +463,16 @@ ok_to_run(IROp op, uint64_t o1, uint64_t o2) return q <= INT32_MAX && q >= INT32_MIN; } + case Iop_DivModS32to32: { + int32_t divisor = o2; + + if (divisor == 0) return 0; + /* Division may trap on overflow */ + if (divisor == -1 && o1 == (0x1UL << 31)) // INT32_MIN + return 0; + return 1; + } + default: return 1; } diff --git a/none/tests/iropt-test/irops.tab b/none/tests/iropt-test/irops.tab index 954654b7c..882ba59ba 100644 --- a/none/tests/iropt-test/irops.tab +++ b/none/tests/iropt-test/irops.tab @@ -176,12 +176,12 @@ // { OPNAME(DivS64E), Ity_I32, 2, Ity_I32, Ity_I32, }, // 128 bit // { OPNAME(DivS128E), Ity_I128, 2, Ity_I128, Ity_I128 }, // 128 bit -// { OPNAME(DivModU32to32), Ity_I64, 2, Ity_I32, Ity_I64 }, // mips no folding yet + { OPNAME(DivModU32to32), Ity_I64, 2, Ity_I32, Ity_I32, ONLY(mipsx) }, { OPNAME(DivModU64to32), Ity_I64, 2, Ity_I64, Ity_I32, EXCEPT2(ppc, mipsx) }, // { OPNAME(DivModU64to64), Ity_I64, 2, Ity_I64, Ity_I128 }, // 128 bit // { OPNAME(DivModU128to64), Ity_I128, 2, Ity_I64, Ity_I128 }, // 128 bit -// { OPNAME(DivModS32to32), Ity_I64, 2, Ity_I32, Ity_I32 }, // mips no folding yet + { OPNAME(DivModS32to32), Ity_I64, 2, Ity_I32, Ity_I32, ONLY(mipsx) }, { OPNAME(DivModS64to32), Ity_I64, 2, Ity_I64, Ity_I32, EXCEPT2(ppc, mipsx) }, // { OPNAME(DivModS64to64), Ity_I64, 2, Ity_I64, Ity_I128 }, // 128 bit // { OPNAME(DivModU128to64), Ity_I128, 2, Ity_I64, Ity_I128 }, // 128 bit diff --git a/none/tests/iropt-test/main.c b/none/tests/iropt-test/main.c index 1ca97e9c0..64ad44d87 100644 --- a/none/tests/iropt-test/main.c +++ b/none/tests/iropt-test/main.c @@ -45,7 +45,7 @@ unsigned num_random_tests; int main(int argc, char *argv[]) { -// FIXME: temporarily until ppc has been fixed +// FIXME: temporarily until ppc and mips have been fixed #if !defined(__s390x__) && !defined(__i386__) && !defined(__x86_64__) return 0; #endif @@ -164,6 +164,9 @@ is_enabled(const irop_t *op) #ifdef __s390x__ return op->enabled_arch & ARCH_s390; #endif +#ifdef __mips__ + return op->enabled_arch & ((__mips == 64) ? ARCH_mips64 : ARCH_mips32); +#endif #ifdef __powerpc__ /* defined for both 32-bit and 64-bit */ #define MIN_POWER_ISA "../../../tests/min_power_isa" int rc;