]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Constant folding for Iop_Shl8/16, Iop_Shr8/16 and Iop_Sar8/16. (BZ 506211)
authorFlorian Krohm <flo2030@eich-krohm.de>
Thu, 17 Jul 2025 07:04:03 +0000 (07:04 +0000)
committerFlorian Krohm <flo2030@eich-krohm.de>
Thu, 17 Jul 2025 07:04:03 +0000 (07:04 +0000)
Part of fixing https://bugs.kde.org/show_bug.cgi?id=506211

VEX/priv/ir_opt.c
none/tests/iropt-test/binary.c
none/tests/iropt-test/irops.tab

index 91b266aa1d1a5189e9647b7a13fb317d5400c219..4653704d3e3b7adbcfe90c924ffe5f318f8be189 100644 (file)
@@ -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;
index 894213a5695d4d234ad4ce0832b76974bd3ce85c..2c815c81368e4c5119d2d56034d0ded56aa90347 100644 (file)
@@ -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:
index a9f57a4ce149889f1bb5511dca271a25ca5df60f..efae871fbfa439e985a05bd27dbfce1e5cc53860 100644 (file)
 // { 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 },