diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-02-12 20:44:30 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-02-12 20:44:30 -0700 |
| commit | a005ac9d3c884c6254074ec150fe536881fe31b5 (patch) | |
| tree | 6c7d2016362d441ad77d77abbf76f5116b329c73 /src/value.zig | |
| parent | 16ec848d2ab5702ad3794d30ed5d776b5abb60ce (diff) | |
| download | zig-a005ac9d3c884c6254074ec150fe536881fe31b5.tar.gz zig-a005ac9d3c884c6254074ec150fe536881fe31b5.zip | |
stage2: implement `@popCount` for SIMD vectors
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 45 |
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()) { |
