| author | |
| committer | |
| log | 2fdc9e6ae8b6f1ec86050011e1170d639d8c9c2c |
| tree | 29ae1289a64ff0568e06da19a4ecaff1dad562ba |
| parent | defef3f1a15be3b8f4e2074d581d43deb8296349 |
15 files changed, 443 insertions(+), 183 deletions(-)
lib/std/crypto/blake3.zig+2-1| ... | @@ -200,7 +200,8 @@ const CompressGeneric = struct { | ... | @@ -200,7 +200,8 @@ const CompressGeneric = struct { |
| 200 | } | 200 | } |
| 201 | }; | 201 | }; |
| 202 | 202 | ||
| 203 | const compress = if (builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_x86_64) | 203 | const compress = if (builtin.cpu.arch == .x86_64 and |
| 204 | (builtin.zig_backend != .stage2_x86_64 or std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3))) | ||
| 204 | CompressVectorized.compress | 205 | CompressVectorized.compress |
| 205 | else | 206 | else |
| 206 | CompressGeneric.compress; | 207 | CompressGeneric.compress; |
lib/std/crypto/salsa20.zig+5-1| ... | @@ -302,7 +302,11 @@ fn SalsaNonVecImpl(comptime rounds: comptime_int) type { | ... | @@ -302,7 +302,11 @@ fn SalsaNonVecImpl(comptime rounds: comptime_int) type { |
| 302 | }; | 302 | }; |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | const SalsaImpl = if (builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_x86_64) SalsaVecImpl else SalsaNonVecImpl; | 305 | const SalsaImpl = if (builtin.cpu.arch == .x86_64 and |
| 306 | (builtin.zig_backend != .stage2_x86_64 or std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3))) | ||
| 307 | SalsaVecImpl | ||
| 308 | else | ||
| 309 | SalsaNonVecImpl; | ||
| 306 | 310 | ||
| 307 | fn keyToWords(key: [32]u8) [8]u32 { | 311 | fn keyToWords(key: [32]u8) [8]u32 { |
| 308 | var k: [8]u32 = undefined; | 312 | var k: [8]u32 = undefined; |
lib/std/meta.zig+2-1| ... | @@ -1286,5 +1286,6 @@ test "hasUniqueRepresentation" { | ... | @@ -1286,5 +1286,6 @@ test "hasUniqueRepresentation" { |
| 1286 | try testing.expect(!hasUniqueRepresentation([]u8)); | 1286 | try testing.expect(!hasUniqueRepresentation([]u8)); |
| 1287 | try testing.expect(!hasUniqueRepresentation([]const u8)); | 1287 | try testing.expect(!hasUniqueRepresentation([]const u8)); |
| 1288 | 1288 | ||
| 1289 | try testing.expect(hasUniqueRepresentation(@Vector(4, u16))); | 1289 | try testing.expect(hasUniqueRepresentation(@Vector(std.simd.suggestVectorLength(u8) orelse 1, u8))); |
| 1290 | try testing.expect(@sizeOf(@Vector(3, u8)) == 3 or !hasUniqueRepresentation(@Vector(3, u8))); | ||
| 1290 | } | 1291 | } |
lib/std/unicode.zig+34-19| ... | @@ -239,18 +239,19 @@ pub fn utf8ValidateSlice(input: []const u8) bool { | ... | @@ -239,18 +239,19 @@ pub fn utf8ValidateSlice(input: []const u8) bool { |
| 239 | fn utf8ValidateSliceImpl(input: []const u8, comptime surrogates: Surrogates) bool { | 239 | fn utf8ValidateSliceImpl(input: []const u8, comptime surrogates: Surrogates) bool { |
| 240 | var remaining = input; | 240 | var remaining = input; |
| 241 | 241 | ||
| 242 | const chunk_len = std.simd.suggestVectorLength(u8) orelse 1; | 242 | if (std.simd.suggestVectorLength(u8)) |chunk_len| { |
| 243 | const Chunk = @Vector(chunk_len, u8); | 243 | const Chunk = @Vector(chunk_len, u8); |
| 244 | 244 | ||
| 245 | // Fast path. Check for and skip ASCII characters at the start of the input. | 245 | // Fast path. Check for and skip ASCII characters at the start of the input. |
| 246 | while (remaining.len >= chunk_len) { | 246 | while (remaining.len >= chunk_len) { |
| 247 | const chunk: Chunk = remaining[0..chunk_len].*; | 247 | const chunk: Chunk = remaining[0..chunk_len].*; |
| 248 | const mask: Chunk = @splat(0x80); | 248 | const mask: Chunk = @splat(0x80); |
| 249 | if (@reduce(.Or, chunk & mask == mask)) { | 249 | if (@reduce(.Or, chunk & mask == mask)) { |
| 250 | // found a non ASCII byte | 250 | // found a non ASCII byte |
| 251 | break; | 251 | break; |
| 252 | } | ||
| 253 | remaining = remaining[chunk_len..]; | ||
| 252 | } | 254 | } |
| 253 | remaining = remaining[chunk_len..]; | ||
| 254 | } | 255 | } |
| 255 | 256 | ||
| 256 | // default lowest and highest continuation byte | 257 | // default lowest and highest continuation byte |
| ... | @@ -937,8 +938,11 @@ fn utf16LeToUtf8ArrayListImpl( | ... | @@ -937,8 +938,11 @@ fn utf16LeToUtf8ArrayListImpl( |
| 937 | try array_list.ensureTotalCapacityPrecise(utf16le.len); | 938 | try array_list.ensureTotalCapacityPrecise(utf16le.len); |
| 938 | 939 | ||
| 939 | var remaining = utf16le; | 940 | var remaining = utf16le; |
| 940 | if (builtin.zig_backend != .stage2_x86_64) { | 941 | if (builtin.zig_backend != .stage2_x86_64 or |
| 941 | const chunk_len = std.simd.suggestVectorLength(u16) orelse 1; | 942 | comptime (std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3) and |
| 943 | !std.Target.x86.featureSetHasAny(builtin.cpu.features, .{ .prefer_256_bit, .avx }))) | ||
| 944 | vectorized: { | ||
| 945 | const chunk_len = std.simd.suggestVectorLength(u16) orelse break :vectorized; | ||
| 942 | const Chunk = @Vector(chunk_len, u16); | 946 | const Chunk = @Vector(chunk_len, u16); |
| 943 | 947 | ||
| 944 | // Fast path. Check for and encode ASCII characters at the start of the input. | 948 | // Fast path. Check for and encode ASCII characters at the start of the input. |
| ... | @@ -1029,8 +1033,11 @@ fn utf16LeToUtf8Impl(utf8: []u8, utf16le: []const u16, comptime surrogates: Surr | ... | @@ -1029,8 +1033,11 @@ fn utf16LeToUtf8Impl(utf8: []u8, utf16le: []const u16, comptime surrogates: Surr |
| 1029 | var end_index: usize = 0; | 1033 | var end_index: usize = 0; |
| 1030 | 1034 | ||
| 1031 | var remaining = utf16le; | 1035 | var remaining = utf16le; |
| 1032 | if (builtin.zig_backend != .stage2_x86_64) { | 1036 | if (builtin.zig_backend != .stage2_x86_64 or |
| 1033 | const chunk_len = std.simd.suggestVectorLength(u16) orelse 1; | 1037 | comptime (std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3) and |
| 1038 | !std.Target.x86.featureSetHasAny(builtin.cpu.features, .{ .prefer_256_bit, .avx }))) | ||
| 1039 | vectorized: { | ||
| 1040 | const chunk_len = std.simd.suggestVectorLength(u16) orelse break :vectorized; | ||
| 1034 | const Chunk = @Vector(chunk_len, u16); | 1041 | const Chunk = @Vector(chunk_len, u16); |
| 1035 | 1042 | ||
| 1036 | // Fast path. Check for and encode ASCII characters at the start of the input. | 1043 | // Fast path. Check for and encode ASCII characters at the start of the input. |
| ... | @@ -1155,8 +1162,12 @@ fn utf8ToUtf16LeArrayListImpl(array_list: *std.ArrayList(u16), utf8: []const u8, | ... | @@ -1155,8 +1162,12 @@ fn utf8ToUtf16LeArrayListImpl(array_list: *std.ArrayList(u16), utf8: []const u8, |
| 1155 | 1162 | ||
| 1156 | var remaining = utf8; | 1163 | var remaining = utf8; |
| 1157 | // Need support for std.simd.interlace | 1164 | // Need support for std.simd.interlace |
| 1158 | if (builtin.zig_backend != .stage2_x86_64 and comptime !builtin.cpu.arch.isMIPS()) { | 1165 | if ((builtin.zig_backend != .stage2_x86_64 or |
| 1159 | const chunk_len = std.simd.suggestVectorLength(u8) orelse 1; | 1166 | comptime (std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3) and |
| 1167 | !std.Target.x86.featureSetHasAny(builtin.cpu.features, .{ .prefer_256_bit, .avx }))) and | ||
| 1168 | comptime !builtin.cpu.arch.isMIPS()) | ||
| 1169 | vectorized: { | ||
| 1170 | const chunk_len = @divExact(std.simd.suggestVectorLength(u8) orelse break :vectorized, 2); | ||
| 1160 | const Chunk = @Vector(chunk_len, u8); | 1171 | const Chunk = @Vector(chunk_len, u8); |
| 1161 | 1172 | ||
| 1162 | // Fast path. Check for and encode ASCII characters at the start of the input. | 1173 | // Fast path. Check for and encode ASCII characters at the start of the input. |
| ... | @@ -1232,8 +1243,12 @@ pub fn utf8ToUtf16LeImpl(utf16le: []u16, utf8: []const u8, comptime surrogates: | ... | @@ -1232,8 +1243,12 @@ pub fn utf8ToUtf16LeImpl(utf16le: []u16, utf8: []const u8, comptime surrogates: |
| 1232 | 1243 | ||
| 1233 | var remaining = utf8; | 1244 | var remaining = utf8; |
| 1234 | // Need support for std.simd.interlace | 1245 | // Need support for std.simd.interlace |
| 1235 | if (builtin.zig_backend != .stage2_x86_64 and comptime !builtin.cpu.arch.isMIPS()) { | 1246 | if ((builtin.zig_backend != .stage2_x86_64 or |
| 1236 | const chunk_len = std.simd.suggestVectorLength(u8) orelse 1; | 1247 | comptime (std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3) and |
| 1248 | !std.Target.x86.featureSetHasAny(builtin.cpu.features, .{ .prefer_256_bit, .avx }))) and | ||
| 1249 | comptime !builtin.cpu.arch.isMIPS()) | ||
| 1250 | vectorized: { | ||
| 1251 | const chunk_len = @divExact(std.simd.suggestVectorLength(u8) orelse break :vectorized, 2); | ||
| 1237 | const Chunk = @Vector(chunk_len, u8); | 1252 | const Chunk = @Vector(chunk_len, u8); |
| 1238 | 1253 | ||
| 1239 | // Fast path. Check for and encode ASCII characters at the start of the input. | 1254 | // Fast path. Check for and encode ASCII characters at the start of the input. |
lib/std/zig/c_translation.zig+3-5| ... | @@ -308,14 +308,12 @@ test "promoteIntLiteral" { | ... | @@ -308,14 +308,12 @@ test "promoteIntLiteral" { |
| 308 | 308 | ||
| 309 | /// Convert from clang __builtin_shufflevector index to Zig @shuffle index | 309 | /// Convert from clang __builtin_shufflevector index to Zig @shuffle index |
| 310 | /// clang requires __builtin_shufflevector index arguments to be integer constants. | 310 | /// clang requires __builtin_shufflevector index arguments to be integer constants. |
| 311 | /// negative values for `this_index` indicate "don't care" so we arbitrarily choose 0 | 311 | /// negative values for `this_index` indicate "don't care". |
| 312 | /// clang enforces that `this_index` is less than the total number of vector elements | 312 | /// clang enforces that `this_index` is less than the total number of vector elements |
| 313 | /// See https://ziglang.org/documentation/master/#shuffle | 313 | /// See https://ziglang.org/documentation/master/#shuffle |
| 314 | /// See https://clang.llvm.org/docs/LanguageExtensions.html#langext-builtin-shufflevector | 314 | /// See https://clang.llvm.org/docs/LanguageExtensions.html#langext-builtin-shufflevector |
| 315 | pub fn shuffleVectorIndex(comptime this_index: c_int, comptime source_vector_len: usize) i32 { | 315 | pub fn shuffleVectorIndex(comptime this_index: c_int, comptime source_vector_len: usize) i32 { |
| 316 | if (this_index <= 0) return 0; | 316 | const positive_index = std.math.cast(usize, this_index) orelse return undefined; |
| 317 | |||
| 318 | const positive_index = @as(usize, @intCast(this_index)); | ||
| 319 | if (positive_index < source_vector_len) return @as(i32, @intCast(this_index)); | 317 | if (positive_index < source_vector_len) return @as(i32, @intCast(this_index)); |
| 320 | const b_index = positive_index - source_vector_len; | 318 | const b_index = positive_index - source_vector_len; |
| 321 | return ~@as(i32, @intCast(b_index)); | 319 | return ~@as(i32, @intCast(b_index)); |
| ... | @@ -324,7 +322,7 @@ pub fn shuffleVectorIndex(comptime this_index: c_int, comptime source_vector_len | ... | @@ -324,7 +322,7 @@ pub fn shuffleVectorIndex(comptime this_index: c_int, comptime source_vector_len |
| 324 | test "shuffleVectorIndex" { | 322 | test "shuffleVectorIndex" { |
| 325 | const vector_len: usize = 4; | 323 | const vector_len: usize = 4; |
| 326 | 324 | ||
| 327 | try testing.expect(shuffleVectorIndex(-1, vector_len) == 0); | 325 | _ = shuffleVectorIndex(-1, vector_len); |
| 328 | 326 | ||
| 329 | try testing.expect(shuffleVectorIndex(0, vector_len) == 0); | 327 | try testing.expect(shuffleVectorIndex(0, vector_len) == 0); |
| 330 | try testing.expect(shuffleVectorIndex(1, vector_len) == 1); | 328 | try testing.expect(shuffleVectorIndex(1, vector_len) == 1); |
src/InternPool.zig+1| ... | @@ -3587,6 +3587,7 @@ pub const Alignment = enum(u6) { | ... | @@ -3587,6 +3587,7 @@ pub const Alignment = enum(u6) { |
| 3587 | @"8" = 3, | 3587 | @"8" = 3, |
| 3588 | @"16" = 4, | 3588 | @"16" = 4, |
| 3589 | @"32" = 5, | 3589 | @"32" = 5, |
| 3590 | @"64" = 6, | ||
| 3590 | none = std.math.maxInt(u6), | 3591 | none = std.math.maxInt(u6), |
| 3591 | _, | 3592 | _, |
| 3592 | 3593 |
src/arch/x86_64/CodeGen.zig+295-101| ... | @@ -2610,7 +2610,8 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt | ... | @@ -2610,7 +2610,8 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt |
| 2610 | 2610 | ||
| 2611 | const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).Array.len]RegisterLock; | 2611 | const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).Array.len]RegisterLock; |
| 2612 | var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) = | 2612 | var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) = |
| 2613 | if (opts.update_tracking) ({}) else std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); | 2613 | if (opts.update_tracking) |
| 2614 | {} else std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); | ||
| 2614 | 2615 | ||
| 2615 | var reg_locks = if (opts.update_tracking) {} else try std.ArrayList(RegisterLock).initCapacity( | 2616 | var reg_locks = if (opts.update_tracking) {} else try std.ArrayList(RegisterLock).initCapacity( |
| 2616 | stack.get(), | 2617 | stack.get(), |
| ... | @@ -14116,30 +14117,8 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo | ... | @@ -14116,30 +14117,8 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 14116 | else => {}, | 14117 | else => {}, |
| 14117 | }, | 14118 | }, |
| 14118 | .Int => switch (ty.childType(mod).intInfo(mod).bits) { | 14119 | .Int => switch (ty.childType(mod).intInfo(mod).bits) { |
| 14119 | 8 => switch (ty.vectorLen(mod)) { | 14120 | 1...8 => switch (ty.vectorLen(mod)) { |
| 14120 | 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{ | 14121 | 1...16 => return .{ .move = if (self.hasFeature(.avx)) |
| 14121 | .insert = .{ .vp_b, .insr }, | ||
| 14122 | .extract = .{ .vp_b, .extr }, | ||
| 14123 | } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{ | ||
| 14124 | .insert = .{ .p_b, .insr }, | ||
| 14125 | .extract = .{ .p_b, .extr }, | ||
| 14126 | } }, | ||
| 14127 | 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ | ||
| 14128 | .insert = .{ .vp_w, .insr }, | ||
| 14129 | .extract = .{ .vp_w, .extr }, | ||
| 14130 | } } else .{ .insert_extract = .{ | ||
| 14131 | .insert = .{ .p_w, .insr }, | ||
| 14132 | .extract = .{ .p_w, .extr }, | ||
| 14133 | } }, | ||
| 14134 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14135 | .{ .v_d, .mov } | ||
| 14136 | else | ||
| 14137 | .{ ._d, .mov } }, | ||
| 14138 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14139 | .{ .v_q, .mov } | ||
| 14140 | else | ||
| 14141 | .{ ._q, .mov } }, | ||
| 14142 | 9...16 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14143 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | 14122 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| 14144 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 14123 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| 14145 | 17...32 => if (self.hasFeature(.avx)) | 14124 | 17...32 => if (self.hasFeature(.avx)) |
| ... | @@ -14149,23 +14128,8 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo | ... | @@ -14149,23 +14128,8 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 14149 | .{ .v_, .movdqu } }, | 14128 | .{ .v_, .movdqu } }, |
| 14150 | else => {}, | 14129 | else => {}, |
| 14151 | }, | 14130 | }, |
| 14152 | 16 => switch (ty.vectorLen(mod)) { | 14131 | 9...16 => switch (ty.vectorLen(mod)) { |
| 14153 | 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ | 14132 | 1...8 => return .{ .move = if (self.hasFeature(.avx)) |
| 14154 | .insert = .{ .vp_w, .insr }, | ||
| 14155 | .extract = .{ .vp_w, .extr }, | ||
| 14156 | } } else .{ .insert_extract = .{ | ||
| 14157 | .insert = .{ .p_w, .insr }, | ||
| 14158 | .extract = .{ .p_w, .extr }, | ||
| 14159 | } }, | ||
| 14160 | 2 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14161 | .{ .v_d, .mov } | ||
| 14162 | else | ||
| 14163 | .{ ._d, .mov } }, | ||
| 14164 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14165 | .{ .v_q, .mov } | ||
| 14166 | else | ||
| 14167 | .{ ._q, .mov } }, | ||
| 14168 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14169 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | 14133 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| 14170 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 14134 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| 14171 | 9...16 => if (self.hasFeature(.avx)) | 14135 | 9...16 => if (self.hasFeature(.avx)) |
| ... | @@ -14175,16 +14139,8 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo | ... | @@ -14175,16 +14139,8 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 14175 | .{ .v_, .movdqu } }, | 14139 | .{ .v_, .movdqu } }, |
| 14176 | else => {}, | 14140 | else => {}, |
| 14177 | }, | 14141 | }, |
| 14178 | 32 => switch (ty.vectorLen(mod)) { | 14142 | 17...32 => switch (ty.vectorLen(mod)) { |
| 14179 | 1 => return .{ .move = if (self.hasFeature(.avx)) | 14143 | 1...4 => return .{ .move = if (self.hasFeature(.avx)) |
| 14180 | .{ .v_d, .mov } | ||
| 14181 | else | ||
| 14182 | .{ ._d, .mov } }, | ||
| 14183 | 2 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14184 | .{ .v_q, .mov } | ||
| 14185 | else | ||
| 14186 | .{ ._q, .mov } }, | ||
| 14187 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14188 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | 14144 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| 14189 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 14145 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| 14190 | 5...8 => if (self.hasFeature(.avx)) | 14146 | 5...8 => if (self.hasFeature(.avx)) |
| ... | @@ -14194,12 +14150,8 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo | ... | @@ -14194,12 +14150,8 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 14194 | .{ .v_, .movdqu } }, | 14150 | .{ .v_, .movdqu } }, |
| 14195 | else => {}, | 14151 | else => {}, |
| 14196 | }, | 14152 | }, |
| 14197 | 64 => switch (ty.vectorLen(mod)) { | 14153 | 33...64 => switch (ty.vectorLen(mod)) { |
| 14198 | 1 => return .{ .move = if (self.hasFeature(.avx)) | 14154 | 1...2 => return .{ .move = if (self.hasFeature(.avx)) |
| 14199 | .{ .v_q, .mov } | ||
| 14200 | else | ||
| 14201 | .{ ._q, .mov } }, | ||
| 14202 | 2 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14203 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | 14155 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| 14204 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 14156 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| 14205 | 3...4 => if (self.hasFeature(.avx)) | 14157 | 3...4 => if (self.hasFeature(.avx)) |
| ... | @@ -14209,7 +14161,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo | ... | @@ -14209,7 +14161,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 14209 | .{ .v_, .movdqu } }, | 14161 | .{ .v_, .movdqu } }, |
| 14210 | else => {}, | 14162 | else => {}, |
| 14211 | }, | 14163 | }, |
| 14212 | 128 => switch (ty.vectorLen(mod)) { | 14164 | 65...128 => switch (ty.vectorLen(mod)) { |
| 14213 | 1 => return .{ .move = if (self.hasFeature(.avx)) | 14165 | 1 => return .{ .move = if (self.hasFeature(.avx)) |
| 14214 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | 14166 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| 14215 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 14167 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| ... | @@ -14220,7 +14172,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo | ... | @@ -14220,7 +14172,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 14220 | .{ .v_, .movdqu } }, | 14172 | .{ .v_, .movdqu } }, |
| 14221 | else => {}, | 14173 | else => {}, |
| 14222 | }, | 14174 | }, |
| 14223 | 256 => switch (ty.vectorLen(mod)) { | 14175 | 129...256 => switch (ty.vectorLen(mod)) { |
| 14224 | 1 => if (self.hasFeature(.avx)) | 14176 | 1 => if (self.hasFeature(.avx)) |
| 14225 | return .{ .move = if (aligned) | 14177 | return .{ .move = if (aligned) |
| 14226 | .{ .v_, .movdqa } | 14178 | .{ .v_, .movdqa } |
| ... | @@ -14232,11 +14184,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo | ... | @@ -14232,11 +14184,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 14232 | }, | 14184 | }, |
| 14233 | .Pointer, .Optional => if (ty.childType(mod).isPtrAtRuntime(mod)) | 14185 | .Pointer, .Optional => if (ty.childType(mod).isPtrAtRuntime(mod)) |
| 14234 | switch (ty.vectorLen(mod)) { | 14186 | switch (ty.vectorLen(mod)) { |
| 14235 | 1 => return .{ .move = if (self.hasFeature(.avx)) | 14187 | 1...2 => return .{ .move = if (self.hasFeature(.avx)) |
| 14236 | .{ .v_q, .mov } | ||
| 14237 | else | ||
| 14238 | .{ ._q, .mov } }, | ||
| 14239 | 2 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14240 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | 14188 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| 14241 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 14189 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| 14242 | 3...4 => if (self.hasFeature(.avx)) | 14190 | 3...4 => if (self.hasFeature(.avx)) |
| ... | @@ -14250,22 +14198,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo | ... | @@ -14250,22 +14198,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 14250 | unreachable, | 14198 | unreachable, |
| 14251 | .Float => switch (ty.childType(mod).floatBits(self.target.*)) { | 14199 | .Float => switch (ty.childType(mod).floatBits(self.target.*)) { |
| 14252 | 16 => switch (ty.vectorLen(mod)) { | 14200 | 16 => switch (ty.vectorLen(mod)) { |
| 14253 | 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ | 14201 | 1...8 => return .{ .move = if (self.hasFeature(.avx)) |
| 14254 | .insert = .{ .vp_w, .insr }, | ||
| 14255 | .extract = .{ .vp_w, .extr }, | ||
| 14256 | } } else .{ .insert_extract = .{ | ||
| 14257 | .insert = .{ .p_w, .insr }, | ||
| 14258 | .extract = .{ .p_w, .extr }, | ||
| 14259 | } }, | ||
| 14260 | 2 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14261 | .{ .v_d, .mov } | ||
| 14262 | else | ||
| 14263 | .{ ._d, .mov } }, | ||
| 14264 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14265 | .{ .v_q, .mov } | ||
| 14266 | else | ||
| 14267 | .{ ._q, .mov } }, | ||
| 14268 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14269 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | 14202 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| 14270 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 14203 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| 14271 | 9...16 => if (self.hasFeature(.avx)) | 14204 | 9...16 => if (self.hasFeature(.avx)) |
| ... | @@ -14276,15 +14209,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo | ... | @@ -14276,15 +14209,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 14276 | else => {}, | 14209 | else => {}, |
| 14277 | }, | 14210 | }, |
| 14278 | 32 => switch (ty.vectorLen(mod)) { | 14211 | 32 => switch (ty.vectorLen(mod)) { |
| 14279 | 1 => return .{ .move = if (self.hasFeature(.avx)) | 14212 | 1...4 => return .{ .move = if (self.hasFeature(.avx)) |
| 14280 | .{ .v_ss, .mov } | ||
| 14281 | else | ||
| 14282 | .{ ._ss, .mov } }, | ||
| 14283 | 2 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14284 | .{ .v_sd, .mov } | ||
| 14285 | else | ||
| 14286 | .{ ._sd, .mov } }, | ||
| 14287 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14288 | if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } | 14213 | if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } |
| 14289 | else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } }, | 14214 | else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } }, |
| 14290 | 5...8 => if (self.hasFeature(.avx)) | 14215 | 5...8 => if (self.hasFeature(.avx)) |
| ... | @@ -14295,11 +14220,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo | ... | @@ -14295,11 +14220,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo |
| 14295 | else => {}, | 14220 | else => {}, |
| 14296 | }, | 14221 | }, |
| 14297 | 64 => switch (ty.vectorLen(mod)) { | 14222 | 64 => switch (ty.vectorLen(mod)) { |
| 14298 | 1 => return .{ .move = if (self.hasFeature(.avx)) | 14223 | 1...2 => return .{ .move = if (self.hasFeature(.avx)) |
| 14299 | .{ .v_sd, .mov } | ||
| 14300 | else | ||
| 14301 | .{ ._sd, .mov } }, | ||
| 14302 | 2 => return .{ .move = if (self.hasFeature(.avx)) | ||
| 14303 | if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } | 14224 | if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } |
| 14304 | else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } }, | 14225 | else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } }, |
| 14305 | 3...4 => if (self.hasFeature(.avx)) | 14226 | 3...4 => if (self.hasFeature(.avx)) |
| ... | @@ -16551,7 +16472,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -16551,7 +16472,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 16551 | const vec_len = ty.vectorLen(mod); | 16472 | const vec_len = ty.vectorLen(mod); |
| 16552 | const elem_ty = ty.childType(mod); | 16473 | const elem_ty = ty.childType(mod); |
| 16553 | const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod)); | 16474 | const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod)); |
| 16554 | const abi_size = elem_abi_size * vec_len; | 16475 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 16555 | const pred_ty = self.typeOf(pl_op.operand); | 16476 | const pred_ty = self.typeOf(pl_op.operand); |
| 16556 | 16477 | ||
| 16557 | const result = result: { | 16478 | const result = result: { |
| ... | @@ -16882,10 +16803,283 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -16882,10 +16803,283 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 16882 | } | 16803 | } |
| 16883 | 16804 | ||
| 16884 | fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { | 16805 | fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 16806 | const mod = self.bin_file.comp.module.?; | ||
| 16885 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 16807 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 16886 | _ = ty_pl; | 16808 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| 16887 | return self.fail("TODO implement airShuffle for x86_64", .{}); | 16809 | |
| 16888 | //return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 16810 | const dst_ty = self.typeOfIndex(inst); |
| 16811 | const elem_ty = dst_ty.childType(mod); | ||
| 16812 | const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod)); | ||
| 16813 | const dst_abi_size: u32 = @intCast(dst_ty.abiSize(mod)); | ||
| 16814 | const lhs_ty = self.typeOf(extra.a); | ||
| 16815 | const lhs_abi_size: u32 = @intCast(lhs_ty.abiSize(mod)); | ||
| 16816 | const rhs_ty = self.typeOf(extra.b); | ||
| 16817 | const rhs_abi_size: u32 = @intCast(rhs_ty.abiSize(mod)); | ||
| 16818 | const max_abi_size = @max(dst_abi_size, lhs_abi_size, rhs_abi_size); | ||
| 16819 | |||
| 16820 | const ExpectedContents = [32]?i32; | ||
| 16821 | var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) = | ||
| 16822 | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); | ||
| 16823 | const allocator = stack.get(); | ||
| 16824 | |||
| 16825 | const mask_elems = try allocator.alloc(?i32, extra.mask_len); | ||
| 16826 | defer allocator.free(mask_elems); | ||
| 16827 | for (mask_elems, 0..) |*mask_elem, elem_index| { | ||
| 16828 | const mask_elem_val = Value | ||
| 16829 | .fromInterned(extra.mask).elemValue(mod, elem_index) catch unreachable; | ||
| 16830 | mask_elem.* = if (mask_elem_val.isUndef(mod)) | ||
| 16831 | null | ||
| 16832 | else | ||
| 16833 | @intCast(mask_elem_val.toSignedInt(mod)); | ||
| 16834 | } | ||
| 16835 | |||
| 16836 | const result = @as(?MCValue, result: { | ||
| 16837 | for (mask_elems) |mask_elem| { | ||
| 16838 | if (mask_elem) |_| break; | ||
| 16839 | } else break :result try self.allocRegOrMem(inst, true); | ||
| 16840 | |||
| 16841 | for (mask_elems, 0..) |mask_elem, elem_index| { | ||
| 16842 | if (mask_elem orelse continue != @as(i32, @intCast(elem_index))) break; | ||
| 16843 | } else { | ||
| 16844 | const lhs_mcv = try self.resolveInst(extra.a); | ||
| 16845 | if (self.reuseOperand(inst, extra.a, 0, lhs_mcv)) break :result lhs_mcv; | ||
| 16846 | const dst_mcv = try self.allocRegOrMem(inst, true); | ||
| 16847 | try self.genCopy(dst_ty, dst_mcv, lhs_mcv, .{}); | ||
| 16848 | break :result dst_mcv; | ||
| 16849 | } | ||
| 16850 | |||
| 16851 | for (mask_elems, 0..) |mask_elem, elem_index| { | ||
| 16852 | if (mask_elem orelse continue != ~@as(i32, @intCast(elem_index))) break; | ||
| 16853 | } else { | ||
| 16854 | const rhs_mcv = try self.resolveInst(extra.b); | ||
| 16855 | if (self.reuseOperand(inst, extra.b, 1, rhs_mcv)) break :result rhs_mcv; | ||
| 16856 | const dst_mcv = try self.allocRegOrMem(inst, true); | ||
| 16857 | try self.genCopy(dst_ty, dst_mcv, rhs_mcv, .{}); | ||
| 16858 | break :result dst_mcv; | ||
| 16859 | } | ||
| 16860 | |||
| 16861 | const has_avx = self.hasFeature(.avx); | ||
| 16862 | shufpd: { | ||
| 16863 | if (elem_abi_size != 8) break :shufpd; | ||
| 16864 | if (max_abi_size > @as(u32, if (has_avx) 32 else 16)) break :shufpd; | ||
| 16865 | |||
| 16866 | var control: u4 = 0b0_0_0_0; | ||
| 16867 | var sources = [1]?u1{null} ** 2; | ||
| 16868 | for (mask_elems, 0..) |maybe_mask_elem, elem_index| { | ||
| 16869 | const mask_elem = maybe_mask_elem orelse continue; | ||
| 16870 | const mask_elem_index: u2 = @intCast(if (mask_elem < 0) ~mask_elem else mask_elem); | ||
| 16871 | if (mask_elem_index & 0b10 != elem_index & 0b10) break :shufpd; | ||
| 16872 | |||
| 16873 | const source = @intFromBool(mask_elem < 0); | ||
| 16874 | if (sources[elem_index & 0b01]) |prev_source| { | ||
| 16875 | if (source != prev_source) break :shufpd; | ||
| 16876 | } else sources[elem_index & 0b01] = source; | ||
| 16877 | |||
| 16878 | control |= @as(u4, @intCast(mask_elem_index & 0b01)) << @intCast(elem_index); | ||
| 16879 | } | ||
| 16880 | if (sources[0] orelse break :shufpd == sources[1] orelse break :shufpd) break :shufpd; | ||
| 16881 | |||
| 16882 | const operands = [2]Air.Inst.Ref{ extra.a, extra.b }; | ||
| 16883 | const operand_tys = [2]Type{ lhs_ty, rhs_ty }; | ||
| 16884 | const lhs_mcv = try self.resolveInst(operands[sources[0].?]); | ||
| 16885 | const rhs_mcv = try self.resolveInst(operands[sources[1].?]); | ||
| 16886 | |||
| 16887 | const dst_mcv: MCValue = if (lhs_mcv.isRegister() and | ||
| 16888 | self.reuseOperand(inst, operands[sources[0].?], sources[0].?, lhs_mcv)) | ||
| 16889 | lhs_mcv | ||
| 16890 | else if (has_avx and lhs_mcv.isRegister()) | ||
| 16891 | .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.sse) } | ||
| 16892 | else | ||
| 16893 | try self.copyToRegisterWithInstTracking(inst, operand_tys[sources[0].?], lhs_mcv); | ||
| 16894 | const dst_reg = dst_mcv.getReg().?; | ||
| 16895 | const dst_alias = registerAlias(dst_reg, max_abi_size); | ||
| 16896 | |||
| 16897 | if (has_avx) if (rhs_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate( | ||
| 16898 | .{ .v_pd, .shuf }, | ||
| 16899 | dst_alias, | ||
| 16900 | registerAlias(lhs_mcv.getReg() orelse dst_reg, max_abi_size), | ||
| 16901 | try rhs_mcv.mem(self, Memory.Size.fromSize(max_abi_size)), | ||
| 16902 | Immediate.u(control), | ||
| 16903 | ) else try self.asmRegisterRegisterRegisterImmediate( | ||
| 16904 | .{ .v_pd, .shuf }, | ||
| 16905 | dst_alias, | ||
| 16906 | registerAlias(lhs_mcv.getReg() orelse dst_reg, max_abi_size), | ||
| 16907 | registerAlias(if (rhs_mcv.isRegister()) | ||
| 16908 | rhs_mcv.getReg().? | ||
| 16909 | else | ||
| 16910 | try self.copyToTmpRegister(operand_tys[sources[1].?], rhs_mcv), max_abi_size), | ||
| 16911 | Immediate.u(control), | ||
| 16912 | ) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate( | ||
| 16913 | .{ ._pd, .shuf }, | ||
| 16914 | dst_alias, | ||
| 16915 | try rhs_mcv.mem(self, Memory.Size.fromSize(max_abi_size)), | ||
| 16916 | Immediate.u(control), | ||
| 16917 | ) else try self.asmRegisterRegisterImmediate( | ||
| 16918 | .{ ._pd, .shuf }, | ||
| 16919 | dst_alias, | ||
| 16920 | registerAlias(if (rhs_mcv.isRegister()) | ||
| 16921 | rhs_mcv.getReg().? | ||
| 16922 | else | ||
| 16923 | try self.copyToTmpRegister(operand_tys[sources[1].?], rhs_mcv), max_abi_size), | ||
| 16924 | Immediate.u(control), | ||
| 16925 | ); | ||
| 16926 | break :result dst_mcv; | ||
| 16927 | } | ||
| 16928 | |||
| 16929 | pshufb: { | ||
| 16930 | if (max_abi_size > 16) break :pshufb; | ||
| 16931 | if (!self.hasFeature(.ssse3)) break :pshufb; | ||
| 16932 | |||
| 16933 | const temp_regs = | ||
| 16934 | try self.register_manager.allocRegs(2, .{ inst, null }, abi.RegisterClass.sse); | ||
| 16935 | const temp_locks = self.register_manager.lockRegsAssumeUnused(2, temp_regs); | ||
| 16936 | defer for (temp_locks) |lock| self.register_manager.unlockReg(lock); | ||
| 16937 | |||
| 16938 | const lhs_temp_alias = registerAlias(temp_regs[0], max_abi_size); | ||
| 16939 | try self.genSetReg(temp_regs[0], lhs_ty, .{ .air_ref = extra.a }, .{}); | ||
| 16940 | |||
| 16941 | const rhs_temp_alias = registerAlias(temp_regs[1], max_abi_size); | ||
| 16942 | try self.genSetReg(temp_regs[1], rhs_ty, .{ .air_ref = extra.b }, .{}); | ||
| 16943 | |||
| 16944 | var lhs_mask_elems: [16]InternPool.Index = undefined; | ||
| 16945 | for (lhs_mask_elems[0..max_abi_size], 0..) |*lhs_mask_elem, byte_index| { | ||
| 16946 | const elem_index = byte_index / elem_abi_size; | ||
| 16947 | lhs_mask_elem.* = try mod.intern(.{ .int = .{ | ||
| 16948 | .ty = .u8_type, | ||
| 16949 | .storage = .{ .u64 = if (elem_index >= mask_elems.len) 0b1_00_00000 else elem: { | ||
| 16950 | const mask_elem = mask_elems[elem_index] orelse break :elem 0b1_00_00000; | ||
| 16951 | if (mask_elem < 0) break :elem 0b1_00_00000; | ||
| 16952 | const mask_elem_index: u31 = @intCast(mask_elem); | ||
| 16953 | const byte_off: u32 = @intCast(byte_index % elem_abi_size); | ||
| 16954 | break :elem @intCast(mask_elem_index * elem_abi_size + byte_off); | ||
| 16955 | } }, | ||
| 16956 | } }); | ||
| 16957 | } | ||
| 16958 | const lhs_mask_ty = try mod.vectorType(.{ .len = max_abi_size, .child = .u8_type }); | ||
| 16959 | const lhs_mask_mcv = try self.genTypedValue(.{ | ||
| 16960 | .ty = lhs_mask_ty, | ||
| 16961 | .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ | ||
| 16962 | .ty = lhs_mask_ty.toIntern(), | ||
| 16963 | .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] }, | ||
| 16964 | } })), | ||
| 16965 | }); | ||
| 16966 | const lhs_mask_mem: Memory = .{ | ||
| 16967 | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, lhs_mask_mcv.address()) }, | ||
| 16968 | .mod = .{ .rm = .{ .size = Memory.Size.fromSize(@max(max_abi_size, 16)) } }, | ||
| 16969 | }; | ||
| 16970 | if (has_avx) try self.asmRegisterRegisterMemory( | ||
| 16971 | .{ .vp_b, .shuf }, | ||
| 16972 | lhs_temp_alias, | ||
| 16973 | lhs_temp_alias, | ||
| 16974 | lhs_mask_mem, | ||
| 16975 | ) else try self.asmRegisterMemory( | ||
| 16976 | .{ .p_b, .shuf }, | ||
| 16977 | lhs_temp_alias, | ||
| 16978 | lhs_mask_mem, | ||
| 16979 | ); | ||
| 16980 | |||
| 16981 | var rhs_mask_elems: [16]InternPool.Index = undefined; | ||
| 16982 | for (rhs_mask_elems[0..max_abi_size], 0..) |*rhs_mask_elem, byte_index| { | ||
| 16983 | const elem_index = byte_index / elem_abi_size; | ||
| 16984 | rhs_mask_elem.* = try mod.intern(.{ .int = .{ | ||
| 16985 | .ty = .u8_type, | ||
| 16986 | .storage = .{ .u64 = if (elem_index >= mask_elems.len) 0b1_00_00000 else elem: { | ||
| 16987 | const mask_elem = mask_elems[elem_index] orelse break :elem 0b1_00_00000; | ||
| 16988 | if (mask_elem >= 0) break :elem 0b1_00_00000; | ||
| 16989 | const mask_elem_index: u31 = @intCast(~mask_elem); | ||
| 16990 | const byte_off: u32 = @intCast(byte_index % elem_abi_size); | ||
| 16991 | break :elem @intCast(mask_elem_index * elem_abi_size + byte_off); | ||
| 16992 | } }, | ||
| 16993 | } }); | ||
| 16994 | } | ||
| 16995 | const rhs_mask_ty = try mod.vectorType(.{ .len = max_abi_size, .child = .u8_type }); | ||
| 16996 | const rhs_mask_mcv = try self.genTypedValue(.{ | ||
| 16997 | .ty = rhs_mask_ty, | ||
| 16998 | .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ | ||
| 16999 | .ty = rhs_mask_ty.toIntern(), | ||
| 17000 | .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] }, | ||
| 17001 | } })), | ||
| 17002 | }); | ||
| 17003 | const rhs_mask_mem: Memory = .{ | ||
| 17004 | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, rhs_mask_mcv.address()) }, | ||
| 17005 | .mod = .{ .rm = .{ .size = Memory.Size.fromSize(@max(max_abi_size, 16)) } }, | ||
| 17006 | }; | ||
| 17007 | if (has_avx) try self.asmRegisterRegisterMemory( | ||
| 17008 | .{ .vp_b, .shuf }, | ||
| 17009 | rhs_temp_alias, | ||
| 17010 | rhs_temp_alias, | ||
| 17011 | rhs_mask_mem, | ||
| 17012 | ) else try self.asmRegisterMemory( | ||
| 17013 | .{ .p_b, .shuf }, | ||
| 17014 | rhs_temp_alias, | ||
| 17015 | rhs_mask_mem, | ||
| 17016 | ); | ||
| 17017 | |||
| 17018 | if (has_avx) try self.asmRegisterRegisterRegister( | ||
| 17019 | .{ switch (elem_ty.zigTypeTag(mod)) { | ||
| 17020 | else => break :result null, | ||
| 17021 | .Int => .vp_, | ||
| 17022 | .Float => switch (elem_ty.floatBits(self.target.*)) { | ||
| 17023 | 32 => .v_ps, | ||
| 17024 | 64 => .v_pd, | ||
| 17025 | 16, 80, 128 => break :result null, | ||
| 17026 | else => unreachable, | ||
| 17027 | }, | ||
| 17028 | }, .@"or" }, | ||
| 17029 | lhs_temp_alias, | ||
| 17030 | lhs_temp_alias, | ||
| 17031 | rhs_temp_alias, | ||
| 17032 | ) else try self.asmRegisterRegister( | ||
| 17033 | .{ switch (elem_ty.zigTypeTag(mod)) { | ||
| 17034 | else => break :result null, | ||
| 17035 | .Int => .p_, | ||
| 17036 | .Float => switch (elem_ty.floatBits(self.target.*)) { | ||
| 17037 | 32 => ._ps, | ||
| 17038 | 64 => ._pd, | ||
| 17039 | 16, 80, 128 => break :result null, | ||
| 17040 | else => unreachable, | ||
| 17041 | }, | ||
| 17042 | }, .@"or" }, | ||
| 17043 | lhs_temp_alias, | ||
| 17044 | rhs_temp_alias, | ||
| 17045 | ); | ||
| 17046 | break :result .{ .register = temp_regs[0] }; | ||
| 17047 | } | ||
| 17048 | |||
| 17049 | if (max_abi_size <= 16) { | ||
| 17050 | const lhs_mcv = try self.resolveInst(extra.a); | ||
| 17051 | const lhs_reg = if (lhs_mcv.isRegister()) | ||
| 17052 | lhs_mcv.getReg().? | ||
| 17053 | else | ||
| 17054 | try self.copyToTmpRegister(lhs_ty, lhs_mcv); | ||
| 17055 | const lhs_lock = self.register_manager.lockRegAssumeUnused(lhs_reg); | ||
| 17056 | defer self.register_manager.unlockReg(lhs_lock); | ||
| 17057 | |||
| 17058 | const rhs_mcv = try self.resolveInst(extra.b); | ||
| 17059 | const rhs_reg = if (rhs_mcv.isRegister()) | ||
| 17060 | rhs_mcv.getReg().? | ||
| 17061 | else | ||
| 17062 | try self.copyToTmpRegister(rhs_ty, rhs_mcv); | ||
| 17063 | const rhs_lock = self.register_manager.lockReg(rhs_reg); | ||
| 17064 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 17065 | |||
| 17066 | //const dst_mcv = try self.register_manager.allocReg(inst, abi.RegisterClass.sse); | ||
| 17067 | switch (elem_ty.zigTypeTag(mod)) { | ||
| 17068 | .Float => switch (elem_ty.floatBits(self.target.*)) { | ||
| 17069 | 16, 32 => {}, | ||
| 17070 | 64 => unreachable, // fully handled by shufpd | ||
| 17071 | 80, 128 => unreachable, // all possible masks already handled | ||
| 17072 | else => unreachable, | ||
| 17073 | }, | ||
| 17074 | else => {}, | ||
| 17075 | } | ||
| 17076 | } | ||
| 17077 | |||
| 17078 | break :result null; | ||
| 17079 | }) orelse return self.fail("TODO implement airShuffle from {} and {} to {}", .{ | ||
| 17080 | lhs_ty.fmt(mod), rhs_ty.fmt(mod), dst_ty.fmt(mod), | ||
| 17081 | }); | ||
| 17082 | return self.finishAir(inst, result, .{ extra.a, extra.b, .none }); | ||
| 16889 | } | 17083 | } |
| 16890 | 17084 | ||
| 16891 | fn airReduce(self: *Self, inst: Air.Inst.Index) !void { | 17085 | fn airReduce(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -17062,7 +17256,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -17062,7 +17256,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 17062 | }, | 17256 | }, |
| 17063 | .Array, .Vector => { | 17257 | .Array, .Vector => { |
| 17064 | const elem_ty = result_ty.childType(mod); | 17258 | const elem_ty = result_ty.childType(mod); |
| 17065 | if (result_ty.isVector(mod) and elem_ty.bitSize(mod) == 1) { | 17259 | if (result_ty.isVector(mod) and elem_ty.toIntern() == .bool_type) { |
| 17066 | const result_size: u32 = @intCast(result_ty.abiSize(mod)); | 17260 | const result_size: u32 = @intCast(result_ty.abiSize(mod)); |
| 17067 | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); | 17261 | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 17068 | try self.asmRegisterRegister( | 17262 | try self.asmRegisterRegister( |
| ... | @@ -18112,7 +18306,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { | ... | @@ -18112,7 +18306,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { |
| 18112 | else => unreachable, | 18306 | else => unreachable, |
| 18113 | }, | 18307 | }, |
| 18114 | .float => Type.f32, | 18308 | .float => Type.f32, |
| 18115 | .float_combine => try mod.vectorType(.{ .len = 2, .child = .f32_type }), | 18309 | .float_combine => try mod.arrayType(.{ .len = 2, .child = .f32_type }), |
| 18116 | .sse => Type.f64, | 18310 | .sse => Type.f64, |
| 18117 | else => break, | 18311 | else => break, |
| 18118 | }; | 18312 | }; |
src/arch/x86_64/Encoding.zig+2-2| ... | @@ -324,7 +324,7 @@ pub const Mnemonic = enum { | ... | @@ -324,7 +324,7 @@ pub const Mnemonic = enum { |
| 324 | // SSE3 | 324 | // SSE3 |
| 325 | movddup, movshdup, movsldup, | 325 | movddup, movshdup, movsldup, |
| 326 | // SSSE3 | 326 | // SSSE3 |
| 327 | pabsb, pabsd, pabsw, palignr, | 327 | pabsb, pabsd, pabsw, palignr, pshufb, |
| 328 | // SSE4.1 | 328 | // SSE4.1 |
| 329 | blendpd, blendps, blendvpd, blendvps, | 329 | blendpd, blendps, blendvpd, blendvps, |
| 330 | extractps, | 330 | extractps, |
| ... | @@ -389,7 +389,7 @@ pub const Mnemonic = enum { | ... | @@ -389,7 +389,7 @@ pub const Mnemonic = enum { |
| 389 | vpmovmskb, | 389 | vpmovmskb, |
| 390 | vpmulhw, vpmulld, vpmullw, | 390 | vpmulhw, vpmulld, vpmullw, |
| 391 | vpor, | 391 | vpor, |
| 392 | vpshufd, vpshufhw, vpshuflw, | 392 | vpshufb, vpshufd, vpshufhw, vpshuflw, |
| 393 | vpslld, vpslldq, vpsllq, vpsllw, | 393 | vpslld, vpslldq, vpsllq, vpsllw, |
| 394 | vpsrad, vpsraq, vpsraw, | 394 | vpsrad, vpsraq, vpsraw, |
| 395 | vpsrld, vpsrldq, vpsrlq, vpsrlw, | 395 | vpsrld, vpsrldq, vpsrlq, vpsrlw, |
src/arch/x86_64/encodings.zig+5| ... | @@ -1185,6 +1185,8 @@ pub const table = [_]Entry{ | ... | @@ -1185,6 +1185,8 @@ pub const table = [_]Entry{ |
| 1185 | 1185 | ||
| 1186 | .{ .palignr, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0f }, 0, .none, .ssse3 }, | 1186 | .{ .palignr, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0f }, 0, .none, .ssse3 }, |
| 1187 | 1187 | ||
| 1188 | .{ .pshufb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x00 }, 0, .none, .ssse3 }, | ||
| 1189 | |||
| 1188 | // SSE4.1 | 1190 | // SSE4.1 |
| 1189 | .{ .blendpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0d }, 0, .none, .sse4_1 }, | 1191 | .{ .blendpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0d }, 0, .none, .sse4_1 }, |
| 1190 | 1192 | ||
| ... | @@ -1593,6 +1595,8 @@ pub const table = [_]Entry{ | ... | @@ -1593,6 +1595,8 @@ pub const table = [_]Entry{ |
| 1593 | 1595 | ||
| 1594 | .{ .vpor, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xeb }, 0, .vex_128_wig, .avx }, | 1596 | .{ .vpor, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xeb }, 0, .vex_128_wig, .avx }, |
| 1595 | 1597 | ||
| 1598 | .{ .vpshufb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x00 }, 0, .vex_128_wig, .avx }, | ||
| 1599 | |||
| 1596 | .{ .vpshufd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x70 }, 0, .vex_128_wig, .avx }, | 1600 | .{ .vpshufd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x70 }, 0, .vex_128_wig, .avx }, |
| 1597 | 1601 | ||
| 1598 | .{ .vpshufhw, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0xf3, 0x0f, 0x70 }, 0, .vex_128_wig, .avx }, | 1602 | .{ .vpshufhw, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0xf3, 0x0f, 0x70 }, 0, .vex_128_wig, .avx }, |
| ... | @@ -1820,6 +1824,7 @@ pub const table = [_]Entry{ | ... | @@ -1820,6 +1824,7 @@ pub const table = [_]Entry{ |
| 1820 | 1824 | ||
| 1821 | .{ .vpor, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xeb }, 0, .vex_256_wig, .avx2 }, | 1825 | .{ .vpor, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xeb }, 0, .vex_256_wig, .avx2 }, |
| 1822 | 1826 | ||
| 1827 | .{ .vpshufb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x00 }, 0, .vex_256_wig, .avx2 }, | ||
| 1823 | .{ .vpshufd, .rmi, &.{ .ymm, .ymm_m256, .imm8 }, &.{ 0x66, 0x0f, 0x70 }, 0, .vex_256_wig, .avx2 }, | 1828 | .{ .vpshufd, .rmi, &.{ .ymm, .ymm_m256, .imm8 }, &.{ 0x66, 0x0f, 0x70 }, 0, .vex_256_wig, .avx2 }, |
| 1824 | 1829 | ||
| 1825 | .{ .vpshufhw, .rmi, &.{ .ymm, .ymm_m256, .imm8 }, &.{ 0xf3, 0x0f, 0x70 }, 0, .vex_256_wig, .avx2 }, | 1830 | .{ .vpshufhw, .rmi, &.{ .ymm, .ymm_m256, .imm8 }, &.{ 0xf3, 0x0f, 0x70 }, 0, .vex_256_wig, .avx2 }, |
src/codegen.zig+27-30| ... | @@ -405,7 +405,7 @@ pub fn generateSymbol( | ... | @@ -405,7 +405,7 @@ pub fn generateSymbol( |
| 405 | .vector_type => |vector_type| { | 405 | .vector_type => |vector_type| { |
| 406 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse | 406 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse |
| 407 | return error.Overflow; | 407 | return error.Overflow; |
| 408 | if (Type.fromInterned(vector_type.child).bitSize(mod) == 1) { | 408 | if (vector_type.child == .bool_type) { |
| 409 | const bytes = try code.addManyAsSlice(abi_size); | 409 | const bytes = try code.addManyAsSlice(abi_size); |
| 410 | @memset(bytes, 0xaa); | 410 | @memset(bytes, 0xaa); |
| 411 | var index: usize = 0; | 411 | var index: usize = 0; |
| ... | @@ -443,37 +443,34 @@ pub fn generateSymbol( | ... | @@ -443,37 +443,34 @@ pub fn generateSymbol( |
| 443 | }, | 443 | }, |
| 444 | }) byte.* |= mask else byte.* &= ~mask; | 444 | }) byte.* |= mask else byte.* &= ~mask; |
| 445 | } | 445 | } |
| 446 | } else switch (aggregate.storage) { | 446 | } else { |
| 447 | .bytes => |bytes| try code.appendSlice(bytes), | 447 | switch (aggregate.storage) { |
| 448 | .elems, .repeated_elem => { | 448 | .bytes => |bytes| try code.appendSlice(bytes), |
| 449 | var index: u64 = 0; | 449 | .elems, .repeated_elem => { |
| 450 | while (index < vector_type.len) : (index += 1) { | 450 | var index: u64 = 0; |
| 451 | switch (try generateSymbol(bin_file, src_loc, .{ | 451 | while (index < vector_type.len) : (index += 1) { |
| 452 | .ty = Type.fromInterned(vector_type.child), | 452 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 453 | .val = Value.fromInterned(switch (aggregate.storage) { | 453 | .ty = Type.fromInterned(vector_type.child), |
| 454 | .bytes => unreachable, | 454 | .val = Value.fromInterned(switch (aggregate.storage) { |
| 455 | .elems => |elems| elems[ | 455 | .bytes => unreachable, |
| 456 | math.cast(usize, index) orelse return error.Overflow | 456 | .elems => |elems| elems[ |
| 457 | ], | 457 | math.cast(usize, index) orelse return error.Overflow |
| 458 | .repeated_elem => |elem| elem, | 458 | ], |
| 459 | }), | 459 | .repeated_elem => |elem| elem, |
| 460 | }, code, debug_output, reloc_info)) { | 460 | }), |
| 461 | .ok => {}, | 461 | }, code, debug_output, reloc_info)) { |
| 462 | .fail => |em| return .{ .fail = em }, | 462 | .ok => {}, |
| 463 | .fail => |em| return .{ .fail = em }, | ||
| 464 | } | ||
| 463 | } | 465 | } |
| 464 | } | 466 | }, |
| 465 | }, | 467 | } |
| 466 | } | ||
| 467 | 468 | ||
| 468 | const padding = abi_size - (math.cast(usize, math.divCeil( | 469 | const padding = abi_size - |
| 469 | u64, | 470 | (math.cast(usize, Type.fromInterned(vector_type.child).abiSize(mod) * vector_type.len) orelse |
| 470 | Type.fromInterned(vector_type.child).bitSize(mod) * vector_type.len, | 471 | return error.Overflow); |
| 471 | 8, | 472 | if (padding > 0) try code.appendNTimes(0, padding); |
| 472 | ) catch |err| switch (err) { | 473 | } |
| 473 | error.DivisionByZero => unreachable, | ||
| 474 | else => |e| return e, | ||
| 475 | }) orelse return error.Overflow); | ||
| 476 | if (padding > 0) try code.appendNTimes(0, padding); | ||
| 477 | }, | 474 | }, |
| 478 | .anon_struct_type => |tuple| { | 475 | .anon_struct_type => |tuple| { |
| 479 | const struct_begin = code.items.len; | 476 | const struct_begin = code.items.len; |
src/type.zig+34-8| ... | @@ -905,11 +905,28 @@ pub const Type = struct { | ... | @@ -905,11 +905,28 @@ pub const Type = struct { |
| 905 | return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat); | 905 | return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat); |
| 906 | }, | 906 | }, |
| 907 | .vector_type => |vector_type| { | 907 | .vector_type => |vector_type| { |
| 908 | const bits_u64 = try bitSizeAdvanced(Type.fromInterned(vector_type.child), mod, opt_sema); | 908 | if (vector_type.len == 0) return .{ .scalar = .@"1" }; |
| 909 | const bits: u32 = @intCast(bits_u64); | 909 | switch (mod.comp.getZigBackend()) { |
| 910 | const bytes = ((bits * vector_type.len) + 7) / 8; | 910 | else => { |
| 911 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); | 911 | const elem_bits: u32 = @intCast(try Type.fromInterned(vector_type.child).bitSizeAdvanced(mod, opt_sema)); |
| 912 | return .{ .scalar = Alignment.fromByteUnits(alignment) }; | 912 | if (elem_bits == 0) return .{ .scalar = .@"1" }; |
| 913 | const bytes = ((elem_bits * vector_type.len) + 7) / 8; | ||
| 914 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); | ||
| 915 | return .{ .scalar = Alignment.fromByteUnits(alignment) }; | ||
| 916 | }, | ||
| 917 | .stage2_x86_64 => { | ||
| 918 | if (vector_type.child == .bool_type) return .{ .scalar = intAbiAlignment(@intCast(vector_type.len), target) }; | ||
| 919 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar); | ||
| 920 | if (elem_bytes == 0) return .{ .scalar = .@"1" }; | ||
| 921 | const bytes = elem_bytes * vector_type.len; | ||
| 922 | if (bytes > 32 and std.Target.x86.featureSetHas(target.cpu.features, .avx512f)) return .{ .scalar = .@"64" }; | ||
| 923 | if (bytes > 16 and std.Target.x86.featureSetHas( | ||
| 924 | target.cpu.features, | ||
| 925 | if (Type.fromInterned(vector_type.child).isRuntimeFloat()) .avx else .avx2, | ||
| 926 | )) return .{ .scalar = .@"32" }; | ||
| 927 | return .{ .scalar = .@"16" }; | ||
| 928 | }, | ||
| 929 | } | ||
| 913 | }, | 930 | }, |
| 914 | 931 | ||
| 915 | .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat), | 932 | .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat), |
| ... | @@ -1237,9 +1254,6 @@ pub const Type = struct { | ... | @@ -1237,9 +1254,6 @@ pub const Type = struct { |
| 1237 | .storage = .{ .lazy_size = ty.toIntern() }, | 1254 | .storage = .{ .lazy_size = ty.toIntern() }, |
| 1238 | } }))) }, | 1255 | } }))) }, |
| 1239 | }; | 1256 | }; |
| 1240 | const elem_bits = try Type.fromInterned(vector_type.child).bitSizeAdvanced(mod, opt_sema); | ||
| 1241 | const total_bits = elem_bits * vector_type.len; | ||
| 1242 | const total_bytes = (total_bits + 7) / 8; | ||
| 1243 | const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) { | 1257 | const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) { |
| 1244 | .scalar => |x| x, | 1258 | .scalar => |x| x, |
| 1245 | .val => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{ | 1259 | .val => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{ |
| ... | @@ -1247,6 +1261,18 @@ pub const Type = struct { | ... | @@ -1247,6 +1261,18 @@ pub const Type = struct { |
| 1247 | .storage = .{ .lazy_size = ty.toIntern() }, | 1261 | .storage = .{ .lazy_size = ty.toIntern() }, |
| 1248 | } }))) }, | 1262 | } }))) }, |
| 1249 | }; | 1263 | }; |
| 1264 | const total_bytes = switch (mod.comp.getZigBackend()) { | ||
| 1265 | else => total_bytes: { | ||
| 1266 | const elem_bits = try Type.fromInterned(vector_type.child).bitSizeAdvanced(mod, opt_sema); | ||
| 1267 | const total_bits = elem_bits * vector_type.len; | ||
| 1268 | break :total_bytes (total_bits + 7) / 8; | ||
| 1269 | }, | ||
| 1270 | .stage2_x86_64 => total_bytes: { | ||
| 1271 | if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable; | ||
| 1272 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar); | ||
| 1273 | break :total_bytes elem_bytes * vector_type.len; | ||
| 1274 | }, | ||
| 1275 | }; | ||
| 1250 | return AbiSizeAdvanced{ .scalar = alignment.forward(total_bytes) }; | 1276 | return AbiSizeAdvanced{ .scalar = alignment.forward(total_bytes) }; |
| 1251 | }, | 1277 | }, |
| 1252 | 1278 |
test/behavior/bitcast.zig+1-1| ... | @@ -336,7 +336,7 @@ test "comptime @bitCast packed struct to int and back" { | ... | @@ -336,7 +336,7 @@ test "comptime @bitCast packed struct to int and back" { |
| 336 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 336 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 337 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 337 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 338 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 338 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 339 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | 339 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 340 | 340 | ||
| 341 | if (builtin.zig_backend == .stage2_llvm and native_endian == .big) { | 341 | if (builtin.zig_backend == .stage2_llvm and native_endian == .big) { |
| 342 | // https://github.com/ziglang/zig/issues/13782 | 342 | // https://github.com/ziglang/zig/issues/13782 |
test/behavior/cast.zig+1| ... | @@ -2441,6 +2441,7 @@ test "@intFromBool on vector" { | ... | @@ -2441,6 +2441,7 @@ test "@intFromBool on vector" { |
| 2441 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 2441 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2442 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2442 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2443 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 2443 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2444 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 2444 | 2445 | ||
| 2445 | const S = struct { | 2446 | const S = struct { |
| 2446 | fn doTheTest() !void { | 2447 | fn doTheTest() !void { |
test/behavior/shuffle.zig+2-1| ... | @@ -4,10 +4,11 @@ const mem = std.mem; | ... | @@ -4,10 +4,11 @@ const mem = std.mem; |
| 4 | const expect = std.testing.expect; | 4 | const expect = std.testing.expect; |
| 5 | 5 | ||
| 6 | test "@shuffle int" { | 6 | test "@shuffle int" { |
| 7 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 8 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 7 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 8 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 10 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 9 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 10 | if (builtin.zig_backend == .stage2_x86_64 and | ||
| 11 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3)) return error.SkipZigTest; | ||
| 11 | 12 | ||
| 12 | const S = struct { | 13 | const S = struct { |
| 13 | fn doTheTest() !void { | 14 | fn doTheTest() !void { |
test/behavior/vector.zig+29-13| ... | @@ -29,7 +29,7 @@ test "vector wrap operators" { | ... | @@ -29,7 +29,7 @@ test "vector wrap operators" { |
| 29 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 29 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 30 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 30 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 31 | if (builtin.zig_backend == .stage2_x86_64 and | 31 | if (builtin.zig_backend == .stage2_x86_64 and |
| 32 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO | 32 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; |
| 33 | 33 | ||
| 34 | const S = struct { | 34 | const S = struct { |
| 35 | fn doTheTest() !void { | 35 | fn doTheTest() !void { |
| ... | @@ -906,22 +906,26 @@ test "vector @reduce comptime" { | ... | @@ -906,22 +906,26 @@ test "vector @reduce comptime" { |
| 906 | } | 906 | } |
| 907 | 907 | ||
| 908 | test "mask parameter of @shuffle is comptime scope" { | 908 | test "mask parameter of @shuffle is comptime scope" { |
| 909 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 910 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 909 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 911 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 910 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 912 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 911 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 912 | if (builtin.zig_backend == .stage2_x86_64 and | ||
| 913 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3)) return error.SkipZigTest; | ||
| 913 | 914 | ||
| 914 | const __v4hi = @Vector(4, i16); | 915 | const __v4hi = @Vector(4, i16); |
| 915 | var v4_a = __v4hi{ 0, 0, 0, 0 }; | 916 | var v4_a = __v4hi{ 1, 2, 3, 4 }; |
| 916 | var v4_b = __v4hi{ 0, 0, 0, 0 }; | 917 | var v4_b = __v4hi{ 5, 6, 7, 8 }; |
| 917 | _ = .{ &v4_a, &v4_b }; | 918 | _ = .{ &v4_a, &v4_b }; |
| 918 | const shuffled: __v4hi = @shuffle(i16, v4_a, v4_b, @Vector(4, i32){ | 919 | const shuffled: __v4hi = @shuffle(i16, v4_a, v4_b, @Vector(4, i32){ |
| 919 | std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len), | 920 | std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len), |
| 920 | std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len), | 921 | std.zig.c_translation.shuffleVectorIndex(2, @typeInfo(@TypeOf(v4_a)).Vector.len), |
| 921 | std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len), | 922 | std.zig.c_translation.shuffleVectorIndex(4, @typeInfo(@TypeOf(v4_a)).Vector.len), |
| 922 | std.zig.c_translation.shuffleVectorIndex(0, @typeInfo(@TypeOf(v4_a)).Vector.len), | 923 | std.zig.c_translation.shuffleVectorIndex(6, @typeInfo(@TypeOf(v4_a)).Vector.len), |
| 923 | }); | 924 | }); |
| 924 | _ = shuffled; | 925 | try expect(shuffled[0] == 1); |
| 926 | try expect(shuffled[1] == 3); | ||
| 927 | try expect(shuffled[2] == 5); | ||
| 928 | try expect(shuffled[3] == 7); | ||
| 925 | } | 929 | } |
| 926 | 930 | ||
| 927 | test "saturating add" { | 931 | test "saturating add" { |
| ... | @@ -1177,10 +1181,22 @@ test "@shlWithOverflow" { | ... | @@ -1177,10 +1181,22 @@ test "@shlWithOverflow" { |
| 1177 | } | 1181 | } |
| 1178 | 1182 | ||
| 1179 | test "alignment of vectors" { | 1183 | test "alignment of vectors" { |
| 1180 | try expect(@alignOf(@Vector(2, u8)) == 2); | 1184 | try expect(@alignOf(@Vector(2, u8)) == switch (builtin.zig_backend) { |
| 1181 | try expect(@alignOf(@Vector(2, u1)) == 1); | 1185 | else => 2, |
| 1182 | try expect(@alignOf(@Vector(1, u1)) == 1); | 1186 | .stage2_x86_64 => 16, |
| 1183 | try expect(@alignOf(@Vector(2, u16)) == 4); | 1187 | }); |
| 1188 | try expect(@alignOf(@Vector(2, u1)) == switch (builtin.zig_backend) { | ||
| 1189 | else => 1, | ||
| 1190 | .stage2_x86_64 => 16, | ||
| 1191 | }); | ||
| 1192 | try expect(@alignOf(@Vector(1, u1)) == switch (builtin.zig_backend) { | ||
| 1193 | else => 1, | ||
| 1194 | .stage2_x86_64 => 16, | ||
| 1195 | }); | ||
| 1196 | try expect(@alignOf(@Vector(2, u16)) == switch (builtin.zig_backend) { | ||
| 1197 | else => 4, | ||
| 1198 | .stage2_x86_64 => 16, | ||
| 1199 | }); | ||
| 1184 | } | 1200 | } |
| 1185 | 1201 | ||
| 1186 | test "loading the second vector from a slice of vectors" { | 1202 | test "loading the second vector from a slice of vectors" { |
| ... | @@ -1316,10 +1332,10 @@ test "modRem with zero divisor" { | ... | @@ -1316,10 +1332,10 @@ test "modRem with zero divisor" { |
| 1316 | 1332 | ||
| 1317 | test "array operands to shuffle are coerced to vectors" { | 1333 | test "array operands to shuffle are coerced to vectors" { |
| 1318 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 1334 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1319 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 1320 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1335 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1321 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1336 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1322 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1337 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1338 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 1323 | 1339 | ||
| 1324 | const mask = [5]i32{ -1, 0, 1, 2, 3 }; | 1340 | const mask = [5]i32{ -1, 0, 1, 2, 3 }; |
| 1325 | 1341 |