authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-11-03 23:18:21-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-11-03 23:18:21-04:00
log509be7cf1f10c5d329d2b0524f2af6bfcabd52de
tree655825e5800a1c79e8ccc0abe5011dd47655a96a
parentf6de3ec963e3a7d96cd4f6c72b0f076f0437c45d

x86_64: fix std test failures


45 files changed, 1413 insertions(+), 842 deletions(-)

lib/std/Thread/Condition.zig-10
......@@ -324,8 +324,6 @@ test "Condition - wait and signal" {
324324 return error.SkipZigTest;
325325 }
326326
327 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
328
329327 const num_threads = 4;
330328
331329 const MultiWait = struct {
......@@ -371,8 +369,6 @@ test "Condition - signal" {
371369 return error.SkipZigTest;
372370 }
373371
374 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
375
376372 const num_threads = 4;
377373
378374 const SignalTest = struct {
......@@ -440,8 +436,6 @@ test "Condition - multi signal" {
440436 return error.SkipZigTest;
441437 }
442438
443 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
444
445439 const num_threads = 4;
446440 const num_iterations = 4;
447441
......@@ -504,8 +498,6 @@ test "Condition - broadcasting" {
504498 return error.SkipZigTest;
505499 }
506500
507 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
508
509501 const num_threads = 10;
510502
511503 const BroadcastTest = struct {
......@@ -573,8 +565,6 @@ test "Condition - broadcasting - wake all threads" {
573565 return error.SkipZigTest;
574566 }
575567
576 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
577
578568 var num_runs: usize = 1;
579569 const num_threads = 10;
580570
lib/std/Thread/Mutex.zig-2
......@@ -289,8 +289,6 @@ test "Mutex - many contended" {
289289 return error.SkipZigTest;
290290 }
291291
292 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
293
294292 const num_threads = 4;
295293 const num_increments = 1000;
296294
lib/std/Thread/RwLock.zig-2
......@@ -297,8 +297,6 @@ test "RwLock - concurrent access" {
297297 if (builtin.single_threaded)
298298 return;
299299
300 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
301
302300 const num_writers: usize = 2;
303301 const num_readers: usize = 4;
304302 const num_writes: usize = 10000;
lib/std/Thread/Semaphore.zig-2
......@@ -39,8 +39,6 @@ test "Thread.Semaphore" {
3939 return error.SkipZigTest;
4040 }
4141
42 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
43
4442 const TestContext = struct {
4543 sem: *Semaphore,
4644 n: *i32,
lib/std/atomic/Atomic.zig-2
......@@ -467,8 +467,6 @@ test "Atomic.fetchSub" {
467467}
468468
469469test "Atomic.fetchMin" {
470 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
471
472470 inline for (atomicIntTypes()) |Int| {
473471 inline for (atomic_rmw_orderings) |ordering| {
474472 var x = Atomic(Int).init(5);
lib/std/atomic/queue.zig-2
......@@ -175,8 +175,6 @@ const puts_per_thread = 500;
175175const put_thread_count = 3;
176176
177177test "std.atomic.Queue" {
178 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
179
180178 var plenty_of_memory = try std.heap.page_allocator.alloc(u8, 300 * 1024);
181179 defer std.heap.page_allocator.free(plenty_of_memory);
182180
lib/std/base64.zig-4
......@@ -355,8 +355,6 @@ pub const Base64DecoderWithIgnore = struct {
355355};
356356
357357test "base64" {
358 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
359
360358 @setEvalBranchQuota(8000);
361359 try testBase64();
362360 try comptime testAllApis(standard, "comptime", "Y29tcHRpbWU=");
......@@ -377,8 +375,6 @@ test "base64 padding dest overflow" {
377375}
378376
379377test "base64 url_safe_no_pad" {
380 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
381
382378 @setEvalBranchQuota(8000);
383379 try testBase64UrlSafeNoPad();
384380 try comptime testAllApis(url_safe_no_pad, "comptime", "Y29tcHRpbWU");
lib/std/bit_set.zig-3
......@@ -1638,7 +1638,6 @@ fn testStaticBitSet(comptime Set: type) !void {
16381638
16391639test "IntegerBitSet" {
16401640 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1641 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
16421641
16431642 try testStaticBitSet(IntegerBitSet(0));
16441643 try testStaticBitSet(IntegerBitSet(1));
......@@ -1651,8 +1650,6 @@ test "IntegerBitSet" {
16511650}
16521651
16531652test "ArrayBitSet" {
1654 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1655
16561653 inline for (.{ 0, 1, 2, 31, 32, 33, 63, 64, 65, 254, 500, 3000 }) |size| {
16571654 try testStaticBitSet(ArrayBitSet(u8, size));
16581655 try testStaticBitSet(ArrayBitSet(u16, size));
lib/std/compress/zstandard.zig-2
......@@ -264,8 +264,6 @@ fn testReader(data: []const u8, comptime expected: []const u8) !void {
264264}
265265
266266test "zstandard decompression" {
267 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
268
269267 const uncompressed = @embedFile("testdata/rfc8478.txt");
270268 const compressed3 = @embedFile("testdata/rfc8478.txt.zst.3");
271269 const compressed19 = @embedFile("testdata/rfc8478.txt.zst.19");
lib/std/crypto/25519/ed25519.zig+2-13
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const crypto = std.crypto;
43const debug = std.debug;
54const fmt = std.fmt;
......@@ -276,8 +275,8 @@ pub const Ed25519 = struct {
276275 pub fn fromSecretKey(secret_key: SecretKey) (NonCanonicalError || EncodingError || IdentityElementError)!KeyPair {
277276 // It is critical for EdDSA to use the correct public key.
278277 // In order to enforce this, a SecretKey implicitly includes a copy of the public key.
279 // In Debug mode, we can still afford checking that the public key is correct for extra safety.
280 if (builtin.mode == .Debug) {
278 // With runtime safety, we can still afford checking that the public key is correct.
279 if (std.debug.runtime_safety) {
281280 const pk_p = try Curve.fromBytes(secret_key.publicKeyBytes());
282281 const recomputed_kp = try create(secret_key.seed());
283282 debug.assert(mem.eql(u8, &recomputed_kp.public_key.toBytes(), &pk_p.toBytes()));
......@@ -493,8 +492,6 @@ test "ed25519 key pair creation" {
493492}
494493
495494test "ed25519 signature" {
496 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
497
498495 var seed: [32]u8 = undefined;
499496 _ = try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
500497 const key_pair = try Ed25519.KeyPair.create(seed);
......@@ -507,8 +504,6 @@ test "ed25519 signature" {
507504}
508505
509506test "ed25519 batch verification" {
510 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
511
512507 var i: usize = 0;
513508 while (i < 100) : (i += 1) {
514509 const key_pair = try Ed25519.KeyPair.create(null);
......@@ -538,8 +533,6 @@ test "ed25519 batch verification" {
538533}
539534
540535test "ed25519 test vectors" {
541 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
542
543536 const Vec = struct {
544537 msg_hex: *const [64:0]u8,
545538 public_key_hex: *const [64:0]u8,
......@@ -642,8 +635,6 @@ test "ed25519 test vectors" {
642635}
643636
644637test "ed25519 with blind keys" {
645 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
646
647638 const BlindKeyPair = Ed25519.key_blinding.BlindKeyPair;
648639
649640 // Create a standard Ed25519 key pair
......@@ -667,8 +658,6 @@ test "ed25519 with blind keys" {
667658}
668659
669660test "ed25519 signatures with streaming" {
670 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
671
672661 const kp = try Ed25519.KeyPair.create(null);
673662
674663 var signer = try kp.signer(null);
lib/std/crypto/Certificate.zig+13-13
......@@ -614,18 +614,18 @@ const Date = struct {
614614};
615615
616616pub fn parseTimeDigits(text: *const [2]u8, min: u8, max: u8) !u8 {
617 const nn: @Vector(2, u16) = .{ text[0], text[1] };
618 const zero: @Vector(2, u16) = .{ '0', '0' };
619 const mm: @Vector(2, u16) = .{ 10, 1 };
620 const result = @reduce(.Add, (nn -% zero) *% mm);
617 const result = if (use_vectors) result: {
618 const nn: @Vector(2, u16) = .{ text[0], text[1] };
619 const zero: @Vector(2, u16) = .{ '0', '0' };
620 const mm: @Vector(2, u16) = .{ 10, 1 };
621 break :result @reduce(.Add, (nn -% zero) *% mm);
622 } else std.fmt.parseInt(u8, text, 10) catch return error.CertificateTimeInvalid;
621623 if (result < min) return error.CertificateTimeInvalid;
622624 if (result > max) return error.CertificateTimeInvalid;
623625 return @truncate(result);
624626}
625627
626628test parseTimeDigits {
627 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
628
629629 const expectEqual = std.testing.expectEqual;
630630 try expectEqual(@as(u8, 0), try parseTimeDigits("00", 0, 99));
631631 try expectEqual(@as(u8, 99), try parseTimeDigits("99", 0, 99));
......@@ -638,17 +638,17 @@ test parseTimeDigits {
638638}
639639
640640pub fn parseYear4(text: *const [4]u8) !u16 {
641 const nnnn: @Vector(4, u32) = .{ text[0], text[1], text[2], text[3] };
642 const zero: @Vector(4, u32) = .{ '0', '0', '0', '0' };
643 const mmmm: @Vector(4, u32) = .{ 1000, 100, 10, 1 };
644 const result = @reduce(.Add, (nnnn -% zero) *% mmmm);
641 const result = if (use_vectors) result: {
642 const nnnn: @Vector(4, u32) = .{ text[0], text[1], text[2], text[3] };
643 const zero: @Vector(4, u32) = .{ '0', '0', '0', '0' };
644 const mmmm: @Vector(4, u32) = .{ 1000, 100, 10, 1 };
645 break :result @reduce(.Add, (nnnn -% zero) *% mmmm);
646 } else std.fmt.parseInt(u16, text, 10) catch return error.CertificateTimeInvalid;
645647 if (result > 9999) return error.CertificateTimeInvalid;
646648 return @truncate(result);
647649}
648650
649651test parseYear4 {
650 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
651
652652 const expectEqual = std.testing.expectEqual;
653653 try expectEqual(@as(u16, 0), try parseYear4("0000"));
654654 try expectEqual(@as(u16, 9999), try parseYear4("9999"));
......@@ -1124,4 +1124,4 @@ pub const rsa = struct {
11241124 }
11251125};
11261126
1127const builtin = @import("builtin");
1127const use_vectors = @import("builtin").zig_backend != .stage2_x86_64;
lib/std/crypto/Certificate/Bundle.zig-2
......@@ -318,8 +318,6 @@ const MapContext = struct {
318318test "scan for OS-provided certificates" {
319319 if (builtin.os.tag == .wasi) return error.SkipZigTest;
320320
321 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
322
323321 var bundle: Bundle = .{};
324322 defer bundle.deinit(std.testing.allocator);
325323
lib/std/crypto/aes.zig-2
......@@ -28,8 +28,6 @@ pub const Aes128 = impl.Aes128;
2828pub const Aes256 = impl.Aes256;
2929
3030test "ctr" {
31 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
32
3331 // NIST SP 800-38A pp 55-58
3432 const ctr = @import("modes.zig").ctr;
3533
lib/std/crypto/aes_gcm.zig+2-11
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const assert = std.debug.assert;
43const crypto = std.crypto;
54const debug = std.debug;
......@@ -42,7 +41,7 @@ fn AesGcm(comptime Aes: anytype) type {
4241 mac.pad();
4342
4443 mem.writeInt(u32, j[nonce_length..][0..4], 2, .big);
45 modes.ctr(@TypeOf(aes), aes, c, m, j, std.builtin.Endian.big);
44 modes.ctr(@TypeOf(aes), aes, c, m, j, .big);
4645 mac.update(c[0..m.len][0..]);
4746 mac.pad();
4847
......@@ -104,7 +103,7 @@ fn AesGcm(comptime Aes: anytype) type {
104103 }
105104
106105 mem.writeInt(u32, j[nonce_length..][0..4], 2, .big);
107 modes.ctr(@TypeOf(aes), aes, m, c, j, std.builtin.Endian.big);
106 modes.ctr(@TypeOf(aes), aes, m, c, j, .big);
108107 }
109108 };
110109}
......@@ -113,8 +112,6 @@ const htest = @import("test.zig");
113112const testing = std.testing;
114113
115114test "Aes256Gcm - Empty message and no associated data" {
116 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
117
118115 const key: [Aes256Gcm.key_length]u8 = [_]u8{0x69} ** Aes256Gcm.key_length;
119116 const nonce: [Aes256Gcm.nonce_length]u8 = [_]u8{0x42} ** Aes256Gcm.nonce_length;
120117 const ad = "";
......@@ -127,8 +124,6 @@ test "Aes256Gcm - Empty message and no associated data" {
127124}
128125
129126test "Aes256Gcm - Associated data only" {
130 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
131
132127 const key: [Aes256Gcm.key_length]u8 = [_]u8{0x69} ** Aes256Gcm.key_length;
133128 const nonce: [Aes256Gcm.nonce_length]u8 = [_]u8{0x42} ** Aes256Gcm.nonce_length;
134129 const m = "";
......@@ -141,8 +136,6 @@ test "Aes256Gcm - Associated data only" {
141136}
142137
143138test "Aes256Gcm - Message only" {
144 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
145
146139 const key: [Aes256Gcm.key_length]u8 = [_]u8{0x69} ** Aes256Gcm.key_length;
147140 const nonce: [Aes256Gcm.nonce_length]u8 = [_]u8{0x42} ** Aes256Gcm.nonce_length;
148141 const m = "Test with message only";
......@@ -160,8 +153,6 @@ test "Aes256Gcm - Message only" {
160153}
161154
162155test "Aes256Gcm - Message and associated data" {
163 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
164
165156 const key: [Aes256Gcm.key_length]u8 = [_]u8{0x69} ** Aes256Gcm.key_length;
166157 const nonce: [Aes256Gcm.nonce_length]u8 = [_]u8{0x42} ** Aes256Gcm.nonce_length;
167158 const m = "Test with message";
lib/std/crypto/argon2.zig-4
......@@ -896,8 +896,6 @@ test "kdf" {
896896}
897897
898898test "phc format hasher" {
899 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
900
901899 const allocator = std.testing.allocator;
902900 const password = "testpass";
903901
......@@ -913,8 +911,6 @@ test "phc format hasher" {
913911}
914912
915913test "password hash and password verify" {
916 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
917
918914 const allocator = std.testing.allocator;
919915 const password = "testpass";
920916
lib/std/crypto/bcrypt.zig-7
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const base64 = std.base64;
43const crypto = std.crypto;
54const debug = std.debug;
......@@ -754,8 +753,6 @@ pub fn strVerify(
754753}
755754
756755test "bcrypt codec" {
757 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
758
759756 var salt: [salt_length]u8 = undefined;
760757 crypto.random.bytes(&salt);
761758 var salt_str: [salt_str_length]u8 = undefined;
......@@ -766,8 +763,6 @@ test "bcrypt codec" {
766763}
767764
768765test "bcrypt crypt format" {
769 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
770
771766 var hash_options = HashOptions{
772767 .params = .{ .rounds_log = 5 },
773768 .encoding = .crypt,
......@@ -808,8 +803,6 @@ test "bcrypt crypt format" {
808803}
809804
810805test "bcrypt phc format" {
811 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
812
813806 var hash_options = HashOptions{
814807 .params = .{ .rounds_log = 5 },
815808 .encoding = .phc,
lib/std/crypto/cmac.zig-9
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const crypto = std.crypto;
43const mem = std.mem;
54
......@@ -94,8 +93,6 @@ pub fn Cmac(comptime BlockCipher: type) type {
9493const testing = std.testing;
9594
9695test "CmacAes128 - Example 1: len = 0" {
97 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
98
9996 const key = [_]u8{
10097 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
10198 };
......@@ -109,8 +106,6 @@ test "CmacAes128 - Example 1: len = 0" {
109106}
110107
111108test "CmacAes128 - Example 2: len = 16" {
112 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
113
114109 const key = [_]u8{
115110 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
116111 };
......@@ -126,8 +121,6 @@ test "CmacAes128 - Example 2: len = 16" {
126121}
127122
128123test "CmacAes128 - Example 3: len = 40" {
129 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
130
131124 const key = [_]u8{
132125 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
133126 };
......@@ -145,8 +138,6 @@ test "CmacAes128 - Example 3: len = 40" {
145138}
146139
147140test "CmacAes128 - Example 4: len = 64" {
148 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
149
150141 const key = [_]u8{
151142 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
152143 };
lib/std/crypto/ecdsa.zig-5
......@@ -373,7 +373,6 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
373373
374374test "ECDSA - Basic operations over EcdsaP384Sha384" {
375375 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
376 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
377376
378377 const Scheme = EcdsaP384Sha384;
379378 const kp = try Scheme.KeyPair.create(null);
......@@ -407,7 +406,6 @@ test "ECDSA - Basic operations over Secp256k1" {
407406
408407test "ECDSA - Basic operations over EcdsaP384Sha256" {
409408 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
410 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
411409
412410 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);
413411 const kp = try Scheme.KeyPair.create(null);
......@@ -424,7 +422,6 @@ test "ECDSA - Basic operations over EcdsaP384Sha256" {
424422
425423test "ECDSA - Verifying a existing signature with EcdsaP384Sha256" {
426424 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
427 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
428425
429426 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);
430427 // zig fmt: off
......@@ -469,7 +466,6 @@ const TestVector = struct {
469466
470467test "ECDSA - Test vectors from Project Wycheproof" {
471468 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
472 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
473469
474470 const vectors = [_]TestVector{
475471 .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76", .result = .valid },
......@@ -884,7 +880,6 @@ fn tvTry(vector: TestVector) !void {
884880
885881test "ECDSA - Sec1 encoding/decoding" {
886882 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
887 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
888883
889884 const Scheme = EcdsaP384Sha384;
890885 const kp = try Scheme.KeyPair.create(null);
lib/std/crypto/ghash_polyval.zig-4
......@@ -422,8 +422,6 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
422422const htest = @import("test.zig");
423423
424424test "ghash" {
425 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
426
427425 const key = [_]u8{0x42} ** 16;
428426 const m = [_]u8{0x69} ** 256;
429427
......@@ -441,8 +439,6 @@ test "ghash" {
441439}
442440
443441test "ghash2" {
444 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
445
446442 var key: [16]u8 = undefined;
447443 var i: usize = 0;
448444 while (i < key.len) : (i += 1) {
lib/std/crypto/pcurves/p256.zig-2
......@@ -478,7 +478,5 @@ pub const AffineCoordinates = struct {
478478};
479479
480480test {
481 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
482
483481 _ = @import("tests/p256.zig");
484482}
lib/std/crypto/phc_encoding.zig-3
......@@ -1,7 +1,6 @@
11// https://github.com/P-H-C/phc-string-format
22
33const std = @import("std");
4const builtin = @import("builtin");
54const fmt = std.fmt;
65const io = std.io;
76const mem = std.mem;
......@@ -264,8 +263,6 @@ fn kvSplit(str: []const u8) !struct { key: []const u8, value: []const u8 } {
264263}
265264
266265test "phc format - encoding/decoding" {
267 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
268
269266 const Input = struct {
270267 str: []const u8,
271268 HashResult: type,
lib/std/crypto/sha2.zig+1-1
......@@ -238,7 +238,7 @@ fn Sha2x32(comptime params: Sha2Params32) type {
238238 return;
239239 },
240240 // C backend doesn't currently support passing vectors to inline asm.
241 .x86_64 => if (builtin.zig_backend != .stage2_c and comptime std.Target.x86.featureSetHasAll(builtin.cpu.features, .{ .sha, .avx2 })) {
241 .x86_64 => if (builtin.zig_backend != .stage2_c and builtin.zig_backend != .stage2_x86_64 and comptime std.Target.x86.featureSetHasAll(builtin.cpu.features, .{ .sha, .avx2 })) {
242242 var x: v4u32 = [_]u32{ d.s[5], d.s[4], d.s[1], d.s[0] };
243243 var y: v4u32 = [_]u32{ d.s[7], d.s[6], d.s[3], d.s[2] };
244244 const s_v = @as(*[16]v4u32, @ptrCast(&s));
lib/std/fmt/parse_float.zig-2
......@@ -83,8 +83,6 @@ test "fmt.parseFloat #11169" {
8383}
8484
8585test "fmt.parseFloat hex.special" {
86 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
87
8886 try testing.expect(math.isNan(try parseFloat(f32, "nAn")));
8987 try testing.expect(math.isPositiveInf(try parseFloat(f32, "iNf")));
9088 try testing.expect(math.isPositiveInf(try parseFloat(f32, "+Inf")));
lib/std/hash/xxhash.zig+2-1
......@@ -2,6 +2,7 @@ const std = @import("std");
22const builtin = @import("builtin");
33const mem = std.mem;
44const expectEqual = std.testing.expectEqual;
5const native_endian = builtin.cpu.arch.endian();
56
67const rotl = std.math.rotl;
78
......@@ -472,7 +473,7 @@ pub const XxHash3 = struct {
472473 }
473474
474475 inline fn swap(x: anytype) @TypeOf(x) {
475 return if (builtin.cpu.arch.endian() == .big) @byteSwap(x) else x;
476 return if (native_endian == .big) @byteSwap(x) else x;
476477 }
477478
478479 inline fn disableAutoVectorization(x: anytype) void {
lib/std/http/Client.zig+16-10
......@@ -9,6 +9,7 @@ const net = std.net;
99const Uri = std.Uri;
1010const Allocator = mem.Allocator;
1111const assert = std.debug.assert;
12const use_vectors = builtin.zig_backend != .stage2_x86_64;
1213
1314const Client = @This();
1415const proto = @import("protocol.zig");
......@@ -408,7 +409,7 @@ pub const Response = struct {
408409 else => return error.HttpHeadersInvalid,
409410 };
410411 if (first_line[8] != ' ') return error.HttpHeadersInvalid;
411 const status = @as(http.Status, @enumFromInt(parseInt3(first_line[9..12].*)));
412 const status: http.Status = @enumFromInt(parseInt3(first_line[9..12]));
412413 const reason = mem.trimLeft(u8, first_line[12..], " ");
413414
414415 res.version = version;
......@@ -481,20 +482,24 @@ pub const Response = struct {
481482 }
482483
483484 inline fn int64(array: *const [8]u8) u64 {
484 return @as(u64, @bitCast(array.*));
485 return @bitCast(array.*);
485486 }
486487
487 fn parseInt3(nnn: @Vector(3, u8)) u10 {
488 const zero: @Vector(3, u8) = .{ '0', '0', '0' };
489 const mmm: @Vector(3, u10) = .{ 100, 10, 1 };
490 return @reduce(.Add, @as(@Vector(3, u10), nnn -% zero) *% mmm);
488 fn parseInt3(text: *const [3]u8) u10 {
489 if (use_vectors) {
490 const nnn: @Vector(3, u8) = text.*;
491 const zero: @Vector(3, u8) = .{ '0', '0', '0' };
492 const mmm: @Vector(3, u10) = .{ 100, 10, 1 };
493 return @reduce(.Add, @as(@Vector(3, u10), nnn -% zero) *% mmm);
494 }
495 return std.fmt.parseInt(u10, text, 10) catch unreachable;
491496 }
492497
493498 test parseInt3 {
494499 const expectEqual = testing.expectEqual;
495 try expectEqual(@as(u10, 0), parseInt3("000".*));
496 try expectEqual(@as(u10, 418), parseInt3("418".*));
497 try expectEqual(@as(u10, 999), parseInt3("999".*));
500 try expectEqual(@as(u10, 0), parseInt3("000"));
501 try expectEqual(@as(u10, 418), parseInt3("418"));
502 try expectEqual(@as(u10, 999), parseInt3("999"));
498503 }
499504
500505 version: http.Version,
......@@ -1588,7 +1593,8 @@ test {
15881593
15891594 if (builtin.os.tag == .wasi) return error.SkipZigTest;
15901595
1591 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1596 if (builtin.zig_backend == .stage2_x86_64 and
1597 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx)) return error.SkipZigTest;
15921598
15931599 std.testing.refAllDecls(@This());
15941600}
lib/std/http/Server.zig-2
......@@ -736,8 +736,6 @@ test "HTTP server handles a chunked transfer coding request" {
736736 return error.SkipZigTest;
737737 }
738738
739 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
740
741739 const native_endian = comptime builtin.cpu.arch.endian();
742740 if (builtin.zig_backend == .stage2_llvm and native_endian == .big) {
743741 // https://github.com/ziglang/zig/issues/13782
lib/std/http/protocol.zig+23-12
......@@ -1,8 +1,10 @@
11const std = @import("../std.zig");
2const builtin = @import("builtin");
23const testing = std.testing;
34const mem = std.mem;
45
56const assert = std.debug.assert;
7const use_vectors = builtin.zig_backend != .stage2_x86_64;
68
79pub const State = enum {
810 /// Begin header parsing states.
......@@ -83,7 +85,7 @@ pub const HeadersParser = struct {
8385 /// first byte of content is located at `bytes[result]`.
8486 pub fn findHeadersEnd(r: *HeadersParser, bytes: []const u8) u32 {
8587 const vector_len: comptime_int = @max(std.simd.suggestVectorSize(u8) orelse 1, 8);
86 const len = @as(u32, @intCast(bytes.len));
88 const len: u32 = @intCast(bytes.len);
8789 var index: u32 = 0;
8890
8991 while (true) {
......@@ -175,18 +177,27 @@ pub const HeadersParser = struct {
175177 continue;
176178 },
177179 else => {
178 const Vector = @Vector(vector_len, u8);
179 // const BoolVector = @Vector(vector_len, bool);
180 const BitVector = @Vector(vector_len, u1);
181 const SizeVector = @Vector(vector_len, u8);
182
183180 const chunk = bytes[index..][0..vector_len];
184 const v: Vector = chunk.*;
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 const matches_or: SizeVector = matches_r | matches_n;
188
189 const matches = @reduce(.Add, matches_or);
181 const matches = if (use_vectors) matches: {
182 const Vector = @Vector(vector_len, u8);
183 // const BoolVector = @Vector(vector_len, bool);
184 const BitVector = @Vector(vector_len, u1);
185 const SizeVector = @Vector(vector_len, u8);
186
187 const v: Vector = chunk.*;
188 const matches_r: BitVector = @bitCast(v == @as(Vector, @splat('\r')));
189 const matches_n: BitVector = @bitCast(v == @as(Vector, @splat('\n')));
190 const matches_or: SizeVector = matches_r | matches_n;
191
192 break :matches @reduce(.Add, matches_or);
193 } else matches: {
194 var matches: u8 = 0;
195 for (chunk) |byte| switch (byte) {
196 '\r', '\n' => matches += 1,
197 else => {},
198 };
199 break :matches matches;
200 };
190201 switch (matches) {
191202 0 => {},
192203 1 => switch (chunk[vector_len - 1]) {
lib/std/math.zig+2-21
......@@ -492,8 +492,6 @@ pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {
492492}
493493
494494test "shl" {
495 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
496
497495 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
498496 // https://github.com/ziglang/zig/issues/12012
499497 return error.SkipZigTest;
......@@ -539,8 +537,6 @@ pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {
539537}
540538
541539test "shr" {
542 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
543
544540 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
545541 // https://github.com/ziglang/zig/issues/12012
546542 return error.SkipZigTest;
......@@ -587,8 +583,6 @@ pub fn rotr(comptime T: type, x: T, r: anytype) T {
587583}
588584
589585test "rotr" {
590 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
591
592586 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
593587 // https://github.com/ziglang/zig/issues/12012
594588 return error.SkipZigTest;
......@@ -634,8 +628,6 @@ pub fn rotl(comptime T: type, x: T, r: anytype) T {
634628}
635629
636630test "rotl" {
637 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
638
639631 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
640632 // https://github.com/ziglang/zig/issues/12012
641633 return error.SkipZigTest;
......@@ -764,8 +756,6 @@ pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
764756}
765757
766758test "divTrunc" {
767 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
768
769759 try testDivTrunc();
770760 try comptime testDivTrunc();
771761}
......@@ -790,8 +780,6 @@ pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
790780}
791781
792782test "divFloor" {
793 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
794
795783 try testDivFloor();
796784 try comptime testDivFloor();
797785}
......@@ -829,8 +817,6 @@ pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T {
829817}
830818
831819test "divCeil" {
832 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
833
834820 try testDivCeil();
835821 try comptime testDivCeil();
836822}
......@@ -875,8 +861,6 @@ pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
875861}
876862
877863test "divExact" {
878 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
879
880864 try testDivExact();
881865 try comptime testDivExact();
882866}
......@@ -903,8 +887,6 @@ pub fn mod(comptime T: type, numerator: T, denominator: T) !T {
903887}
904888
905889test "mod" {
906 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
907
908890 try testMod();
909891 try comptime testMod();
910892}
......@@ -931,8 +913,6 @@ pub fn rem(comptime T: type, numerator: T, denominator: T) !T {
931913}
932914
933915test "rem" {
934 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
935
936916 try testRem();
937917 try comptime testRem();
938918}
......@@ -1285,7 +1265,8 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) {
12851265}
12861266
12871267test "lerp" {
1288 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1268 if (builtin.zig_backend == .stage2_x86_64 and
1269 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .fma)) return error.SkipZigTest;
12891270
12901271 try testing.expectEqual(@as(f64, 75), lerp(50, 100, 0.5));
12911272 try testing.expectEqual(@as(f32, 43.75), lerp(50, 25, 0.25));
lib/std/math/big/int.zig+3-3
......@@ -1318,7 +1318,7 @@ pub const Mutable = struct {
13181318 ///
13191319 /// `limbs_buffer` is used for temporary storage.
13201320 /// The amount required is given by `calcPowLimbsBufferLen`.
1321 pub fn pow(r: *Mutable, a: Const, b: u32, limbs_buffer: []Limb) !void {
1321 pub fn pow(r: *Mutable, a: Const, b: u32, limbs_buffer: []Limb) void {
13221322 assert(r.limbs.ptr != a.limbs.ptr); // illegal aliasing
13231323
13241324 // Handle all the trivial cases first
......@@ -3213,7 +3213,7 @@ pub const Managed = struct {
32133213 var m = try Managed.initCapacity(rma.allocator, needed_limbs);
32143214 errdefer m.deinit();
32153215 var m_mut = m.toMutable();
3216 try m_mut.pow(a.toConst(), b, limbs_buffer);
3216 m_mut.pow(a.toConst(), b, limbs_buffer);
32173217 m.setMetadata(m_mut.positive, m_mut.len);
32183218
32193219 rma.deinit();
......@@ -3221,7 +3221,7 @@ pub const Managed = struct {
32213221 } else {
32223222 try rma.ensureCapacity(needed_limbs);
32233223 var rma_mut = rma.toMutable();
3224 try rma_mut.pow(a.toConst(), b, limbs_buffer);
3224 rma_mut.pow(a.toConst(), b, limbs_buffer);
32253225 rma.setMetadata(rma_mut.positive, rma_mut.len);
32263226 }
32273227 }
lib/std/math/big/int_test.zig-6
......@@ -2568,8 +2568,6 @@ test "big.int const to managed" {
25682568}
25692569
25702570test "big.int pow" {
2571 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2572
25732571 {
25742572 var a = try Managed.initSet(testing.allocator, -3);
25752573 defer a.deinit();
......@@ -2763,8 +2761,6 @@ fn popCountTest(val: *const Managed, bit_count: usize, expected: usize) !void {
27632761}
27642762
27652763test "big int conversion read/write twos complement" {
2766 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2767
27682764 var a = try Managed.initSet(testing.allocator, (1 << 493) - 1);
27692765 defer a.deinit();
27702766 var b = try Managed.initSet(testing.allocator, (1 << 493) - 1);
......@@ -2863,8 +2859,6 @@ test "big int write twos complement +/- zero" {
28632859}
28642860
28652861test "big int conversion write twos complement with padding" {
2866 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2867
28682862 var a = try Managed.initSet(testing.allocator, 0x01_ffffffff_ffffffff_ffffffff);
28692863 defer a.deinit();
28702864
lib/std/mem.zig-4
......@@ -315,8 +315,6 @@ pub fn zeroes(comptime T: type) T {
315315}
316316
317317test "zeroes" {
318 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
319
320318 const C_struct = extern struct {
321319 x: u32,
322320 y: u32 align(128),
......@@ -4342,8 +4340,6 @@ pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice
43424340}
43434341
43444342test "read/write(Var)PackedInt" {
4345 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
4346
43474343 switch (builtin.cpu.arch) {
43484344 // This test generates too much code to execute on WASI.
43494345 // LLVM backend fails with "too many locals: locals exceed maximum"
lib/std/net/test.zig+1-1
......@@ -60,7 +60,7 @@ test "parse and render IPv6 addresses" {
6060}
6161
6262test "invalid but parseable IPv6 scope ids" {
63 if (builtin.os.tag != .linux or comptime !builtin.os.tag.isDarwin()) {
63 if (builtin.os.tag != .linux and comptime !builtin.os.tag.isDarwin()) {
6464 // Currently, resolveIp6 with alphanumerical scope IDs only works on Linux.
6565 // TODO Make this test pass on other operating systems.
6666 return error.SkipZigTest;
lib/std/once.zig-2
......@@ -46,8 +46,6 @@ fn incr() void {
4646}
4747
4848test "Once executes its function just once" {
49 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
50
5149 if (builtin.single_threaded) {
5250 global_once.call();
5351 global_once.call();
lib/std/os/test.zig-4
......@@ -375,8 +375,6 @@ fn testThreadIdFn(thread_id: *Thread.Id) void {
375375test "std.Thread.getCurrentId" {
376376 if (builtin.single_threaded) return error.SkipZigTest;
377377
378 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
379
380378 var thread_current_id: Thread.Id = undefined;
381379 const thread = try Thread.spawn(.{}, testThreadIdFn, .{&thread_current_id});
382380 thread.join();
......@@ -420,8 +418,6 @@ test "cpu count" {
420418test "thread local storage" {
421419 if (builtin.single_threaded) return error.SkipZigTest;
422420
423 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
424
425421 const thread1 = try Thread.spawn(.{}, testTls, .{});
426422 const thread2 = try Thread.spawn(.{}, testTls, .{});
427423 try testTls();
lib/std/rand/test.zig-7
......@@ -1,5 +1,4 @@
11const std = @import("../std.zig");
2const builtin = @import("builtin");
32const math = std.math;
43const DefaultPrng = std.rand.DefaultPrng;
54const Random = std.rand.Random;
......@@ -200,8 +199,6 @@ fn testRandomIntLessThan() !void {
200199}
201200
202201test "Random intAtMost" {
203 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
204
205202 @setEvalBranchQuota(10000);
206203 try testRandomIntAtMost();
207204 try comptime testRandomIntAtMost();
......@@ -242,8 +239,6 @@ fn testRandomIntAtMost() !void {
242239}
243240
244241test "Random Biased" {
245 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
246
247242 var prng = DefaultPrng.init(0);
248243 const random = prng.random();
249244 // Not thoroughly checking the logic here.
......@@ -452,8 +447,6 @@ test "CSPRNG" {
452447}
453448
454449test "Random weightedIndex" {
455 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
456
457450 // Make sure weightedIndex works for various integers and floats
458451 inline for (.{ u64, i4, f32, f64 }) |T| {
459452 var prng = DefaultPrng.init(0);
lib/std/zig/tokenizer.zig-9
......@@ -1,5 +1,4 @@
11const std = @import("../std.zig");
2const builtin = @import("builtin");
32
43pub const Token = struct {
54 tag: Tag,
......@@ -1450,8 +1449,6 @@ test "chars" {
14501449}
14511450
14521451test "invalid token characters" {
1453 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1454
14551452 try testTokenize("#", &.{.invalid});
14561453 try testTokenize("`", &.{.invalid});
14571454 try testTokenize("'c", &.{.invalid});
......@@ -1571,8 +1568,6 @@ test "pipe and then invalid" {
15711568}
15721569
15731570test "line comment and doc comment" {
1574 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1575
15761571 try testTokenize("//", &.{});
15771572 try testTokenize("// a / b", &.{});
15781573 try testTokenize("// /", &.{});
......@@ -1647,8 +1642,6 @@ test "range literals" {
16471642}
16481643
16491644test "number literals decimal" {
1650 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1651
16521645 try testTokenize("0", &.{.number_literal});
16531646 try testTokenize("1", &.{.number_literal});
16541647 try testTokenize("2", &.{.number_literal});
......@@ -1897,8 +1890,6 @@ test "invalid token with unfinished escape right before eof" {
18971890}
18981891
18991892test "saturating operators" {
1900 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1901
19021893 try testTokenize("<<", &.{.angle_bracket_angle_bracket_left});
19031894 try testTokenize("<<|", &.{.angle_bracket_angle_bracket_left_pipe});
19041895 try testTokenize("<<|=", &.{.angle_bracket_angle_bracket_left_pipe_equal});
src/Compilation.zig+3-1
......@@ -1121,7 +1121,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
11211121 const include_compiler_rt = options.want_compiler_rt orelse needs_c_symbols;
11221122
11231123 const must_single_thread = target_util.isSingleThreaded(options.target);
1124 const single_threaded = options.single_threaded orelse must_single_thread;
1124 const single_threaded = options.single_threaded orelse must_single_thread or
1125 // x86_64 codegen doesn't support TLV for most object formats
1126 (!use_llvm and options.target.cpu.arch == .x86_64 and options.target.ofmt != .macho);
11251127 if (must_single_thread and !single_threaded) {
11261128 return error.TargetRequiresSingleThreaded;
11271129 }
src/arch/x86_64/CodeGen.zig+1317-641
......@@ -388,7 +388,7 @@ pub const MCValue = union(enum) {
388388 };
389389 }
390390
391 fn mem(mcv: MCValue, size: Memory.Size) Memory {
391 fn mem(mcv: MCValue, function: *Self, size: Memory.Size) !Memory {
392392 return switch (mcv) {
393393 .none,
394394 .unreach,
......@@ -409,7 +409,6 @@ pub const MCValue = union(enum) {
409409 .lea_frame,
410410 .reserved_frame,
411411 .air_ref,
412 .load_symbol,
413412 .lea_symbol,
414413 => unreachable,
415414 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{
......@@ -433,6 +432,19 @@ pub const MCValue = union(enum) {
433432 .disp = frame_addr.off,
434433 } },
435434 },
435 .load_symbol => |sym_off| {
436 assert(sym_off.off == 0);
437 return .{
438 .base = .{ .reloc = .{
439 .atom_index = try function.owner.getSymbolIndex(function),
440 .sym_index = sym_off.sym,
441 } },
442 .mod = .{ .rm = .{
443 .size = size,
444 .disp = sym_off.off,
445 } },
446 };
447 },
436448 };
437449 }
438450
......@@ -722,12 +734,14 @@ const InstTracking = struct {
722734
723735const FrameAlloc = struct {
724736 abi_size: u31,
737 spill_pad: u3,
725738 abi_align: Alignment,
726739 ref_count: u16,
727740
728 fn init(alloc_abi: struct { size: u64, alignment: Alignment }) FrameAlloc {
741 fn init(alloc_abi: struct { size: u64, pad: u3 = 0, alignment: Alignment }) FrameAlloc {
729742 return .{
730743 .abi_size = @intCast(alloc_abi.size),
744 .spill_pad = alloc_abi.pad,
731745 .abi_align = alloc_abi.alignment,
732746 .ref_count = 0,
733747 };
......@@ -738,6 +752,20 @@ const FrameAlloc = struct {
738752 .alignment = ty.abiAlignment(mod),
739753 });
740754 }
755 fn initSpill(ty: Type, mod: *Module) FrameAlloc {
756 const abi_size = ty.abiSize(mod);
757 const spill_size = if (abi_size < 8)
758 math.ceilPowerOfTwoAssert(u64, abi_size)
759 else
760 std.mem.alignForward(u64, abi_size, 8);
761 return init(.{
762 .size = spill_size,
763 .pad = @intCast(spill_size - abi_size),
764 .alignment = ty.abiAlignment(mod).maxStrict(
765 Alignment.fromNonzeroByteUnits(@min(spill_size, 8)),
766 ),
767 });
768 }
741769};
742770
743771const StackAllocation = struct {
......@@ -1668,8 +1696,7 @@ fn gen(self: *Self) InnerError!void {
16681696 // The address where to store the return value for the caller is in a
16691697 // register which the callee is free to clobber. Therefore, we purposely
16701698 // spill it to stack immediately.
1671 const frame_index =
1672 try self.allocFrameIndex(FrameAlloc.initType(Type.usize, mod));
1699 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(Type.usize, mod));
16731700 try self.genSetMem(
16741701 .{ .frame = frame_index },
16751702 0,
......@@ -2434,7 +2461,7 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b
24342461 }
24352462 }
24362463
2437 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ty, mod));
2464 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ty, mod));
24382465 return .{ .load_frame = .{ .index = frame_index } };
24392466}
24402467
......@@ -2445,7 +2472,10 @@ fn regClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet {
24452472 80 => abi.RegisterClass.x87,
24462473 else => abi.RegisterClass.sse,
24472474 },
2448 .Vector => abi.RegisterClass.sse,
2475 .Vector => switch (ty.childType(mod).toIntern()) {
2476 .bool_type => abi.RegisterClass.gp,
2477 else => abi.RegisterClass.sse,
2478 },
24492479 else => abi.RegisterClass.gp,
24502480 };
24512481}
......@@ -2699,7 +2729,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
26992729 .{ .v_ss, .cvtsd2 },
27002730 dst_reg,
27012731 dst_reg,
2702 src_mcv.mem(.qword),
2732 try src_mcv.mem(self, .qword),
27032733 ) else try self.asmRegisterRegisterRegister(
27042734 .{ .v_ss, .cvtsd2 },
27052735 dst_reg,
......@@ -2711,7 +2741,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
27112741 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
27122742 .{ ._ss, .cvtsd2 },
27132743 dst_reg,
2714 src_mcv.mem(.qword),
2744 try src_mcv.mem(self, .qword),
27152745 ) else try self.asmRegisterRegister(
27162746 .{ ._ss, .cvtsd2 },
27172747 dst_reg,
......@@ -2798,7 +2828,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
27982828 .{ .v_sd, .cvtss2 },
27992829 dst_reg,
28002830 dst_reg,
2801 src_mcv.mem(.dword),
2831 try src_mcv.mem(self, .dword),
28022832 ) else try self.asmRegisterRegisterRegister(
28032833 .{ .v_sd, .cvtss2 },
28042834 dst_reg,
......@@ -2810,7 +2840,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
28102840 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
28112841 .{ ._sd, .cvtss2 },
28122842 dst_reg,
2813 src_mcv.mem(.dword),
2843 try src_mcv.mem(self, .dword),
28142844 ) else try self.asmRegisterRegister(
28152845 .{ ._sd, .cvtss2 },
28162846 dst_reg,
......@@ -2851,8 +2881,8 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
28512881 };
28522882
28532883 const dst_mcv = if (dst_int_info.bits <= src_storage_bits and
2854 std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
2855 std.math.divCeil(u32, src_storage_bits, 64) catch unreachable and
2884 math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
2885 math.divCeil(u32, src_storage_bits, 64) catch unreachable and
28562886 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
28572887 const dst_mcv = try self.allocRegOrMem(inst, true);
28582888 try self.genCopy(min_ty, dst_mcv, src_mcv);
......@@ -2869,22 +2899,28 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
28692899 break :result .{ .register = registerAlias(dst_mcv.getReg().?, abi_size) };
28702900 }
28712901
2872 const src_limbs_len = std.math.divCeil(u16, src_int_info.bits, 64) catch unreachable;
2873 const dst_limbs_len = std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable;
2902 const src_limbs_len = math.divCeil(u16, src_int_info.bits, 64) catch unreachable;
2903 const dst_limbs_len = math.divCeil(u16, dst_int_info.bits, 64) catch unreachable;
28742904
2875 const high_mcv = dst_mcv.address().offset((src_limbs_len - 1) * 8).deref();
2876 const high_reg = try self.copyToTmpRegister(switch (src_int_info.signedness) {
2877 .signed => Type.isize,
2878 .unsigned => Type.usize,
2879 }, high_mcv);
2905 const high_mcv: MCValue = if (dst_mcv.isMemory())
2906 dst_mcv.address().offset((src_limbs_len - 1) * 8).deref()
2907 else
2908 .{ .register = dst_mcv.register_pair[1] };
2909 const high_reg = if (high_mcv.isRegister())
2910 high_mcv.getReg().?
2911 else
2912 try self.copyToTmpRegister(switch (src_int_info.signedness) {
2913 .signed => Type.isize,
2914 .unsigned => Type.usize,
2915 }, high_mcv);
28802916 const high_lock = self.register_manager.lockRegAssumeUnused(high_reg);
28812917 defer self.register_manager.unlockReg(high_lock);
28822918
28832919 const high_bits = src_int_info.bits % 64;
28842920 if (high_bits > 0) {
2885 const high_ty = try mod.intType(extend, high_bits);
2886 try self.truncateRegister(high_ty, high_reg);
2887 try self.genCopy(Type.usize, high_mcv, .{ .register = high_reg });
2921 try self.truncateRegister(src_ty, high_reg);
2922 const high_ty = if (dst_int_info.bits >= 64) Type.usize else dst_ty;
2923 try self.genCopy(high_ty, high_mcv, .{ .register = high_reg });
28882924 }
28892925
28902926 if (dst_limbs_len > src_limbs_len) try self.genInlineMemset(
......@@ -2995,14 +3031,14 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
29953031 .{ .vp_, .@"and" },
29963032 dst_reg,
29973033 dst_reg,
2998 splat_addr_mcv.deref().mem(Memory.Size.fromSize(splat_abi_size)),
3034 try splat_addr_mcv.deref().mem(self, Memory.Size.fromSize(splat_abi_size)),
29993035 );
30003036 try self.asmRegisterRegisterRegister(mir_tag, dst_reg, dst_reg, dst_reg);
30013037 } else {
30023038 try self.asmRegisterMemory(
30033039 .{ .p_, .@"and" },
30043040 dst_reg,
3005 splat_addr_mcv.deref().mem(Memory.Size.fromSize(splat_abi_size)),
3041 try splat_addr_mcv.deref().mem(self, Memory.Size.fromSize(splat_abi_size)),
30063042 );
30073043 try self.asmRegisterRegister(mir_tag, dst_reg, dst_reg);
30083044 }
......@@ -3048,7 +3084,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
30483084 const len = try self.resolveInst(bin_op.rhs);
30493085 const len_ty = self.typeOf(bin_op.rhs);
30503086
3051 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, mod));
3087 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod));
30523088 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);
30533089 try self.genSetMem(
30543090 .{ .frame = frame_index },
......@@ -3068,8 +3104,36 @@ fn airUnOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
30683104}
30693105
30703106fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
3107 const mod = self.bin_file.options.module.?;
30713108 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
30723109 const dst_mcv = try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs);
3110
3111 const dst_ty = self.typeOfIndex(inst);
3112 if (dst_ty.isAbiInt(mod)) {
3113 const abi_size: u32 = @intCast(dst_ty.abiSize(mod));
3114 const bit_size: u32 = @intCast(dst_ty.bitSize(mod));
3115 if (abi_size * 8 > bit_size) {
3116 const dst_lock = switch (dst_mcv) {
3117 .register => |dst_reg| self.register_manager.lockRegAssumeUnused(dst_reg),
3118 else => null,
3119 };
3120 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
3121
3122 if (dst_mcv.isRegister()) {
3123 try self.truncateRegister(dst_ty, dst_mcv.getReg().?);
3124 } else {
3125 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
3126 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
3127 defer self.register_manager.unlockReg(tmp_lock);
3128
3129 const hi_ty = try mod.intType(.unsigned, @intCast((dst_ty.bitSize(mod) - 1) % 64 + 1));
3130 const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref();
3131 try self.genSetReg(tmp_reg, hi_ty, hi_mcv);
3132 try self.truncateRegister(dst_ty, tmp_reg);
3133 try self.genCopy(hi_ty, hi_mcv, .{ .register = tmp_reg });
3134 }
3135 }
3136 }
30733137 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
30743138}
30753139
......@@ -3176,7 +3240,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
31763240 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
31773241 .{ ._, .mov },
31783242 tmp_reg,
3179 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
3243 try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword),
31803244 ) else try self.asmRegisterRegister(
31813245 .{ ._, .mov },
31823246 tmp_reg,
......@@ -3200,7 +3264,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
32003264 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
32013265 .{ ._, .xor },
32023266 tmp_reg,
3203 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
3267 try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword),
32043268 ) else try self.asmRegisterRegister(
32053269 .{ ._, .xor },
32063270 tmp_reg,
......@@ -3300,12 +3364,12 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
33003364 try self.asmRegisterMemory(
33013365 .{ ._, .add },
33023366 tmp_regs[0],
3303 mat_rhs_mcv.mem(.qword),
3367 try mat_rhs_mcv.mem(self, .qword),
33043368 );
33053369 try self.asmRegisterMemory(
33063370 .{ ._, .adc },
33073371 tmp_regs[1],
3308 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
3372 try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword),
33093373 );
33103374 } else for (
33113375 [_]Mir.Inst.Tag{ .add, .adc },
......@@ -3534,7 +3598,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
35343598 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
35353599 .{ ._, .mov },
35363600 tmp_reg,
3537 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
3601 try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword),
35383602 ) else try self.asmRegisterRegister(
35393603 .{ ._, .mov },
35403604 tmp_reg,
......@@ -3558,7 +3622,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
35583622 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
35593623 .{ ._, .xor },
35603624 tmp_reg,
3561 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
3625 try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword),
35623626 ) else try self.asmRegisterRegister(
35633627 .{ ._, .xor },
35643628 tmp_reg,
......@@ -3567,7 +3631,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
35673631
35683632 try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, Immediate.u(63));
35693633 try self.asmRegister(.{ ._, .not }, tmp_reg);
3570 try self.asmMemoryImmediate(.{ ._, .cmp }, overflow.mem(.dword), Immediate.s(0));
3634 try self.asmMemoryImmediate(.{ ._, .cmp }, try overflow.mem(self, .dword), Immediate.s(0));
35713635 try self.freeValue(overflow);
35723636 try self.asmCmovccRegisterRegister(.ne, dst_mcv.register_pair[0], tmp_reg);
35733637 try self.asmRegisterImmediate(.{ ._c, .bt }, tmp_reg, Immediate.u(63));
......@@ -3665,7 +3729,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
36653729 }
36663730
36673731 const frame_index =
3668 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3732 try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
36693733 try self.genSetMem(
36703734 .{ .frame = frame_index },
36713735 @intCast(tuple_ty.structFieldOffset(1, mod)),
......@@ -3682,7 +3746,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
36823746 }
36833747
36843748 const frame_index =
3685 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3749 try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
36863750 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
36873751 break :result .{ .load_frame = .{ .index = frame_index } };
36883752 },
......@@ -3738,7 +3802,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
37383802 }
37393803
37403804 const frame_index =
3741 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3805 try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
37423806 try self.genSetMem(
37433807 .{ .frame = frame_index },
37443808 @intCast(tuple_ty.structFieldOffset(1, mod)),
......@@ -3755,7 +3819,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
37553819 }
37563820
37573821 const frame_index =
3758 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3822 try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
37593823 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
37603824 break :result .{ .load_frame = .{ .index = frame_index } };
37613825 },
......@@ -3874,7 +3938,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
38743938 );
38753939 try self.asmMemoryImmediate(
38763940 .{ ._, .cmp },
3877 overflow.mem(self.memSize(Type.c_int)),
3941 try overflow.mem(self, self.memSize(Type.c_int)),
38783942 Immediate.s(0),
38793943 );
38803944 try self.genSetMem(
......@@ -3926,14 +3990,19 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
39263990 };
39273991 defer if (mat_rhs_lock) |lock| self.register_manager.unlockReg(lock);
39283992
3929 if (mat_lhs_mcv.isMemory())
3930 try self.asmRegisterMemory(.{ ._, .mov }, .rax, mat_lhs_mcv.mem(.qword))
3931 else
3932 try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]);
3993 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
3994 .{ ._, .mov },
3995 .rax,
3996 try mat_lhs_mcv.mem(self, .qword),
3997 ) else try self.asmRegisterRegister(
3998 .{ ._, .mov },
3999 .rax,
4000 mat_lhs_mcv.register_pair[0],
4001 );
39334002 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
39344003 .{ ._, .mov },
39354004 tmp_regs[0],
3936 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
4005 try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword),
39374006 ) else try self.asmRegisterRegister(
39384007 .{ ._, .mov },
39394008 tmp_regs[0],
......@@ -3944,7 +4013,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
39444013 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_regs[0], .rax);
39454014 try self.asmSetccRegister(.o, tmp_regs[2].to8());
39464015 if (mat_rhs_mcv.isMemory())
3947 try self.asmMemory(.{ ._, .mul }, mat_rhs_mcv.mem(.qword))
4016 try self.asmMemory(.{ ._, .mul }, try mat_rhs_mcv.mem(self, .qword))
39484017 else
39494018 try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]);
39504019 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]);
......@@ -3953,7 +4022,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
39534022 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
39544023 .{ ._, .mov },
39554024 tmp_regs[0],
3956 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
4025 try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword),
39574026 ) else try self.asmRegisterRegister(
39584027 .{ ._, .mov },
39594028 tmp_regs[0],
......@@ -3967,14 +4036,15 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
39674036 tmp_regs[3].to8(),
39684037 );
39694038 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());
3970 if (mat_rhs_mcv.isMemory())
3971 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_regs[0], mat_rhs_mcv.mem(.qword))
3972 else
3973 try self.asmRegisterRegister(
3974 .{ .i_, .mul },
3975 tmp_regs[0],
3976 mat_rhs_mcv.register_pair[0],
3977 );
4039 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
4040 .{ .i_, .mul },
4041 tmp_regs[0],
4042 try mat_rhs_mcv.mem(self, .qword),
4043 ) else try self.asmRegisterRegister(
4044 .{ .i_, .mul },
4045 tmp_regs[0],
4046 mat_rhs_mcv.register_pair[0],
4047 );
39784048 try self.asmSetccRegister(.o, tmp_regs[2].to8());
39794049 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());
39804050 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]);
......@@ -4020,8 +4090,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
40204090 self.eflags_inst = inst;
40214091 break :result .{ .register_overflow = .{ .reg = reg, .eflags = cc } };
40224092 } else {
4023 const frame_index =
4024 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
4093 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
40254094 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
40264095 break :result .{ .load_frame = .{ .index = frame_index } };
40274096 },
......@@ -4032,8 +4101,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
40324101 src_ty.fmt(mod), dst_ty.fmt(mod),
40334102 });
40344103
4035 const frame_index =
4036 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
4104 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
40374105 if (dst_info.bits >= lhs_active_bits + rhs_active_bits) {
40384106 try self.genSetMem(
40394107 .{ .frame = frame_index },
......@@ -4106,7 +4174,7 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue
41064174 .register => |reg| try self.asmRegister(tag, registerAlias(reg, abi_size)),
41074175 .memory, .indirect, .load_frame => try self.asmMemory(
41084176 tag,
4109 mat_rhs.mem(Memory.Size.fromSize(abi_size)),
4177 try mat_rhs.mem(self, Memory.Size.fromSize(abi_size)),
41104178 ),
41114179 else => unreachable,
41124180 }
......@@ -4160,8 +4228,8 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
41604228 );
41614229 try self.asmCmovccRegisterRegister(
41624230 .z,
4163 registerAlias(divisor, abi_size),
4164 registerAlias(.rdx, abi_size),
4231 registerAlias(divisor, @max(abi_size, 2)),
4232 registerAlias(.rdx, @max(abi_size, 2)),
41654233 );
41664234 try self.genBinOpMir(.{ ._, .add }, ty, .{ .register = divisor }, .{ .register = .rax });
41674235 return MCValue{ .register = divisor };
......@@ -4171,47 +4239,268 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
41714239 const mod = self.bin_file.options.module.?;
41724240 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
41734241
4174 try self.spillRegisters(&.{.rcx});
4175
4176 const tag = self.air.instructions.items(.tag)[inst];
4177 try self.register_manager.getReg(.rcx, null);
4178 const lhs = try self.resolveInst(bin_op.lhs);
4179 const rhs = try self.resolveInst(bin_op.rhs);
4242 const air_tags = self.air.instructions.items(.tag);
4243 const tag = air_tags[inst];
41804244 const lhs_ty = self.typeOf(bin_op.lhs);
41814245 const rhs_ty = self.typeOf(bin_op.rhs);
4246 const result: MCValue = result: {
4247 switch (lhs_ty.zigTypeTag(mod)) {
4248 .Int => {
4249 try self.spillRegisters(&.{.rcx});
4250 try self.register_manager.getReg(.rcx, null);
4251 const lhs_mcv = try self.resolveInst(bin_op.lhs);
4252 const rhs_mcv = try self.resolveInst(bin_op.rhs);
41824253
4183 const dst_mcv = try self.genShiftBinOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
4184 switch (tag) {
4185 .shr, .shr_exact, .shl_exact => {},
4186 .shl => switch (dst_mcv) {
4187 .register => |dst_reg| try self.truncateRegister(lhs_ty, dst_reg),
4188 .register_pair => |dst_regs| try self.truncateRegister(lhs_ty, dst_regs[1]),
4189 .load_frame => |frame_addr| {
4190 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4191 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
4192 defer self.register_manager.unlockReg(tmp_lock);
4254 const dst_mcv = try self.genShiftBinOp(tag, inst, lhs_mcv, rhs_mcv, lhs_ty, rhs_ty);
4255 switch (tag) {
4256 .shr, .shr_exact, .shl_exact => {},
4257 .shl => switch (dst_mcv) {
4258 .register => |dst_reg| try self.truncateRegister(lhs_ty, dst_reg),
4259 .register_pair => |dst_regs| try self.truncateRegister(lhs_ty, dst_regs[1]),
4260 .load_frame => |frame_addr| {
4261 const tmp_reg =
4262 try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4263 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
4264 defer self.register_manager.unlockReg(tmp_lock);
41934265
4194 const lhs_bits: u31 = @intCast(lhs_ty.bitSize(mod));
4195 const tmp_ty = if (lhs_bits > 64) Type.usize else lhs_ty;
4196 const off = frame_addr.off + lhs_bits / 64 * 8;
4197 try self.genSetReg(
4198 tmp_reg,
4199 tmp_ty,
4200 .{ .load_frame = .{ .index = frame_addr.index, .off = off } },
4201 );
4202 try self.truncateRegister(lhs_ty, tmp_reg);
4203 try self.genSetMem(
4204 .{ .frame = frame_addr.index },
4205 off,
4206 tmp_ty,
4207 .{ .register = tmp_reg },
4208 );
4266 const lhs_bits: u31 = @intCast(lhs_ty.bitSize(mod));
4267 const tmp_ty = if (lhs_bits > 64) Type.usize else lhs_ty;
4268 const off = frame_addr.off + (lhs_bits - 1) / 64 * 8;
4269 try self.genSetReg(
4270 tmp_reg,
4271 tmp_ty,
4272 .{ .load_frame = .{ .index = frame_addr.index, .off = off } },
4273 );
4274 try self.truncateRegister(lhs_ty, tmp_reg);
4275 try self.genSetMem(
4276 .{ .frame = frame_addr.index },
4277 off,
4278 tmp_ty,
4279 .{ .register = tmp_reg },
4280 );
4281 },
4282 else => {},
4283 },
4284 else => unreachable,
4285 }
4286 break :result dst_mcv;
4287 },
4288 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
4289 .Int => if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.childType(mod).intInfo(mod).bits) {
4290 else => null,
4291 16 => switch (lhs_ty.vectorLen(mod)) {
4292 else => null,
4293 1...8 => switch (tag) {
4294 else => unreachable,
4295 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4296 .signed => if (self.hasFeature(.avx))
4297 .{ .vp_w, .sra }
4298 else
4299 .{ .p_w, .sra },
4300 .unsigned => if (self.hasFeature(.avx))
4301 .{ .vp_w, .srl }
4302 else
4303 .{ .p_w, .srl },
4304 },
4305 .shl, .shl_exact => if (self.hasFeature(.avx))
4306 .{ .vp_w, .sll }
4307 else
4308 .{ .p_w, .sll },
4309 },
4310 9...16 => switch (tag) {
4311 else => unreachable,
4312 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4313 .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .sra } else null,
4314 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_w, .srl } else null,
4315 },
4316 .shl, .shl_exact => if (self.hasFeature(.avx2)) .{ .vp_w, .sll } else null,
4317 },
4318 },
4319 32 => switch (lhs_ty.vectorLen(mod)) {
4320 else => null,
4321 1...4 => switch (tag) {
4322 else => unreachable,
4323 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4324 .signed => if (self.hasFeature(.avx))
4325 .{ .vp_d, .sra }
4326 else
4327 .{ .p_d, .sra },
4328 .unsigned => if (self.hasFeature(.avx))
4329 .{ .vp_d, .srl }
4330 else
4331 .{ .p_d, .srl },
4332 },
4333 .shl, .shl_exact => if (self.hasFeature(.avx))
4334 .{ .vp_d, .sll }
4335 else
4336 .{ .p_d, .sll },
4337 },
4338 5...8 => switch (tag) {
4339 else => unreachable,
4340 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4341 .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .sra } else null,
4342 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_d, .srl } else null,
4343 },
4344 .shl, .shl_exact => if (self.hasFeature(.avx2)) .{ .vp_d, .sll } else null,
4345 },
4346 },
4347 64 => switch (lhs_ty.vectorLen(mod)) {
4348 else => null,
4349 1...2 => switch (tag) {
4350 else => unreachable,
4351 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4352 .signed => if (self.hasFeature(.avx))
4353 .{ .vp_q, .sra }
4354 else
4355 .{ .p_q, .sra },
4356 .unsigned => if (self.hasFeature(.avx))
4357 .{ .vp_q, .srl }
4358 else
4359 .{ .p_q, .srl },
4360 },
4361 .shl, .shl_exact => if (self.hasFeature(.avx))
4362 .{ .vp_q, .sll }
4363 else
4364 .{ .p_q, .sll },
4365 },
4366 3...4 => switch (tag) {
4367 else => unreachable,
4368 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4369 .signed => if (self.hasFeature(.avx2)) .{ .vp_q, .sra } else null,
4370 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_q, .srl } else null,
4371 },
4372 .shl, .shl_exact => if (self.hasFeature(.avx2)) .{ .vp_q, .sll } else null,
4373 },
4374 },
4375 })) |mir_tag| if (try self.air.value(bin_op.rhs, mod)) |rhs_val| {
4376 switch (mod.intern_pool.indexToKey(rhs_val.toIntern())) {
4377 .aggregate => |rhs_aggregate| switch (rhs_aggregate.storage) {
4378 .repeated_elem => |rhs_elem| {
4379 const abi_size: u32 = @intCast(lhs_ty.abiSize(mod));
4380
4381 const lhs_mcv = try self.resolveInst(bin_op.lhs);
4382 const dst_reg, const lhs_reg = if (lhs_mcv.isRegister() and
4383 self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))
4384 .{lhs_mcv.getReg().?} ** 2
4385 else if (lhs_mcv.isRegister() and self.hasFeature(.avx)) .{
4386 try self.register_manager.allocReg(inst, abi.RegisterClass.sse),
4387 lhs_mcv.getReg().?,
4388 } else .{(try self.copyToRegisterWithInstTracking(
4389 inst,
4390 lhs_ty,
4391 lhs_mcv,
4392 )).register} ** 2;
4393 const reg_locks =
4394 self.register_manager.lockRegs(2, .{ dst_reg, lhs_reg });
4395 defer for (reg_locks) |reg_lock| if (reg_lock) |lock|
4396 self.register_manager.unlockReg(lock);
4397
4398 const shift_imm =
4399 Immediate.u(@intCast(rhs_elem.toValue().toUnsignedInt(mod)));
4400 if (self.hasFeature(.avx)) try self.asmRegisterRegisterImmediate(
4401 mir_tag,
4402 registerAlias(dst_reg, abi_size),
4403 registerAlias(lhs_reg, abi_size),
4404 shift_imm,
4405 ) else {
4406 assert(dst_reg.id() == lhs_reg.id());
4407 try self.asmRegisterImmediate(
4408 mir_tag,
4409 registerAlias(dst_reg, abi_size),
4410 shift_imm,
4411 );
4412 }
4413 break :result .{ .register = dst_reg };
4414 },
4415 else => {},
4416 },
4417 else => {},
4418 }
4419 } else if (Air.refToIndex(bin_op.rhs)) |rhs_inst| switch (air_tags[rhs_inst]) {
4420 .splat => {
4421 const abi_size: u32 = @intCast(lhs_ty.abiSize(mod));
4422
4423 const lhs_mcv = try self.resolveInst(bin_op.lhs);
4424 const dst_reg, const lhs_reg = if (lhs_mcv.isRegister() and
4425 self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))
4426 .{lhs_mcv.getReg().?} ** 2
4427 else if (lhs_mcv.isRegister() and self.hasFeature(.avx)) .{
4428 try self.register_manager.allocReg(inst, abi.RegisterClass.sse),
4429 lhs_mcv.getReg().?,
4430 } else .{(try self.copyToRegisterWithInstTracking(
4431 inst,
4432 lhs_ty,
4433 lhs_mcv,
4434 )).register} ** 2;
4435 const reg_locks = self.register_manager.lockRegs(2, .{ dst_reg, lhs_reg });
4436 defer for (reg_locks) |reg_lock| if (reg_lock) |lock|
4437 self.register_manager.unlockReg(lock);
4438
4439 const shift_reg =
4440 try self.copyToTmpRegister(rhs_ty, .{ .air_ref = bin_op.rhs });
4441 const shift_lock = self.register_manager.lockRegAssumeUnused(shift_reg);
4442 defer self.register_manager.unlockReg(shift_lock);
4443
4444 const mask_ty = try mod.vectorType(.{ .len = 16, .child = .u8_type });
4445 const mask_mcv = try self.genTypedValue(.{
4446 .ty = mask_ty,
4447 .val = (try mod.intern(.{ .aggregate = .{
4448 .ty = mask_ty.toIntern(),
4449 .storage = .{ .elems = &([1]InternPool.Index{
4450 (try rhs_ty.childType(mod).maxIntScalar(mod, Type.u8)).toIntern(),
4451 } ++ [1]InternPool.Index{
4452 (try mod.intValue(Type.u8, 0)).toIntern(),
4453 } ** 15) },
4454 } })).toValue(),
4455 });
4456 const mask_addr_reg =
4457 try self.copyToTmpRegister(Type.usize, mask_mcv.address());
4458 const mask_addr_lock = self.register_manager.lockRegAssumeUnused(mask_addr_reg);
4459 defer self.register_manager.unlockReg(mask_addr_lock);
4460
4461 if (self.hasFeature(.avx)) {
4462 try self.asmRegisterRegisterMemory(
4463 .{ .vp_, .@"and" },
4464 shift_reg.to128(),
4465 shift_reg.to128(),
4466 .{
4467 .base = .{ .reg = mask_addr_reg },
4468 .mod = .{ .rm = .{ .size = .xword } },
4469 },
4470 );
4471 try self.asmRegisterRegisterRegister(
4472 mir_tag,
4473 registerAlias(dst_reg, abi_size),
4474 registerAlias(lhs_reg, abi_size),
4475 shift_reg.to128(),
4476 );
4477 } else {
4478 try self.asmRegisterMemory(
4479 .{ .p_, .@"and" },
4480 shift_reg.to128(),
4481 .{
4482 .base = .{ .reg = mask_addr_reg },
4483 .mod = .{ .rm = .{ .size = .xword } },
4484 },
4485 );
4486 assert(dst_reg.id() == lhs_reg.id());
4487 try self.asmRegisterRegister(
4488 mir_tag,
4489 registerAlias(dst_reg, abi_size),
4490 shift_reg.to128(),
4491 );
4492 }
4493 break :result .{ .register = dst_reg };
4494 },
4495 else => {},
4496 },
4497 else => {},
42094498 },
42104499 else => {},
4211 },
4212 else => unreachable,
4213 }
4214 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
4500 }
4501 return self.fail("TODO implement airShlShrBinOp for {}", .{lhs_ty.fmt(mod)});
4502 };
4503 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
42154504}
42164505
42174506fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
......@@ -4230,12 +4519,18 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
42304519
42314520 const opt_mcv = try self.resolveInst(ty_op.operand);
42324521 if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv)) {
4233 switch (opt_mcv) {
4234 .register => |reg| try self.truncateRegister(pl_ty, reg),
4235 .register_overflow => |ro| try self.truncateRegister(pl_ty, ro.reg),
4522 const pl_mcv: MCValue = switch (opt_mcv) {
4523 .register_overflow => |ro| pl: {
4524 self.eflags_inst = null; // actually stop tracking the overflow part
4525 break :pl .{ .register = ro.reg };
4526 },
4527 else => opt_mcv,
4528 };
4529 switch (pl_mcv) {
4530 .register => |pl_reg| try self.truncateRegister(pl_ty, pl_reg),
42364531 else => {},
42374532 }
4238 break :result opt_mcv;
4533 break :result pl_mcv;
42394534 }
42404535
42414536 const pl_mcv = try self.allocRegOrMem(inst, true);
......@@ -4472,8 +4767,9 @@ fn genUnwrapErrUnionPayloadMir(
44724767 const eu_lock = self.register_manager.lockReg(reg);
44734768 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);
44744769
4475 const result_mcv: MCValue = if (maybe_inst) |inst|
4476 try self.copyToRegisterWithInstTracking(inst, err_union_ty, err_union)
4770 const payload_in_gp = self.regClassForType(payload_ty).supersetOf(abi.RegisterClass.gp);
4771 const result_mcv: MCValue = if (payload_in_gp and maybe_inst != null)
4772 try self.copyToRegisterWithInstTracking(maybe_inst.?, err_union_ty, err_union)
44774773 else
44784774 .{ .register = try self.copyToTmpRegister(err_union_ty, err_union) };
44794775 if (payload_off > 0) try self.genShiftBinOpMir(
......@@ -4482,7 +4778,12 @@ fn genUnwrapErrUnionPayloadMir(
44824778 result_mcv,
44834779 .{ .immediate = @as(u6, @intCast(payload_off * 8)) },
44844780 ) else try self.truncateRegister(payload_ty, result_mcv.register);
4485 break :result result_mcv;
4781 break :result if (payload_in_gp)
4782 result_mcv
4783 else if (maybe_inst) |inst|
4784 try self.copyToRegisterWithInstTracking(inst, payload_ty, result_mcv)
4785 else
4786 .{ .register = try self.copyToTmpRegister(payload_ty, result_mcv) };
44864787 },
44874788 else => return self.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),
44884789 }
......@@ -4593,7 +4894,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
45934894 const result: MCValue = result: {
45944895 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .{ .immediate = 0 };
45954896
4596 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod));
4897 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, mod));
45974898 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod));
45984899 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod));
45994900 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand);
......@@ -4615,7 +4916,7 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
46154916 const result: MCValue = result: {
46164917 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result try self.resolveInst(ty_op.operand);
46174918
4618 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod));
4919 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, mod));
46194920 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod));
46204921 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod));
46214922 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef);
......@@ -4770,14 +5071,19 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
47705071fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
47715072 const mod = self.bin_file.options.module.?;
47725073 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4773 const slice_ty = self.typeOf(bin_op.lhs);
47745074
4775 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
4776 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);
4777 const dst_mcv = try self.allocRegOrMem(inst, false);
4778 try self.load(dst_mcv, slice_ptr_field_type, elem_ptr);
5075 const result: MCValue = result: {
5076 const elem_ty = self.typeOfIndex(inst);
5077 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
47795078
4780 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
5079 const slice_ty = self.typeOf(bin_op.lhs);
5080 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
5081 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);
5082 const dst_mcv = try self.allocRegOrMem(inst, false);
5083 try self.load(dst_mcv, slice_ptr_field_type, elem_ptr);
5084 break :result dst_mcv;
5085 };
5086 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
47815087}
47825088
47835089fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
......@@ -4810,11 +5116,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
48105116 };
48115117 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
48125118
4813 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
4814 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
4815 defer self.register_manager.unlockReg(offset_reg_lock);
4816
48175119 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
5120 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
5121 defer self.register_manager.unlockReg(addr_lock);
5122
48185123 switch (array) {
48195124 .register => {
48205125 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod));
......@@ -4843,6 +5148,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
48435148 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
48445149 }
48455150
5151 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
5152 const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
5153 defer self.register_manager.unlockReg(offset_lock);
5154
48465155 // TODO we could allocate register here, but need to expect addr register and potentially
48475156 // offset register.
48485157 try self.spillEflagsIfOccupied();
......@@ -5093,7 +5402,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
50935402 .{ ._, .sub },
50945403 dst_ty,
50955404 dst_mcv,
5096 .{ .immediate = 8 + self.regExtraBits(src_ty) },
5405 .{ .immediate = 32 - src_bits },
50975406 );
50985407 } else if (src_bits <= 64) {
50995408 try self.genBinOpMir(.{ ._, .lzcnt }, src_ty, dst_mcv, mat_src_mcv);
......@@ -5361,7 +5670,9 @@ fn airPopCount(self: *Self, inst: Air.Inst.Index) !void {
53615670 mat_src_mcv
53625671 else
53635672 .{ .register = mat_src_mcv.register_pair[0] }, false);
5364 try self.genPopCount(tmp_regs[1], Type.usize, if (mat_src_mcv.isMemory())
5673 const src_info = src_ty.intInfo(mod);
5674 const hi_ty = try mod.intType(src_info.signedness, (src_info.bits - 1) % 64 + 1);
5675 try self.genPopCount(tmp_regs[1], hi_ty, if (mat_src_mcv.isMemory())
53655676 mat_src_mcv.address().offset(8).deref()
53665677 else
53675678 .{ .register = mat_src_mcv.register_pair[1] }, false);
......@@ -5383,9 +5694,13 @@ fn genPopCount(
53835694 const src_abi_size: u32 = @intCast(src_ty.abiSize(mod));
53845695 if (self.hasFeature(.popcnt)) return self.genBinOpMir(
53855696 .{ ._, .popcnt },
5386 if (src_abi_size > 1) src_ty else Type.u16,
5697 if (src_abi_size > 1) src_ty else Type.u32,
53875698 .{ .register = dst_reg },
5388 src_mcv,
5699 if (src_abi_size > 1) src_mcv else src: {
5700 if (!dst_contains_src) try self.genSetReg(dst_reg, src_ty, src_mcv);
5701 try self.truncateRegister(try src_ty.toUnsigned(mod), dst_reg);
5702 break :src .{ .register = dst_reg };
5703 },
53895704 );
53905705
53915706 const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - src_abi_size * 8);
......@@ -5517,9 +5832,9 @@ fn genByteSwap(
55175832 try self.asmRegisterMemory(
55185833 .{ ._, .movbe },
55195834 dst_regs[0],
5520 src_mcv.address().offset(8).deref().mem(.qword),
5835 try src_mcv.address().offset(8).deref().mem(self, .qword),
55215836 );
5522 try self.asmRegisterMemory(.{ ._, .movbe }, dst_regs[1], src_mcv.mem(.qword));
5837 try self.asmRegisterMemory(.{ ._, .movbe }, dst_regs[1], try src_mcv.mem(self, .qword));
55235838 } else for (dst_regs, src_mcv.register_pair) |dst_reg, src_reg| {
55245839 try self.asmRegisterRegister(.{ ._, .mov }, dst_reg.to64(), src_reg.to64());
55255840 try self.asmRegister(.{ ._, .bswap }, dst_reg.to64());
......@@ -5762,7 +6077,7 @@ fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type)
57626077 else => unreachable,
57636078 } });
57646079 const sign_mem: Memory = if (sign_mcv.isMemory())
5765 sign_mcv.mem(Memory.Size.fromSize(abi_size))
6080 try sign_mcv.mem(self, Memory.Size.fromSize(abi_size))
57666081 else
57676082 .{
57686083 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) },
......@@ -5945,7 +6260,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro
59456260 mir_tag,
59466261 dst_alias,
59476262 dst_alias,
5948 src_mcv.mem(Memory.Size.fromSize(abi_size)),
6263 try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
59496264 Immediate.u(@as(u5, @bitCast(mode))),
59506265 ) else try self.asmRegisterRegisterRegisterImmediate(
59516266 mir_tag,
......@@ -5960,7 +6275,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro
59606275 else => if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
59616276 mir_tag,
59626277 dst_alias,
5963 src_mcv.mem(Memory.Size.fromSize(abi_size)),
6278 try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
59646279 Immediate.u(@as(u5, @bitCast(mode))),
59656280 ) else try self.asmRegisterRegisterImmediate(
59666281 mir_tag,
......@@ -6000,7 +6315,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
60006315 .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
60016316 .l,
60026317 registerAlias(dst_mcv.register, cmov_abi_size),
6003 src_mcv.mem(Memory.Size.fromSize(cmov_abi_size)),
6318 try src_mcv.mem(self, Memory.Size.fromSize(cmov_abi_size)),
60046319 ),
60056320 else => {
60066321 const val_reg = try self.copyToTmpRegister(ty, src_mcv);
......@@ -6100,7 +6415,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
61006415 if (src_mcv.isMemory()) try self.asmRegisterMemory(
61016416 mir_tag,
61026417 dst_alias,
6103 src_mcv.mem(self.memSize(ty)),
6418 try src_mcv.mem(self, self.memSize(ty)),
61046419 ) else try self.asmRegisterRegister(
61056420 mir_tag,
61066421 dst_alias,
......@@ -6206,7 +6521,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
62066521 if (src_mcv.isMemory()) try self.asmRegisterMemory(
62076522 .{ .v_ps, .cvtph2 },
62086523 wide_reg,
6209 src_mcv.mem(Memory.Size.fromSize(
6524 try src_mcv.mem(self, Memory.Size.fromSize(
62106525 @intCast(@divExact(wide_reg.bitSize(), 16)),
62116526 )),
62126527 ) else try self.asmRegisterRegister(
......@@ -6254,7 +6569,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
62546569 mir_tag,
62556570 dst_reg,
62566571 dst_reg,
6257 src_mcv.mem(Memory.Size.fromSize(abi_size)),
6572 try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
62586573 ) else try self.asmRegisterRegisterRegister(
62596574 mir_tag,
62606575 dst_reg,
......@@ -6267,7 +6582,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
62676582 else => if (src_mcv.isMemory()) try self.asmRegisterMemory(
62686583 mir_tag,
62696584 dst_reg,
6270 src_mcv.mem(Memory.Size.fromSize(abi_size)),
6585 try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
62716586 ) else try self.asmRegisterRegister(
62726587 mir_tag,
62736588 dst_reg,
......@@ -6332,7 +6647,7 @@ fn reuseOperandAdvanced(
63326647 return false;
63336648
63346649 switch (mcv) {
6335 .register, .register_pair => for (mcv.getRegs()) |reg| {
6650 .register, .register_pair, .register_overflow => for (mcv.getRegs()) |reg| {
63366651 // If it's in the registers table, need to associate the register(s) with the
63376652 // new instruction.
63386653 if (maybe_tracked_inst) |tracked_inst| {
......@@ -6346,6 +6661,10 @@ fn reuseOperandAdvanced(
63466661 .load_frame => |frame_addr| if (frame_addr.index.isNamed()) return false,
63476662 else => return false,
63486663 }
6664 switch (mcv) {
6665 .eflags, .register_overflow => self.eflags_inst = maybe_tracked_inst,
6666 else => {},
6667 }
63496668
63506669 // Prevent the operand deaths processing code from deallocating it.
63516670 self.liveness.clearOperandDeath(inst, op_index);
......@@ -6363,11 +6682,36 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
63636682 if (!val_ty.hasRuntimeBitsIgnoreComptime(mod)) return;
63646683 const val_abi_size: u32 = @intCast(val_ty.abiSize(mod));
63656684
6685 if (ptr_info.packed_offset.bit_offset % 8 == 0) {
6686 try self.load(
6687 dst_mcv,
6688 ptr_ty,
6689 ptr_mcv.offset(@intCast(@divExact(ptr_info.packed_offset.bit_offset, 8))),
6690 );
6691 const val_bit_size: u32 = @intCast(val_ty.bitSize(mod));
6692 if (val_abi_size * 8 > val_bit_size) {
6693 if (dst_mcv.isRegister()) {
6694 try self.truncateRegister(val_ty, dst_mcv.getReg().?);
6695 } else {
6696 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6697 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6698 defer self.register_manager.unlockReg(tmp_lock);
6699
6700 const hi_mcv = dst_mcv.address().offset(@intCast(val_bit_size / 64 * 8)).deref();
6701 try self.genSetReg(tmp_reg, Type.usize, hi_mcv);
6702 try self.truncateRegister(val_ty, tmp_reg);
6703 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });
6704 }
6705 }
6706 return;
6707 }
6708
63666709 if (val_abi_size > 8) return self.fail("TODO implement packed load of {}", .{val_ty.fmt(mod)});
63676710
63686711 const limb_abi_size: u32 = @min(val_abi_size, 8);
63696712 const limb_abi_bits = limb_abi_size * 8;
6370 const val_byte_off: i32 = @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size);
6713 const val_byte_off: i32 =
6714 @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size);
63716715 const val_bit_off = ptr_info.packed_offset.bit_offset % limb_abi_bits;
63726716 const val_extra_bits = self.regExtraBits(val_ty);
63736717
......@@ -6530,7 +6874,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
65306874 .base = .{ .reg = ptr_reg },
65316875 .mod = .{ .rm = .{
65326876 .size = Memory.Size.fromSize(limb_abi_size),
6533 .disp = src_byte_off + limb_i * limb_abi_bits,
6877 .disp = src_byte_off + limb_i * limb_abi_size,
65346878 } },
65356879 };
65366880
......@@ -6575,6 +6919,22 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
65756919 limb_mem,
65766920 registerAlias(tmp_reg, limb_abi_size),
65776921 );
6922 } else if (src_bit_size <= 128 and src_bit_off == 0) {
6923 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6924 const tmp_mcv = MCValue{ .register = tmp_reg };
6925 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6926 defer self.register_manager.unlockReg(tmp_lock);
6927
6928 try self.genSetReg(tmp_reg, limb_ty, switch (limb_i) {
6929 0 => src_mcv,
6930 else => src_mcv.address().offset(limb_i * limb_abi_size).deref(),
6931 });
6932 try self.genBinOpMir(.{ ._, .@"and" }, limb_ty, tmp_mcv, .{ .immediate = part_mask });
6933 try self.asmMemoryRegister(
6934 .{ ._, .@"or" },
6935 limb_mem,
6936 registerAlias(tmp_reg, limb_abi_size),
6937 );
65786938 } else return self.fail("TODO: implement packed store of {}", .{src_ty.fmt(mod)});
65796939 }
65806940}
......@@ -6808,17 +7168,17 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
68087168 .register_overflow => |ro| {
68097169 switch (index) {
68107170 // Get wrapped value for overflow operation.
6811 0 => break :result if (self.liveness.operandDies(inst, 0))
6812 .{ .register = ro.reg }
6813 else
6814 try self.copyToRegisterWithInstTracking(
6815 inst,
6816 Type.usize,
6817 .{ .register = ro.reg },
6818 ),
7171 0 => if (self.reuseOperand(inst, extra.struct_operand, 0, src_mcv)) {
7172 self.eflags_inst = null; // actually stop tracking the overflow part
7173 break :result .{ .register = ro.reg };
7174 } else break :result try self.copyToRegisterWithInstTracking(
7175 inst,
7176 Type.usize,
7177 .{ .register = ro.reg },
7178 ),
68197179 // Get overflow bit.
6820 1 => if (self.liveness.operandDies(inst, 0)) {
6821 self.eflags_inst = inst;
7180 1 => if (self.reuseOperandAdvanced(inst, extra.struct_operand, 0, src_mcv, null)) {
7181 self.eflags_inst = inst; // actually keep tracking the overflow part
68227182 break :result .{ .eflags = ro.eflags };
68237183 } else {
68247184 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
......@@ -6833,11 +7193,12 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
68337193 if (field_off % 8 == 0) {
68347194 const off_mcv =
68357195 src_mcv.address().offset(@intCast(@divExact(field_off, 8))).deref();
7196 const field_bit_size = field_ty.bitSize(mod);
68367197
68377198 if (field_abi_size <= 8) {
68387199 const int_ty = try mod.intType(
68397200 if (field_ty.isAbiInt(mod)) field_ty.intInfo(mod).signedness else .unsigned,
6840 @intCast(field_ty.bitSize(mod)),
7201 @intCast(field_bit_size),
68417202 );
68427203
68437204 const dst_reg = try self.register_manager.allocReg(
......@@ -6856,10 +7217,24 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
68567217 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);
68577218 }
68587219
6859 if (self.reuseOperand(inst, operand, 0, src_mcv)) break :result off_mcv;
6860
6861 const dst_mcv = try self.allocRegOrMem(inst, true);
6862 try self.genCopy(field_ty, dst_mcv, off_mcv);
7220 const dst_mcv = if (self.reuseOperand(inst, operand, 0, src_mcv))
7221 off_mcv
7222 else dst: {
7223 const dst_mcv = try self.allocRegOrMem(inst, true);
7224 try self.genCopy(field_ty, dst_mcv, off_mcv);
7225 break :dst dst_mcv;
7226 };
7227 if (field_abi_size * 8 > field_bit_size and dst_mcv.isMemory()) {
7228 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
7229 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7230 defer self.register_manager.unlockReg(tmp_lock);
7231
7232 const hi_mcv =
7233 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();
7234 try self.genSetReg(tmp_reg, Type.usize, hi_mcv);
7235 try self.truncateRegister(field_ty, tmp_reg);
7236 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });
7237 }
68637238 break :result dst_mcv;
68647239 }
68657240
......@@ -7013,7 +7388,25 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
70137388 } else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv);
70147389 }
70157390 },
7016 .neg => try self.genUnOpMir(.{ ._, .neg }, src_ty, dst_mcv),
7391 .neg => {
7392 try self.genUnOpMir(.{ ._, .neg }, src_ty, dst_mcv);
7393 const abi_size: u16 = @intCast(src_ty.abiSize(mod));
7394 const bit_size = src_ty.intInfo(mod).bits;
7395 if (abi_size * 8 > bit_size) {
7396 if (dst_mcv.isRegister()) {
7397 try self.truncateRegister(src_ty, dst_mcv.getReg().?);
7398 } else {
7399 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
7400 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7401 defer self.register_manager.unlockReg(tmp_lock);
7402
7403 const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref();
7404 try self.genSetReg(tmp_reg, Type.usize, hi_mcv);
7405 try self.truncateRegister(src_ty, tmp_reg);
7406 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });
7407 }
7408 }
7409 },
70177410 else => unreachable,
70187411 }
70197412 return dst_mcv;
......@@ -7054,7 +7447,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC
70547447 },
70557448 .indirect, .load_frame => try self.asmMemory(
70567449 mir_tag,
7057 dst_mcv.mem(Memory.Size.fromSize(abi_size)),
7450 try dst_mcv.mem(self, Memory.Size.fromSize(abi_size)),
70587451 ),
70597452 }
70607453}
......@@ -7552,27 +7945,27 @@ fn genMulDivBinOp(
75527945 defer self.register_manager.unlockReg(tmp_lock);
75537946
75547947 if (mat_lhs_mcv.isMemory())
7555 try self.asmRegisterMemory(.{ ._, .mov }, .rax, mat_lhs_mcv.mem(.qword))
7948 try self.asmRegisterMemory(.{ ._, .mov }, .rax, try mat_lhs_mcv.mem(self, .qword))
75567949 else
75577950 try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]);
75587951 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
75597952 .{ ._, .mov },
75607953 tmp_reg,
7561 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
7954 try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword),
75627955 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_rhs_mcv.register_pair[1]);
75637956 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, .rax);
75647957 if (mat_rhs_mcv.isMemory())
7565 try self.asmMemory(.{ ._, .mul }, mat_rhs_mcv.mem(.qword))
7958 try self.asmMemory(.{ ._, .mul }, try mat_rhs_mcv.mem(self, .qword))
75667959 else
75677960 try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]);
75687961 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg);
75697962 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
75707963 .{ ._, .mov },
75717964 tmp_reg,
7572 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
7965 try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword),
75737966 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_lhs_mcv.register_pair[1]);
75747967 if (mat_rhs_mcv.isMemory())
7575 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, mat_rhs_mcv.mem(.qword))
7968 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, try mat_rhs_mcv.mem(self, .qword))
75767969 else
75777970 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, mat_rhs_mcv.register_pair[0]);
75787971 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg);
......@@ -7833,7 +8226,7 @@ fn genBinOp(
78338226 .{ .vp_w, .insr },
78348227 dst_reg,
78358228 dst_reg,
7836 rhs_mcv.mem(.word),
8229 try rhs_mcv.mem(self, .word),
78378230 Immediate.u(1),
78388231 ) else try self.asmRegisterRegisterRegister(
78398232 .{ .vp_, .unpcklwd },
......@@ -7858,7 +8251,7 @@ fn genBinOp(
78588251 mir_tag,
78598252 dst_reg,
78608253 dst_reg,
7861 src_mcv.mem(Memory.Size.fromBitSize(float_bits)),
8254 try src_mcv.mem(self, Memory.Size.fromBitSize(float_bits)),
78628255 ) else try self.asmRegisterRegisterRegister(
78638256 mir_tag,
78648257 dst_reg,
......@@ -7877,7 +8270,7 @@ fn genBinOp(
78778270 if (src_mcv.isMemory()) try self.asmRegisterMemory(
78788271 mir_tag,
78798272 dst_reg,
7880 src_mcv.mem(Memory.Size.fromBitSize(float_bits)),
8273 try src_mcv.mem(self, Memory.Size.fromBitSize(float_bits)),
78818274 ) else try self.asmRegisterRegister(
78828275 mir_tag,
78838276 dst_reg,
......@@ -7919,12 +8312,18 @@ fn genBinOp(
79198312 };
79208313 }
79218314
7922 if ((lhs_ty.scalarType(mod).isRuntimeFloat() and
8315 const sse_op = switch (lhs_ty.zigTypeTag(mod)) {
8316 else => false,
8317 .Float => true,
8318 .Vector => switch (lhs_ty.childType(mod).toIntern()) {
8319 .bool_type => false,
8320 else => true,
8321 },
8322 };
8323 if (sse_op and ((lhs_ty.scalarType(mod).isRuntimeFloat() and
79238324 lhs_ty.scalarType(mod).floatBits(self.target.*) == 80) or
7924 lhs_ty.abiSize(mod) > @as(u6, if (self.hasFeature(.avx)) 32 else 16))
7925 return self.fail("TODO implement genBinOp for {s} {}", .{
7926 @tagName(air_tag), lhs_ty.fmt(mod),
7927 });
8325 lhs_ty.abiSize(mod) > @as(u6, if (self.hasFeature(.avx)) 32 else 16)))
8326 return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(air_tag), lhs_ty.fmt(mod) });
79288327
79298328 const maybe_mask_reg = switch (air_tag) {
79308329 else => null,
......@@ -7941,10 +8340,16 @@ fn genBinOp(
79418340 if (maybe_mask_reg) |mask_reg| self.register_manager.lockRegAssumeUnused(mask_reg) else null;
79428341 defer if (mask_lock) |lock| self.register_manager.unlockReg(lock);
79438342
7944 const ordered_air = if (lhs_ty.isVector(mod) and lhs_ty.childType(mod).isAbiInt(mod) and
7945 switch (air_tag) {
7946 .cmp_lt, .cmp_gte => true,
7947 else => false,
8343 const ordered_air = if (lhs_ty.isVector(mod) and switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
8344 .Int => switch (air_tag) {
8345 .cmp_lt, .cmp_gte => true,
8346 else => false,
8347 },
8348 .Float => switch (air_tag) {
8349 .cmp_gte, .cmp_gt => true,
8350 else => false,
8351 },
8352 else => unreachable,
79488353 }) .{ .lhs = rhs_air, .rhs = lhs_air } else .{ .lhs = lhs_air, .rhs = rhs_air };
79498354
79508355 const lhs_mcv = try self.resolveInst(ordered_air.lhs);
......@@ -7971,14 +8376,12 @@ fn genBinOp(
79718376 .xor,
79728377 .min,
79738378 .max,
8379 .cmp_eq,
8380 .cmp_neq,
79748381 => true,
79758382
79768383 else => false,
79778384 };
7978 const vec_op = switch (lhs_ty.zigTypeTag(mod)) {
7979 else => false,
7980 .Float, .Vector => true,
7981 };
79828385
79838386 const lhs_locks: [2]?RegisterLock = switch (lhs_mcv) {
79848387 .register => |lhs_reg| .{ self.register_manager.lockRegAssumeUnused(lhs_reg), null },
......@@ -8000,23 +8403,23 @@ fn genBinOp(
80008403 var flipped = false;
80018404 var copied_to_dst = true;
80028405 const dst_mcv: MCValue = dst: {
8406 const tracked_inst = switch (air_tag) {
8407 else => maybe_inst,
8408 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => null,
8409 };
80038410 if (maybe_inst) |inst| {
8004 const tracked_inst = switch (air_tag) {
8005 else => inst,
8006 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => null,
8007 };
8008 if ((!vec_op or lhs_mcv.isRegister()) and
8411 if ((!sse_op or lhs_mcv.isRegister()) and
80098412 self.reuseOperandAdvanced(inst, ordered_air.lhs, 0, lhs_mcv, tracked_inst))
80108413 break :dst lhs_mcv;
8011 if (is_commutative and (!vec_op or rhs_mcv.isRegister()) and
8414 if (is_commutative and (!sse_op or rhs_mcv.isRegister()) and
80128415 self.reuseOperandAdvanced(inst, ordered_air.rhs, 1, rhs_mcv, tracked_inst))
80138416 {
80148417 flipped = true;
80158418 break :dst rhs_mcv;
80168419 }
80178420 }
8018 const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, maybe_inst, true);
8019 if (vec_op and lhs_mcv.isRegister() and self.hasFeature(.avx))
8421 const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, tracked_inst, true);
8422 if (sse_op and lhs_mcv.isRegister() and self.hasFeature(.avx))
80208423 copied_to_dst = false
80218424 else
80228425 try self.genCopy(lhs_ty, dst_mcv, lhs_mcv);
......@@ -8046,7 +8449,7 @@ fn genBinOp(
80468449 };
80478450 defer for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock);
80488451
8049 if (!vec_op) {
8452 if (!sse_op) {
80508453 switch (air_tag) {
80518454 .add,
80528455 .add_wrap,
......@@ -8130,17 +8533,25 @@ fn genBinOp(
81308533
81318534 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_regs[1]);
81328535 if (src_mcv.isMemory()) {
8133 try self.asmRegisterMemory(.{ ._, .cmp }, dst_regs[0], src_mcv.mem(.qword));
8536 try self.asmRegisterMemory(
8537 .{ ._, .cmp },
8538 dst_regs[0],
8539 try src_mcv.mem(self, .qword),
8540 );
81348541 try self.asmRegisterMemory(
81358542 .{ ._, .sbb },
81368543 tmp_reg,
8137 src_mcv.address().offset(8).deref().mem(.qword),
8544 try src_mcv.address().offset(8).deref().mem(self, .qword),
8545 );
8546 try self.asmCmovccRegisterMemory(
8547 cc,
8548 dst_regs[0],
8549 try src_mcv.mem(self, .qword),
81388550 );
8139 try self.asmCmovccRegisterMemory(cc, dst_regs[0], src_mcv.mem(.qword));
81408551 try self.asmCmovccRegisterMemory(
81418552 cc,
81428553 dst_regs[1],
8143 src_mcv.address().offset(8).deref().mem(.qword),
8554 try src_mcv.address().offset(8).deref().mem(self, .qword),
81448555 );
81458556 } else {
81468557 try self.asmRegisterRegister(
......@@ -8292,7 +8703,7 @@ fn genBinOp(
82928703 .{ .vp_w, .insr },
82938704 dst_reg,
82948705 dst_reg,
8295 src_mcv.mem(.word),
8706 try src_mcv.mem(self, .word),
82968707 Immediate.u(1),
82978708 ) else try self.asmRegisterRegisterRegister(
82988709 .{ .vp_, .unpcklwd },
......@@ -8738,7 +9149,7 @@ fn genBinOp(
87389149 .{ .vp_w, .insr },
87399150 dst_reg,
87409151 dst_reg,
8741 src_mcv.mem(.word),
9152 try src_mcv.mem(self, .word),
87429153 Immediate.u(1),
87439154 ) else try self.asmRegisterRegisterRegister(
87449155 .{ .vp_, .unpcklwd },
......@@ -8784,7 +9195,7 @@ fn genBinOp(
87849195 if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
87859196 .{ .vp_d, .insr },
87869197 dst_reg,
8787 src_mcv.mem(.dword),
9198 try src_mcv.mem(self, .dword),
87889199 Immediate.u(1),
87899200 ) else try self.asmRegisterRegisterRegister(
87909201 .{ .v_ps, .unpckl },
......@@ -8836,7 +9247,7 @@ fn genBinOp(
88369247 if (src_mcv.isMemory()) try self.asmRegisterMemory(
88379248 .{ .v_ps, .cvtph2 },
88389249 tmp_reg,
8839 src_mcv.mem(.qword),
9250 try src_mcv.mem(self, .qword),
88409251 ) else try self.asmRegisterRegister(
88419252 .{ .v_ps, .cvtph2 },
88429253 tmp_reg,
......@@ -8879,7 +9290,7 @@ fn genBinOp(
88799290 if (src_mcv.isMemory()) try self.asmRegisterMemory(
88809291 .{ .v_ps, .cvtph2 },
88819292 tmp_reg,
8882 src_mcv.mem(.xword),
9293 try src_mcv.mem(self, .xword),
88839294 ) else try self.asmRegisterRegister(
88849295 .{ .v_ps, .cvtph2 },
88859296 tmp_reg,
......@@ -8925,6 +9336,13 @@ fn genBinOp(
89259336 => if (self.hasFeature(.avx)) .{ .v_ss, .div } else .{ ._ss, .div },
89269337 .max => if (self.hasFeature(.avx)) .{ .v_ss, .max } else .{ ._ss, .max },
89279338 .min => if (self.hasFeature(.avx)) .{ .v_ss, .min } else .{ ._ss, .min },
9339 .cmp_lt,
9340 .cmp_lte,
9341 .cmp_eq,
9342 .cmp_gte,
9343 .cmp_gt,
9344 .cmp_neq,
9345 => if (self.hasFeature(.avx)) .{ .v_ss, .cmp } else .{ ._ss, .cmp },
89289346 else => unreachable,
89299347 },
89309348 2...4 => switch (air_tag) {
......@@ -8938,7 +9356,14 @@ fn genBinOp(
89389356 => if (self.hasFeature(.avx)) .{ .v_ps, .div } else .{ ._ps, .div },
89399357 .max => if (self.hasFeature(.avx)) .{ .v_ps, .max } else .{ ._ps, .max },
89409358 .min => if (self.hasFeature(.avx)) .{ .v_ps, .min } else .{ ._ps, .min },
8941 else => unreachable,
9359 .cmp_lt,
9360 .cmp_lte,
9361 .cmp_eq,
9362 .cmp_gte,
9363 .cmp_gt,
9364 .cmp_neq,
9365 => if (self.hasFeature(.avx)) .{ .v_ps, .cmp } else .{ ._ps, .cmp },
9366 else => unreachable,
89429367 },
89439368 5...8 => if (self.hasFeature(.avx)) switch (air_tag) {
89449369 .add => .{ .v_ps, .add },
......@@ -8947,6 +9372,7 @@ fn genBinOp(
89479372 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
89489373 .max => .{ .v_ps, .max },
89499374 .min => .{ .v_ps, .min },
9375 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => .{ .v_ps, .cmp },
89509376 else => unreachable,
89519377 } else null,
89529378 else => null,
......@@ -8963,6 +9389,13 @@ fn genBinOp(
89639389 => if (self.hasFeature(.avx)) .{ .v_sd, .div } else .{ ._sd, .div },
89649390 .max => if (self.hasFeature(.avx)) .{ .v_sd, .max } else .{ ._sd, .max },
89659391 .min => if (self.hasFeature(.avx)) .{ .v_sd, .min } else .{ ._sd, .min },
9392 .cmp_lt,
9393 .cmp_lte,
9394 .cmp_eq,
9395 .cmp_gte,
9396 .cmp_gt,
9397 .cmp_neq,
9398 => if (self.hasFeature(.avx)) .{ .v_sd, .cmp } else .{ ._sd, .cmp },
89669399 else => unreachable,
89679400 },
89689401 2 => switch (air_tag) {
......@@ -8976,6 +9409,13 @@ fn genBinOp(
89769409 => if (self.hasFeature(.avx)) .{ .v_pd, .div } else .{ ._pd, .div },
89779410 .max => if (self.hasFeature(.avx)) .{ .v_pd, .max } else .{ ._pd, .max },
89789411 .min => if (self.hasFeature(.avx)) .{ .v_pd, .min } else .{ ._pd, .min },
9412 .cmp_lt,
9413 .cmp_lte,
9414 .cmp_eq,
9415 .cmp_gte,
9416 .cmp_gt,
9417 .cmp_neq,
9418 => if (self.hasFeature(.avx)) .{ .v_pd, .cmp } else .{ ._pd, .cmp },
89799419 else => unreachable,
89809420 },
89819421 3...4 => if (self.hasFeature(.avx)) switch (air_tag) {
......@@ -8984,6 +9424,7 @@ fn genBinOp(
89849424 .mul => .{ .v_pd, .mul },
89859425 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_pd, .div },
89869426 .max => .{ .v_pd, .max },
9427 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => .{ .v_pd, .cmp },
89879428 .min => .{ .v_pd, .min },
89889429 else => unreachable,
89899430 } else null,
......@@ -9004,43 +9445,96 @@ fn genBinOp(
90049445 const lhs_copy_lock = if (lhs_copy_reg) |reg| self.register_manager.lockReg(reg) else null;
90059446 defer if (lhs_copy_lock) |lock| self.register_manager.unlockReg(lock);
90069447
9007 if (self.hasFeature(.avx)) {
9008 const lhs_reg =
9009 if (copied_to_dst) dst_reg else registerAlias(lhs_mcv.getReg().?, abi_size);
9010 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
9011 mir_tag,
9012 dst_reg,
9013 lhs_reg,
9014 src_mcv.mem(switch (lhs_ty.zigTypeTag(mod)) {
9015 else => Memory.Size.fromSize(abi_size),
9016 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9017 }),
9018 ) else try self.asmRegisterRegisterRegister(
9019 mir_tag,
9020 dst_reg,
9021 lhs_reg,
9022 registerAlias(if (src_mcv.isRegister())
9023 src_mcv.getReg().?
9024 else
9025 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9026 );
9027 } else {
9028 assert(copied_to_dst);
9029 if (src_mcv.isMemory()) try self.asmRegisterMemory(
9030 mir_tag,
9031 dst_reg,
9032 src_mcv.mem(switch (lhs_ty.zigTypeTag(mod)) {
9033 else => Memory.Size.fromSize(abi_size),
9034 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9035 }),
9036 ) else try self.asmRegisterRegister(
9037 mir_tag,
9038 dst_reg,
9039 registerAlias(if (src_mcv.isRegister())
9040 src_mcv.getReg().?
9041 else
9042 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9043 );
9448 switch (mir_tag[1]) {
9449 else => if (self.hasFeature(.avx)) {
9450 const lhs_reg =
9451 if (copied_to_dst) dst_reg else registerAlias(lhs_mcv.getReg().?, abi_size);
9452 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
9453 mir_tag,
9454 dst_reg,
9455 lhs_reg,
9456 try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(mod)) {
9457 else => Memory.Size.fromSize(abi_size),
9458 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9459 }),
9460 ) else try self.asmRegisterRegisterRegister(
9461 mir_tag,
9462 dst_reg,
9463 lhs_reg,
9464 registerAlias(if (src_mcv.isRegister())
9465 src_mcv.getReg().?
9466 else
9467 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9468 );
9469 } else {
9470 assert(copied_to_dst);
9471 if (src_mcv.isMemory()) try self.asmRegisterMemory(
9472 mir_tag,
9473 dst_reg,
9474 try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(mod)) {
9475 else => Memory.Size.fromSize(abi_size),
9476 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9477 }),
9478 ) else try self.asmRegisterRegister(
9479 mir_tag,
9480 dst_reg,
9481 registerAlias(if (src_mcv.isRegister())
9482 src_mcv.getReg().?
9483 else
9484 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9485 );
9486 },
9487 .cmp => {
9488 const imm = Immediate.u(switch (air_tag) {
9489 .cmp_eq => 0,
9490 .cmp_lt, .cmp_gt => 1,
9491 .cmp_lte, .cmp_gte => 2,
9492 .cmp_neq => 4,
9493 else => unreachable,
9494 });
9495 if (self.hasFeature(.avx)) {
9496 const lhs_reg =
9497 if (copied_to_dst) dst_reg else registerAlias(lhs_mcv.getReg().?, abi_size);
9498 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(
9499 mir_tag,
9500 dst_reg,
9501 lhs_reg,
9502 try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(mod)) {
9503 else => Memory.Size.fromSize(abi_size),
9504 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9505 }),
9506 imm,
9507 ) else try self.asmRegisterRegisterRegisterImmediate(
9508 mir_tag,
9509 dst_reg,
9510 lhs_reg,
9511 registerAlias(if (src_mcv.isRegister())
9512 src_mcv.getReg().?
9513 else
9514 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9515 imm,
9516 );
9517 } else {
9518 assert(copied_to_dst);
9519 if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
9520 mir_tag,
9521 dst_reg,
9522 try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(mod)) {
9523 else => Memory.Size.fromSize(abi_size),
9524 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9525 }),
9526 imm,
9527 ) else try self.asmRegisterRegisterImmediate(
9528 mir_tag,
9529 dst_reg,
9530 registerAlias(if (src_mcv.isRegister())
9531 src_mcv.getReg().?
9532 else
9533 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9534 imm,
9535 );
9536 }
9537 },
90449538 }
90459539
90469540 switch (air_tag) {
......@@ -9281,48 +9775,46 @@ fn genBinOp(
92819775 );
92829776 }
92839777 },
9284 .cmp_lt,
9285 .cmp_lte,
9286 .cmp_eq,
9287 .cmp_gte,
9288 .cmp_gt,
9289 .cmp_neq,
9290 => {
9291 switch (air_tag) {
9292 .cmp_lt,
9293 .cmp_eq,
9294 .cmp_gt,
9295 => {},
9296 .cmp_lte,
9297 .cmp_gte,
9298 .cmp_neq,
9299 => {
9300 const unsigned_ty = try lhs_ty.toUnsigned(mod);
9301 const not_mcv = try self.genTypedValue(.{
9302 .ty = lhs_ty,
9303 .val = try unsigned_ty.maxInt(mod, unsigned_ty),
9304 });
9305 const not_mem: Memory = if (not_mcv.isMemory())
9306 not_mcv.mem(Memory.Size.fromSize(abi_size))
9307 else
9308 .{ .base = .{
9309 .reg = try self.copyToTmpRegister(Type.usize, not_mcv.address()),
9310 }, .mod = .{ .rm = .{ .size = Memory.Size.fromSize(abi_size) } } };
9311 switch (mir_tag[0]) {
9312 .vp_b, .vp_d, .vp_q, .vp_w => try self.asmRegisterRegisterMemory(
9313 .{ .vp_, .xor },
9314 dst_reg,
9315 dst_reg,
9316 not_mem,
9317 ),
9318 .p_b, .p_d, .p_q, .p_w => try self.asmRegisterMemory(
9319 .{ .p_, .xor },
9320 dst_reg,
9321 not_mem,
9322 ),
9323 else => unreachable,
9324 }
9778 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => {
9779 switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
9780 .Int => switch (air_tag) {
9781 .cmp_lt,
9782 .cmp_eq,
9783 .cmp_gt,
9784 => {},
9785 .cmp_lte,
9786 .cmp_gte,
9787 .cmp_neq,
9788 => {
9789 const unsigned_ty = try lhs_ty.toUnsigned(mod);
9790 const not_mcv = try self.genTypedValue(.{
9791 .ty = lhs_ty,
9792 .val = try unsigned_ty.maxInt(mod, unsigned_ty),
9793 });
9794 const not_mem: Memory = if (not_mcv.isMemory())
9795 try not_mcv.mem(self, Memory.Size.fromSize(abi_size))
9796 else
9797 .{ .base = .{
9798 .reg = try self.copyToTmpRegister(Type.usize, not_mcv.address()),
9799 }, .mod = .{ .rm = .{ .size = Memory.Size.fromSize(abi_size) } } };
9800 switch (mir_tag[0]) {
9801 .vp_b, .vp_d, .vp_q, .vp_w => try self.asmRegisterRegisterMemory(
9802 .{ .vp_, .xor },
9803 dst_reg,
9804 dst_reg,
9805 not_mem,
9806 ),
9807 .p_b, .p_d, .p_q, .p_w => try self.asmRegisterMemory(
9808 .{ .p_, .xor },
9809 dst_reg,
9810 not_mem,
9811 ),
9812 else => unreachable,
9813 }
9814 },
9815 else => unreachable,
93259816 },
9817 .Float => {},
93269818 else => unreachable,
93279819 }
93289820
......@@ -9331,8 +9823,12 @@ fn genBinOp(
93319823 defer self.register_manager.unlockReg(gp_lock);
93329824
93339825 try self.asmRegisterRegister(switch (mir_tag[0]) {
9334 .vp_b, .vp_d, .vp_q, .vp_w => .{ .vp_b, .movmsk },
9826 ._pd, ._sd => .{ ._pd, .movmsk },
9827 ._ps, ._ss => .{ ._ps, .movmsk },
93359828 .p_b, .p_d, .p_q, .p_w => .{ .p_b, .movmsk },
9829 .v_pd, .v_sd => .{ .v_pd, .movmsk },
9830 .v_ps, .v_ss => .{ .v_ps, .movmsk },
9831 .vp_b, .vp_d, .vp_q, .vp_w => .{ .vp_b, .movmsk },
93369832 else => unreachable,
93379833 }, gp_reg.to32(), dst_reg);
93389834 return .{ .register = gp_reg };
......@@ -9459,13 +9955,13 @@ fn genBinOpMir(
94599955 .load_frame,
94609956 .lea_frame,
94619957 => {
9462 blk: {
9463 return self.asmRegisterMemory(mir_limb_tag, dst_alias, switch (src_mcv) {
9958 direct: {
9959 try self.asmRegisterMemory(mir_limb_tag, dst_alias, switch (src_mcv) {
94649960 .memory => |addr| .{
94659961 .base = .{ .reg = .ds },
94669962 .mod = .{ .rm = .{
94679963 .size = Memory.Size.fromSize(limb_abi_size),
9468 .disp = math.cast(i32, addr + off) orelse break :blk,
9964 .disp = math.cast(i32, addr + off) orelse break :direct,
94699965 } },
94709966 },
94719967 .indirect => |reg_off| .{
......@@ -9482,8 +9978,9 @@ fn genBinOpMir(
94829978 .disp = frame_addr.off + off,
94839979 } },
94849980 },
9485 else => break :blk,
9981 else => break :direct,
94869982 });
9983 continue;
94879984 }
94889985
94899986 switch (src_mcv) {
......@@ -10180,7 +10677,7 @@ fn genCall(self: *Self, info: union(enum) {
1018010677 .none, .unreach => {},
1018110678 .indirect => |reg_off| {
1018210679 const ret_ty = fn_info.return_type.toType();
10183 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));
10680 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ret_ty, mod));
1018410681 try self.genSetReg(reg_off.reg, Type.usize, .{
1018510682 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
1018610683 });
......@@ -10306,19 +10803,20 @@ fn genCall(self: *Self, info: union(enum) {
1030610803fn airRet(self: *Self, inst: Air.Inst.Index) !void {
1030710804 const mod = self.bin_file.options.module.?;
1030810805 const un_op = self.air.instructions.items(.data)[inst].un_op;
10309 const operand = try self.resolveInst(un_op);
1031010806
1031110807 const ret_ty = self.fn_type.fnReturnType(mod);
1031210808 switch (self.ret_mcv.short) {
1031310809 .none => {},
10314 .register, .register_pair => try self.genCopy(ret_ty, self.ret_mcv.short, operand),
10810 .register,
10811 .register_pair,
10812 => try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }),
1031510813 .indirect => |reg_off| {
1031610814 try self.register_manager.getReg(reg_off.reg, null);
1031710815 const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg);
1031810816 defer self.register_manager.unlockReg(lock);
1031910817
1032010818 try self.genSetReg(reg_off.reg, Type.usize, self.ret_mcv.long);
10321 try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ret_ty, operand);
10819 try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ret_ty, .{ .air_ref = un_op });
1032210820 },
1032310821 else => unreachable,
1032410822 }
......@@ -10593,7 +11091,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1059311091 const locks = self.register_manager.lockRegsAssumeUnused(2, regs);
1059411092 defer for (locks) |lock| self.register_manager.unlockReg(lock);
1059511093
10596 const limbs_len = std.math.divCeil(u16, abi_size, 8) catch unreachable;
11094 const limbs_len = math.divCeil(u16, abi_size, 8) catch unreachable;
1059711095 var limb_i: u16 = 0;
1059811096 while (limb_i < limbs_len) : (limb_i += 1) {
1059911097 const off = limb_i * 8;
......@@ -10688,7 +11186,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1068811186 .{ .vp_w, .insr },
1068911187 tmp1_reg,
1069011188 dst_reg.to128(),
10691 src_mcv.mem(.word),
11189 try src_mcv.mem(self, .word),
1069211190 Immediate.u(1),
1069311191 ) else try self.asmRegisterRegisterRegister(
1069411192 .{ .vp_, .unpcklwd },
......@@ -10892,8 +11390,8 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index {
1089211390 },
1089311391 .register => |reg| {
1089411392 try self.spillEflagsIfOccupied();
10895 try self.asmRegisterImmediate(.{ ._, .@"test" }, reg, Immediate.u(1));
10896 return self.asmJccReloc(.e, undefined);
11393 try self.asmRegisterImmediate(.{ ._, .@"test" }, reg.to8(), Immediate.u(1));
11394 return self.asmJccReloc(.z, undefined);
1089711395 },
1089811396 .immediate,
1089911397 .load_frame,
......@@ -11433,12 +11931,12 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
1143311931 if (self.reuseOperandAdvanced(inst, br.operand, 0, src_mcv, br.block_inst)) {
1143411932 if (first_br) break :result src_mcv;
1143511933
11436 if (block_tracking.getReg()) |block_reg|
11934 for (block_tracking.getRegs()) |block_reg|
1143711935 try self.register_manager.getReg(block_reg, br.block_inst);
1143811936 // .long = .none to avoid merging operand and block result stack frames.
1143911937 var current_tracking = InstTracking{ .long = .none, .short = src_mcv };
1144011938 try current_tracking.materializeUnsafe(self, br.block_inst, block_tracking.*);
11441 if (src_mcv.getReg()) |src_reg| self.register_manager.freeReg(src_reg);
11939 for (src_mcv.getRegs()) |src_reg| self.register_manager.freeReg(src_reg);
1144211940 break :result block_tracking.short;
1144311941 }
1144411942
......@@ -12177,16 +12675,87 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo
1217712675 .general_purpose, .segment => return .{ .move = .{ ._, .mov } },
1217812676 .x87 => return .x87_load_store,
1217912677 .mmx => {},
12180 .sse => {
12181 switch (ty.zigTypeTag(mod)) {
12182 else => {
12183 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
12184 assert(std.mem.indexOfNone(abi.Class, classes, &.{
12185 .integer, .sse, .float, .float_combine,
12186 }) == null);
12187 const abi_size = ty.abiSize(mod);
12188 if (abi_size < 4 or
12189 std.mem.indexOfScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
12678 .sse => switch (ty.zigTypeTag(mod)) {
12679 else => {
12680 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
12681 assert(std.mem.indexOfNone(abi.Class, classes, &.{
12682 .integer, .sse, .float, .float_combine,
12683 }) == null);
12684 const abi_size = ty.abiSize(mod);
12685 if (abi_size < 4 or
12686 std.mem.indexOfScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
12687 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
12688 .insert = .{ .vp_b, .insr },
12689 .extract = .{ .vp_b, .extr },
12690 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
12691 .insert = .{ .p_b, .insr },
12692 .extract = .{ .p_b, .extr },
12693 } },
12694 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12695 .insert = .{ .vp_w, .insr },
12696 .extract = .{ .vp_w, .extr },
12697 } } else .{ .insert_extract = .{
12698 .insert = .{ .p_w, .insr },
12699 .extract = .{ .p_w, .extr },
12700 } },
12701 3...4 => return .{ .move = if (self.hasFeature(.avx))
12702 .{ .v_d, .mov }
12703 else
12704 .{ ._d, .mov } },
12705 5...8 => return .{ .move = if (self.hasFeature(.avx))
12706 .{ .v_q, .mov }
12707 else
12708 .{ ._q, .mov } },
12709 9...16 => return .{ .move = if (self.hasFeature(.avx))
12710 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12711 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12712 17...32 => if (self.hasFeature(.avx))
12713 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
12714 else => {},
12715 } else switch (abi_size) {
12716 4 => return .{ .move = if (self.hasFeature(.avx))
12717 .{ .v_ss, .mov }
12718 else
12719 .{ ._ss, .mov } },
12720 5...8 => return .{ .move = if (self.hasFeature(.avx))
12721 .{ .v_sd, .mov }
12722 else
12723 .{ ._sd, .mov } },
12724 9...16 => return .{ .move = if (self.hasFeature(.avx))
12725 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12726 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12727 17...32 => if (self.hasFeature(.avx)) return .{ .move = if (aligned)
12728 .{ .v_pd, .mova }
12729 else
12730 .{ .v_pd, .movu } },
12731 else => {},
12732 }
12733 },
12734 .Float => switch (ty.floatBits(self.target.*)) {
12735 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12736 .insert = .{ .vp_w, .insr },
12737 .extract = .{ .vp_w, .extr },
12738 } } else .{ .insert_extract = .{
12739 .insert = .{ .p_w, .insr },
12740 .extract = .{ .p_w, .extr },
12741 } },
12742 32 => return .{ .move = if (self.hasFeature(.avx))
12743 .{ .v_ss, .mov }
12744 else
12745 .{ ._ss, .mov } },
12746 64 => return .{ .move = if (self.hasFeature(.avx))
12747 .{ .v_sd, .mov }
12748 else
12749 .{ ._sd, .mov } },
12750 128 => return .{ .move = if (self.hasFeature(.avx))
12751 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12752 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12753 else => {},
12754 },
12755 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
12756 .Bool => {},
12757 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
12758 8 => switch (ty.vectorLen(mod)) {
1219012759 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
1219112760 .insert = .{ .vp_b, .insr },
1219212761 .extract = .{ .vp_b, .extr },
......@@ -12213,242 +12782,169 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo
1221312782 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
1221412783 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
1221512784 17...32 => if (self.hasFeature(.avx))
12216 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
12785 return .{ .move = if (aligned)
12786 .{ .v_, .movdqa }
12787 else
12788 .{ .v_, .movdqu } },
1221712789 else => {},
12218 } else switch (abi_size) {
12219 4 => return .{ .move = if (self.hasFeature(.avx))
12220 .{ .v_ss, .mov }
12790 },
12791 16 => switch (ty.vectorLen(mod)) {
12792 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12793 .insert = .{ .vp_w, .insr },
12794 .extract = .{ .vp_w, .extr },
12795 } } else .{ .insert_extract = .{
12796 .insert = .{ .p_w, .insr },
12797 .extract = .{ .p_w, .extr },
12798 } },
12799 2 => return .{ .move = if (self.hasFeature(.avx))
12800 .{ .v_d, .mov }
1222112801 else
12222 .{ ._ss, .mov } },
12802 .{ ._d, .mov } },
12803 3...4 => return .{ .move = if (self.hasFeature(.avx))
12804 .{ .v_q, .mov }
12805 else
12806 .{ ._q, .mov } },
1222312807 5...8 => return .{ .move = if (self.hasFeature(.avx))
12224 .{ .v_sd, .mov }
12808 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12809 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12810 9...16 => if (self.hasFeature(.avx))
12811 return .{ .move = if (aligned)
12812 .{ .v_, .movdqa }
12813 else
12814 .{ .v_, .movdqu } },
12815 else => {},
12816 },
12817 32 => switch (ty.vectorLen(mod)) {
12818 1 => return .{ .move = if (self.hasFeature(.avx))
12819 .{ .v_d, .mov }
1222512820 else
12226 .{ ._sd, .mov } },
12227 9...16 => return .{ .move = if (self.hasFeature(.avx))
12228 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12229 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12230 17...32 => if (self.hasFeature(.avx)) return .{ .move = if (aligned)
12231 .{ .v_pd, .mova }
12821 .{ ._d, .mov } },
12822 2 => return .{ .move = if (self.hasFeature(.avx))
12823 .{ .v_q, .mov }
1223212824 else
12233 .{ .v_pd, .movu } },
12234 else => {},
12235 }
12236 },
12237 .Float => switch (ty.floatBits(self.target.*)) {
12238 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12239 .insert = .{ .vp_w, .insr },
12240 .extract = .{ .vp_w, .extr },
12241 } } else .{ .insert_extract = .{
12242 .insert = .{ .p_w, .insr },
12243 .extract = .{ .p_w, .extr },
12244 } },
12245 32 => return .{ .move = if (self.hasFeature(.avx))
12246 .{ .v_ss, .mov }
12247 else
12248 .{ ._ss, .mov } },
12249 64 => return .{ .move = if (self.hasFeature(.avx))
12250 .{ .v_sd, .mov }
12251 else
12252 .{ ._sd, .mov } },
12253 128 => return .{ .move = if (self.hasFeature(.avx))
12254 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12255 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12256 else => {},
12257 },
12258 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
12259 .Bool => return .{ .move = .{ ._, .mov } },
12260 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
12261 8 => switch (ty.vectorLen(mod)) {
12262 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
12263 .insert = .{ .vp_b, .insr },
12264 .extract = .{ .vp_b, .extr },
12265 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
12266 .insert = .{ .p_b, .insr },
12267 .extract = .{ .p_b, .extr },
12268 } },
12269 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12270 .insert = .{ .vp_w, .insr },
12271 .extract = .{ .vp_w, .extr },
12272 } } else .{ .insert_extract = .{
12273 .insert = .{ .p_w, .insr },
12274 .extract = .{ .p_w, .extr },
12275 } },
12276 3...4 => return .{ .move = if (self.hasFeature(.avx))
12277 .{ .v_d, .mov }
12278 else
12279 .{ ._d, .mov } },
12280 5...8 => return .{ .move = if (self.hasFeature(.avx))
12281 .{ .v_q, .mov }
12282 else
12283 .{ ._q, .mov } },
12284 9...16 => return .{ .move = if (self.hasFeature(.avx))
12285 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12286 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12287 17...32 => if (self.hasFeature(.avx))
12288 return .{ .move = if (aligned)
12289 .{ .v_, .movdqa }
12290 else
12291 .{ .v_, .movdqu } },
12292 else => {},
12293 },
12294 16 => switch (ty.vectorLen(mod)) {
12295 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12296 .insert = .{ .vp_w, .insr },
12297 .extract = .{ .vp_w, .extr },
12298 } } else .{ .insert_extract = .{
12299 .insert = .{ .p_w, .insr },
12300 .extract = .{ .p_w, .extr },
12301 } },
12302 2 => return .{ .move = if (self.hasFeature(.avx))
12303 .{ .v_d, .mov }
12304 else
12305 .{ ._d, .mov } },
12306 3...4 => return .{ .move = if (self.hasFeature(.avx))
12307 .{ .v_q, .mov }
12308 else
12309 .{ ._q, .mov } },
12310 5...8 => return .{ .move = if (self.hasFeature(.avx))
12311 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12312 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12313 9...16 => if (self.hasFeature(.avx))
12314 return .{ .move = if (aligned)
12315 .{ .v_, .movdqa }
12316 else
12317 .{ .v_, .movdqu } },
12318 else => {},
12319 },
12320 32 => switch (ty.vectorLen(mod)) {
12321 1 => return .{ .move = if (self.hasFeature(.avx))
12322 .{ .v_d, .mov }
12825 .{ ._q, .mov } },
12826 3...4 => return .{ .move = if (self.hasFeature(.avx))
12827 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12828 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12829 5...8 => if (self.hasFeature(.avx))
12830 return .{ .move = if (aligned)
12831 .{ .v_, .movdqa }
1232312832 else
12324 .{ ._d, .mov } },
12325 2 => return .{ .move = if (self.hasFeature(.avx))
12326 .{ .v_q, .mov }
12833 .{ .v_, .movdqu } },
12834 else => {},
12835 },
12836 64 => switch (ty.vectorLen(mod)) {
12837 1 => return .{ .move = if (self.hasFeature(.avx))
12838 .{ .v_q, .mov }
12839 else
12840 .{ ._q, .mov } },
12841 2 => return .{ .move = if (self.hasFeature(.avx))
12842 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12843 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12844 3...4 => if (self.hasFeature(.avx))
12845 return .{ .move = if (aligned)
12846 .{ .v_, .movdqa }
1232712847 else
12328 .{ ._q, .mov } },
12329 3...4 => return .{ .move = if (self.hasFeature(.avx))
12330 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12331 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12332 5...8 => if (self.hasFeature(.avx))
12333 return .{ .move = if (aligned)
12334 .{ .v_, .movdqa }
12335 else
12336 .{ .v_, .movdqu } },
12337 else => {},
12338 },
12339 64 => switch (ty.vectorLen(mod)) {
12340 1 => return .{ .move = if (self.hasFeature(.avx))
12341 .{ .v_q, .mov }
12848 .{ .v_, .movdqu } },
12849 else => {},
12850 },
12851 128 => switch (ty.vectorLen(mod)) {
12852 1 => return .{ .move = if (self.hasFeature(.avx))
12853 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12854 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12855 2 => if (self.hasFeature(.avx))
12856 return .{ .move = if (aligned)
12857 .{ .v_, .movdqa }
1234212858 else
12343 .{ ._q, .mov } },
12344 2 => return .{ .move = if (self.hasFeature(.avx))
12345 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12346 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12347 3...4 => if (self.hasFeature(.avx))
12348 return .{ .move = if (aligned)
12349 .{ .v_, .movdqa }
12350 else
12351 .{ .v_, .movdqu } },
12352 else => {},
12353 },
12354 128 => switch (ty.vectorLen(mod)) {
12355 1 => return .{ .move = if (self.hasFeature(.avx))
12356 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12357 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12358 2 => if (self.hasFeature(.avx))
12359 return .{ .move = if (aligned)
12360 .{ .v_, .movdqa }
12361 else
12362 .{ .v_, .movdqu } },
12363 else => {},
12364 },
12365 256 => switch (ty.vectorLen(mod)) {
12366 1 => if (self.hasFeature(.avx))
12367 return .{ .move = if (aligned)
12368 .{ .v_, .movdqa }
12369 else
12370 .{ .v_, .movdqu } },
12371 else => {},
12372 },
12859 .{ .v_, .movdqu } },
1237312860 else => {},
1237412861 },
12375 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
12376 16 => switch (ty.vectorLen(mod)) {
12377 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12378 .insert = .{ .vp_w, .insr },
12379 .extract = .{ .vp_w, .extr },
12380 } } else .{ .insert_extract = .{
12381 .insert = .{ .p_w, .insr },
12382 .extract = .{ .p_w, .extr },
12383 } },
12384 2 => return .{ .move = if (self.hasFeature(.avx))
12385 .{ .v_d, .mov }
12862 256 => switch (ty.vectorLen(mod)) {
12863 1 => if (self.hasFeature(.avx))
12864 return .{ .move = if (aligned)
12865 .{ .v_, .movdqa }
1238612866 else
12387 .{ ._d, .mov } },
12388 3...4 => return .{ .move = if (self.hasFeature(.avx))
12389 .{ .v_q, .mov }
12867 .{ .v_, .movdqu } },
12868 else => {},
12869 },
12870 else => {},
12871 },
12872 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
12873 16 => switch (ty.vectorLen(mod)) {
12874 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12875 .insert = .{ .vp_w, .insr },
12876 .extract = .{ .vp_w, .extr },
12877 } } else .{ .insert_extract = .{
12878 .insert = .{ .p_w, .insr },
12879 .extract = .{ .p_w, .extr },
12880 } },
12881 2 => return .{ .move = if (self.hasFeature(.avx))
12882 .{ .v_d, .mov }
12883 else
12884 .{ ._d, .mov } },
12885 3...4 => return .{ .move = if (self.hasFeature(.avx))
12886 .{ .v_q, .mov }
12887 else
12888 .{ ._q, .mov } },
12889 5...8 => return .{ .move = if (self.hasFeature(.avx))
12890 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12891 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12892 9...16 => if (self.hasFeature(.avx))
12893 return .{ .move = if (aligned)
12894 .{ .v_, .movdqa }
1239012895 else
12391 .{ ._q, .mov } },
12392 5...8 => return .{ .move = if (self.hasFeature(.avx))
12393 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12394 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12395 9...16 => if (self.hasFeature(.avx))
12396 return .{ .move = if (aligned)
12397 .{ .v_, .movdqa }
12398 else
12399 .{ .v_, .movdqu } },
12400 else => {},
12401 },
12402 32 => switch (ty.vectorLen(mod)) {
12403 1 => return .{ .move = if (self.hasFeature(.avx))
12404 .{ .v_ss, .mov }
12896 .{ .v_, .movdqu } },
12897 else => {},
12898 },
12899 32 => switch (ty.vectorLen(mod)) {
12900 1 => return .{ .move = if (self.hasFeature(.avx))
12901 .{ .v_ss, .mov }
12902 else
12903 .{ ._ss, .mov } },
12904 2 => return .{ .move = if (self.hasFeature(.avx))
12905 .{ .v_sd, .mov }
12906 else
12907 .{ ._sd, .mov } },
12908 3...4 => return .{ .move = if (self.hasFeature(.avx))
12909 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
12910 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } },
12911 5...8 => if (self.hasFeature(.avx))
12912 return .{ .move = if (aligned)
12913 .{ .v_ps, .mova }
1240512914 else
12406 .{ ._ss, .mov } },
12407 2 => return .{ .move = if (self.hasFeature(.avx))
12408 .{ .v_sd, .mov }
12915 .{ .v_ps, .movu } },
12916 else => {},
12917 },
12918 64 => switch (ty.vectorLen(mod)) {
12919 1 => return .{ .move = if (self.hasFeature(.avx))
12920 .{ .v_sd, .mov }
12921 else
12922 .{ ._sd, .mov } },
12923 2 => return .{ .move = if (self.hasFeature(.avx))
12924 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12925 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12926 3...4 => if (self.hasFeature(.avx))
12927 return .{ .move = if (aligned)
12928 .{ .v_pd, .mova }
1240912929 else
12410 .{ ._sd, .mov } },
12411 3...4 => return .{ .move = if (self.hasFeature(.avx))
12412 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
12413 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } },
12414 5...8 => if (self.hasFeature(.avx))
12415 return .{ .move = if (aligned)
12416 .{ .v_ps, .mova }
12417 else
12418 .{ .v_ps, .movu } },
12419 else => {},
12420 },
12421 64 => switch (ty.vectorLen(mod)) {
12422 1 => return .{ .move = if (self.hasFeature(.avx))
12423 .{ .v_sd, .mov }
12930 .{ .v_pd, .movu } },
12931 else => {},
12932 },
12933 128 => switch (ty.vectorLen(mod)) {
12934 1 => return .{ .move = if (self.hasFeature(.avx))
12935 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12936 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12937 2 => if (self.hasFeature(.avx))
12938 return .{ .move = if (aligned)
12939 .{ .v_, .movdqa }
1242412940 else
12425 .{ ._sd, .mov } },
12426 2 => return .{ .move = if (self.hasFeature(.avx))
12427 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12428 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12429 3...4 => if (self.hasFeature(.avx))
12430 return .{ .move = if (aligned)
12431 .{ .v_pd, .mova }
12432 else
12433 .{ .v_pd, .movu } },
12434 else => {},
12435 },
12436 128 => switch (ty.vectorLen(mod)) {
12437 1 => return .{ .move = if (self.hasFeature(.avx))
12438 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12439 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12440 2 => if (self.hasFeature(.avx))
12441 return .{ .move = if (aligned)
12442 .{ .v_, .movdqa }
12443 else
12444 .{ .v_, .movdqu } },
12445 else => {},
12446 },
12941 .{ .v_, .movdqu } },
1244712942 else => {},
1244812943 },
1244912944 else => {},
1245012945 },
12451 }
12946 else => {},
12947 },
1245212948 },
1245312949 }
1245412950 return self.fail("TODO moveStrategy for {}", .{ty.fmt(mod)});
......@@ -12514,32 +13010,18 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
1251413010 };
1251513011 defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
1251613012
12517 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
12518 for (dst_regs, classes, 0..) |dst_reg, class, dst_reg_i| {
12519 const class_ty = switch (class) {
12520 .integer => Type.usize,
12521 .sse, .float, .float_combine => Type.f64,
12522 else => unreachable,
12523 };
12524 const off: i32 = @intCast(dst_reg_i * 8);
12525 switch (src_mcv) {
12526 .register_pair => |src_regs| try self.genSetReg(
12527 dst_reg,
12528 class_ty,
12529 .{ .register = src_regs[dst_reg_i] },
12530 ),
12531 .memory, .indirect, .load_frame => try self.genSetReg(
12532 dst_reg,
12533 class_ty,
12534 src_mcv.address().offset(off).deref(),
12535 ),
12536 .load_symbol, .load_direct, .load_got, .load_tlv => try self.genSetReg(
12537 dst_reg,
12538 class_ty,
12539 .{ .indirect = .{ .reg = src_info.?.addr_reg, .off = off } },
12540 ),
13013 var part_disp: i32 = 0;
13014 for (dst_regs, try self.splitType(ty), 0..) |dst_reg, dst_ty, part_i| {
13015 try self.genSetReg(dst_reg, dst_ty, switch (src_mcv) {
13016 .register_pair => |src_regs| .{ .register = src_regs[part_i] },
13017 .memory, .indirect, .load_frame => src_mcv.address().offset(part_disp).deref(),
13018 .load_symbol, .load_direct, .load_got, .load_tlv => .{ .indirect = .{
13019 .reg = src_info.?.addr_reg,
13020 .off = part_disp,
13021 } },
1254113022 else => unreachable,
12542 }
13023 });
13024 part_disp += @intCast(dst_ty.abiSize(mod));
1254313025 }
1254413026 },
1254513027 .indirect => |reg_off| try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ty, src_mcv),
......@@ -12584,6 +13066,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1258413066 if (imm == 0) {
1258513067 // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit
1258613068 // register is the fastest way to zero a register.
13069 try self.spillEflagsIfOccupied();
1258713070 try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
1258813071 } else if (abi_size > 4 and math.cast(u32, imm) != null) {
1258913072 // 32-bit moves zero-extend to 64-bit.
......@@ -12933,44 +13416,65 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1293313416 .eflags => |cc| try self.asmSetccMemory(cc, .{ .base = base, .mod = .{
1293413417 .rm = .{ .size = .byte, .disp = disp },
1293513418 } }),
12936 .register => |src_reg| try (try self.moveStrategy(ty, src_reg.class(), switch (base) {
12937 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12938 .reg => |reg| switch (reg) {
12939 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12940 else => false,
12941 },
12942 .frame => |frame_index| self.getFrameAddrAlignment(
12943 .{ .index = frame_index, .off = disp },
12944 ).compare(.gte, ty.abiAlignment(mod)),
12945 .reloc => false,
12946 })).write(
12947 self,
12948 .{ .base = base, .mod = .{ .rm = .{
12949 .size = self.memSize(ty),
12950 .disp = disp,
12951 } } },
12952 registerAlias(src_reg, abi_size),
12953 ),
12954 .register_pair => |src_regs| for (src_regs, 0..) |src_reg, src_reg_i| {
12955 const part_size: u16 = @min(abi_size - src_reg_i * 8, 8);
12956 try (try self.moveStrategy(
12957 try mod.intType(.unsigned, part_size * 8),
12958 src_reg.class(),
12959 switch (base) {
12960 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12961 .reg => |reg| switch (reg) {
12962 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12963 else => false,
12964 },
12965 .frame => |frame_index| self.getFrameAddrAlignment(
12966 .{ .index = frame_index, .off = disp },
12967 ).compare(.gte, ty.abiAlignment(mod)),
12968 .reloc => false,
13419 .register => |src_reg| {
13420 const mem_size = switch (base) {
13421 .frame => |base_fi| mem_size: {
13422 assert(disp >= 0);
13423 const frame_abi_size = self.frame_allocs.items(.abi_size)[@intFromEnum(base_fi)];
13424 const frame_spill_pad = self.frame_allocs.items(.spill_pad)[@intFromEnum(base_fi)];
13425 assert(frame_abi_size - frame_spill_pad - disp >= abi_size);
13426 break :mem_size if (frame_abi_size - frame_spill_pad - disp == abi_size)
13427 frame_abi_size
13428 else
13429 abi_size;
13430 },
13431 else => abi_size,
13432 };
13433 const src_alias = registerAlias(src_reg, abi_size);
13434 const src_size: u32 = @intCast(switch (src_alias.class()) {
13435 .general_purpose, .segment, .x87 => @divExact(src_alias.bitSize(), 8),
13436 .mmx, .sse => abi_size,
13437 });
13438 if (src_size > mem_size) {
13439 const frame_index = try self.allocFrameIndex(FrameAlloc.init(.{
13440 .size = src_size,
13441 .alignment = Alignment.fromNonzeroByteUnits(src_size),
13442 }));
13443 const frame_mcv: MCValue = .{ .load_frame = .{ .index = frame_index } };
13444 try (try self.moveStrategy(ty, src_alias.class(), true)).write(
13445 self,
13446 .{ .base = .{ .frame = frame_index }, .mod = .{ .rm = .{
13447 .size = Memory.Size.fromSize(src_size),
13448 } } },
13449 src_alias,
13450 );
13451 try self.genSetMem(base, disp, ty, frame_mcv);
13452 try self.freeValue(frame_mcv);
13453 } else try (try self.moveStrategy(ty, src_alias.class(), switch (base) {
13454 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
13455 .reg => |reg| switch (reg) {
13456 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
13457 else => false,
1296913458 },
12970 )).write(self, .{ .base = base, .mod = .{ .rm = .{
12971 .size = Memory.Size.fromSize(part_size),
12972 .disp = disp + @as(i32, @intCast(src_reg_i * 8)),
12973 } } }, registerAlias(src_reg, part_size));
13459 .frame => |frame_index| self.getFrameAddrAlignment(
13460 .{ .index = frame_index, .off = disp },
13461 ).compare(.gte, ty.abiAlignment(mod)),
13462 .reloc => false,
13463 })).write(
13464 self,
13465 .{ .base = base, .mod = .{ .rm = .{
13466 .size = self.memSize(ty),
13467 .disp = disp,
13468 } } },
13469 src_alias,
13470 );
13471 },
13472 .register_pair => |src_regs| {
13473 var part_disp: i32 = disp;
13474 for (try self.splitType(ty), src_regs) |src_ty, src_reg| {
13475 try self.genSetMem(base, part_disp, src_ty, .{ .register = src_reg });
13476 part_disp += @intCast(src_ty.abiSize(mod));
13477 }
1297413478 },
1297513479 .register_overflow => |ro| switch (ty.zigTypeTag(mod)) {
1297613480 .Struct => {
......@@ -13226,50 +13730,43 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
1322613730 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
1322713731 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
1322813732
13229 const dst_mcv = if (dst_rc.supersetOf(src_rc) and
13230 self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
13231 src_mcv
13232 else dst: {
13733 const dst_mcv = if (dst_rc.supersetOf(src_rc) and dst_ty.abiSize(mod) <= src_ty.abiSize(mod) and
13734 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
1323313735 const dst_mcv = try self.allocRegOrMem(inst, true);
13234 try self.genCopy(
13235 if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,
13236 dst_mcv,
13237 src_mcv,
13238 );
13736 try self.genCopy(switch (math.order(dst_ty.abiSize(mod), src_ty.abiSize(mod))) {
13737 .lt => dst_ty,
13738 .eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,
13739 .gt => src_ty,
13740 }, dst_mcv, src_mcv);
1323913741 break :dst dst_mcv;
1324013742 };
1324113743
1324213744 if (dst_ty.isRuntimeFloat()) break :result dst_mcv;
1324313745
13244 const dst_signedness =
13245 if (dst_ty.isAbiInt(mod)) dst_ty.intInfo(mod).signedness else .unsigned;
13246 if (!src_ty.isRuntimeFloat() or src_ty.floatBits(self.target.*) != 80) {
13247 const src_signedness =
13248 if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned;
13249 if (dst_signedness == src_signedness) break :result dst_mcv;
13250 }
13746 if (dst_ty.isAbiInt(mod) and src_ty.isAbiInt(mod) and
13747 dst_ty.intInfo(mod).signedness == src_ty.intInfo(mod).signedness) break :result dst_mcv;
1325113748
13252 const abi_size: u16 = @intCast(dst_ty.abiSize(mod));
13253 const bit_size: u16 = @intCast(dst_ty.bitSize(mod));
13254 if (abi_size * 8 <= bit_size) break :result dst_mcv;
13749 const abi_size = dst_ty.abiSize(mod);
13750 const bit_size = dst_ty.bitSize(mod);
13751 if (abi_size * 8 <= bit_size or dst_ty.isVector(mod)) break :result dst_mcv;
1325513752
13256 const dst_limbs_len = math.divCeil(i32, bit_size, 64) catch unreachable;
13257 const high_reg = if (dst_mcv.isRegister())
13258 dst_mcv.getReg().?
13753 const dst_limbs_len = math.divCeil(i32, @intCast(bit_size), 64) catch unreachable;
13754 const high_mcv: MCValue = switch (dst_mcv) {
13755 .register => |dst_reg| .{ .register = dst_reg },
13756 .register_pair => |dst_regs| .{ .register = dst_regs[1] },
13757 else => dst_mcv.address().offset((dst_limbs_len - 1) * 8).deref(),
13758 };
13759 const high_reg = if (high_mcv.isRegister())
13760 high_mcv.getReg().?
1325913761 else
13260 try self.copyToTmpRegister(
13261 Type.usize,
13262 dst_mcv.address().offset((dst_limbs_len - 1) * 8).deref(),
13263 );
13762 try self.copyToTmpRegister(Type.usize, high_mcv);
1326413763 const high_lock = self.register_manager.lockReg(high_reg);
1326513764 defer if (high_lock) |lock| self.register_manager.unlockReg(lock);
1326613765
13267 const high_ty = try mod.intType(dst_signedness, bit_size % 64);
13268
13269 try self.truncateRegister(high_ty, high_reg);
13270 if (!dst_mcv.isRegister()) try self.genCopy(
13271 Type.usize,
13272 dst_mcv.address().offset((dst_limbs_len - 1) * 8).deref(),
13766 try self.truncateRegister(dst_ty, high_reg);
13767 if (!high_mcv.isRegister()) try self.genCopy(
13768 if (abi_size <= 8) dst_ty else Type.usize,
13769 high_mcv,
1327313770 .{ .register = high_reg },
1327413771 );
1327513772 break :result dst_mcv;
......@@ -13287,7 +13784,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
1328713784 const array_ty = ptr_ty.childType(mod);
1328813785 const array_len = array_ty.arrayLen(mod);
1328913786
13290 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, mod));
13787 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod));
1329113788 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);
1329213789 try self.genSetMem(
1329313790 .{ .frame = frame_index },
......@@ -13497,7 +13994,7 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
1349713994 const ptr_mcv = try self.resolveInst(extra.ptr);
1349813995 const mem_size = Memory.Size.fromSize(val_abi_size);
1349913996 const ptr_mem: Memory = switch (ptr_mcv) {
13500 .immediate, .register, .register_offset, .lea_frame => ptr_mcv.deref().mem(mem_size),
13997 .immediate, .register, .register_offset, .lea_frame => try ptr_mcv.deref().mem(self, mem_size),
1350113998 else => .{
1350213999 .base = .{ .reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv) },
1350314000 .mod = .{ .rm = .{ .size = mem_size } },
......@@ -13563,7 +14060,7 @@ fn atomicOp(
1356314060 const val_abi_size: u32 = @intCast(val_ty.abiSize(mod));
1356414061 const mem_size = Memory.Size.fromSize(val_abi_size);
1356514062 const ptr_mem: Memory = switch (ptr_mcv) {
13566 .immediate, .register, .register_offset, .lea_frame => ptr_mcv.deref().mem(mem_size),
14063 .immediate, .register, .register_offset, .lea_frame => try ptr_mcv.deref().mem(self, mem_size),
1356714064 else => .{
1356814065 .base = .{ .reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv) },
1356914066 .mod = .{ .rm = .{ .size = mem_size } },
......@@ -13671,27 +14168,41 @@ fn atomicOp(
1367114168 },
1367214169 };
1367314170
13674 try self.genBinOpMir(.{ ._, .cmp }, val_ty, tmp_mcv, val_mcv);
1367514171 const cmov_abi_size = @max(val_abi_size, 2);
1367614172 switch (val_mcv) {
13677 .register => |val_reg| try self.asmCmovccRegisterRegister(
13678 cc,
13679 registerAlias(tmp_reg, cmov_abi_size),
13680 registerAlias(val_reg, cmov_abi_size),
13681 ),
13682 .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
13683 cc,
13684 registerAlias(tmp_reg, cmov_abi_size),
13685 val_mcv.mem(Memory.Size.fromSize(cmov_abi_size)),
13686 ),
13687 else => {
13688 const val_reg = try self.copyToTmpRegister(val_ty, val_mcv);
14173 .register => |val_reg| {
14174 try self.genBinOpMir(.{ ._, .cmp }, val_ty, tmp_mcv, val_mcv);
1368914175 try self.asmCmovccRegisterRegister(
1369014176 cc,
1369114177 registerAlias(tmp_reg, cmov_abi_size),
1369214178 registerAlias(val_reg, cmov_abi_size),
1369314179 );
1369414180 },
14181 .memory, .indirect, .load_frame => {
14182 try self.genBinOpMir(.{ ._, .cmp }, val_ty, tmp_mcv, val_mcv);
14183 try self.asmCmovccRegisterMemory(
14184 cc,
14185 registerAlias(tmp_reg, cmov_abi_size),
14186 try val_mcv.mem(self, Memory.Size.fromSize(cmov_abi_size)),
14187 );
14188 },
14189 else => {
14190 const mat_reg = try self.copyToTmpRegister(val_ty, val_mcv);
14191 const mat_lock = self.register_manager.lockRegAssumeUnused(mat_reg);
14192 defer self.register_manager.unlockReg(mat_lock);
14193
14194 try self.genBinOpMir(
14195 .{ ._, .cmp },
14196 val_ty,
14197 tmp_mcv,
14198 .{ .register = mat_reg },
14199 );
14200 try self.asmCmovccRegisterRegister(
14201 cc,
14202 registerAlias(tmp_reg, cmov_abi_size),
14203 registerAlias(mat_reg, cmov_abi_size),
14204 );
14205 },
1369514206 }
1369614207 },
1369714208 };
......@@ -13728,8 +14239,8 @@ fn atomicOp(
1372814239 .reg = try self.copyToTmpRegister(Type.usize, val_mcv.address()),
1372914240 } },
1373014241 };
13731 const val_lo_mem = val_mem_mcv.mem(.qword);
13732 const val_hi_mem = val_mem_mcv.address().offset(8).deref().mem(.qword);
14242 const val_lo_mem = try val_mem_mcv.mem(self, .qword);
14243 const val_hi_mem = try val_mem_mcv.address().offset(8).deref().mem(self, .qword);
1373314244 if (rmw_op != std.builtin.AtomicRmwOp.Xchg) {
1373414245 try self.asmRegisterRegister(.{ ._, .mov }, .rbx, .rax);
1373514246 try self.asmRegisterRegister(.{ ._, .mov }, .rcx, .rdx);
......@@ -14000,7 +14511,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
1400014511 try self.asmRegisterMemoryImmediate(
1400114512 .{ .i_, .mul },
1400214513 len_reg,
14003 dst_ptr.address().offset(8).deref().mem(.qword),
14514 try dst_ptr.address().offset(8).deref().mem(self, .qword),
1400414515 Immediate.s(@intCast(dst_ptr_ty.childType(mod).abiSize(mod))),
1400514516 );
1400614517 break :len .{ .register = len_reg };
......@@ -14171,28 +14682,162 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1417114682 const mod = self.bin_file.options.module.?;
1417214683 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1417314684 const vector_ty = self.typeOfIndex(inst);
14685 const vector_len = vector_ty.vectorLen(mod);
1417414686 const dst_rc = self.regClassForType(vector_ty);
14175 const scalar_ty = vector_ty.scalarType(mod);
14687 const scalar_ty = self.typeOf(ty_op.operand);
1417614688
14177 const src_mcv = try self.resolveInst(ty_op.operand);
1417814689 const result: MCValue = result: {
1417914690 switch (scalar_ty.zigTypeTag(mod)) {
1418014691 else => {},
14692 .Bool => {
14693 const regs =
14694 try self.register_manager.allocRegs(2, .{ inst, null }, abi.RegisterClass.gp);
14695 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, regs);
14696 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
14697
14698 try self.genSetReg(regs[1], vector_ty, .{ .immediate = 0 });
14699 try self.genSetReg(
14700 regs[1],
14701 vector_ty,
14702 .{ .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - vector_len) },
14703 );
14704 const src_mcv = try self.resolveInst(ty_op.operand);
14705 const abi_size = @max(math.divCeil(u32, vector_len, 8) catch unreachable, 4);
14706 try self.asmCmovccRegisterRegister(
14707 switch (src_mcv) {
14708 .eflags => |cc| cc,
14709 .register => |src_reg| cc: {
14710 try self.asmRegisterImmediate(
14711 .{ ._, .@"test" },
14712 src_reg.to8(),
14713 Immediate.u(1),
14714 );
14715 break :cc .nz;
14716 },
14717 else => cc: {
14718 try self.asmMemoryImmediate(
14719 .{ ._, .@"test" },
14720 try src_mcv.mem(self, .byte),
14721 Immediate.u(1),
14722 );
14723 break :cc .nz;
14724 },
14725 },
14726 registerAlias(regs[0], abi_size),
14727 registerAlias(regs[1], abi_size),
14728 );
14729 break :result .{ .register = regs[0] };
14730 },
14731 .Int => if (self.hasFeature(.avx2)) avx2: {
14732 const mir_tag = @as(?Mir.Inst.FixedTag, switch (scalar_ty.intInfo(mod).bits) {
14733 else => null,
14734 1...8 => switch (vector_len) {
14735 else => null,
14736 1...32 => .{ .vp_b, .broadcast },
14737 },
14738 9...16 => switch (vector_len) {
14739 else => null,
14740 1...16 => .{ .vp_w, .broadcast },
14741 },
14742 17...32 => switch (vector_len) {
14743 else => null,
14744 1...8 => .{ .vp_d, .broadcast },
14745 },
14746 33...64 => switch (vector_len) {
14747 else => null,
14748 1...4 => .{ .vp_q, .broadcast },
14749 },
14750 65...128 => switch (vector_len) {
14751 else => null,
14752 1...2 => .{ .vp_i128, .broadcast },
14753 },
14754 }) orelse break :avx2;
14755
14756 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.sse);
14757 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
14758 defer self.register_manager.unlockReg(dst_lock);
14759
14760 const src_mcv = try self.resolveInst(ty_op.operand);
14761 if (src_mcv.isMemory()) try self.asmRegisterMemory(
14762 mir_tag,
14763 registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod))),
14764 try src_mcv.mem(self, self.memSize(scalar_ty)),
14765 ) else {
14766 if (mir_tag[0] == .vp_i128) break :avx2;
14767 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
14768 try self.asmRegisterRegister(
14769 mir_tag,
14770 registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod))),
14771 registerAlias(dst_reg, @intCast(scalar_ty.abiSize(mod))),
14772 );
14773 }
14774 break :result .{ .register = dst_reg };
14775 } else {
14776 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.sse);
14777 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
14778 defer self.register_manager.unlockReg(dst_lock);
14779
14780 try self.genSetReg(dst_reg, scalar_ty, .{ .air_ref = ty_op.operand });
14781 if (vector_len == 1) break :result .{ .register = dst_reg };
14782
14783 const dst_alias = registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod)));
14784 const scalar_bits = scalar_ty.intInfo(mod).bits;
14785 if (switch (scalar_bits) {
14786 1...8 => true,
14787 9...128 => false,
14788 else => unreachable,
14789 }) if (self.hasFeature(.avx)) try self.asmRegisterRegisterRegister(
14790 .{ .vp_, .unpcklbw },
14791 dst_alias,
14792 dst_alias,
14793 dst_alias,
14794 ) else try self.asmRegisterRegister(
14795 .{ .p_, .unpcklbw },
14796 dst_alias,
14797 dst_alias,
14798 );
14799 if (switch (scalar_bits) {
14800 1...8 => vector_len > 2,
14801 9...16 => true,
14802 17...128 => false,
14803 else => unreachable,
14804 }) try self.asmRegisterRegisterImmediate(
14805 .{ if (self.hasFeature(.avx)) .vp_w else .p_w, .shufl },
14806 dst_alias,
14807 dst_alias,
14808 Immediate.u(0),
14809 );
14810 if (switch (scalar_bits) {
14811 1...8 => vector_len > 4,
14812 9...16 => vector_len > 2,
14813 17...64 => true,
14814 65...128 => false,
14815 else => unreachable,
14816 }) try self.asmRegisterRegisterImmediate(
14817 .{ if (self.hasFeature(.avx)) .vp_d else .p_d, .shuf },
14818 dst_alias,
14819 dst_alias,
14820 Immediate.u(if (scalar_bits <= 64) 0b00_00_00_00 else 0b01_00_01_00),
14821 );
14822 break :result .{ .register = dst_reg };
14823 },
1418114824 .Float => switch (scalar_ty.floatBits(self.target.*)) {
14182 32 => switch (vector_ty.vectorLen(mod)) {
14825 32 => switch (vector_len) {
1418314826 1 => {
14827 const src_mcv = try self.resolveInst(ty_op.operand);
1418414828 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
1418514829 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1418614830 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
1418714831 break :result .{ .register = dst_reg };
1418814832 },
1418914833 2...4 => {
14834 const src_mcv = try self.resolveInst(ty_op.operand);
1419014835 if (self.hasFeature(.avx)) {
1419114836 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1419214837 if (src_mcv.isMemory()) try self.asmRegisterMemory(
1419314838 .{ .v_ss, .broadcast },
1419414839 dst_reg.to128(),
14195 src_mcv.mem(.dword),
14840 try src_mcv.mem(self, .dword),
1419614841 ) else {
1419714842 const src_reg = if (src_mcv.isRegister())
1419814843 src_mcv.getReg().?
......@@ -14224,11 +14869,12 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1422414869 }
1422514870 },
1422614871 5...8 => if (self.hasFeature(.avx)) {
14872 const src_mcv = try self.resolveInst(ty_op.operand);
1422714873 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1422814874 if (src_mcv.isMemory()) try self.asmRegisterMemory(
1422914875 .{ .v_ss, .broadcast },
1423014876 dst_reg.to256(),
14231 src_mcv.mem(.dword),
14877 try src_mcv.mem(self, .dword),
1423214878 ) else {
1423314879 const src_reg = if (src_mcv.isRegister())
1423414880 src_mcv.getReg().?
......@@ -14259,20 +14905,22 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1425914905 },
1426014906 else => {},
1426114907 },
14262 64 => switch (vector_ty.vectorLen(mod)) {
14908 64 => switch (vector_len) {
1426314909 1 => {
14910 const src_mcv = try self.resolveInst(ty_op.operand);
1426414911 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
1426514912 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1426614913 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
1426714914 break :result .{ .register = dst_reg };
1426814915 },
1426914916 2 => {
14917 const src_mcv = try self.resolveInst(ty_op.operand);
1427014918 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1427114919 if (self.hasFeature(.sse3)) {
1427214920 if (src_mcv.isMemory()) try self.asmRegisterMemory(
1427314921 if (self.hasFeature(.avx)) .{ .v_, .movddup } else .{ ._, .movddup },
1427414922 dst_reg.to128(),
14275 src_mcv.mem(.qword),
14923 try src_mcv.mem(self, .qword),
1427614924 ) else try self.asmRegisterRegister(
1427714925 if (self.hasFeature(.avx)) .{ .v_, .movddup } else .{ ._, .movddup },
1427814926 dst_reg.to128(),
......@@ -14292,11 +14940,12 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1429214940 );
1429314941 },
1429414942 3...4 => if (self.hasFeature(.avx)) {
14943 const src_mcv = try self.resolveInst(ty_op.operand);
1429514944 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1429614945 if (src_mcv.isMemory()) try self.asmRegisterMemory(
1429714946 .{ .v_sd, .broadcast },
1429814947 dst_reg.to256(),
14299 src_mcv.mem(.qword),
14948 try src_mcv.mem(self, .qword),
1430014949 ) else {
1430114950 const src_reg = if (src_mcv.isRegister())
1430214951 src_mcv.getReg().?
......@@ -14325,19 +14974,21 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1432514974 },
1432614975 else => {},
1432714976 },
14328 128 => switch (vector_ty.vectorLen(mod)) {
14977 128 => switch (vector_len) {
1432914978 1 => {
14979 const src_mcv = try self.resolveInst(ty_op.operand);
1433014980 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
1433114981 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1433214982 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
1433314983 break :result .{ .register = dst_reg };
1433414984 },
1433514985 2 => if (self.hasFeature(.avx)) {
14986 const src_mcv = try self.resolveInst(ty_op.operand);
1433614987 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1433714988 if (src_mcv.isMemory()) try self.asmRegisterMemory(
1433814989 .{ .v_f128, .broadcast },
1433914990 dst_reg.to256(),
14340 src_mcv.mem(.xword),
14991 try src_mcv.mem(self, .xword),
1434114992 ) else {
1434214993 const src_reg = if (src_mcv.isRegister())
1434314994 src_mcv.getReg().?
......@@ -14389,7 +15040,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
1438915040 try self.spillEflagsIfOccupied();
1439015041
1439115042 const operand_mcv = try self.resolveInst(reduce.operand);
14392 const mask_len = (std.math.cast(u6, operand_ty.vectorLen(mod)) orelse
15043 const mask_len = (math.cast(u6, operand_ty.vectorLen(mod)) orelse
1439315044 return self.fail("TODO implement airReduce for {}", .{operand_ty.fmt(mod)}));
1439415045 const mask = (@as(u64, 1) << mask_len) - 1;
1439515046 const abi_size: u32 = @intCast(operand_ty.abiSize(mod));
......@@ -14397,7 +15048,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
1439715048 .Or => {
1439815049 if (operand_mcv.isMemory()) try self.asmMemoryImmediate(
1439915050 .{ ._, .@"test" },
14400 operand_mcv.mem(Memory.Size.fromSize(abi_size)),
15051 try operand_mcv.mem(self, Memory.Size.fromSize(abi_size)),
1440115052 Immediate.u(mask),
1440215053 ) else {
1440315054 const operand_reg = registerAlias(if (operand_mcv.isRegister())
......@@ -14445,8 +15096,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1444515096 const result: MCValue = result: {
1444615097 switch (result_ty.zigTypeTag(mod)) {
1444715098 .Struct => {
14448 const frame_index =
14449 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));
15099 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod));
1445015100 if (result_ty.containerLayout(mod) == .Packed) {
1445115101 const struct_type = mod.typeToStruct(result_ty).?;
1445215102 try self.genInlineMemset(
......@@ -14542,8 +15192,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1454215192 break :result .{ .load_frame = .{ .index = frame_index } };
1454315193 },
1454415194 .Array => {
14545 const frame_index =
14546 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));
15195 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod));
1454715196 const elem_ty = result_ty.childType(mod);
1454815197 const elem_size: u32 = @intCast(elem_ty.abiSize(mod));
1454915198
......@@ -14789,7 +15438,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1478915438 mir_tag,
1479015439 mop1_reg,
1479115440 mop2_reg,
14792 mops[2].mem(Memory.Size.fromSize(abi_size)),
15441 try mops[2].mem(self, Memory.Size.fromSize(abi_size)),
1479315442 );
1479415443 break :result mops[0];
1479515444 };
......@@ -14807,7 +15456,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {
1480715456 )) {
1480815457 .SysV => result: {
1480915458 const info = self.va_info.sysv;
14810 const dst_fi = try self.allocFrameIndex(FrameAlloc.initType(va_list_ty, mod));
15459 const dst_fi = try self.allocFrameIndex(FrameAlloc.initSpill(va_list_ty, mod));
1481115460 var field_off: u31 = 0;
1481215461 // gp_offset: c_uint,
1481315462 try self.genSetMem(
......@@ -15015,7 +15664,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1501515664 .{ .v_ss, .cvtsd2 },
1501615665 dst_reg,
1501715666 dst_reg,
15018 promote_mcv.mem(.qword),
15667 try promote_mcv.mem(self, .qword),
1501915668 ) else try self.asmRegisterRegisterRegister(
1502015669 .{ .v_ss, .cvtsd2 },
1502115670 dst_reg,
......@@ -15027,7 +15676,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1502715676 ) else if (promote_mcv.isMemory()) try self.asmRegisterMemory(
1502815677 .{ ._ss, .cvtsd2 },
1502915678 dst_reg,
15030 promote_mcv.mem(.qword),
15679 try promote_mcv.mem(self, .qword),
1503115680 ) else try self.asmRegisterRegister(
1503215681 .{ ._ss, .cvtsd2 },
1503315682 dst_reg,
......@@ -15473,6 +16122,33 @@ fn memSize(self: *Self, ty: Type) Memory.Size {
1547316122 };
1547416123}
1547516124
16125fn splitType(self: *Self, ty: Type) ![2]Type {
16126 const mod = self.bin_file.options.module.?;
16127 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
16128 var parts: [2]Type = undefined;
16129 if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| {
16130 part.* = switch (class) {
16131 .integer => switch (part_i) {
16132 0 => Type.u64,
16133 1 => part: {
16134 const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnitsOptional().?;
16135 const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8));
16136 break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) {
16137 1 => elem_ty,
16138 else => |len| try mod.arrayType(.{ .len = len, .child = elem_ty.toIntern() }),
16139 };
16140 },
16141 else => unreachable,
16142 },
16143 .float => Type.f32,
16144 .float_combine => try mod.vectorType(.{ .len = 2, .child = .f32_type }),
16145 .sse => Type.f64,
16146 else => break,
16147 };
16148 } else if (parts[0].abiSize(mod) + parts[1].abiSize(mod) == ty.abiSize(mod)) return parts;
16149 return self.fail("TODO implement splitType for {}", .{ty.fmt(mod)});
16150}
16151
1547616152/// Truncates the value in the register in place.
1547716153/// Clobbers any remaining bits.
1547816154fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
src/arch/x86_64/Encoding.zig+10-8
......@@ -410,6 +410,8 @@ pub const Mnemonic = enum {
410410 vfmadd132ps, vfmadd213ps, vfmadd231ps,
411411 vfmadd132sd, vfmadd213sd, vfmadd231sd,
412412 vfmadd132ss, vfmadd213ss, vfmadd231ss,
413 // AVX2
414 vpbroadcastb, vpbroadcastd, vpbroadcasti128, vpbroadcastq, vpbroadcastw,
413415 // zig fmt: on
414416};
415417
......@@ -444,7 +446,7 @@ pub const Op = enum {
444446 moffs,
445447 sreg,
446448 st, mm, mm_m64,
447 xmm0, xmm, xmm_m32, xmm_m64, xmm_m128,
449 xmm0, xmm, xmm_m8, xmm_m16, xmm_m32, xmm_m64, xmm_m128,
448450 ymm, ymm_m256,
449451 // zig fmt: on
450452
......@@ -534,7 +536,7 @@ pub const Op = enum {
534536 .eax, .r32, .rm32, .r32_m16 => unreachable,
535537 .rax, .r64, .rm64, .r64_m16 => unreachable,
536538 .st, .mm, .mm_m64 => unreachable,
537 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,
539 .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,
538540 .ymm, .ymm_m256 => unreachable,
539541 .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable,
540542 .unity => 1,
......@@ -556,7 +558,7 @@ pub const Op = enum {
556558 .eax, .r32, .rm32, .r32_m8, .r32_m16 => 32,
557559 .rax, .r64, .rm64, .r64_m16, .mm, .mm_m64 => 64,
558560 .st => 80,
559 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => 128,
561 .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128 => 128,
560562 .ymm, .ymm_m256 => 256,
561563 };
562564 }
......@@ -568,8 +570,8 @@ pub const Op = enum {
568570 .rel8, .rel16, .rel32 => unreachable,
569571 .al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64 => unreachable,
570572 .st, .mm, .xmm0, .xmm, .ymm => unreachable,
571 .m8, .rm8, .r32_m8 => 8,
572 .m16, .rm16, .r32_m16, .r64_m16 => 16,
573 .m8, .rm8, .r32_m8, .xmm_m8 => 8,
574 .m16, .rm16, .r32_m16, .r64_m16, .xmm_m16 => 16,
573575 .m32, .rm32, .xmm_m32 => 32,
574576 .m64, .rm64, .mm_m64, .xmm_m64 => 64,
575577 .m80 => 80,
......@@ -600,7 +602,7 @@ pub const Op = enum {
600602 .rm8, .rm16, .rm32, .rm64,
601603 .r32_m8, .r32_m16, .r64_m16,
602604 .st, .mm, .mm_m64,
603 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128,
605 .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128,
604606 .ymm, .ymm_m256,
605607 => true,
606608 else => false,
......@@ -629,7 +631,7 @@ pub const Op = enum {
629631 .m8, .m16, .m32, .m64, .m80, .m128, .m256,
630632 .m,
631633 .mm_m64,
632 .xmm_m32, .xmm_m64, .xmm_m128,
634 .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128,
633635 .ymm_m256,
634636 => true,
635637 else => false,
......@@ -654,7 +656,7 @@ pub const Op = enum {
654656 .sreg => .segment,
655657 .st => .x87,
656658 .mm, .mm_m64 => .mmx,
657 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,
659 .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,
658660 .ymm, .ymm_m256 => .sse,
659661 };
660662 }
src/arch/x86_64/Mir.zig+2
......@@ -255,6 +255,8 @@ pub const Inst = struct {
255255 vp_q,
256256 /// VEX-Encoded Packed ___ Double Quadword
257257 vp_dq,
258 /// VEX-Encoded Packed ___ Integer Data
259 vp_i128,
258260 /// VEX-Encoded ___ Scalar Single-Precision Values
259261 v_ss,
260262 /// VEX-Encoded ___ Packed Single-Precision Values
src/arch/x86_64/bits.zig+1-1
......@@ -237,7 +237,7 @@ pub const Register = enum(u7) {
237237 return @intCast(@intFromEnum(reg) - base);
238238 }
239239
240 pub fn bitSize(reg: Register) u64 {
240 pub fn bitSize(reg: Register) u10 {
241241 return switch (@intFromEnum(reg)) {
242242 // zig fmt: off
243243 @intFromEnum(Register.rax) ... @intFromEnum(Register.r15) => 64,
src/arch/x86_64/encodings.zig+10
......@@ -1742,6 +1742,16 @@ pub const table = [_]Entry{
17421742
17431743 .{ .vpandn, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xdf }, 0, .vex_256_wig, .avx2 },
17441744
1745 .{ .vpbroadcastb, .rm, &.{ .xmm, .xmm_m8 }, &.{ 0x66, 0x0f, 0x38, 0x78 }, 0, .vex_128_w0, .avx2 },
1746 .{ .vpbroadcastb, .rm, &.{ .ymm, .xmm_m8 }, &.{ 0x66, 0x0f, 0x38, 0x78 }, 0, .vex_256_w0, .avx2 },
1747 .{ .vpbroadcastw, .rm, &.{ .xmm, .xmm_m16 }, &.{ 0x66, 0x0f, 0x38, 0x79 }, 0, .vex_128_w0, .avx2 },
1748 .{ .vpbroadcastw, .rm, &.{ .ymm, .xmm_m16 }, &.{ 0x66, 0x0f, 0x38, 0x79 }, 0, .vex_256_w0, .avx2 },
1749 .{ .vpbroadcastd, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0x66, 0x0f, 0x38, 0x58 }, 0, .vex_128_w0, .avx2 },
1750 .{ .vpbroadcastd, .rm, &.{ .ymm, .xmm_m32 }, &.{ 0x66, 0x0f, 0x38, 0x58 }, 0, .vex_256_w0, .avx2 },
1751 .{ .vpbroadcastq, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x38, 0x59 }, 0, .vex_128_w0, .avx2 },
1752 .{ .vpbroadcastq, .rm, &.{ .ymm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x38, 0x59 }, 0, .vex_256_w0, .avx2 },
1753 .{ .vpbroadcasti128, .rm, &.{ .ymm, .m128 }, &.{ 0x66, 0x0f, 0x38, 0x5a }, 0, .vex_256_w0, .avx2 },
1754
17451755 .{ .vpcmpeqb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x74 }, 0, .vex_256_wig, .avx2 },
17461756 .{ .vpcmpeqw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x75 }, 0, .vex_256_wig, .avx2 },
17471757 .{ .vpcmpeqd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x76 }, 0, .vex_256_wig, .avx2 },
src/codegen.zig+4-1
......@@ -376,7 +376,10 @@ pub fn generateSymbol(
376376 .val = switch (aggregate.storage) {
377377 .bytes => unreachable,
378378 .elems => |elems| elems[@as(usize, @intCast(index))],
379 .repeated_elem => |elem| elem,
379 .repeated_elem => |elem| if (index < array_type.len)
380 elem
381 else
382 array_type.sentinel,
380383 }.toValue(),
381384 }, code, debug_output, reloc_info)) {
382385 .ok => {},
src/link/Coff.zig+1
......@@ -388,6 +388,7 @@ fn populateMissingMetadata(self: *Coff) !void {
388388 self.rdata_section_index = try self.allocateSection(".rdata", file_size, .{
389389 .CNT_INITIALIZED_DATA = 1,
390390 .MEM_READ = 1,
391 .MEM_WRITE = 1,
391392 });
392393 }
393394
test/behavior/vector.zig-1
......@@ -1260,7 +1260,6 @@ test "zero multiplicand" {
12601260
12611261test "@intCast to u0" {
12621262 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1263 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12641263 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12651264 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12661265 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO