| author | |
| committer | |
| log | e05c242cd89d03ae67fa7b8d5fc33fb5dc42dbe3 |
| tree | a9224a9d47bfda3873284718515cccda78ec32ba |
| parent | d78517f4f0f540f0d0254a78e47a7b4a30e98c74 |
| parent | 47d5bf26164b4ddb3228d17ae2158d1c29b8d040 |
| signature |
Apply RLS to @splat builtin, eliminating its length parameter24 files changed, 174 insertions(+), 156 deletions(-)
doc/langref.html.in+7-7| ... | ... | @@ -9239,10 +9239,10 @@ test "vector @shuffle" { |
| 9239 | 9239 | {#header_close#} |
| 9240 | 9240 | |
| 9241 | 9241 | {#header_open|@splat#} |
| 9242 | <pre>{#syntax#}@splat(comptime len: u32, scalar: anytype) @Vector(len, @TypeOf(scalar)){#endsyntax#}</pre> | |
| 9242 | <pre>{#syntax#}@splat(scalar: anytype) anytype{#endsyntax#}</pre> | |
| 9243 | 9243 | <p> |
| 9244 | Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value | |
| 9245 | {#syntax#}scalar{#endsyntax#}: | |
| 9244 | Produces a vector where each element is the value {#syntax#}scalar{#endsyntax#}. | |
| 9245 | The return type and thus the length of the vector is inferred. | |
| 9246 | 9246 | </p> |
| 9247 | 9247 | {#code_begin|test|test_splat_builtin#} |
| 9248 | 9248 | const std = @import("std"); |
| ... | ... | @@ -9250,8 +9250,7 @@ const expect = std.testing.expect; |
| 9250 | 9250 | |
| 9251 | 9251 | test "vector @splat" { |
| 9252 | 9252 | const scalar: u32 = 5; |
| 9253 | const result = @splat(4, scalar); | |
| 9254 | try comptime expect(@TypeOf(result) == @Vector(4, u32)); | |
| 9253 | const result: @Vector(4, u32) = @splat(scalar); | |
| 9255 | 9254 | try expect(std.mem.eql(u32, &@as([4]u32, result), &[_]u32{ 5, 5, 5, 5 })); |
| 9256 | 9255 | } |
| 9257 | 9256 | {#code_end#} |
| ... | ... | @@ -9292,8 +9291,9 @@ const std = @import("std"); |
| 9292 | 9291 | const expect = std.testing.expect; |
| 9293 | 9292 | |
| 9294 | 9293 | test "vector @reduce" { |
| 9295 | const value = @Vector(4, i32){ 1, -1, 1, -1 }; | |
| 9296 | const result = value > @splat(4, @as(i32, 0)); | |
| 9294 | const V = @Vector(4, i32); | |
| 9295 | const value = V{ 1, -1, 1, -1 }; | |
| 9296 | const result = value > @as(V, @splat(0)); | |
| 9297 | 9297 | // result is { true, false, true, false }; |
| 9298 | 9298 | try comptime expect(@TypeOf(result) == @Vector(4, bool)); |
| 9299 | 9299 | const is_all_true = @reduce(.And, result); |
lib/std/http/protocol.zig+2-2| ... | ... | @@ -182,8 +182,8 @@ pub const HeadersParser = struct { |
| 182 | 182 | |
| 183 | 183 | const chunk = bytes[index..][0..vector_len]; |
| 184 | 184 | const v: Vector = chunk.*; |
| 185 | const matches_r = @as(BitVector, @bitCast(v == @splat(vector_len, @as(u8, '\r')))); | |
| 186 | const matches_n = @as(BitVector, @bitCast(v == @splat(vector_len, @as(u8, '\n')))); | |
| 185 | const matches_r = @as(BitVector, @bitCast(v == @as(Vector, @splat('\r')))); | |
| 186 | const matches_n = @as(BitVector, @bitCast(v == @as(Vector, @splat('\n')))); | |
| 187 | 187 | const matches_or: SizeVector = matches_r | matches_n; |
| 188 | 188 | |
| 189 | 189 | const matches = @reduce(.Add, matches_or); |
lib/std/json/stringify_test.zig+1-1| ... | ... | @@ -197,7 +197,7 @@ test "stringify struct with custom stringifier" { |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | 199 | test "stringify vector" { |
| 200 | try teststringify("[1,1]", @splat(2, @as(u32, 1)), StringifyOptions{}); | |
| 200 | try teststringify("[1,1]", @as(@Vector(2, u32), @splat(1)), StringifyOptions{}); | |
| 201 | 201 | } |
| 202 | 202 | |
| 203 | 203 | test "stringify tuple" { |
lib/std/math.zig+31-21| ... | ... | @@ -507,8 +507,8 @@ pub fn shl(comptime T: type, a: T, shift_amt: anytype) T { |
| 507 | 507 | if (@typeInfo(T) == .Vector) { |
| 508 | 508 | const C = @typeInfo(T).Vector.child; |
| 509 | 509 | const len = @typeInfo(T).Vector.len; |
| 510 | if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(len, @as(C, 0)); | |
| 511 | break :blk @splat(len, @as(Log2Int(C), @intCast(abs_shift_amt))); | |
| 510 | if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(0); | |
| 511 | break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt)))); | |
| 512 | 512 | } else { |
| 513 | 513 | if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0; |
| 514 | 514 | 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 { |
| 551 | 551 | if (@typeInfo(T) == .Vector) { |
| 552 | 552 | const C = @typeInfo(T).Vector.child; |
| 553 | 553 | const len = @typeInfo(T).Vector.len; |
| 554 | if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(len, @as(C, 0)); | |
| 555 | break :blk @splat(len, @as(Log2Int(C), @intCast(abs_shift_amt))); | |
| 554 | if (abs_shift_amt >= @typeInfo(C).Int.bits) return @splat(0); | |
| 555 | break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt)))); | |
| 556 | 556 | } else { |
| 557 | 557 | if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0; |
| 558 | 558 | break :blk @as(Log2Int(T), @intCast(abs_shift_amt)); |
| ... | ... | @@ -597,7 +597,7 @@ pub fn rotr(comptime T: type, x: T, r: anytype) T { |
| 597 | 597 | @compileError("cannot rotate signed integers"); |
| 598 | 598 | } |
| 599 | 599 | const ar = @as(Log2Int(C), @intCast(@mod(r, @typeInfo(C).Int.bits))); |
| 600 | return (x >> @splat(@typeInfo(T).Vector.len, ar)) | (x << @splat(@typeInfo(T).Vector.len, 1 + ~ar)); | |
| 600 | return (x >> @splat(ar)) | (x << @splat(1 + ~ar)); | |
| 601 | 601 | } else if (@typeInfo(T).Int.signedness == .signed) { |
| 602 | 602 | @compileError("cannot rotate signed integer"); |
| 603 | 603 | } else { |
| ... | ... | @@ -641,7 +641,7 @@ pub fn rotl(comptime T: type, x: T, r: anytype) T { |
| 641 | 641 | @compileError("cannot rotate signed integers"); |
| 642 | 642 | } |
| 643 | 643 | const ar = @as(Log2Int(C), @intCast(@mod(r, @typeInfo(C).Int.bits))); |
| 644 | return (x << @splat(@typeInfo(T).Vector.len, ar)) | (x >> @splat(@typeInfo(T).Vector.len, 1 +% ~ar)); | |
| 644 | return (x << @splat(ar)) | (x >> @splat(1 +% ~ar)); | |
| 645 | 645 | } else if (@typeInfo(T).Int.signedness == .signed) { |
| 646 | 646 | @compileError("cannot rotate signed integer"); |
| 647 | 647 | } else { |
| ... | ... | @@ -794,10 +794,10 @@ pub fn absInt(x: anytype) !@TypeOf(x) { |
| 794 | 794 | switch (@typeInfo(vinfo.child)) { |
| 795 | 795 | .Int => |info| { |
| 796 | 796 | comptime assert(info.signedness == .signed); // must pass a signed integer to absInt |
| 797 | if (@reduce(.Or, x == @splat(vinfo.len, @as(vinfo.child, minInt(vinfo.child))))) { | |
| 797 | if (@reduce(.Or, x == @as(T, @splat(minInt(vinfo.child))))) { | |
| 798 | 798 | return error.Overflow; |
| 799 | 799 | } |
| 800 | const zero = @splat(vinfo.len, @as(vinfo.child, 0)); | |
| 800 | const zero: T = @splat(0); | |
| 801 | 801 | break :blk @select(vinfo.child, x > zero, x, -x); |
| 802 | 802 | }, |
| 803 | 803 | 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) { |
| 1368 | 1368 | |
| 1369 | 1369 | switch (@typeInfo(Type)) { |
| 1370 | 1370 | .Float, .ComptimeFloat => assert(t >= 0 and t <= 1), |
| 1371 | .Vector => |vector| { | |
| 1372 | const lower_bound = @reduce(.And, t >= @splat(vector.len, @as(vector.child, 0))); | |
| 1373 | const upper_bound = @reduce(.And, t <= @splat(vector.len, @as(vector.child, 1))); | |
| 1371 | .Vector => { | |
| 1372 | const lower_bound = @reduce(.And, t >= @as(Type, @splat(0))); | |
| 1373 | const upper_bound = @reduce(.And, t <= @as(Type, @splat(1))); | |
| 1374 | 1374 | assert(lower_bound and upper_bound); |
| 1375 | 1375 | }, |
| 1376 | 1376 | else => comptime unreachable, |
| ... | ... | @@ -1392,14 +1392,24 @@ test "lerp" { |
| 1392 | 1392 | try testing.expectEqual(@as(f32, 1.0), lerp(@as(f32, 1.0e7), 1.0, 1.0)); |
| 1393 | 1393 | try testing.expectEqual(@as(f64, 1.0), lerp(@as(f64, 1.0e15), 1.0, 1.0)); |
| 1394 | 1394 | |
| 1395 | try testing.expectEqual( | |
| 1396 | lerp(@splat(3, @as(f32, 0)), @splat(3, @as(f32, 50)), @splat(3, @as(f32, 0.5))), | |
| 1397 | @Vector(3, f32){ 25, 25, 25 }, | |
| 1398 | ); | |
| 1399 | try testing.expectEqual( | |
| 1400 | lerp(@splat(3, @as(f64, 50)), @splat(3, @as(f64, 100)), @splat(3, @as(f64, 0.5))), | |
| 1401 | @Vector(3, f64){ 75, 75, 75 }, | |
| 1402 | ); | |
| 1395 | { | |
| 1396 | const a: @Vector(3, f32) = @splat(0); | |
| 1397 | const b: @Vector(3, f32) = @splat(50); | |
| 1398 | const t: @Vector(3, f32) = @splat(0.5); | |
| 1399 | try testing.expectEqual( | |
| 1400 | lerp(a, b, t), | |
| 1401 | @Vector(3, f32){ 25, 25, 25 }, | |
| 1402 | ); | |
| 1403 | } | |
| 1404 | { | |
| 1405 | const a: @Vector(3, f64) = @splat(50); | |
| 1406 | const b: @Vector(3, f64) = @splat(100); | |
| 1407 | const t: @Vector(3, f64) = @splat(0.5); | |
| 1408 | try testing.expectEqual( | |
| 1409 | lerp(a, b, t), | |
| 1410 | @Vector(3, f64){ 75, 75, 75 }, | |
| 1411 | ); | |
| 1412 | } | |
| 1403 | 1413 | } |
| 1404 | 1414 | |
| 1405 | 1415 | /// Returns the maximum value of integer type T. |
| ... | ... | @@ -1719,8 +1729,8 @@ pub inline fn sign(i: anytype) @TypeOf(i) { |
| 1719 | 1729 | .Vector => |vinfo| blk: { |
| 1720 | 1730 | switch (@typeInfo(vinfo.child)) { |
| 1721 | 1731 | .Int, .Float => { |
| 1722 | const zero = @splat(vinfo.len, @as(vinfo.child, 0)); | |
| 1723 | const one = @splat(vinfo.len, @as(vinfo.child, 1)); | |
| 1732 | const zero: T = @splat(0); | |
| 1733 | const one: T = @splat(1); | |
| 1724 | 1734 | break :blk @select(vinfo.child, i > zero, one, zero) - @select(vinfo.child, i < zero, one, zero); |
| 1725 | 1735 | }, |
| 1726 | 1736 | else => @compileError("Expected vector of ints or floats, found " ++ @typeName(T)), |
lib/std/mem.zig+4-4| ... | ... | @@ -289,7 +289,7 @@ pub fn zeroes(comptime T: type) T { |
| 289 | 289 | return [_]info.child{zeroes(info.child)} ** info.len; |
| 290 | 290 | }, |
| 291 | 291 | .Vector => |info| { |
| 292 | return @splat(info.len, zeroes(info.child)); | |
| 292 | return @splat(zeroes(info.child)); | |
| 293 | 293 | }, |
| 294 | 294 | .Union => |info| { |
| 295 | 295 | if (comptime meta.containerLayout(T) == .Extern) { |
| ... | ... | @@ -393,9 +393,9 @@ test "zeroes" { |
| 393 | 393 | for (b.array) |e| { |
| 394 | 394 | try testing.expectEqual(@as(u32, 0), e); |
| 395 | 395 | } |
| 396 | try testing.expectEqual(@splat(2, @as(u32, 0)), b.vector_u32); | |
| 397 | try testing.expectEqual(@splat(2, @as(f32, 0.0)), b.vector_f32); | |
| 398 | try testing.expectEqual(@splat(2, @as(bool, false)), b.vector_bool); | |
| 396 | try testing.expectEqual(@as(@TypeOf(b.vector_u32), @splat(0)), b.vector_u32); | |
| 397 | try testing.expectEqual(@as(@TypeOf(b.vector_f32), @splat(0.0)), b.vector_f32); | |
| 398 | try testing.expectEqual(@as(@TypeOf(b.vector_bool), @splat(false)), b.vector_bool); | |
| 399 | 399 | try testing.expectEqual(@as(?u8, null), b.optional_int); |
| 400 | 400 | for (b.sentinel) |e| { |
| 401 | 401 | try testing.expectEqual(@as(u8, 0), e); |
lib/std/meta.zig+4-3| ... | ... | @@ -860,9 +860,10 @@ test "std.meta.eql" { |
| 860 | 860 | try testing.expect(eql(EU.tst(false), EU.tst(false))); |
| 861 | 861 | try testing.expect(!eql(EU.tst(false), EU.tst(true))); |
| 862 | 862 | |
| 863 | var v1 = @splat(4, @as(u32, 1)); | |
| 864 | var v2 = @splat(4, @as(u32, 1)); | |
| 865 | var v3 = @splat(4, @as(u32, 2)); | |
| 863 | const V = @Vector(4, u32); | |
| 864 | var v1: V = @splat(1); | |
| 865 | var v2: V = @splat(1); | |
| 866 | var v3: V = @splat(2); | |
| 866 | 867 | |
| 867 | 868 | try testing.expect(eql(v1, v2)); |
| 868 | 869 | try testing.expect(!eql(v1, v3)); |
lib/std/simd.zig+34-25| ... | ... | @@ -107,7 +107,7 @@ pub inline fn iota(comptime T: type, comptime len: usize) @Vector(len, T) { |
| 107 | 107 | pub fn repeat(comptime len: usize, vec: anytype) @Vector(len, std.meta.Child(@TypeOf(vec))) { |
| 108 | 108 | const Child = std.meta.Child(@TypeOf(vec)); |
| 109 | 109 | |
| 110 | return @shuffle(Child, vec, undefined, iota(i32, len) % @splat(len, @as(i32, @intCast(vectorLength(@TypeOf(vec)))))); | |
| 110 | return @shuffle(Child, vec, undefined, iota(i32, len) % @as(@Vector(len, i32), @splat(@intCast(vectorLength(@TypeOf(vec)))))); | |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | /// 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 |
| 147 | 147 | const len = a_len + b_len; |
| 148 | 148 | |
| 149 | 149 | const indices = comptime blk: { |
| 150 | const Vi32 = @Vector(len, i32); | |
| 150 | 151 | const count_up = iota(i32, len); |
| 151 | const cycle = @divFloor(count_up, @splat(len, @as(i32, @intCast(vecs_arr.len)))); | |
| 152 | const select_mask = repeat(len, join(@splat(a_vec_count, true), @splat(b_vec_count, false))); | |
| 153 | const a_indices = count_up - cycle * @splat(len, @as(i32, @intCast(b_vec_count))); | |
| 154 | const b_indices = shiftElementsRight(count_up - cycle * @splat(len, @as(i32, @intCast(a_vec_count))), a_vec_count, 0); | |
| 152 | const cycle = @divFloor(count_up, @as(Vi32, @splat(@intCast(vecs_arr.len)))); | |
| 153 | const select_mask = repeat(len, join(@as(@Vector(a_vec_count, bool), @splat(true)), @as(@Vector(b_vec_count, bool), @splat(false)))); | |
| 154 | const a_indices = count_up - cycle * @as(Vi32, @splat(@intCast(b_vec_count))); | |
| 155 | const b_indices = shiftElementsRight(count_up - cycle * @as(Vi32, @splat(@intCast(a_vec_count))), a_vec_count, 0); | |
| 155 | 156 | break :blk @select(i32, select_mask, a_indices, ~b_indices); |
| 156 | 157 | }; |
| 157 | 158 | |
| ... | ... | @@ -174,7 +175,7 @@ pub fn deinterlace( |
| 174 | 175 | |
| 175 | 176 | comptime var i: usize = 0; // for-loops don't work for this, apparently. |
| 176 | 177 | inline while (i < out.len) : (i += 1) { |
| 177 | const indices = comptime iota(i32, vec_len) * @splat(vec_len, @as(i32, @intCast(vec_count))) + @splat(vec_len, @as(i32, @intCast(i))); | |
| 178 | const indices = comptime iota(i32, vec_len) * @as(@Vector(vec_len, i32), @splat(@intCast(vec_count))) + @as(@Vector(vec_len, i32), @splat(@intCast(i))); | |
| 178 | 179 | out[i] = @shuffle(Child, interlaced, undefined, indices); |
| 179 | 180 | } |
| 180 | 181 | |
| ... | ... | @@ -191,7 +192,7 @@ pub fn extract( |
| 191 | 192 | |
| 192 | 193 | std.debug.assert(@as(comptime_int, @intCast(first)) + @as(comptime_int, @intCast(count)) <= len); |
| 193 | 194 | |
| 194 | return @shuffle(Child, vec, undefined, iota(i32, count) + @splat(count, @as(i32, @intCast(first)))); | |
| 195 | return @shuffle(Child, vec, undefined, iota(i32, count) + @as(@Vector(count, i32), @splat(@intCast(first)))); | |
| 195 | 196 | } |
| 196 | 197 | |
| 197 | 198 | test "vector patterns" { |
| ... | ... | @@ -236,17 +237,18 @@ pub fn shiftElementsRight(vec: anytype, comptime amount: VectorCount(@TypeOf(vec |
| 236 | 237 | // It may be possible to implement shifts and rotates with a runtime-friendly slice of two joined vectors, as the length of the |
| 237 | 238 | // slice would be comptime-known. This would permit vector shifts and rotates by a non-comptime-known amount. |
| 238 | 239 | // However, I am unsure whether compiler optimizations would handle that well enough on all platforms. |
| 239 | const len = vectorLength(@TypeOf(vec)); | |
| 240 | const V = @TypeOf(vec); | |
| 241 | const len = vectorLength(V); | |
| 240 | 242 | |
| 241 | return mergeShift(@splat(len, shift_in), vec, len - amount); | |
| 243 | return mergeShift(@as(V, @splat(shift_in)), vec, len - amount); | |
| 242 | 244 | } |
| 243 | 245 | |
| 244 | 246 | /// Elements are shifted leftwards (towards lower indices). New elements are added to the right, and the leftmost elements are cut off |
| 245 | 247 | /// so that no elements with indices below 0 remain. |
| 246 | 248 | pub fn shiftElementsLeft(vec: anytype, comptime amount: VectorCount(@TypeOf(vec)), shift_in: std.meta.Child(@TypeOf(vec))) @TypeOf(vec) { |
| 247 | const len = vectorLength(@TypeOf(vec)); | |
| 249 | const V = @TypeOf(vec); | |
| 248 | 250 | |
| 249 | return mergeShift(vec, @splat(len, shift_in), amount); | |
| 251 | return mergeShift(vec, @as(V, @splat(shift_in)), amount); | |
| 250 | 252 | } |
| 251 | 253 | |
| 252 | 254 | /// 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) { |
| 263 | 265 | const Child = std.meta.Child(@TypeOf(vec)); |
| 264 | 266 | const len = vectorLength(@TypeOf(vec)); |
| 265 | 267 | |
| 266 | return @shuffle(Child, vec, undefined, @splat(len, @as(i32, @intCast(len)) - 1) - iota(i32, len)); | |
| 268 | return @shuffle(Child, vec, undefined, @as(@Vector(len, i32), @splat(@as(i32, @intCast(len)) - 1)) - iota(i32, len)); | |
| 267 | 269 | } |
| 268 | 270 | |
| 269 | 271 | test "vector shifting" { |
| ... | ... | @@ -283,7 +285,8 @@ pub fn firstTrue(vec: anytype) ?VectorIndex(@TypeOf(vec)) { |
| 283 | 285 | if (!@reduce(.Or, vec)) { |
| 284 | 286 | return null; |
| 285 | 287 | } |
| 286 | const indices = @select(IndexInt, vec, iota(IndexInt, len), @splat(len, ~@as(IndexInt, 0))); | |
| 288 | const all_max: @Vector(len, IndexInt) = @splat(~@as(IndexInt, 0)); | |
| 289 | const indices = @select(IndexInt, vec, iota(IndexInt, len), all_max); | |
| 287 | 290 | return @reduce(.Min, indices); |
| 288 | 291 | } |
| 289 | 292 | |
| ... | ... | @@ -294,7 +297,9 @@ pub fn lastTrue(vec: anytype) ?VectorIndex(@TypeOf(vec)) { |
| 294 | 297 | if (!@reduce(.Or, vec)) { |
| 295 | 298 | return null; |
| 296 | 299 | } |
| 297 | const indices = @select(IndexInt, vec, iota(IndexInt, len), @splat(len, @as(IndexInt, 0))); | |
| 300 | ||
| 301 | const all_zeroes: @Vector(len, IndexInt) = @splat(0); | |
| 302 | const indices = @select(IndexInt, vec, iota(IndexInt, len), all_zeroes); | |
| 298 | 303 | return @reduce(.Max, indices); |
| 299 | 304 | } |
| 300 | 305 | |
| ... | ... | @@ -302,26 +307,29 @@ pub fn countTrues(vec: anytype) VectorCount(@TypeOf(vec)) { |
| 302 | 307 | const len = vectorLength(@TypeOf(vec)); |
| 303 | 308 | const CountIntType = VectorCount(@TypeOf(vec)); |
| 304 | 309 | |
| 305 | const one_if_true = @select(CountIntType, vec, @splat(len, @as(CountIntType, 1)), @splat(len, @as(CountIntType, 0))); | |
| 310 | const all_ones: @Vector(len, CountIntType) = @splat(1); | |
| 311 | const all_zeroes: @Vector(len, CountIntType) = @splat(0); | |
| 312 | ||
| 313 | const one_if_true = @select(CountIntType, vec, all_ones, all_zeroes); | |
| 306 | 314 | return @reduce(.Add, one_if_true); |
| 307 | 315 | } |
| 308 | 316 | |
| 309 | 317 | pub fn firstIndexOfValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) ?VectorIndex(@TypeOf(vec)) { |
| 310 | const len = vectorLength(@TypeOf(vec)); | |
| 318 | const V = @TypeOf(vec); | |
| 311 | 319 | |
| 312 | return firstTrue(vec == @splat(len, value)); | |
| 320 | return firstTrue(vec == @as(V, @splat(value))); | |
| 313 | 321 | } |
| 314 | 322 | |
| 315 | 323 | pub fn lastIndexOfValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) ?VectorIndex(@TypeOf(vec)) { |
| 316 | const len = vectorLength(@TypeOf(vec)); | |
| 324 | const V = @TypeOf(vec); | |
| 317 | 325 | |
| 318 | return lastTrue(vec == @splat(len, value)); | |
| 326 | return lastTrue(vec == @as(V, @splat(value))); | |
| 319 | 327 | } |
| 320 | 328 | |
| 321 | 329 | pub fn countElementsWithValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) VectorCount(@TypeOf(vec)) { |
| 322 | const len = vectorLength(@TypeOf(vec)); | |
| 330 | const V = @TypeOf(vec); | |
| 323 | 331 | |
| 324 | return countTrues(vec == @splat(len, value)); | |
| 332 | return countTrues(vec == @as(V, @splat(value))); | |
| 325 | 333 | } |
| 326 | 334 | |
| 327 | 335 | test "vector searching" { |
| ... | ... | @@ -370,7 +378,6 @@ pub fn prefixScanWithFunc( |
| 370 | 378 | pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: anytype) @TypeOf(vec) { |
| 371 | 379 | const VecType = @TypeOf(vec); |
| 372 | 380 | const Child = std.meta.Child(VecType); |
| 373 | const len = vectorLength(VecType); | |
| 374 | 381 | |
| 375 | 382 | const identity = comptime switch (@typeInfo(Child)) { |
| 376 | 383 | .Bool => switch (op) { |
| ... | ... | @@ -397,8 +404,8 @@ pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: a |
| 397 | 404 | const fn_container = struct { |
| 398 | 405 | fn opFn(a: VecType, b: VecType) VecType { |
| 399 | 406 | return if (Child == bool) switch (op) { |
| 400 | .And => @select(bool, a, b, @splat(len, false)), | |
| 401 | .Or => @select(bool, a, @splat(len, true), b), | |
| 407 | .And => @select(bool, a, b, @as(VecType, @splat(false))), | |
| 408 | .Or => @select(bool, a, @as(VecType, @splat(true)), b), | |
| 402 | 409 | .Xor => a != b, |
| 403 | 410 | else => unreachable, |
| 404 | 411 | } else switch (op) { |
| ... | ... | @@ -431,7 +438,9 @@ test "vector prefix scan" { |
| 431 | 438 | const float_base = @Vector(4, f32){ 2, 0.5, -10, 6.54321 }; |
| 432 | 439 | const bool_base = @Vector(4, bool){ true, false, true, false }; |
| 433 | 440 | |
| 434 | try std.testing.expectEqual(iota(u8, 32) + @splat(32, @as(u8, 1)), prefixScan(.Add, 1, @splat(32, @as(u8, 1)))); | |
| 441 | const ones: @Vector(32, u8) = @splat(1); | |
| 442 | ||
| 443 | try std.testing.expectEqual(iota(u8, 32) + ones, prefixScan(.Add, 1, ones)); | |
| 435 | 444 | try std.testing.expectEqual(@Vector(4, i32){ 11, 3, 1, 1 }, prefixScan(.And, 1, int_base)); |
| 436 | 445 | try std.testing.expectEqual(@Vector(4, i32){ 11, 31, 31, -1 }, prefixScan(.Or, 1, int_base)); |
| 437 | 446 | try std.testing.expectEqual(@Vector(4, i32){ 11, 28, 21, -2 }, prefixScan(.Xor, 1, int_base)); |
lib/std/testing.zig+3-3| ... | ... | @@ -606,8 +606,8 @@ test "expectEqual nested array" { |
| 606 | 606 | } |
| 607 | 607 | |
| 608 | 608 | test "expectEqual vector" { |
| 609 | var a = @splat(4, @as(u32, 4)); | |
| 610 | var b = @splat(4, @as(u32, 4)); | |
| 609 | var a: @Vector(4, u32) = @splat(4); | |
| 610 | var b: @Vector(4, u32) = @splat(4); | |
| 611 | 611 | |
| 612 | 612 | try expectEqual(a, b); |
| 613 | 613 | } |
| ... | ... | @@ -903,7 +903,7 @@ test "expectEqualDeep composite type" { |
| 903 | 903 | try expectEqualDeep([_][]const u8{ "a", "b", "c" }, [_][]const u8{ "a", "b", "c" }); |
| 904 | 904 | |
| 905 | 905 | // vector |
| 906 | try expectEqualDeep(@splat(4, @as(u32, 4)), @splat(4, @as(u32, 4))); | |
| 906 | try expectEqualDeep(@as(@Vector(4, u32), @splat(4)), @as(@Vector(4, u32), @splat(4))); | |
| 907 | 907 | |
| 908 | 908 | // nested array |
| 909 | 909 | { |
src/AstGen.zig+10-3| ... | ... | @@ -8591,10 +8591,17 @@ fn builtinCall( |
| 8591 | 8591 | }, |
| 8592 | 8592 | |
| 8593 | 8593 | .splat => { |
| 8594 | const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]); | |
| 8595 | const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]); | |
| 8594 | const result_type = try ri.rl.resultType(gz, node, "@splat"); | |
| 8595 | const elem_type = try gz.add(.{ | |
| 8596 | .tag = .elem_type_index, | |
| 8597 | .data = .{ .bin = .{ | |
| 8598 | .lhs = result_type, | |
| 8599 | .rhs = @as(Zir.Inst.Ref, @enumFromInt(0)), | |
| 8600 | } }, | |
| 8601 | }); | |
| 8602 | const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]); | |
| 8596 | 8603 | const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{ |
| 8597 | .lhs = len, | |
| 8604 | .lhs = result_type, | |
| 8598 | 8605 | .rhs = scalar, |
| 8599 | 8606 | }); |
| 8600 | 8607 | return rvalue(gz, ri, result, node); |
src/BuiltinFn.zig+1-1| ... | ... | @@ -792,7 +792,7 @@ pub const list = list: { |
| 792 | 792 | "@splat", |
| 793 | 793 | .{ |
| 794 | 794 | .tag = .splat, |
| 795 | .param_count = 2, | |
| 795 | .param_count = 1, | |
| 796 | 796 | }, |
| 797 | 797 | }, |
| 798 | 798 | .{ |
src/Sema.zig+24-25| ... | ... | @@ -1820,7 +1820,7 @@ pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Ins |
| 1820 | 1820 | return ty; |
| 1821 | 1821 | } |
| 1822 | 1822 | |
| 1823 | fn resolveCastDestType( | |
| 1823 | fn resolveDestType( | |
| 1824 | 1824 | sema: *Sema, |
| 1825 | 1825 | block: *Block, |
| 1826 | 1826 | src: LazySrcLoc, |
| ... | ... | @@ -8337,7 +8337,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8337 | 8337 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 8338 | 8338 | const src = inst_data.src(); |
| 8339 | 8339 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 8340 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@enumFromInt"); | |
| 8340 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@enumFromInt"); | |
| 8341 | 8341 | const operand = try sema.resolveInst(extra.rhs); |
| 8342 | 8342 | |
| 8343 | 8343 | if (dest_ty.zigTypeTag(mod) != .Enum) { |
| ... | ... | @@ -9666,7 +9666,7 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9666 | 9666 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9667 | 9667 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 9668 | 9668 | |
| 9669 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@intCast"); | |
| 9669 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intCast"); | |
| 9670 | 9670 | const operand = try sema.resolveInst(extra.rhs); |
| 9671 | 9671 | |
| 9672 | 9672 | 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 |
| 9827 | 9827 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9828 | 9828 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 9829 | 9829 | |
| 9830 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@bitCast"); | |
| 9830 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@bitCast"); | |
| 9831 | 9831 | const operand = try sema.resolveInst(extra.rhs); |
| 9832 | 9832 | const operand_ty = sema.typeOf(operand); |
| 9833 | 9833 | switch (dest_ty.zigTypeTag(mod)) { |
| ... | ... | @@ -9970,7 +9970,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 9970 | 9970 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9971 | 9971 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 9972 | 9972 | |
| 9973 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast"); | |
| 9973 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast"); | |
| 9974 | 9974 | const operand = try sema.resolveInst(extra.rhs); |
| 9975 | 9975 | |
| 9976 | 9976 | const target = mod.getTarget(); |
| ... | ... | @@ -20783,7 +20783,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 20783 | 20783 | const src = inst_data.src(); |
| 20784 | 20784 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 20785 | 20785 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 20786 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@intFromFloat"); | |
| 20786 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intFromFloat"); | |
| 20787 | 20787 | const operand = try sema.resolveInst(extra.rhs); |
| 20788 | 20788 | const operand_ty = sema.typeOf(operand); |
| 20789 | 20789 | |
| ... | ... | @@ -20823,7 +20823,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 20823 | 20823 | const src = inst_data.src(); |
| 20824 | 20824 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 20825 | 20825 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 20826 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@floatFromInt"); | |
| 20826 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatFromInt"); | |
| 20827 | 20827 | const operand = try sema.resolveInst(extra.rhs); |
| 20828 | 20828 | const operand_ty = sema.typeOf(operand); |
| 20829 | 20829 | |
| ... | ... | @@ -20852,7 +20852,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 20852 | 20852 | const operand_res = try sema.resolveInst(extra.rhs); |
| 20853 | 20853 | const operand_coerced = try sema.coerce(block, Type.usize, operand_res, operand_src); |
| 20854 | 20854 | |
| 20855 | const ptr_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu, "@ptrFromInt"); | |
| 20855 | const ptr_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrFromInt"); | |
| 20856 | 20856 | try sema.checkPtrType(block, src, ptr_ty); |
| 20857 | 20857 | const elem_ty = ptr_ty.elemType2(mod); |
| 20858 | 20858 | const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema); |
| ... | ... | @@ -20910,7 +20910,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 20910 | 20910 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 20911 | 20911 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 20912 | 20912 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 20913 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@errSetCast"); | |
| 20913 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@errSetCast"); | |
| 20914 | 20914 | const operand = try sema.resolveInst(extra.rhs); |
| 20915 | 20915 | const operand_ty = sema.typeOf(operand); |
| 20916 | 20916 | try sema.checkErrorSetType(block, src, dest_ty); |
| ... | ... | @@ -20997,7 +20997,7 @@ fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa |
| 20997 | 20997 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 20998 | 20998 | const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node }; |
| 20999 | 20999 | const operand = try sema.resolveInst(extra.rhs); |
| 21000 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu, flags.needResultTypeBuiltinName()); | |
| 21000 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, flags.needResultTypeBuiltinName()); | |
| 21001 | 21001 | return sema.ptrCastFull( |
| 21002 | 21002 | block, |
| 21003 | 21003 | flags, |
| ... | ... | @@ -21013,7 +21013,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 21013 | 21013 | const src = inst_data.src(); |
| 21014 | 21014 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 21015 | 21015 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 21016 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu, "@ptrCast"); | |
| 21016 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrCast"); | |
| 21017 | 21017 | const operand = try sema.resolveInst(extra.rhs); |
| 21018 | 21018 | |
| 21019 | 21019 | return sema.ptrCastFull( |
| ... | ... | @@ -21426,7 +21426,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 21426 | 21426 | const src = inst_data.src(); |
| 21427 | 21427 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 21428 | 21428 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 21429 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@truncate"); | |
| 21429 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@truncate"); | |
| 21430 | 21430 | const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, src); |
| 21431 | 21431 | const operand = try sema.resolveInst(extra.rhs); |
| 21432 | 21432 | const operand_ty = sema.typeOf(operand); |
| ... | ... | @@ -22358,23 +22358,22 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 22358 | 22358 | const mod = sema.mod; |
| 22359 | 22359 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 22360 | 22360 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 22361 | const len_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | |
| 22362 | const scalar_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; | |
| 22363 | const len = @as(u32, @intCast(try sema.resolveInt(block, len_src, extra.lhs, Type.u32, "vector splat destination length must be comptime-known"))); | |
| 22364 | const scalar = try sema.resolveInst(extra.rhs); | |
| 22365 | const scalar_ty = sema.typeOf(scalar); | |
| 22366 | try sema.checkVectorElemType(block, scalar_src, scalar_ty); | |
| 22367 | const vector_ty = try mod.vectorType(.{ | |
| 22368 | .len = len, | |
| 22369 | .child = scalar_ty.toIntern(), | |
| 22370 | }); | |
| 22361 | const src = inst_data.src(); | |
| 22362 | const scalar_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | |
| 22363 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@splat"); | |
| 22364 | ||
| 22365 | if (!dest_ty.isVector(mod)) return sema.fail(block, src, "expected vector type, found '{}'", .{dest_ty.fmt(mod)}); | |
| 22366 | ||
| 22367 | const operand = try sema.resolveInst(extra.rhs); | |
| 22368 | const scalar_ty = dest_ty.childType(mod); | |
| 22369 | const scalar = try sema.coerce(block, scalar_ty, operand, scalar_src); | |
| 22371 | 22370 | if (try sema.resolveMaybeUndefVal(scalar)) |scalar_val| { |
| 22372 | if (scalar_val.isUndef(mod)) return sema.addConstUndef(vector_ty); | |
| 22373 | return sema.addConstant(try sema.splat(vector_ty, scalar_val)); | |
| 22371 | if (scalar_val.isUndef(mod)) return sema.addConstUndef(dest_ty); | |
| 22372 | return sema.addConstant(try sema.splat(dest_ty, scalar_val)); | |
| 22374 | 22373 | } |
| 22375 | 22374 | |
| 22376 | 22375 | try sema.requireRuntimeBlock(block, inst_data.src(), scalar_src); |
| 22377 | return block.addTyOp(.splat, vector_ty, scalar); | |
| 22376 | return block.addTyOp(.splat, dest_ty, scalar); | |
| 22378 | 22377 | } |
| 22379 | 22378 | |
| 22380 | 22379 | fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
src/translate_c.zig+6-6| ... | ... | @@ -2799,14 +2799,14 @@ fn transInitListExprVector( |
| 2799 | 2799 | const element_qt = vector_ty.getElementType(); |
| 2800 | 2800 | |
| 2801 | 2801 | if (init_count == 0) { |
| 2802 | const zero_node = try Tag.as.create(c.arena, .{ | |
| 2803 | .lhs = try transQualType(c, scope, element_qt, loc), | |
| 2804 | .rhs = Tag.zero_literal.init(), | |
| 2802 | const vec_node = try Tag.vector.create(c.arena, .{ | |
| 2803 | .lhs = try transCreateNodeNumber(c, num_elements, .int), | |
| 2804 | .rhs = try transQualType(c, scope, element_qt, loc), | |
| 2805 | 2805 | }); |
| 2806 | 2806 | |
| 2807 | return Tag.vector_zero_init.create(c.arena, .{ | |
| 2808 | .lhs = try transCreateNodeNumber(c, num_elements, .int), | |
| 2809 | .rhs = zero_node, | |
| 2807 | return Tag.as.create(c.arena, .{ | |
| 2808 | .lhs = vec_node, | |
| 2809 | .rhs = try Tag.vector_zero_init.create(c.arena, Tag.zero_literal.init()), | |
| 2810 | 2810 | }); |
| 2811 | 2811 | } |
| 2812 | 2812 |
src/translate_c/ast.zig+3-3| ... | ... | @@ -153,7 +153,7 @@ pub const Node = extern union { |
| 153 | 153 | div_exact, |
| 154 | 154 | /// @offsetOf(lhs, rhs) |
| 155 | 155 | offset_of, |
| 156 | /// @splat(lhs, rhs) | |
| 156 | /// @splat(operand) | |
| 157 | 157 | vector_zero_init, |
| 158 | 158 | /// @shuffle(type, a, b, mask) |
| 159 | 159 | shuffle, |
| ... | ... | @@ -284,6 +284,7 @@ pub const Node = extern union { |
| 284 | 284 | .int_cast, |
| 285 | 285 | .const_cast, |
| 286 | 286 | .volatile_cast, |
| 287 | .vector_zero_init, | |
| 287 | 288 | => Payload.UnOp, |
| 288 | 289 | |
| 289 | 290 | .add, |
| ... | ... | @@ -334,7 +335,6 @@ pub const Node = extern union { |
| 334 | 335 | .div_exact, |
| 335 | 336 | .offset_of, |
| 336 | 337 | .helpers_cast, |
| 337 | .vector_zero_init, | |
| 338 | 338 | => Payload.BinOp, |
| 339 | 339 | |
| 340 | 340 | .integer_literal, |
| ... | ... | @@ -1918,7 +1918,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1918 | 1918 | }, |
| 1919 | 1919 | .vector_zero_init => { |
| 1920 | 1920 | const payload = node.castTag(.vector_zero_init).?.data; |
| 1921 | return renderBuiltinCall(c, "@splat", &.{ payload.lhs, payload.rhs }); | |
| 1921 | return renderBuiltinCall(c, "@splat", &.{payload}); | |
| 1922 | 1922 | }, |
| 1923 | 1923 | .field_access => { |
| 1924 | 1924 | const payload = node.castTag(.field_access).?.data; |
stage1/zig.h-6| ... | ... | @@ -3178,12 +3178,6 @@ zig_bitCast_float(f64, uint64_t) |
| 3178 | 3178 | zig_bitCast_float(f80, zig_u128) |
| 3179 | 3179 | zig_bitCast_float(f128, zig_u128) |
| 3180 | 3180 | |
| 3181 | #define zig_cast_f16 | |
| 3182 | #define zig_cast_f32 | |
| 3183 | #define zig_cast_f64 | |
| 3184 | #define zig_cast_f80 | |
| 3185 | #define zig_cast_f128 | |
| 3186 | ||
| 3187 | 3181 | #define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \ |
| 3188 | 3182 | zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ |
| 3189 | 3183 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \ |
stage1/zig1.wasm| Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ |
test/behavior/bitcast.zig+1-1| ... | ... | @@ -396,7 +396,7 @@ test "bitcast vector to integer and back" { |
| 396 | 396 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 397 | 397 | |
| 398 | 398 | const arr: [16]bool = [_]bool{ true, false } ++ [_]bool{true} ** 14; |
| 399 | var x = @splat(16, true); | |
| 399 | var x: @Vector(16, bool) = @splat(true); | |
| 400 | 400 | x[1] = false; |
| 401 | 401 | try expect(@as(u16, @bitCast(x)) == comptime @as(u16, @bitCast(@as(@Vector(16, bool), arr)))); |
| 402 | 402 | } |
test/behavior/cast.zig+1-1| ... | ... | @@ -639,7 +639,7 @@ test "vector casts" { |
| 639 | 639 | } |
| 640 | 640 | |
| 641 | 641 | fn doTheTestFloat() !void { |
| 642 | var vec = @splat(2, @as(f32, 1234.0)); | |
| 642 | var vec: @Vector(2, f32) = @splat(1234.0); | |
| 643 | 643 | var wider: @Vector(2, f64) = vec; |
| 644 | 644 | try expect(wider[0] == 1234.0); |
| 645 | 645 | try expect(wider[1] == 1234.0); |
test/behavior/math.zig+16-10| ... | ... | @@ -111,13 +111,17 @@ test "@clz vectors" { |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | fn testClzVectors() !void { |
| 114 | const Vu4 = @Vector(64, u4); | |
| 115 | const Vu8 = @Vector(64, u8); | |
| 116 | const Vu128 = @Vector(64, u128); | |
| 117 | ||
| 114 | 118 | @setEvalBranchQuota(10_000); |
| 115 | try testOneClzVector(u8, 64, @splat(64, @as(u8, 0b10001010)), @splat(64, @as(u4, 0))); | |
| 116 | try testOneClzVector(u8, 64, @splat(64, @as(u8, 0b00001010)), @splat(64, @as(u4, 4))); | |
| 117 | try testOneClzVector(u8, 64, @splat(64, @as(u8, 0b00011010)), @splat(64, @as(u4, 3))); | |
| 118 | try testOneClzVector(u8, 64, @splat(64, @as(u8, 0b00000000)), @splat(64, @as(u4, 8))); | |
| 119 | try testOneClzVector(u128, 64, @splat(64, @as(u128, 0xffffffffffffffff)), @splat(64, @as(u8, 64))); | |
| 120 | try testOneClzVector(u128, 64, @splat(64, @as(u128, 0x10000000000000000)), @splat(64, @as(u8, 63))); | |
| 119 | try testOneClzVector(u8, 64, @as(Vu8, @splat(0b10001010)), @as(Vu4, @splat(0))); | |
| 120 | try testOneClzVector(u8, 64, @as(Vu8, @splat(0b00001010)), @as(Vu4, @splat(4))); | |
| 121 | try testOneClzVector(u8, 64, @as(Vu8, @splat(0b00011010)), @as(Vu4, @splat(3))); | |
| 122 | try testOneClzVector(u8, 64, @as(Vu8, @splat(0b00000000)), @as(Vu4, @splat(8))); | |
| 123 | try testOneClzVector(u128, 64, @as(Vu128, @splat(0xffffffffffffffff)), @as(Vu8, @splat(64))); | |
| 124 | try testOneClzVector(u128, 64, @as(Vu128, @splat(0x10000000000000000)), @as(Vu8, @splat(63))); | |
| 121 | 125 | } |
| 122 | 126 | |
| 123 | 127 | fn testOneClzVector( |
| ... | ... | @@ -180,11 +184,13 @@ test "@ctz vectors" { |
| 180 | 184 | } |
| 181 | 185 | |
| 182 | 186 | fn testCtzVectors() !void { |
| 187 | const Vu4 = @Vector(64, u4); | |
| 188 | const Vu8 = @Vector(64, u8); | |
| 183 | 189 | @setEvalBranchQuota(10_000); |
| 184 | try testOneCtzVector(u8, 64, @splat(64, @as(u8, 0b10100000)), @splat(64, @as(u4, 5))); | |
| 185 | try testOneCtzVector(u8, 64, @splat(64, @as(u8, 0b10001010)), @splat(64, @as(u4, 1))); | |
| 186 | try testOneCtzVector(u8, 64, @splat(64, @as(u8, 0b00000000)), @splat(64, @as(u4, 8))); | |
| 187 | try testOneCtzVector(u16, 64, @splat(64, @as(u16, 0b00000000)), @splat(64, @as(u5, 16))); | |
| 190 | try testOneCtzVector(u8, 64, @as(Vu8, @splat(0b10100000)), @as(Vu4, @splat(5))); | |
| 191 | try testOneCtzVector(u8, 64, @as(Vu8, @splat(0b10001010)), @as(Vu4, @splat(1))); | |
| 192 | try testOneCtzVector(u8, 64, @as(Vu8, @splat(0b00000000)), @as(Vu4, @splat(8))); | |
| 193 | try testOneCtzVector(u16, 64, @as(@Vector(64, u16), @splat(0b00000000)), @as(@Vector(64, u5), @splat(16))); | |
| 188 | 194 | } |
| 189 | 195 | |
| 190 | 196 | fn testOneCtzVector( |
test/behavior/vector.zig+21-18| ... | ... | @@ -299,8 +299,7 @@ test "vector @splat" { |
| 299 | 299 | const S = struct { |
| 300 | 300 | fn testForT(comptime N: comptime_int, v: anytype) !void { |
| 301 | 301 | const T = @TypeOf(v); |
| 302 | var vec = @splat(N, v); | |
| 303 | try expect(@Vector(N, T) == @TypeOf(vec)); | |
| 302 | var vec: @Vector(N, T) = @splat(v); | |
| 304 | 303 | var as_array = @as([N]T, vec); |
| 305 | 304 | for (as_array) |elem| try expect(v == elem); |
| 306 | 305 | } |
| ... | ... | @@ -458,26 +457,28 @@ test "vector comparison operators" { |
| 458 | 457 | const S = struct { |
| 459 | 458 | fn doTheTest() !void { |
| 460 | 459 | { |
| 461 | var v1: @Vector(4, bool) = [_]bool{ true, false, true, false }; | |
| 462 | var v2: @Vector(4, bool) = [_]bool{ false, true, false, true }; | |
| 463 | try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 == v1))); | |
| 464 | try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v1 == v2))); | |
| 465 | try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 != v2))); | |
| 466 | try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v2 != v2))); | |
| 460 | const V = @Vector(4, bool); | |
| 461 | var v1: V = [_]bool{ true, false, true, false }; | |
| 462 | var v2: V = [_]bool{ false, true, false, true }; | |
| 463 | try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 == v1))); | |
| 464 | try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v1 == v2))); | |
| 465 | try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 != v2))); | |
| 466 | try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v2 != v2))); | |
| 467 | 467 | } |
| 468 | 468 | { |
| 469 | var v1 = @splat(4, @as(u32, 0xc0ffeeee)); | |
| 469 | const V = @Vector(4, bool); | |
| 470 | var v1: @Vector(4, u32) = @splat(0xc0ffeeee); | |
| 470 | 471 | var v2: @Vector(4, c_uint) = v1; |
| 471 | var v3 = @splat(4, @as(u32, 0xdeadbeef)); | |
| 472 | try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 == v2))); | |
| 473 | try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v1 == v3))); | |
| 474 | try expect(mem.eql(bool, &@as([4]bool, @splat(4, true)), &@as([4]bool, v1 != v3))); | |
| 475 | try expect(mem.eql(bool, &@as([4]bool, @splat(4, false)), &@as([4]bool, v1 != v2))); | |
| 472 | var v3: @Vector(4, u32) = @splat(0xdeadbeef); | |
| 473 | try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 == v2))); | |
| 474 | try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v1 == v3))); | |
| 475 | try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(true))), &@as([4]bool, v1 != v3))); | |
| 476 | try expect(mem.eql(bool, &@as([4]bool, @as(V, @splat(false))), &@as([4]bool, v1 != v2))); | |
| 476 | 477 | } |
| 477 | 478 | { |
| 478 | 479 | // Comptime-known LHS/RHS |
| 479 | 480 | var v1: @Vector(4, u32) = [_]u32{ 2, 1, 2, 1 }; |
| 480 | const v2 = @splat(4, @as(u32, 2)); | |
| 481 | const v2: @Vector(4, u32) = @splat(2); | |
| 481 | 482 | const v3: @Vector(4, bool) = [_]bool{ true, false, true, false }; |
| 482 | 483 | try expect(mem.eql(bool, &@as([4]bool, v3), &@as([4]bool, v1 == v2))); |
| 483 | 484 | try expect(mem.eql(bool, &@as([4]bool, v3), &@as([4]bool, v2 == v1))); |
| ... | ... | @@ -847,8 +848,10 @@ test "vector @reduce comptime" { |
| 847 | 848 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 848 | 849 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 849 | 850 | |
| 850 | const value = @Vector(4, i32){ 1, -1, 1, -1 }; | |
| 851 | const result = value > @splat(4, @as(i32, 0)); | |
| 851 | const V = @Vector(4, i32); | |
| 852 | ||
| 853 | const value = V{ 1, -1, 1, -1 }; | |
| 854 | const result = value > @as(V, @splat(0)); | |
| 852 | 855 | // result is { true, false, true, false }; |
| 853 | 856 | try comptime expect(@TypeOf(result) == @Vector(4, bool)); |
| 854 | 857 | const is_all_true = @reduce(.And, result); |
| ... | ... | @@ -1270,7 +1273,7 @@ test "array operands to shuffle are coerced to vectors" { |
| 1270 | 1273 | const mask = [5]i32{ -1, 0, 1, 2, 3 }; |
| 1271 | 1274 | |
| 1272 | 1275 | var a = [5]u32{ 3, 5, 7, 9, 0 }; |
| 1273 | var b = @shuffle(u32, a, @splat(5, @as(u24, 0)), mask); | |
| 1276 | var b = @shuffle(u32, a, @as(@Vector(5, u24), @splat(0)), mask); | |
| 1274 | 1277 | try expectEqual([_]u32{ 0, 3, 5, 7, 9 }, b); |
| 1275 | 1278 | } |
| 1276 | 1279 |
test/cases/compile_errors/bad_splat_type.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | const c = 4; | |
| 3 | var v = @splat(4, c); | |
| 4 | _ = v; | |
| 5 | } | |
| 6 | ||
| 7 | // error | |
| 8 | // backend=stage2 | |
| 9 | // target=native | |
| 10 | // | |
| 11 | // :3:23: error: expected integer, float, bool, or pointer for the vector element type; found 'comptime_int' |
test/cases/compile_errors/branch_in_comptime_only_scope_uses_condbr_inline.zig+2-2| ... | ... | @@ -1,13 +1,13 @@ |
| 1 | 1 | pub export fn entry1() void { |
| 2 | 2 | var x: u32 = 3; |
| 3 | _ = @shuffle(u32, [_]u32{0}, @splat(1, @as(u32, 0)), [_]i8{ | |
| 3 | _ = @shuffle(u32, [_]u32{0}, @as(@Vector(1, u32), @splat(0)), [_]i8{ | |
| 4 | 4 | if (x > 1) 1 else -1, |
| 5 | 5 | }); |
| 6 | 6 | } |
| 7 | 7 | |
| 8 | 8 | pub export fn entry2() void { |
| 9 | 9 | var y: ?i8 = -1; |
| 10 | _ = @shuffle(u32, [_]u32{0}, @splat(1, @as(u32, 0)), [_]i8{ | |
| 10 | _ = @shuffle(u32, [_]u32{0}, @as(@Vector(1, u32), @splat(0)), [_]i8{ | |
| 11 | 11 | y orelse 1, |
| 12 | 12 | }); |
| 13 | 13 | } |
test/cases/safety/signed-unsigned vector cast.zig	+1-1| ... | ... | @@ -9,7 +9,7 @@ pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usi |
| 9 | 9 | } |
| 10 | 10 | |
| 11 | 11 | pub fn main() !void { |
| 12 | var x = @splat(4, @as(i32, -2147483647)); | |
| 12 | var x: @Vector(4, i32) = @splat(-2147483647); | |
| 13 | 13 | var y: @Vector(4, u32) = @intCast(x); |
| 14 | 14 | _ = y; |
| 15 | 15 | return error.TestFailed; |
test/cases/safety/truncating vector cast.zig	+1-1| ... | ... | @@ -9,7 +9,7 @@ pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usi |
| 9 | 9 | } |
| 10 | 10 | |
| 11 | 11 | pub fn main() !void { |
| 12 | var x = @splat(4, @as(u32, 0xdeadbeef)); | |
| 12 | var x: @Vector(4, u32) = @splat(0xdeadbeef); | |
| 13 | 13 | var y: @Vector(4, u16) = @intCast(x); |
| 14 | 14 | _ = y; |
| 15 | 15 | return error.TestFailed; |
test/cases/safety/unsigned-signed vector cast.zig	+1-1| ... | ... | @@ -9,7 +9,7 @@ pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usi |
| 9 | 9 | } |
| 10 | 10 | |
| 11 | 11 | pub fn main() !void { |
| 12 | var x = @splat(4, @as(u32, 0x80000000)); | |
| 12 | var x: @Vector(4, u32) = @splat(0x80000000); | |
| 13 | 13 | var y: @Vector(4, i32) = @intCast(x); |
| 14 | 14 | _ = y; |
| 15 | 15 | return error.TestFailed; |