aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-01-12 23:53:26 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-01-12 23:53:26 -0700
commit93b854eb745ab3294054ae71150fe60f134f4d10 (patch)
treed40e26fcf2524c70c30302f0b503d14a0cdf4e51 /src/value.zig
parentc4681b4889652d5228a84ac7af5ad5e17ac39055 (diff)
downloadzig-93b854eb745ab3294054ae71150fe60f134f4d10.tar.gz
zig-93b854eb745ab3294054ae71150fe60f134f4d10.zip
stage2: implement `@ctz` and `@clz` including SIMD
AIR: * `array_elem_val` is now allowed to be used with a vector as the array type. * New instructions: splat, vector_init AstGen: * The splat ZIR instruction uses coerced_ty for the ResultLoc, avoiding an unnecessary `as` instruction, since the coercion will be performed in Sema. * Builtins that accept vectors now ignore the type parameter. Comment from this commit reproduced here: The accepted proposal #6835 tells us to remove the type parameter from these builtins. To stay source-compatible with stage1, we still observe the parameter here, but we do not encode it into the ZIR. To implement this proposal in stage2, only AstGen code will need to be changed. Sema: * `clz` and `ctz` ZIR instructions are now handled by the same function which accept AIR tag and comptime eval function pointer to differentiate. * `@typeInfo` for vectors is implemented. * `@splat` is implemented. It takes advantage of `Value.Tag.repeated` 😎 * `elemValue` is implemented for vectors, when the index is a scalar. Handling a vector index is still TODO. * Element-wise coercion is implemented for vectors. It could probably be optimized a bit, but it is at least complete & correct. * `Type.intInfo` supports vectors, returning int info for the element. * `Value.ctz` initial implementation. Needs work. * `Value.eql` is implemented for arrays and vectors. LLVM backend: * Implement vector support when lowering `array_elem_val`. * Implement vector support when lowering `ctz` and `clz`. * Implement `splat` and `vector_init`.
Diffstat (limited to 'src/value.zig')
-rw-r--r--src/value.zig65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/value.zig b/src/value.zig
index c4d35ad006..1e7f713307 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1172,6 +1172,44 @@ pub const Value = extern union {
}
}
+ pub fn ctz(val: Value, ty: Type, target: Target) u64 {
+ const ty_bits = ty.intInfo(target).bits;
+ switch (val.tag()) {
+ .zero, .bool_false => return ty_bits,
+ .one, .bool_true => return 0,
+
+ .int_u64 => {
+ const big = @ctz(u64, val.castTag(.int_u64).?.data);
+ return if (big == 64) ty_bits else big;
+ },
+ .int_i64 => {
+ @panic("TODO implement i64 Value ctz");
+ },
+ .int_big_positive => {
+ // TODO: move this code into std lib big ints
+ const bigint = val.castTag(.int_big_positive).?.asBigInt();
+ // Limbs are stored in little-endian order.
+ var result: u64 = 0;
+ for (bigint.limbs) |limb| {
+ const limb_tz = @ctz(std.math.big.Limb, limb);
+ result += limb_tz;
+ if (limb_tz != @sizeOf(std.math.big.Limb) * 8) break;
+ }
+ return result;
+ },
+ .int_big_negative => {
+ @panic("TODO implement int_big_negative Value ctz");
+ },
+
+ .the_only_possible_value => {
+ assert(ty_bits == 0);
+ return ty_bits;
+ },
+
+ else => 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) usize {
@@ -1455,6 +1493,20 @@ pub const Value = extern union {
.field_ptr => @panic("TODO: Implement more pointer eql cases"),
.eu_payload_ptr => @panic("TODO: Implement more pointer eql cases"),
.opt_payload_ptr => @panic("TODO: Implement more pointer eql cases"),
+ .array => {
+ const a_array = a.castTag(.array).?.data;
+ const b_array = b.castTag(.array).?.data;
+
+ if (a_array.len != b_array.len) return false;
+
+ const elem_ty = ty.childType();
+ for (a_array) |a_elem, i| {
+ const b_elem = b_array[i];
+
+ if (!eql(a_elem, b_elem, elem_ty)) return false;
+ }
+ return true;
+ },
else => {},
}
} else if (a_tag == .null_value or b_tag == .null_value) {
@@ -1488,6 +1540,19 @@ pub const Value = extern union {
const int_ty = ty.intTagType(&buf_ty);
return eql(a_val, b_val, int_ty);
},
+ .Array, .Vector => {
+ const len = ty.arrayLen();
+ const elem_ty = ty.childType();
+ var i: usize = 0;
+ var a_buf: ElemValueBuffer = undefined;
+ var b_buf: ElemValueBuffer = undefined;
+ while (i < len) : (i += 1) {
+ const a_elem = elemValueBuffer(a, i, &a_buf);
+ const b_elem = elemValueBuffer(b, i, &b_buf);
+ if (!eql(a_elem, b_elem, elem_ty)) return false;
+ }
+ return true;
+ },
else => return order(a, b).compare(.eq),
}
}