From: Florian Krohm Date: Thu, 17 Jul 2025 20:39:12 +0000 (+0000) Subject: Constant folding for various division IROps. (BZ 506211) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4ecf8d2832530de0904803c772126aabcf8fb075;p=thirdparty%2Fvalgrind.git Constant folding for various division IROps. (BZ 506211) 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 fa0b76a96..ebea8ba0e 100644 --- a/VEX/priv/ir_opt.c +++ b/VEX/priv/ir_opt.c @@ -2149,6 +2149,54 @@ static IRExpr* fold_Expr_WRK ( IRExpr** env, IRExpr* e ) break; } + /* -- Div -- */ + case Iop_DivS32: { + 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) + e2 = IRExpr_Const(IRConst_U32(s32a / s32b)); + break; + } + case Iop_DivS64: { + Long s64a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U64; + Long s64b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64; + if (s64b != 0) + e2 = IRExpr_Const(IRConst_U64(s64a / s64b)); + break; + } + case Iop_DivU32: { + 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) + e2 = IRExpr_Const(IRConst_U32(u32a / u32b)); + break; + } + case Iop_DivU64: { + ULong u64a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U64; + ULong u64b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64; + if (u64b != 0) + e2 = IRExpr_Const(IRConst_U64(u64a / u64b)); + break; + } + case Iop_DivS32E: { + 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) { + Long s64a = (Long)s32a << 32; + e2 = IRExpr_Const(IRConst_U32(toUInt(s64a / s32b))); + } + break; + } + case Iop_DivU32E: { + 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) { + ULong u64a = (ULong)u32a << 32; + e2 = IRExpr_Const(IRConst_U32(toUInt(u64a / u32b))); + } + break; + } + /* -- Shl -- */ case Iop_Shl8: vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); diff --git a/none/tests/iropt-test/binary.c b/none/tests/iropt-test/binary.c index 96e71a068..62c9faeb3 100644 --- a/none/tests/iropt-test/binary.c +++ b/none/tests/iropt-test/binary.c @@ -30,6 +30,7 @@ static void check_result(const irop_t *, const test_data_t *); static void run_tests(const irop_t *, test_data_t *); static void run_shift_tests(const irop_t *, test_data_t *); static int is_shift_op(IROp); +static int is_division_op(IROp); void @@ -56,6 +57,8 @@ run_selected_tests(const irop_t *op, test_data_t *data) for (unsigned j = 0; j < num_val_r; ++j) { opnd_r->value = values_r[j]; + if (is_division_op(op->op) && opnd_r->value == 0) continue; + valgrind_execute_test(op, data); check_result(op, data); } @@ -74,6 +77,8 @@ run_random_tests(const irop_t *op, test_data_t *data) opnd_l->value = get_random_value(opnd_l->type); opnd_r->value = get_random_value(opnd_r->type); + if (is_division_op(op->op) && opnd_r->value == 0) continue; + valgrind_execute_test(op, data); check_result(op, data); } @@ -190,6 +195,27 @@ check_result(const irop_t *op, const test_data_t *data) expected = (int64_t)(int32_t)opnd_l * (int64_t)(int32_t)opnd_r; break; + case Iop_DivU32: + case Iop_DivU64: + expected = opnd_l / opnd_r; + break; + + case Iop_DivS32: + expected = (int32_t)opnd_l / (int32_t)opnd_r; + break; + + case Iop_DivS64: + expected = (int64_t)opnd_l / (int64_t)opnd_r; + break; + + case Iop_DivU32E: + expected = (opnd_l << 32) / opnd_r; + break; + + case Iop_DivS32E: + expected = (int64_t)(opnd_l << 32) / (int32_t)opnd_r; + break; + case Iop_Shl8: case Iop_Shl16: case Iop_Shl32: @@ -392,3 +418,18 @@ is_shift_op(IROp op) return 0; } } + + +static int +is_division_op(IROp op) +{ + switch (op) { + case Iop_DivU32: case Iop_DivU64: + case Iop_DivS32: case Iop_DivS64: + case Iop_DivU32E: + case Iop_DivS32E: + return 1; + default: + return 0; + } +} diff --git a/none/tests/iropt-test/irops.tab b/none/tests/iropt-test/irops.tab index 5fb201663..f2ffd007c 100644 --- a/none/tests/iropt-test/irops.tab +++ b/none/tests/iropt-test/irops.tab @@ -135,20 +135,20 @@ { OPNAME(MullS32), Ity_I64, 2, Ity_I32, Ity_I32 }, // { OPNAME(MullS64), Ity_I128, 2, Ity_I64, Ity_I64 }, // 128 bit -// { OPNAME(DivU32), Ity_I32, 2, Ity_I32, Ity_I32 }, // no folding yet -// { OPNAME(DivU64), Ity_I64, 2, Ity_I64, Ity_I64 }, // no folding yet + { OPNAME(DivU32), Ity_I32, 2, Ity_I32, Ity_I32 }, + { OPNAME(DivU64), Ity_I64, 2, Ity_I64, Ity_I64 }, // { OPNAME(DivU128), Ity_I128, 2, Ity_I128, Ity_I128 }, // 128 bit -// { OPNAME(DivS32), Ity_I32, 2, Ity_I32, Ity_I32 }, // no folding yet -// { OPNAME(DivS64), Ity_I64, 2, Ity_I64, Ity_I64 }, // no folding yet + { OPNAME(DivS32), Ity_I32, 2, Ity_I32, Ity_I32 }, + { OPNAME(DivS64), Ity_I64, 2, Ity_I64, Ity_I64 }, // { OPNAME(DivS128), Ity_I128, 2, Ity_I128, Ity_I128 }, // 128 bit -// { OPNAME(DivU32E), Ity_I32, 2, Ity_I32, Ity_I32 }, // semantics ? -// { OPNAME(DivU64E), Ity_I32, 2, Ity_I32, Ity_I32 }, // semantics ? + { OPNAME(DivU32E), Ity_I32, 2, Ity_I32, Ity_I32 }, +// { OPNAME(DivU64E), Ity_I64, 2, Ity_I64, Ity_I64 }, // 128 bit // { OPNAME(DivU128E), Ity_I128, 2, Ity_I128, Ity_I128 }, // 128 bit -// { OPNAME(DivS32E), Ity_I32, 2, Ity_I32, Ity_I32 }, // semantics ? -// { OPNAME(DivS64E), Ity_I32, 2, Ity_I32, Ity_I32 }, // semantics ? + { OPNAME(DivS32E), Ity_I32, 2, Ity_I32, Ity_I32 }, +// { 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 }, // no folding yet