From: Florian K. <fk...@so...> - 2025-07-17 15:07:11
|
https://sourceware.org/cgit/valgrind/commit/?id=a3b172bd1235f9b74736a7f12a4a4072037b7900 commit a3b172bd1235f9b74736a7f12a4a4072037b7900 Author: Florian Krohm <fl...@ei...> Date: Thu Jul 17 14:04:50 2025 +0000 Constant folding for various multiplication IROps. (BZ 506211) Part of fixing https://bugs.kde.org/show_bug.cgi?id=506211 Diff: --- VEX/priv/ir_opt.c | 57 +++++++++++++++++++++++++++++++++++++++++ none/tests/iropt-test/binary.c | 42 ++++++++++++++++++++++++++++++ none/tests/iropt-test/irops.tab | 20 +++++++-------- 3 files changed, 109 insertions(+), 10 deletions(-) diff --git a/VEX/priv/ir_opt.c b/VEX/priv/ir_opt.c index 8e4d95692d..fa0b76a961 100644 --- a/VEX/priv/ir_opt.c +++ b/VEX/priv/ir_opt.c @@ -2067,6 +2067,16 @@ static IRExpr* fold_Expr_WRK ( IRExpr** env, IRExpr* e ) } /* -- Mul -- */ + case Iop_Mul8: + e2 = IRExpr_Const(IRConst_U8(toUChar( + (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8 + * e->Iex.Binop.arg2->Iex.Const.con->Ico.U8)))); + break; + case Iop_Mul16: + e2 = IRExpr_Const(IRConst_U16(toUShort( + (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16 + * e->Iex.Binop.arg2->Iex.Const.con->Ico.U16)))); + break; case Iop_Mul32: e2 = IRExpr_Const(IRConst_U32( (e->Iex.Binop.arg1->Iex.Const.con->Ico.U32 @@ -2078,6 +2088,53 @@ static IRExpr* fold_Expr_WRK ( IRExpr** env, IRExpr* e ) * e->Iex.Binop.arg2->Iex.Const.con->Ico.U64))); break; + case Iop_MullU8: { + UChar u8a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U8; + UChar u8b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; + Int res = u8a * u8b; /* Compiler will promote to int */ + e2 = IRExpr_Const(IRConst_U16(toUShort(res))); + break; + } + case Iop_MullU16: { + UShort u16a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U16; + UShort u16b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U16; + Int res = u16a * u16b; /* Compiler will promote to int */ + e2 = IRExpr_Const(IRConst_U32(res)); + break; + } + case Iop_MullU32: { + UInt u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32; + UInt u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; + ULong res = (ULong)u32a * (ULong)u32b; + e2 = IRExpr_Const(IRConst_U64(res)); + break; + } + case Iop_MullS8: { + /* very paranoid */ + UChar u8a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U8; + UChar u8b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; + Char s8a = (Char)u8a; + Char s8b = (Char)u8b; + Short s16a = (Short)s8a; + Short s16b = (Short)s8b; + Int sres = s16a * s16b; + UShort ures = toUShort(sres); + e2 = IRExpr_Const(IRConst_U16(ures)); + break; + } + case Iop_MullS16: { + /* very paranoid */ + UShort u16a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U16; + UShort u16b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U16; + Short s16a = (Short)u16a; + Short s16b = (Short)u16b; + Int s32a = (Int)s16a; + Int s32b = (Int)s16b; + Int sres = s32a * s32b; + UInt ures = (UInt)sres; + e2 = IRExpr_Const(IRConst_U32(ures)); + break; + } case Iop_MullS32: { /* very paranoid */ UInt u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32; diff --git a/none/tests/iropt-test/binary.c b/none/tests/iropt-test/binary.c index 1ec2d77e3d..96e71a068e 100644 --- a/none/tests/iropt-test/binary.c +++ b/none/tests/iropt-test/binary.c @@ -144,6 +144,48 @@ check_result(const irop_t *op, const test_data_t *data) expected = opnd_l - opnd_r; break; + case Iop_Mul8: + case Iop_MullU8: { + uint8_t u8l = opnd_l; + uint8_t u8r = opnd_r; + expected = u8l * u8r; + break; + } + case Iop_Mul16: + case Iop_MullU16: { + uint16_t u16l = opnd_l; + uint16_t u16r = opnd_r; + expected = u16l * u16r; + break; + } + case Iop_Mul32: + case Iop_MullU32: { + uint32_t u32l = opnd_l; + uint32_t u32r = opnd_r; + expected = (uint64_t)u32l * (uint64_t)u32r; + break; + } + + case Iop_Mul64: + expected = opnd_l * opnd_r; + break; + + case Iop_MullS8: { + uint8_t u8l = opnd_l; + uint8_t u8r = opnd_r; + int8_t s8l = (int8_t)u8l; + int8_t s8r = (int8_t)u8r; + expected = (int16_t)s8l * (int16_t)s8r; + break; + } + case Iop_MullS16: { + uint16_t u16l = opnd_l; + uint16_t u16r = opnd_r; + int16_t s16l = (int16_t)u16l; + int16_t s16r = (int16_t)u16r; + expected = (int32_t)s16l * (int32_t)s16r; + break; + } case Iop_MullS32: expected = (int64_t)(int32_t)opnd_l * (int64_t)(int32_t)opnd_r; break; diff --git a/none/tests/iropt-test/irops.tab b/none/tests/iropt-test/irops.tab index 68f8cc8860..5fb2016634 100644 --- a/none/tests/iropt-test/irops.tab +++ b/none/tests/iropt-test/irops.tab @@ -120,18 +120,18 @@ { OPNAME(Sub32), Ity_I32, 2, Ity_I32, Ity_I32 }, { OPNAME(Sub64), Ity_I64, 2, Ity_I64, Ity_I64 }, -// { OPNAME(Mul8), Ity_I8, 2, Ity_I8, Ity_I8 }, -// { OPNAME(Mul16), Ity_I16, 2, Ity_I16, Ity_I16 }, -// { OPNAME(Mul32), Ity_I32, 2, Ity_I32, Ity_I32 }, -// { OPNAME(Mul64), Ity_I64, 2, Ity_I64, Ity_I64 }, - -// { OPNAME(MullU8), Ity_I16, 2, Ity_I8, Ity_I8 }, // no folding yet -// { OPNAME(MullU16), Ity_I32, 2, Ity_I16, Ity_I16 }, // no folding yet -// { OPNAME(MullU32), Ity_I64, 2, Ity_I32, Ity_I32 }, // no folding yet + { OPNAME(Mul8), Ity_I8, 2, Ity_I8, Ity_I8 }, + { OPNAME(Mul16), Ity_I16, 2, Ity_I16, Ity_I16 }, + { OPNAME(Mul32), Ity_I32, 2, Ity_I32, Ity_I32 }, + { OPNAME(Mul64), Ity_I64, 2, Ity_I64, Ity_I64 }, + + { OPNAME(MullU8), Ity_I16, 2, Ity_I8, Ity_I8 }, + { OPNAME(MullU16), Ity_I32, 2, Ity_I16, Ity_I16 }, + { OPNAME(MullU32), Ity_I64, 2, Ity_I32, Ity_I32 }, // { OPNAME(MullU64), Ity_I128, 2, Ity_I64, Ity_I64 }, // 128 bit -// { OPNAME(MullS8), Ity_I16, 2, Ity_I8, Ity_I8 }, // no folding yet -// { OPNAME(MullS16), Ity_I32, 2, Ity_I16, Ity_I16 }, // no folding yet + { OPNAME(MullS8), Ity_I16, 2, Ity_I8, Ity_I8 }, + { OPNAME(MullS16), Ity_I32, 2, Ity_I16, Ity_I16 }, { OPNAME(MullS32), Ity_I64, 2, Ity_I32, Ity_I32 }, // { OPNAME(MullS64), Ity_I128, 2, Ity_I64, Ity_I64 }, // 128 bit |