return 0;
}
+/* Helpers for folding ClzNat32/64. */
+static UInt fold_ClzNat64 ( ULong value )
+{
+ UInt i;
+ for (i = 0; i < 64; ++i) {
+ if (0ULL != (value & (((ULong)1) << (63 - i)))) return i;
+ }
+ return 64;
+}
+
+static UInt fold_ClzNat32 ( UInt value )
+{
+ UInt i;
+ for (i = 0; i < 32; ++i) {
+ if (0 != (value & (((UInt)1) << (31 - i)))) return i;
+ }
+ return 32;
+}
+
/* Helpers for folding PopCount32/64.
https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
As many iterations as 1-bits present.
break;
}
+ case Iop_ClzNat32: {
+ UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
+ e2 = IRExpr_Const(IRConst_U32(fold_ClzNat32(u32)));
+ break;
+ }
+ case Iop_ClzNat64: {
+ ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
+ e2 = IRExpr_Const(IRConst_U64(fold_ClzNat64(u64)));
+ break;
+ }
+
case Iop_PopCount32: {
UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
e2 = IRExpr_Const(IRConst_U32(fold_PopCount32(u32)));
// { OPNAME(Ctz32), Ity_I32, 1, Ity_I32 }, // deprecated, undefined behaviour
// { OPNAME(Ctz64), Ity_I64, 1, Ity_I64 }, // deprecated, undefined behaviour
-// { OPNAME(ClzNat32), Ity_I32, 1, Ity_I32 }, // no folding yet
-// { OPNAME(ClzNat64), Ity_I64, 1, Ity_I64 }, // no folding yet
+ { OPNAME(ClzNat32), Ity_I32, 1, Ity_I32 },
+ { OPNAME(ClzNat64), Ity_I64, 1, Ity_I64 },
// { OPNAME(CtzNat32), Ity_I32, 1, Ity_I32 }, // no folding yet
// { OPNAME(CtzNat64), Ity_I64, 1, Ity_I64 }, // no folding yet
static void run_random_tests(const irop_t *, test_data_t *);
static uint64_t left(uint64_t, unsigned);
static uint32_t popcount(uint64_t);
+static uint32_t clz(uint64_t, unsigned);
void
expected = popcount(opnd);
break;
+ case Iop_ClzNat32: expected = clz(opnd, 32); break;
+ case Iop_ClzNat64: expected = clz(opnd, 64); break;
+
default:
panic("%s: operator %s not handled\n", __func__, op->name);
}
}
return count;
}
+
+
+static uint32_t
+clz(uint64_t value, unsigned num_bits)
+{
+ unsigned last_seen_1bit = 0;
+
+ for (int i = 1; i <= num_bits; ++i) {
+ if (value & 0x1)
+ last_seen_1bit = i;
+ value >>= 1;
+ }
+ return num_bits - last_seen_1bit;
+}