]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Constant folding for various division IROps. (BZ 506211)
authorFlorian Krohm <flo2030@eich-krohm.de>
Thu, 17 Jul 2025 20:39:12 +0000 (20:39 +0000)
committerFlorian Krohm <flo2030@eich-krohm.de>
Thu, 17 Jul 2025 20:39:12 +0000 (20:39 +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 fa0b76a961443e63aa5e5ed0a5362f56f5a8189c..ebea8ba0e34a93ff38801cf2dee8ee3051733662 100644 (file)
@@ -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);
index 96e71a068e9c2a4cb226c17ae030ed824bc817dd..62c9faeb35f4626b1ad1eb72a2d77a3eb8490dc1 100644 (file)
@@ -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;
+   }
+}
index 5fb2016634c25064b703d327d55cf8a33ccfe78d..f2ffd007c6285637b971f1453cf2d87352273289 100644 (file)
    { 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