From: Florian K. <fk...@so...> - 2025-07-17 15:07:06
|
https://sourceware.org/cgit/valgrind/commit/?id=c84404c4f8ba52edd9bd3c68fae316510adc1a90 commit c84404c4f8ba52edd9bd3c68fae316510adc1a90 Author: Florian Krohm <fl...@ei...> Date: Thu Jul 17 12:23:22 2025 +0000 Constant folding for Iop_CmpORD.. and Iop_8HLto16, Iop16HLto32. (BZ 506211) Part of fixing https://bugs.kde.org/show_bug.cgi?id=506211 Diff: --- VEX/priv/ir_opt.c | 56 +++++++++++++++++++++++++++++++++++++++++ none/tests/iropt-test/binary.c | 41 ++++++++++++++++++++++++------ none/tests/iropt-test/irops.tab | 10 ++++---- 3 files changed, 94 insertions(+), 13 deletions(-) diff --git a/VEX/priv/ir_opt.c b/VEX/priv/ir_opt.c index 4653704d3e..8e4d95692d 100644 --- a/VEX/priv/ir_opt.c +++ b/VEX/priv/ir_opt.c @@ -2339,8 +2339,64 @@ static IRExpr* fold_Expr_WRK ( IRExpr** env, IRExpr* e ) e2 = IRExpr_Const(IRConst_U32(r)); break; } + case Iop_CmpORD64S: { + /* very paranoid */ + ULong u64a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U64; + ULong u64b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64; + Long s64a = (Long)u64a; + Long s64b = (Long)u64b; + Int r = 0x2; /* EQ */ + if (s64a < s64b) { + r = 0x8; /* LT */ + } + else if (s64a > s64b) { + r = 0x4; /* GT */ + } + e2 = IRExpr_Const(IRConst_U64(r)); + break; + } + case Iop_CmpORD32U: { + UInt u32a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U32; + UInt u32b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; + Int r = 0x2; /* EQ */ + if (u32a < u32b) { + r = 0x8; /* LT */ + } + else if (u32a > u32b) { + r = 0x4; /* GT */ + } + e2 = IRExpr_Const(IRConst_U32(r)); + break; + } + case Iop_CmpORD64U: { + ULong u64a = e->Iex.Binop.arg1->Iex.Const.con->Ico.U64; + ULong u64b = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64; + Int r = 0x2; /* EQ */ + if (u64a < u64b) { + r = 0x8; /* LT */ + } + else if (u64a > u64b) { + r = 0x4; /* GT */ + } + e2 = IRExpr_Const(IRConst_U64(r)); + break; + } /* -- nHLto2n -- */ + case Iop_8HLto16: + e2 = IRExpr_Const(IRConst_U16(toUShort( + (((UInt)(e->Iex.Binop.arg1 + ->Iex.Const.con->Ico.U8)) << 8) + | ((UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8))) + )); + break; + case Iop_16HLto32: + e2 = IRExpr_Const(IRConst_U32( + (((UInt)(e->Iex.Binop.arg1 + ->Iex.Const.con->Ico.U16)) << 16) + | ((UInt)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U16)) + )); + break; case Iop_32HLto64: e2 = IRExpr_Const(IRConst_U64( (((ULong)(e->Iex.Binop.arg1 diff --git a/none/tests/iropt-test/binary.c b/none/tests/iropt-test/binary.c index 2c815c8136..1ec2d77e3d 100644 --- a/none/tests/iropt-test/binary.c +++ b/none/tests/iropt-test/binary.c @@ -233,9 +233,11 @@ check_result(const irop_t *op, const test_data_t *data) break; case Iop_CmpLT32S: { - int32_t opnd_ls = (int32_t)(opnd_l & UINT32_MAX); - int32_t opnd_rs = (int32_t)(opnd_r & UINT32_MAX); - expected = opnd_ls < opnd_rs; + uint32_t u32l = opnd_l & UINT32_MAX; + uint32_t u32r = opnd_r & UINT32_MAX; + int32_t s32l = (int32_t)u32l; + int32_t s32r = (int32_t)u32r; + expected = s32l < s32r; break; } @@ -249,9 +251,11 @@ check_result(const irop_t *op, const test_data_t *data) break; case Iop_CmpLE32S: { - int32_t opnd_ls = (int32_t)(opnd_l & UINT32_MAX); - int32_t opnd_rs = (int32_t)(opnd_r & UINT32_MAX); - expected = opnd_ls <= opnd_rs; + uint32_t u32l = opnd_l & UINT32_MAX; + uint32_t u32r = opnd_r & UINT32_MAX; + int32_t s32l = (int32_t)u32l; + int32_t s32r = (int32_t)u32r; + expected = s32l <= s32r; break; } @@ -259,9 +263,22 @@ check_result(const irop_t *op, const test_data_t *data) expected = (int64_t)opnd_l <= (int64_t)opnd_r; break; + case Iop_CmpORD32U: + case Iop_CmpORD64U: + expected = (opnd_l < opnd_r) ? 8 : (opnd_l > opnd_r) ? 4 : 2; + break; + case Iop_CmpORD32S: { - int32_t opnd_ls = (int32_t)(opnd_l & UINT32_MAX); - int32_t opnd_rs = (int32_t)(opnd_r & UINT32_MAX); + uint32_t u32l = opnd_l & UINT32_MAX; + uint32_t u32r = opnd_r & UINT32_MAX; + int32_t s32l = (int32_t)u32l; + int32_t s32r = (int32_t)u32r; + expected = (s32l < s32r) ? 8 : (s32l > s32r) ? 4 : 2; + break; + } + case Iop_CmpORD64S: { + int64_t opnd_ls = (int64_t)opnd_l; + int64_t opnd_rs = (int64_t)opnd_r; expected = (opnd_ls < opnd_rs) ? 8 : (opnd_ls > opnd_rs) ? 4 : 2; break; } @@ -272,6 +289,14 @@ check_result(const irop_t *op, const test_data_t *data) expected = opnd_l > opnd_r ? opnd_l : opnd_r; break; + case Iop_8HLto16: + expected = (opnd_l << 8) | opnd_r; + break; + + case Iop_16HLto32: + expected = (opnd_l << 16) | opnd_r; + break; + case Iop_32HLto64: expected = (opnd_l << 32) | opnd_r; break; diff --git a/none/tests/iropt-test/irops.tab b/none/tests/iropt-test/irops.tab index efae871fbf..68f8cc8860 100644 --- a/none/tests/iropt-test/irops.tab +++ b/none/tests/iropt-test/irops.tab @@ -234,15 +234,15 @@ { OPNAME(ExpCmpNE32), Ity_I1, 2, Ity_I32, Ity_I32 }, { OPNAME(ExpCmpNE64), Ity_I1, 2, Ity_I64, Ity_I64 }, -// { OPNAME(CmpORD32U), Ity_I32, 2, Ity_I32, Ity_I32 }, // no folding yet -// { OPNAME(CmpORD64U), Ity_I64, 2, Ity_I64, Ity_I64 }, // no folding yet + { OPNAME(CmpORD32U), Ity_I32, 2, Ity_I32, Ity_I32 }, + { OPNAME(CmpORD64U), Ity_I64, 2, Ity_I64, Ity_I64 }, { OPNAME(CmpORD32S), Ity_I32, 2, Ity_I32, Ity_I32 }, -// { OPNAME(CmpORD64S), Ity_I64, 2, Ity_I64, Ity_I64 }, // no folding yet + { OPNAME(CmpORD64S), Ity_I64, 2, Ity_I64, Ity_I64 }, { OPNAME(Max32U), Ity_I32, 2, Ity_I32, Ity_I32 }, -// { OPNAME(8HLto16), Ity_I16, 2, Ity_I8, Ity_I8 }, // no folding yet -// { OPNAME(16HLto32), Ity_I32, 2, Ity_I16, Ity_I16 }, // no folding yet + { OPNAME(8HLto16), Ity_I16, 2, Ity_I8, Ity_I8 }, + { OPNAME(16HLto32), Ity_I32, 2, Ity_I16, Ity_I16 }, { OPNAME(32HLto64), Ity_I64, 2, Ity_I32, Ity_I32 }, // { OPNAME(64HLto128), Ity_I128, 2, Ity_I64, Ity_I64 }, // 128 bit |