return 32;
}
+/* Helpers for folding CtzNat32/64. */
+static UInt fold_CtzNat_WRK ( ULong value, UInt num_bits )
+{
+ UInt count = 0;
+
+ for (UInt i = 1; i <= num_bits; ++i) {
+ if (value & 0x1)
+ return count;
+ value >>= 1;
+ ++count;
+ }
+ return count;
+}
+
+static UInt fold_CtzNat64 ( ULong value )
+{
+ return fold_CtzNat_WRK(value, 64);
+}
+
+static UInt fold_CtzNat32 ( UInt value )
+{
+ return fold_CtzNat_WRK(value, 32);
+}
+
/* Helpers for folding PopCount32/64.
https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
As many iterations as 1-bits present.
break;
}
+ case Iop_CtzNat32: {
+ UInt u32 = e->Iex.Unop.arg->Iex.Const.con->Ico.U32;
+ e2 = IRExpr_Const(IRConst_U32(fold_CtzNat32(u32)));
+ break;
+ }
+ case Iop_CtzNat64: {
+ ULong u64 = e->Iex.Unop.arg->Iex.Const.con->Ico.U64;
+ e2 = IRExpr_Const(IRConst_U64(fold_CtzNat64(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(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
+ { OPNAME(CtzNat32), Ity_I32, 1, Ity_I32 },
+ { OPNAME(CtzNat64), Ity_I64, 1, Ity_I64 },
{ OPNAME(PopCount32), Ity_I32, 1, Ity_I32 },
{ OPNAME(PopCount64), Ity_I64, 1, Ity_I64 },
static uint64_t left(uint64_t, unsigned);
static uint32_t popcount(uint64_t);
static uint32_t clz(uint64_t, unsigned);
+static uint32_t ctz(uint64_t, unsigned);
void
case Iop_ClzNat32: expected = clz(opnd, 32); break;
case Iop_ClzNat64: expected = clz(opnd, 64); break;
+ case Iop_CtzNat32: expected = ctz(opnd, 32); break;
+ case Iop_CtzNat64: expected = ctz(opnd, 64); break;
+
default:
panic("%s: operator %s not handled\n", __func__, op->name);
}
}
return num_bits - last_seen_1bit;
}
+
+
+static uint32_t
+ctz(uint64_t value, unsigned num_bits )
+{
+ unsigned count = 0;
+ unsigned num_nibbles = num_bits / 4;
+
+ for (unsigned i = 0; i < num_nibbles; ++i) {
+ UInt nibble = value & 0xF;
+ if ((nibble & 0x1) == 0x1) return count;
+ if ((nibble & 0x2) == 0x2) return count + 1;
+ if ((nibble & 0x4) == 0x4) return count + 2;
+ if ((nibble & 0x8) == 0x8) return count + 3;
+ count += 4;
+ value >>= 4;
+ }
+ return count;
+}