Merge pull request #16346 from antlilja/splat-rls
Apply RLS to @splat builtin, eliminating its length parameter
This commit is contained in:
@@ -9239,10 +9239,10 @@ test "vector @shuffle" {
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@splat#}
|
||||
<pre>{#syntax#}@splat(comptime len: u32, scalar: anytype) @Vector(len, @TypeOf(scalar)){#endsyntax#}</pre>
|
||||
<pre>{#syntax#}@splat(scalar: anytype) anytype{#endsyntax#}</pre>
|
||||
<p>
|
||||
Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value
|
||||
{#syntax#}scalar{#endsyntax#}:
|
||||
Produces a vector where each element is the value {#syntax#}scalar{#endsyntax#}.
|
||||
The return type and thus the length of the vector is inferred.
|
||||
</p>
|
||||
{#code_begin|test|test_splat_builtin#}
|
||||
const std = @import("std");
|
||||
@@ -9250,8 +9250,7 @@ const expect = std.testing.expect;
|
||||
|
||||
test "vector @splat" {
|
||||
const scalar: u32 = 5;
|
||||
const result = @splat(4, scalar);
|
||||
try comptime expect(@TypeOf(result) == @Vector(4, u32));
|
||||
const result: @Vector(4, u32) = @splat(scalar);
|
||||
try expect(std.mem.eql(u32, &@as([4]u32, result), &[_]u32{ 5, 5, 5, 5 }));
|
||||
}
|
||||
{#code_end#}
|
||||
@@ -9292,8 +9291,9 @@ const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
test "vector @reduce" {
|
||||
const value = @Vector(4, i32){ 1, -1, 1, -1 };
|
||||
const result = value > @splat(4, @as(i32, 0));
|
||||
const V = @Vector(4, i32);
|
||||
const value = V{ 1, -1, 1, -1 };
|
||||
const result = value > @as(V, @splat(0));
|
||||
// result is { true, false, true, false };
|
||||
try comptime expect(@TypeOf(result) == @Vector(4, bool));
|
||||
const is_all_true = @reduce(.And, result);
|
||||
|
||||
@@ -182,8 +182,8 @@ pub const HeadersParser = struct {
|
||||
|
||||
const chunk = bytes[index..][0..vector_len];
|
||||
const v: Vector = chunk.*;
|
||||
const matches_r = @as(BitVector, @bitCast(v == @splat(vector_len, @as(u8, '\r'))));
|
||||
const matches_n = @as(BitVector, @bitCast(v == @splat(vector_len, @as(u8, '\n'))));
|
||||
const matches_r = @as(BitVector, @bitCast(v == @as(Vector, @splat('\r'))));
|
||||
const matches_n = @as(BitVector, @bitCast(v == @as(Vector, @splat('\n'))));
|
||||
const matches_or: SizeVector = matches_r | matches_n;
|
||||
|
||||
const matches = @reduce(.Add, matches_or);
|
||||
|
||||
@@ -197,7 +197,7 @@ test "stringify struct with custom stringifier" {
|
||||
}
|
||||
|
||||
test "stringify vector" {
|
||||
try teststringify("[1,1]", @splat(2, @as(u32, 1)), StringifyOptions{});
|
||||
try teststringify("[1,1]", @as(@Vector(2, u32), @splat(1)), StringifyOptions{});
|
||||
}
|
||||
|
||||
test "stringify tuple" {
|
||||
|
||||
@@ -507,8 +507,8 @@ pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {
|
||||
if (@typeInfo(T) == .Vector) {
|
||||
const C = @typeInfo(T).Vector.child;
|
||||
const len = @typeInfo(T).Vector.len;
|
||||
if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(len, @as(C, 0));
|
||||
break :blk @splat(len, @as(Log2Int(C), @intCast(abs_shift_amt)));
|
||||
if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(0);
|
||||
break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt))));
|
||||
} else {
|
||||
if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0;
|
||||
break :blk @as(Log2Int(T), @intCast(abs_shift_amt));
|
||||
@@ -551,8 +551,8 @@ pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {
|
||||
if (@typeInfo(T) == .Vector) {
|
||||
const C = @typeInfo(T).Vector.child;
|
||||
const len = @typeInfo(T).Vector.len;
|
||||
if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(len, @as(C, 0));
|
||||
break :blk @splat(len, @as(Log2Int(C), @intCast(abs_shift_amt)));
|
||||
if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(0);
|
||||
break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt))));
|
||||
} else {
|
||||
if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0;
|
||||
break :blk @as(Log2Int(T), @intCast(abs_shift_amt));
|
||||
@@ -597,7 +597,7 @@ pub fn rotr(comptime T: type, x: T, r: anytype) T {
|
||||
@compileError("cannot rotate signed integers");
|
||||
}
|
||||
const ar = @as(Log2Int(C), @intCast(@mod(r, @typeInfo(C).Int.bits)));
|
||||
return (x >> @splat(@typeInfo(T).Vector.len, ar)) | (x << @splat(@typeInfo(T).Vector.len, 1 + ~ar));
|
||||
return (x >> @splat(ar)) | (x << @splat(1 + ~ar));
|
||||
} else if (@typeInfo(T).Int.signedness == .signed) {
|
||||
@compileError("cannot rotate signed integer");
|
||||
} else {
|
||||
@@ -641,7 +641,7 @@ pub fn rotl(comptime T: type, x: T, r: anytype) T {
|
||||
@compileError("cannot rotate signed integers");
|
||||
}
|
||||
const ar = @as(Log2Int(C), @intCast(@mod(r, @typeInfo(C).Int.bits)));
|
||||
return (x << @splat(@typeInfo(T).Vector.len, ar)) | (x >> @splat(@typeInfo(T).Vector.len, 1 +% ~ar));
|
||||
return (x << @splat(ar)) | (x >> @splat(1 +% ~ar));
|
||||
} else if (@typeInfo(T).Int.signedness == .signed) {
|
||||
@compileError("cannot rotate signed integer");
|
||||
} else {
|
||||
@@ -794,10 +794,10 @@ pub fn absInt(x: anytype) !@TypeOf(x) {
|
||||
switch (@typeInfo(vinfo.child)) {
|
||||
.Int => |info| {
|
||||
comptime assert(info.signedness == .signed); // must pass a signed integer to absInt
|
||||
if (@reduce(.Or, x == @splat(vinfo.len, @as(vinfo.child, minInt(vinfo.child))))) {
|
||||
if (@reduce(.Or, x == @as(T, @splat(minInt(vinfo.child))))) {
|
||||
return error.Overflow;
|
||||
}
|
||||
const zero = @splat(vinfo.len, @as(vinfo.child, 0));
|
||||
const zero: T = @splat(0);
|
||||
break :blk @select(vinfo.child, x > zero, x, -x);
|
||||
},
|
||||
else => @compileError("Expected vector of ints, found " ++ @typeName(T)),
|
||||
@@ -1368,9 +1368,9 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) {
|
||||
|
||||
switch (@typeInfo(Type)) {
|
||||
.Float, .ComptimeFloat => assert(t >= 0 and t <= 1),
|
||||
.Vector => |vector| {
|
||||
const lower_bound = @reduce(.And, t >= @splat(vector.len, @as(vector.child, 0)));
|
||||
const upper_bound = @reduce(.And, t <= @splat(vector.len, @as(vector.child, 1)));
|
||||
.Vector => {
|
||||
const lower_bound = @reduce(.And, t >= @as(Type, @splat(0)));
|
||||
const upper_bound = @reduce(.And, t <= @as(Type, @splat(1)));
|
||||
assert(lower_bound and upper_bound);
|
||||
},
|
||||
else => comptime unreachable,
|
||||
@@ -1392,14 +1392,24 @@ test "lerp" {
|
||||
try testing.expectEqual(@as(f32, 1.0), lerp(@as(f32, 1.0e7), 1.0, 1.0));
|
||||
try testing.expectEqual(@as(f64, 1.0), lerp(@as(f64, 1.0e15), 1.0, 1.0));
|
||||
|
||||
try testing.expectEqual(
|
||||
lerp(@splat(3, @as(f32, 0)), @splat(3, @as(f32, 50)), @splat(3, @as(f32, 0.5))),
|
||||
@Vector(3, f32){ 25, 25, 25 },
|
||||
);
|
||||
try testing.expectEqual(
|
||||
lerp(@splat(3, @as(f64, 50)), @splat(3, @as(f64, 100)), @splat(3, @as(f64, 0.5))),
|
||||
@Vector(3, f64){ 75, 75, 75 },
|
||||
);
|
||||
{
|
||||
const a: @Vector(3, f32) = @splat(0);
|
||||
const b: @Vector(3, f32) = @splat(50);
|
||||
const t: @Vector(3, f32) = @splat(0.5);
|
||||
try testing.expectEqual(
|
||||
lerp(a, b, t),
|
||||
@Vector(3, f32){ 25, 25, 25 },
|
||||
);
|
||||
}
|
||||
{
|
||||
const a: @Vector(3, f64) = @splat(50);
|
||||
const b: @Vector(3, f64) = @splat(100);
|
||||
const t: @Vector(3, f64) = @splat(0.5);
|
||||
try testing.expectEqual(
|
||||
lerp(a, b, t),
|
||||
@Vector(3, f64){ 75, 75, 75 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the maximum value of integer type T.
|
||||
@@ -1719,8 +1729,8 @@ pub inline fn sign(i: anytype) @TypeOf(i) {
|
||||
.Vector => |vinfo| blk: {
|
||||
switch (@typeInfo(vinfo.child)) {
|
||||
.Int, .Float => {
|
||||
const zero = @splat(vinfo.len, @as(vinfo.child, 0));
|
||||
const one = @splat(vinfo.len, @as(vinfo.child, 1));
|
||||
const zero: T = @splat(0);
|
||||
const one: T = @splat(1);
|
||||
break :blk @select(vinfo.child, i > zero, one, zero) - @select(vinfo.child, i < zero, one, zero);
|
||||
},
|
||||
else => @compileError("Expected vector of ints or floats, found " ++ @typeName(T)),
|
||||
|
||||
@@ -289,7 +289,7 @@ pub fn zeroes(comptime T: type) T {
|
||||
return [_]info.child{zeroes(info.child)} ** info.len;
|
||||
},
|
||||
.Vector => |info| {
|
||||
return @splat(info.len, zeroes(info.child));
|
||||
return @splat(zeroes(info.child));
|
||||
},
|
||||
.Union => |info| {
|
||||
if (comptime meta.containerLayout(T) == .Extern) {
|
||||
@@ -393,9 +393,9 @@ test "zeroes" {
|
||||
for (b.array) |e| {
|
||||
try testing.expectEqual(@as(u32, 0), e);
|
||||
}
|
||||
try testing.expectEqual(@splat(2, @as(u32, 0)), b.vector_u32);
|
||||
try testing.expectEqual(@splat(2, @as(f32, 0.0)), b.vector_f32);
|
||||
try testing.expectEqual(@splat(2, @as(bool, false)), b.vector_bool);
|
||||
try testing.expectEqual(@as(@TypeOf(b.vector_u32), @splat(0)), b.vector_u32);
|
||||
try testing.expectEqual(@as(@TypeOf(b.vector_f32), @splat(0.0)), b.vector_f32);
|
||||
try testing.expectEqual(@as(@TypeOf(b.vector_bool), @splat(false)), b.vector_bool);
|
||||
try testing.expectEqual(@as(?u8, null), b.optional_int);
|
||||
for (b.sentinel) |e| {
|
||||
try testing.expectEqual(@as(u8, 0), e);
|
||||
|
||||
@@ -860,9 +860,10 @@ test "std.meta.eql" {
|
||||
try testing.expect(eql(EU.tst(false), EU.tst(false)));
|
||||
try testing.expect(!eql(EU.tst(false), EU.tst(true)));
|
||||
|
||||
var v1 = @splat(4, @as(u32, 1));
|
||||
var v2 = @splat(4, @as(u32, 1));
|
||||
var v3 = @splat(4, @as(u32, 2));
|
||||
const V = @Vector(4, u32);
|
||||
var v1: V = @splat(1);
|
||||
var v2: V = @splat(1);
|
||||
var v3: V = @splat(2);
|
||||
|
||||
try testing.expect(eql(v1, v2));
|
||||
try testing.expect(!eql(v1, v3));
|
||||
|
||||
@@ -107,7 +107,7 @@ pub inline fn iota(comptime T: type, comptime len: usize) @Vector(len, T) {
|
||||
pub fn repeat(comptime len: usize, vec: anytype) @Vector(len, std.meta.Child(@TypeOf(vec))) {
|
||||
const Child = std.meta.Child(@TypeOf(vec));
|
||||
|
||||
return @shuffle(Child, vec, undefined, iota(i32, len) % @splat(len, @as(i32, @intCast(vectorLength(@TypeOf(vec))))));
|
||||
return @shuffle(Child, vec, undefined, iota(i32, len) % @as(@Vector(len, i32), @splat(@intCast(vectorLength(@TypeOf(vec))))));
|
||||
}
|
||||
|
||||
/// Returns a vector containing all elements of the first vector at the lower indices followed by all elements of the second vector
|
||||
@@ -147,11 +147,12 @@ pub fn interlace(vecs: anytype) @Vector(vectorLength(@TypeOf(vecs[0])) * vecs.le
|
||||
const len = a_len + b_len;
|
||||
|
||||
const indices = comptime blk: {
|
||||
const Vi32 = @Vector(len, i32);
|
||||
const count_up = iota(i32, len);
|
||||
const cycle = @divFloor(count_up, @splat(len, @as(i32, @intCast(vecs_arr.len))));
|
||||
const select_mask = repeat(len, join(@splat(a_vec_count, true), @splat(b_vec_count, false)));
|
||||
const a_indices = count_up - cycle * @splat(len, @as(i32, @intCast(b_vec_count)));
|
||||
const b_indices = shiftElementsRight(count_up - cycle * @splat(len, @as(i32, @intCast(a_vec_count))), a_vec_count, 0);
|
||||
const cycle = @divFloor(count_up, @as(Vi32, @splat(@intCast(vecs_arr.len))));
|
||||
const select_mask = repeat(len, join(@as(@Vector(a_vec_count, bool), @splat(true)), @as(@Vector(b_vec_count, bool), @splat(false))));
|
||||
const a_indices = count_up - cycle * @as(Vi32, @splat(@intCast(b_vec_count)));
|
||||
const b_indices = shiftElementsRight(count_up - cycle * @as(Vi32, @splat(@intCast(a_vec_count))), a_vec_count, 0);
|
||||
break :blk @select(i32, select_mask, a_indices, ~b_indices);
|
||||
};
|
||||
|
||||
@@ -174,7 +175,7 @@ pub fn deinterlace(
|
||||
|
||||
comptime var i: usize = 0; // for-loops don't work for this, apparently.
|
||||
inline while (i < out.len) : (i += 1) {
|
||||
const indices = comptime iota(i32, vec_len) * @splat(vec_len, @as(i32, @intCast(vec_count))) + @splat(vec_len, @as(i32, @intCast(i)));
|
||||
const indices = comptime iota(i32, vec_len) * @as(@Vector(vec_len, i32), @splat(@intCast(vec_count))) + @as(@Vector(vec_len, i32), @splat(@intCast(i)));
|
||||
out[i] = @shuffle(Child, interlaced, undefined, indices);
|
||||
}
|
||||
|
||||
@@ -191,7 +192,7 @@ pub fn extract(
|
||||
|
||||
std.debug.assert(@as(comptime_int, @intCast(first)) + @as(comptime_int, @intCast(count)) <= len);
|
||||
|
||||
return @shuffle(Child, vec, undefined, iota(i32, count) + @splat(count, @as(i32, @intCast(first))));
|
||||
return @shuffle(Child, vec, undefined, iota(i32, count) + @as(@Vector(count, i32), @splat(@intCast(first))));
|
||||
}
|
||||
|
||||
test "vector patterns" {
|
||||
@@ -236,17 +237,18 @@ pub fn shiftElementsRight(vec: anytype, comptime amount: VectorCount(@TypeOf(vec
|
||||
// It may be possible to implement shifts and rotates with a runtime-friendly slice of two joined vectors, as the length of the
|
||||
// slice would be comptime-known. This would permit vector shifts and rotates by a non-comptime-known amount.
|
||||
// However, I am unsure whether compiler optimizations would handle that well enough on all platforms.
|
||||
const len = vectorLength(@TypeOf(vec));
|
||||
const V = @TypeOf(vec);
|
||||
const len = vectorLength(V);
|
||||
|
||||
return mergeShift(@splat(len, shift_in), vec, len - amount);
|
||||
return mergeShift(@as(V, @splat(shift_in)), vec, len - amount);
|
||||
}
|
||||
|
||||
/// Elements are shifted leftwards (towards lower indices). New elements are added to the right, and the leftmost elements are cut off
|
||||
/// so that no elements with indices below 0 remain.
|
||||
pub fn shiftElementsLeft(vec: anytype, comptime amount: VectorCount(@TypeOf(vec)), shift_in: std.meta.Child(@TypeOf(vec))) @TypeOf(vec) {
|
||||
const len = vectorLength(@TypeOf(vec));
|
||||
const V = @TypeOf(vec);
|
||||
|
||||
return mergeShift(vec, @splat(len, shift_in), amount);
|
||||
return mergeShift(vec, @as(V, @splat(shift_in)), amount);
|
||||
}
|
||||
|
||||
/// Elements are shifted leftwards (towards lower indices). Elements that leave to the left will reappear to the right in the same order.
|
||||
@@ -263,7 +265,7 @@ pub fn reverseOrder(vec: anytype) @TypeOf(vec) {
|
||||
const Child = std.meta.Child(@TypeOf(vec));
|
||||
const len = vectorLength(@TypeOf(vec));
|
||||
|
||||
return @shuffle(Child, vec, undefined, @splat(len, @as(i32, @intCast(len)) - 1) - iota(i32, len));
|
||||
return @shuffle(Child, vec, undefined, @as(@Vector(len, i32), @splat(@as(i32, @intCast(len)) - 1)) - iota(i32, len));
|
||||
}
|
||||
|
||||
test "vector shifting" {
|
||||
@@ -283,7 +285,8 @@ pub fn firstTrue(vec: anytype) ?VectorIndex(@TypeOf(vec)) {
|
||||
if (!@reduce(.Or, vec)) {
|
||||
return null;
|
||||
}
|
||||
const indices = @select(IndexInt, vec, iota(IndexInt, len), @splat(len, ~@as(IndexInt, 0)));
|
||||
const all_max: @Vector(len, IndexInt) = @splat(~@as(IndexInt, 0));
|
||||
const indices = @select(IndexInt, vec, iota(IndexInt, len), all_max);
|
||||
return @reduce(.Min, indices);
|
||||
}
|
||||
|
||||
@@ -294,7 +297,9 @@ pub fn lastTrue(vec: anytype) ?VectorIndex(@TypeOf(vec)) {
|
||||
if (!@reduce(.Or, vec)) {
|
||||
return null;
|
||||
}
|
||||
const indices = @select(IndexInt, vec, iota(IndexInt, len), @splat(len, @as(IndexInt, 0)));
|
||||
|
||||
const all_zeroes: @Vector(len, IndexInt) = @splat(0);
|
||||
const indices = @select(IndexInt, vec, iota(IndexInt, len), all_zeroes);
|
||||
return @reduce(.Max, indices);
|
||||
}
|
||||
|
||||
@@ -302,26 +307,29 @@ pub fn countTrues(vec: anytype) VectorCount(@TypeOf(vec)) {
|
||||
const len = vectorLength(@TypeOf(vec));
|
||||
const CountIntType = VectorCount(@TypeOf(vec));
|
||||
|
||||
const one_if_true = @select(CountIntType, vec, @splat(len, @as(CountIntType, 1)), @splat(len, @as(CountIntType, 0)));
|
||||
const all_ones: @Vector(len, CountIntType) = @splat(1);
|
||||
const all_zeroes: @Vector(len, CountIntType) = @splat(0);
|
||||
|
||||
const one_if_true = @select(CountIntType, vec, all_ones, all_zeroes);
|
||||
return @reduce(.Add, one_if_true);
|
||||
}
|
||||
|
||||
pub fn firstIndexOfValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) ?VectorIndex(@TypeOf(vec)) {
|
||||
const len = vectorLength(@TypeOf(vec));
|
||||
const V = @TypeOf(vec);
|
||||
|
||||
return firstTrue(vec == @splat(len, value));
|
||||
return firstTrue(vec == @as(V, @splat(value)));
|
||||
}
|
||||
|
||||
pub fn lastIndexOfValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) ?VectorIndex(@TypeOf(vec)) {
|
||||
const len = vectorLength(@TypeOf(vec));
|
||||
const V = @TypeOf(vec);
|
||||
|
||||
return lastTrue(vec == @splat(len, value));
|
||||
return lastTrue(vec == @as(V, @splat(value)));
|
||||
}
|
||||
|
||||
pub fn countElementsWithValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) VectorCount(@TypeOf(vec)) {
|
||||
const len = vectorLength(@TypeOf(vec));
|
||||
const V = @TypeOf(vec);
|
||||
|
||||
return countTrues(vec == @splat(len, value));
|
||||
return countTrues(vec == @as(V, @splat(value)));
|
||||
}
|
||||
|
||||
test "vector searching" {
|
||||
@@ -370,7 +378,6 @@ pub fn prefixScanWithFunc(
|
||||
pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: anytype) @TypeOf(vec) {
|
||||
const VecType = @TypeOf(vec);
|
||||
const Child = std.meta.Child(VecType);
|
||||
const len = vectorLength(VecType);
|
||||
|
||||
const identity = comptime switch (@typeInfo(Child)) {
|
||||
.Bool => switch (op) {
|
||||
@@ -397,8 +404,8 @@ pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: a
|
||||
const fn_container = struct {
|
||||
fn opFn(a: VecType, b: VecType) VecType {
|
||||
return if (Child == bool) switch (op) {
|
||||
.And => @select(bool, a, b, @splat(len, false)),
|
||||
.Or => @select(bool, a, @splat(len, true), b),
|
||||
.And => @select(bool, a, b, @as(VecType, @splat(false))),
|
||||
.Or => @select(bool, a, @as(VecType, @splat(true)), b),
|
||||
.Xor => a != b,
|
||||
else => unreachable,
|
||||
} else switch (op) {
|
||||
@@ -431,7 +438,9 @@ test "vector prefix scan" {
|
||||
const float_base = @Vector(4, f32){ 2, 0.5, -10, 6.54321 };
|
||||
const bool_base = @Vector(4, bool){ true, false, true, false };
|
||||
|
||||
try std.testing.expectEqual(iota(u8, 32) + @splat(32, @as(u8, 1)), prefixScan(.Add, 1, @splat(32, @as(u8, 1))));
|
||||
const ones: @Vector(32, u8) = @splat(1);
|
||||
|
||||
try std.testing.expectEqual(iota(u8, 32) + ones, prefixScan(.Add, 1, ones));
|
||||
try std.testing.expectEqual(@Vector(4, i32){ 11, 3, 1, 1 }, prefixScan(.And, 1, int_base));
|
||||
try std.testing.expectEqual(@Vector(4, i32){ 11, 31, 31, -1 }, prefixScan(.Or, 1, int_base));
|
||||
try std.testing.expectEqual(@Vector(4, i32){ 11, 28, 21, -2 }, prefixScan(.Xor, 1, int_base));
|
||||
|
||||
@@ -606,8 +606,8 @@ test "expectEqual nested array" {
|
||||
}
|
||||
|
||||
test "expectEqual vector" {
|
||||
var a = @splat(4, @as(u32, 4));
|
||||
var b = @splat(4, @as(u32, 4));
|
||||
var a: @Vector(4, u32) = @splat(4);
|
||||
var b: @Vector(4, u32) = @splat(4);
|
||||
|
||||
try expectEqual(a, b);
|
||||
}
|
||||
@@ -903,7 +903,7 @@ test "expectEqualDeep composite type" {
|
||||
try expectEqualDeep([_][]const u8{ "a", "b", "c" }, [_][]const u8{ "a", "b", "c" });
|
||||
|
||||
// vector
|
||||
try expectEqualDeep(@splat(4, @as(u32, 4)), @splat(4, @as(u32, 4)));
|
||||
try expectEqualDeep(@as(@Vector(4, u32), @splat(4)), @as(@Vector(4, u32), @splat(4)));
|
||||
|
||||
// nested array
|
||||
{
|
||||
|
||||
@@ -8591,10 +8591,17 @@ fn builtinCall(
|
||||
},
|
||||
|
||||
.splat => {
|
||||
const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
|
||||
const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]);
|
||||
const result_type = try ri.rl.resultType(gz, node, "@splat");
|
||||
const elem_type = try gz.add(.{
|
||||
.tag = .elem_type_index,
|
||||
.data = .{ .bin = .{
|
||||
.lhs = result_type,
|
||||
.rhs = @as(Zir.Inst.Ref, @enumFromInt(0)),
|
||||
} },
|
||||
});
|
||||
const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);
|
||||
const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
|
||||
.lhs = len,
|
||||
.lhs = result_type,
|
||||
.rhs = scalar,
|
||||
});
|
||||
return rvalue(gz, ri, result, node);
|
||||
|
||||
@@ -792,7 +792,7 @@ pub const list = list: {
|
||||
"@splat",
|
||||
.{
|
||||
.tag = .splat,
|
||||
.param_count = 2,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
.{
|
||||
|
||||
49
src/Sema.zig
49
src/Sema.zig
@@ -1820,7 +1820,7 @@ pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Ins
|
||||
return ty;
|
||||
}
|
||||
|
||||
fn resolveCastDestType(
|
||||
fn resolveDestType(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
@@ -8337,7 +8337,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const src = inst_data.src();
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@enumFromInt");
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@enumFromInt");
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
|
||||
if (dest_ty.zigTypeTag(mod) != .Enum) {
|
||||
@@ -9666,7 +9666,7 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
|
||||
const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@intCast");
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intCast");
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
|
||||
return sema.intCast(block, inst_data.src(), dest_ty, src, operand, operand_src, true);
|
||||
@@ -9827,7 +9827,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
|
||||
const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@bitCast");
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@bitCast");
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
switch (dest_ty.zigTypeTag(mod)) {
|
||||
@@ -9970,7 +9970,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
|
||||
const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast");
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast");
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
|
||||
const target = mod.getTarget();
|
||||
@@ -20783,7 +20783,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
|
||||
const src = inst_data.src();
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@intFromFloat");
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intFromFloat");
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
|
||||
@@ -20823,7 +20823,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
|
||||
const src = inst_data.src();
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@floatFromInt");
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatFromInt");
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
|
||||
@@ -20852,7 +20852,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
|
||||
const operand_res = try sema.resolveInst(extra.rhs);
|
||||
const operand_coerced = try sema.coerce(block, Type.usize, operand_res, operand_src);
|
||||
|
||||
const ptr_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu, "@ptrFromInt");
|
||||
const ptr_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrFromInt");
|
||||
try sema.checkPtrType(block, src, ptr_ty);
|
||||
const elem_ty = ptr_ty.elemType2(mod);
|
||||
const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema);
|
||||
@@ -20910,7 +20910,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
|
||||
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
||||
const src = LazySrcLoc.nodeOffset(extra.node);
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
|
||||
const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@errSetCast");
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@errSetCast");
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
try sema.checkErrorSetType(block, src, dest_ty);
|
||||
@@ -20997,7 +20997,7 @@ fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa
|
||||
const src = LazySrcLoc.nodeOffset(extra.node);
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node };
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu, flags.needResultTypeBuiltinName());
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, flags.needResultTypeBuiltinName());
|
||||
return sema.ptrCastFull(
|
||||
block,
|
||||
flags,
|
||||
@@ -21013,7 +21013,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
const src = inst_data.src();
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu, "@ptrCast");
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrCast");
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
|
||||
return sema.ptrCastFull(
|
||||
@@ -21426,7 +21426,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
const src = inst_data.src();
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@truncate");
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@truncate");
|
||||
const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, src);
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
@@ -22358,23 +22358,22 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
|
||||
const mod = sema.mod;
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const len_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
|
||||
const scalar_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
|
||||
const len = @as(u32, @intCast(try sema.resolveInt(block, len_src, extra.lhs, Type.u32, "vector splat destination length must be comptime-known")));
|
||||
const scalar = try sema.resolveInst(extra.rhs);
|
||||
const scalar_ty = sema.typeOf(scalar);
|
||||
try sema.checkVectorElemType(block, scalar_src, scalar_ty);
|
||||
const vector_ty = try mod.vectorType(.{
|
||||
.len = len,
|
||||
.child = scalar_ty.toIntern(),
|
||||
});
|
||||
const src = inst_data.src();
|
||||
const scalar_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@splat");
|
||||
|
||||
if (!dest_ty.isVector(mod)) return sema.fail(block, src, "expected vector type, found '{}'", .{dest_ty.fmt(mod)});
|
||||
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
const scalar_ty = dest_ty.childType(mod);
|
||||
const scalar = try sema.coerce(block, scalar_ty, operand, scalar_src);
|
||||
if (try sema.resolveMaybeUndefVal(scalar)) |scalar_val| {
|
||||
if (scalar_val.isUndef(mod)) return sema.addConstUndef(vector_ty);
|
||||
return sema.addConstant(try sema.splat(vector_ty, scalar_val));
|
||||
if (scalar_val.isUndef(mod)) return sema.addConstUndef(dest_ty);
|
||||
return sema.addConstant(try sema.splat(dest_ty, scalar_val));
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, inst_data.src(), scalar_src);
|
||||
return block.addTyOp(.splat, vector_ty, scalar);
|
||||
return block.addTyOp(.splat, dest_ty, scalar);
|
||||
}
|
||||
|
||||
fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
|
||||
@@ -2799,14 +2799,14 @@ fn transInitListExprVector(
|
||||
const element_qt = vector_ty.getElementType();
|
||||
|
||||
if (init_count == 0) {
|
||||
const zero_node = try Tag.as.create(c.arena, .{
|
||||
.lhs = try transQualType(c, scope, element_qt, loc),
|
||||
.rhs = Tag.zero_literal.init(),
|
||||
const vec_node = try Tag.vector.create(c.arena, .{
|
||||
.lhs = try transCreateNodeNumber(c, num_elements, .int),
|
||||
.rhs = try transQualType(c, scope, element_qt, loc),
|
||||
});
|
||||
|
||||
return Tag.vector_zero_init.create(c.arena, .{
|
||||
.lhs = try transCreateNodeNumber(c, num_elements, .int),
|
||||
.rhs = zero_node,
|
||||
return Tag.as.create(c.arena, .{
|
||||
.lhs = vec_node,
|
||||
.rhs = try Tag.vector_zero_init.create(c.arena, Tag.zero_literal.init()),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ pub const Node = extern union {
|
||||
div_exact,
|
||||
/// @offsetOf(lhs, rhs)
|
||||
offset_of,
|
||||
/// @splat(lhs, rhs)
|
||||
/// @splat(operand)
|
||||
vector_zero_init,
|
||||
/// @shuffle(type, a, b, mask)
|
||||
shuffle,
|
||||
@@ -284,6 +284,7 @@ pub const Node = extern union {
|
||||
.int_cast,
|
||||
.const_cast,
|
||||
.volatile_cast,
|
||||
.vector_zero_init,
|
||||
=> Payload.UnOp,
|
||||
|
||||
.add,
|
||||
@@ -334,7 +335,6 @@ pub const Node = extern union {
|
||||
.div_exact,
|
||||
.offset_of,
|
||||
.helpers_cast,
|
||||
.vector_zero_init,
|
||||
=> Payload.BinOp,
|
||||
|
||||
.integer_literal,
|
||||
@@ -1918,7 +1918,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
|
||||
},
|
||||
.vector_zero_init => {
|
||||
const payload = node.castTag(.vector_zero_init).?.data;
|
||||
return renderBuiltinCall(c, "@splat", &.{ payload.lhs, payload.rhs });
|
||||
return renderBuiltinCall(c, "@splat", &.{payload});
|
||||
},
|
||||
.field_access => {
|
||||
const payload = node.castTag(.field_access).?.data;
|
||||
|
||||
@@ -3178,12 +3178,6 @@ zig_bitCast_float(f64, uint64_t)
|
||||
zig_bitCast_float(f80, zig_u128)
|
||||
zig_bitCast_float(f128, zig_u128)
|
||||
|
||||
#define zig_cast_f16
|
||||
#define zig_cast_f32
|
||||
#define zig_cast_f64
|
||||
#define zig_cast_f80
|
||||
#define zig_cast_f128
|
||||
|
||||
#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \
|
||||
zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
|
||||
zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \
|
||||
|
||||
BIN
stage1/zig1.wasm
BIN
stage1/zig1.wasm
Binary file not shown.
@@ -396,7 +396,7 @@ test "bitcast vector to integer and back" {
|
||||
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
||||
|
||||
const arr: [16]bool = [_]bool{ true, false } ++ [_]bool{true} ** 14;
|
||||
var x = @splat(16, true);
|
||||
var x: @Vector(16, bool) = @splat(true);
|
||||
x[1] = false;
|
||||
try expect(@as(u16, @bitCast(x)) == comptime @as(u16, @bitCast(@as(@Vector(16, bool), arr))));
|
||||
}
|
||||
|
||||
@@ -639,7 +639,7 @@ test "vector casts" {
|
||||
}
|
||||
|
||||
fn doTheTestFloat() !void {
|
||||
var vec = @splat(2, @as(f32, 1234.0));
|
||||
var vec: @Vector(2, f32) = @splat(1234.0);
|
||||
var wider: @Vector(2, f64) = vec;
|
||||
try expect(wider[0] == 1234.0);
|
||||
try expect(wider[1] == 1234.0);
|
||||
|
||||
@@ -111,13 +111,17 @@ test "@clz vectors" {
|
||||
}
|
||||
|
||||
fn testClzVectors() !void {
|
||||
const Vu4 = @Vector(64, u4);
|
||||
const Vu8 = @Vector(64, u8);
|
||||
const Vu128 = @Vector(64, u128);
|
||||
|
||||
@setEvalBranchQuota(10_000);
|
||||
try testOneClzVector(u8, 64, @splat(64, @as(u8, 0b10001010)), @splat(64, @as(u4, 0)));
|
||||
try testOneClzVector(u8, 64, @splat(64, @as(u8, 0b00001010)), @splat(64, @as(u4, 4)));
|
||||
try testOneClzVector(u8, 64, @splat(64, @as(u8, 0b00011010)), @splat(64, @as(u4, 3)));
|
||||
try testOneClzVector(u8, 64, @splat(64, @as(u8, 0b00000000)), @splat(64, @as(u4, 8)));
|
||||
try testOneClzVector(u128, 64, @splat(64, @as(u128, 0xffffffffffffffff)), @splat(64, @as(u8, 64)));
|
||||
try testOneClzVector(u128, 64, @splat(64, @as(u128, 0x10000000000000000)), @splat(64, @as(u8, 63)));
|
||||
try testOneClzVector(u8, 64, @as(Vu8, @splat(0b10001010)), @as(Vu4, @splat(0)));
|
||||
try testOneClzVector(u8, 64, @as(Vu8, @splat(0b00001010)), @as(Vu4, @splat(4)));
|
||||
try testOneClzVector(u8, 64, @as(Vu8, @splat(0b00011010)), @as(Vu4, @splat(3)));
|
||||
try testOneClzVector(u8, 64, @as(Vu8, @splat(0b00000000)), @as(Vu4, @splat(8)));
|
||||
try testOneClzVector(u128, 64, @as(Vu128, @splat(0xffffffffffffffff)), @as(Vu8, @splat(64)));
|
||||
try testOneClzVector(u128, 64, @as(Vu128, @splat(0x10000000000000000)), @as(Vu8, @splat(63)));
|
||||
}
|
||||
|
||||
fn testOneClzVector(
|
||||
@@ -180,11 +184,13 @@ test "@ctz vectors" {
|
||||
}
|
||||
|
||||
fn testCtzVectors() !void {
|
||||
const Vu4 = @Vector(64, u4);
|
||||
const Vu8 = @Vector(64, u8);
|
||||
@setEvalBranchQuota(10_000);
|
||||
try testOneCtzVector(u8, 64, @splat(64, @as(u8, 0b10100000)), @splat(64, @as(u4, 5)));
|
||||
try testOneCtzVector(u8, 64, @splat(64, @as(u8, 0b10001010)), @splat(64, @as(u4, 1)));
|
||||
try testOneCtzVector(u8, 64, @splat(64, @as(u8, 0b00000000)), @splat(64, @as(u4, 8)));
|
||||
try testOneCtzVector(u16, 64, @splat(64, @as(u16, 0b00000000)), @splat(64, @as(u5, 16)));
|
||||
try testOneCtzVector(u8, 64, @as(Vu8, @splat(0b10100000)), @as(Vu4, @splat(5)));
|
||||
try testOneCtzVector(u8, 64, @as(Vu8, @splat(0b10001010)), @as(Vu4, @splat(1)));
|
||||
try testOneCtzVector(u8, 64, @as(Vu8, @splat(0b00000000)), @as(Vu4, @splat(8)));
|
||||
try testOneCtzVector(u16, 64, @as(@Vector(64, u16), @splat(0b00000000)), @as(@Vector(64, u5), @splat(16)));
|
||||
}
|
||||
|
||||
fn testOneCtzVector(
|
||||
|
||||
@@ -299,8 +299,7 @@ test "vector @splat" {
|
||||
const S = struct {
|
||||
fn testForT(comptime N: comptime_int, v: anytype) !void {
|
||||
const T = @TypeOf(v);
|
||||
var vec = @splat(N, v);
|
||||
try expect(@Vector(N, T) == @TypeOf(vec));
|
||||
var vec: @Vector(N, T) = @splat(v);
|
||||
var as_array = @as([N]T, vec);
|
||||
for (as_array) |elem| try expect(v == elem);
|
||||
}
|
||||
@@ -458,26 +457,28 @@ test "vector comparison operators" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
{
|
||||
var v1: @Vector(4, bool) = [_]bool{ true, false, true, false };
|
||||
var v2: @Vector(4, bool) = [_]bool{ false, true, false, true };
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 == v1)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v1 == v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 != v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v2 != v2)));
|
||||
const V = @Vector(4, bool);
|
||||
var v1: V = [_]bool{ true, false, true, false };
|
||||
var v2: V = [_]bool{ false, true, false, true };
|
||||
try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 == v1)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v1 == v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 != v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v2 != v2)));
|
||||
}
|
||||
{
|
||||
var v1 = @splat(4, @as(u32, 0xc0ffeeee));
|
||||
const V = @Vector(4, bool);
|
||||
var v1: @Vector(4, u32) = @splat(0xc0ffeeee);
|
||||
var v2: @Vector(4, c_uint) = v1;
|
||||
var v3 = @splat(4, @as(u32, 0xdeadbeef));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 == v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v1 == v3)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 != v3)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v1 != v2)));
|
||||
var v3: @Vector(4, u32) = @splat(0xdeadbeef);
|
||||
try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 == v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v1 == v3)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 != v3)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v1 != v2)));
|
||||
}
|
||||
{
|
||||
// Comptime-known LHS/RHS
|
||||
var v1: @Vector(4, u32) = [_]u32{ 2, 1, 2, 1 };
|
||||
const v2 = @splat(4, @as(u32, 2));
|
||||
const v2: @Vector(4, u32) = @splat(2);
|
||||
const v3: @Vector(4, bool) = [_]bool{ true, false, true, false };
|
||||
try expect(mem.eql(bool, &@as([4]bool, v3), &@as([4]bool, v1 == v2)));
|
||||
try expect(mem.eql(bool, &@as([4]bool, v3), &@as([4]bool, v2 == v1)));
|
||||
@@ -847,8 +848,10 @@ test "vector @reduce comptime" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
const value = @Vector(4, i32){ 1, -1, 1, -1 };
|
||||
const result = value > @splat(4, @as(i32, 0));
|
||||
const V = @Vector(4, i32);
|
||||
|
||||
const value = V{ 1, -1, 1, -1 };
|
||||
const result = value > @as(V, @splat(0));
|
||||
// result is { true, false, true, false };
|
||||
try comptime expect(@TypeOf(result) == @Vector(4, bool));
|
||||
const is_all_true = @reduce(.And, result);
|
||||
@@ -1270,7 +1273,7 @@ test "array operands to shuffle are coerced to vectors" {
|
||||
const mask = [5]i32{ -1, 0, 1, 2, 3 };
|
||||
|
||||
var a = [5]u32{ 3, 5, 7, 9, 0 };
|
||||
var b = @shuffle(u32, a, @splat(5, @as(u24, 0)), mask);
|
||||
var b = @shuffle(u32, a, @as(@Vector(5, u24), @splat(0)), mask);
|
||||
try expectEqual([_]u32{ 0, 3, 5, 7, 9 }, b);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
export fn entry() void {
|
||||
const c = 4;
|
||||
var v = @splat(4, c);
|
||||
_ = v;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:23: error: expected integer, float, bool, or pointer for the vector element type; found 'comptime_int'
|
||||
@@ -1,13 +1,13 @@
|
||||
pub export fn entry1() void {
|
||||
var x: u32 = 3;
|
||||
_ = @shuffle(u32, [_]u32{0}, @splat(1, @as(u32, 0)), [_]i8{
|
||||
_ = @shuffle(u32, [_]u32{0}, @as(@Vector(1, u32), @splat(0)), [_]i8{
|
||||
if (x > 1) 1 else -1,
|
||||
});
|
||||
}
|
||||
|
||||
pub export fn entry2() void {
|
||||
var y: ?i8 = -1;
|
||||
_ = @shuffle(u32, [_]u32{0}, @splat(1, @as(u32, 0)), [_]i8{
|
||||
_ = @shuffle(u32, [_]u32{0}, @as(@Vector(1, u32), @splat(0)), [_]i8{
|
||||
y orelse 1,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usi
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var x = @splat(4, @as(i32, -2147483647));
|
||||
var x: @Vector(4, i32) = @splat(-2147483647);
|
||||
var y: @Vector(4, u32) = @intCast(x);
|
||||
_ = y;
|
||||
return error.TestFailed;
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usi
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var x = @splat(4, @as(u32, 0xdeadbeef));
|
||||
var x: @Vector(4, u32) = @splat(0xdeadbeef);
|
||||
var y: @Vector(4, u16) = @intCast(x);
|
||||
_ = y;
|
||||
return error.TestFailed;
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usi
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var x = @splat(4, @as(u32, 0x80000000));
|
||||
var x: @Vector(4, u32) = @splat(0x80000000);
|
||||
var y: @Vector(4, i32) = @intCast(x);
|
||||
_ = y;
|
||||
return error.TestFailed;
|
||||
|
||||
Reference in New Issue
Block a user