aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-02-12 20:44:30 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-02-12 20:44:30 -0700
commita005ac9d3c884c6254074ec150fe536881fe31b5 (patch)
tree6c7d2016362d441ad77d77abbf76f5116b329c73 /src/value.zig
parent16ec848d2ab5702ad3794d30ed5d776b5abb60ce (diff)
downloadzig-a005ac9d3c884c6254074ec150fe536881fe31b5.tar.gz
zig-a005ac9d3c884c6254074ec150fe536881fe31b5.zip
stage2: implement `@popCount` for SIMD vectors
Diffstat (limited to 'src/value.zig')
-rw-r--r--src/value.zig45
1 files changed, 27 insertions, 18 deletions
diff --git a/src/value.zig b/src/value.zig
index 3479819160..1f93a828aa 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1303,6 +1303,33 @@ pub const Value = extern union {
}
}
+ pub fn popCount(val: Value, ty: Type, target: Target) u64 {
+ assert(!val.isUndef());
+ switch (val.tag()) {
+ .zero, .bool_false => return 0,
+ .one, .bool_true => return 1,
+
+ .int_u64 => return @popCount(u64, val.castTag(.int_u64).?.data),
+
+ else => {
+ const info = ty.intInfo(target);
+
+ var buffer: Value.BigIntSpace = undefined;
+ const operand_bigint = val.toBigInt(&buffer);
+
+ var limbs_buffer: [4]std.math.big.Limb = undefined;
+ var result_bigint = BigIntMutable{
+ .limbs = &limbs_buffer,
+ .positive = undefined,
+ .len = undefined,
+ };
+ result_bigint.popCount(operand_bigint, info.bits);
+
+ return result_bigint.toConst().to(u64) catch unreachable;
+ },
+ }
+ }
+
/// Asserts the value is an integer and not undefined.
/// Returns the number of bits the value requires to represent stored in twos complement form.
pub fn intBitCountTwosComp(self: Value, target: Target) usize {
@@ -1340,24 +1367,6 @@ pub const Value = extern union {
}
}
- pub fn popCount(val: Value, ty: Type, target: Target, arena: Allocator) !Value {
- assert(!val.isUndef());
-
- const info = ty.intInfo(target);
-
- var buffer: Value.BigIntSpace = undefined;
- const operand_bigint = val.toBigInt(&buffer);
-
- const limbs = try arena.alloc(
- std.math.big.Limb,
- std.math.big.int.calcTwosCompLimbCount(info.bits),
- );
- var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
- result_bigint.popCount(operand_bigint, info.bits);
-
- return fromBigInt(arena, result_bigint.toConst());
- }
-
/// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
pub fn intFitsInType(self: Value, ty: Type, target: Target) bool {
switch (self.tag()) {