From: Florian K. <fk...@so...> - 2025-07-17 07:04:34
|
https://sourceware.org/cgit/valgrind/commit/?id=92b886de45265ca15e87f67d4245d77f292de80e commit 92b886de45265ca15e87f67d4245d77f292de80e Author: Florian Krohm <fl...@ei...> Date: Thu Jul 17 07:04:03 2025 +0000 Constant folding for Iop_Shl8/16, Iop_Shr8/16 and Iop_Sar8/16. (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 | 16 ++++++++---- none/tests/iropt-test/irops.tab | 12 ++++----- 3 files changed, 73 insertions(+), 11 deletions(-) diff --git a/VEX/priv/ir_opt.c b/VEX/priv/ir_opt.c index 91b266aa1d..4653704d3e 100644 --- a/VEX/priv/ir_opt.c +++ b/VEX/priv/ir_opt.c @@ -2093,6 +2093,22 @@ static IRExpr* fold_Expr_WRK ( IRExpr** env, IRExpr* e ) } /* -- Shl -- */ + case Iop_Shl8: + vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); + shift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; + if (shift >= 0 && shift <= 7) + e2 = IRExpr_Const(IRConst_U8(toUChar( + (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8 + << shift)))); + break; + case Iop_Shl16: + vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); + shift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; + if (shift >= 0 && shift <= 15) + e2 = IRExpr_Const(IRConst_U16(toUShort( + (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16 + << shift)))); + break; case Iop_Shl32: vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8); @@ -2111,6 +2127,28 @@ static IRExpr* fold_Expr_WRK ( IRExpr** env, IRExpr* e ) break; /* -- Sar -- */ + case Iop_Sar8: { + Int s8; + vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); + s8 = (Char)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U8); + shift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; + if (shift >= 0 && shift <= 7) { + s8 >>=/*signed*/ shift; + e2 = IRExpr_Const(IRConst_U8(toUChar(s8))); + } + break; + } + case Iop_Sar16: { + Int s16; + vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); + s16 = (Short)(e->Iex.Binop.arg1->Iex.Const.con->Ico.U16); + shift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; + if (shift >= 0 && shift <= 15) { + s16 >>=/*signed*/ shift; + e2 = IRExpr_Const(IRConst_U16(toUShort(s16))); + } + break; + } case Iop_Sar32: { /* paranoid ... */ /*signed*/ Int s32; @@ -2137,6 +2175,24 @@ static IRExpr* fold_Expr_WRK ( IRExpr** env, IRExpr* e ) } /* -- Shr -- */ + case Iop_Shr8: { + vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); + shift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; + if (shift >= 0 && shift <= 7) + e2 = IRExpr_Const(IRConst_U8(toUChar( + (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8 + >> shift)))); + break; + } + case Iop_Shr16: { + vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); + shift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; + if (shift >= 0 && shift <= 15) + e2 = IRExpr_Const(IRConst_U16(toUShort( + (e->Iex.Binop.arg1->Iex.Const.con->Ico.U16 + >> shift)))); + break; + } case Iop_Shr32: { /* paranoid ... */ /*unsigned*/ UInt u32; diff --git a/none/tests/iropt-test/binary.c b/none/tests/iropt-test/binary.c index 894213a569..2c815c8136 100644 --- a/none/tests/iropt-test/binary.c +++ b/none/tests/iropt-test/binary.c @@ -148,20 +148,26 @@ 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_Shl8: + case Iop_Shl16: case Iop_Shl32: - expected = opnd_l << opnd_r; - break; - case Iop_Shl64: expected = opnd_l << opnd_r; break; + case Iop_Shr8: + case Iop_Shr16: case Iop_Shr32: + case Iop_Shr64: expected = opnd_l >> opnd_r; break; - case Iop_Shr64: - expected = opnd_l >> opnd_r; + case Iop_Sar8: + expected = ((int64_t)(opnd_l << 56) >> 56) >> opnd_r; + break; + + case Iop_Sar16: + expected = ((int64_t)(opnd_l << 48) >> 48) >> opnd_r; break; case Iop_Sar32: diff --git a/none/tests/iropt-test/irops.tab b/none/tests/iropt-test/irops.tab index a9f57a4ce1..efae871fbf 100644 --- a/none/tests/iropt-test/irops.tab +++ b/none/tests/iropt-test/irops.tab @@ -164,18 +164,18 @@ // { OPNAME(ModU128), Ity_I128, 2, Ity_I128, Ity_I128 }, // 128 bit // { OPNAME(ModS128), Ity_I128, 2, Ity_I128, Ity_I128 }, // 128 bit -// { OPNAME(Shl8), Ity_I8, 2, Ity_I8, Ity_I8 }, // no folding yet -// { OPNAME(Shl16), Ity_I16, 2, Ity_I16, Ity_I8 }, // no folding yet + { OPNAME(Shl8), Ity_I8, 2, Ity_I8, Ity_I8 }, + { OPNAME(Shl16), Ity_I16, 2, Ity_I16, Ity_I8 }, { OPNAME(Shl32), Ity_I32, 2, Ity_I32, Ity_I8 }, { OPNAME(Shl64), Ity_I64, 2, Ity_I64, Ity_I8 }, -// { OPNAME(Shr8), Ity_I8, 2, Ity_I8, Ity_I8 }, // no folding yet -// { OPNAME(Shr16), Ity_I16, 2, Ity_I16, Ity_I8 }, // no folding yet + { OPNAME(Shr8), Ity_I8, 2, Ity_I8, Ity_I8 }, + { OPNAME(Shr16), Ity_I16, 2, Ity_I16, Ity_I8 }, { OPNAME(Shr32), Ity_I32, 2, Ity_I32, Ity_I8 }, { OPNAME(Shr64), Ity_I64, 2, Ity_I64, Ity_I8 }, -// { OPNAME(Sar8), Ity_I8, 2, Ity_I8, Ity_I8 }, // no folding yet -// { OPNAME(Sar16), Ity_I16, 2, Ity_I16, Ity_I8 }, // no folding yet + { OPNAME(Sar8), Ity_I8, 2, Ity_I8, Ity_I8 }, + { OPNAME(Sar16), Ity_I16, 2, Ity_I16, Ity_I8 }, { OPNAME(Sar32), Ity_I32, 2, Ity_I32, Ity_I8 }, { OPNAME(Sar64), Ity_I64, 2, Ity_I64, Ity_I8 }, |