From fc5209c139c4905ff697a664da5f4cc099184d7e Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Tue, 22 Nov 2022 23:44:12 +0200 Subject: [PATCH] llvm: fix x86_64 sysV ABI of big vectors on avx512 enabled CPUs Closes #13629 --- src/arch/x86_64/abi.zig | 22 +++++++++++++++++----- test/c_abi/main.zig | 4 ---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/arch/x86_64/abi.zig b/src/arch/x86_64/abi.zig index dd1ee9f86c..b0b9848de0 100644 --- a/src/arch/x86_64/abi.zig +++ b/src/arch/x86_64/abi.zig @@ -60,7 +60,7 @@ pub fn classifyWindows(ty: Type, target: Target) Class { } } -pub const Context = enum { ret, arg }; +pub const Context = enum { ret, arg, other }; /// There are a maximum of 8 possible return slots. Returned values are in /// the beginning of the array; unused slots are filled with .none. @@ -138,7 +138,18 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { const elem_ty = ty.childType(); if (ctx == .arg) { const bit_size = ty.bitSize(target); - if (bit_size > 128) return memory_class; + if (bit_size > 128) { + const has_avx512 = target.cpu.features.isEnabled(@enumToInt(std.Target.x86.Feature.avx512f)); + if (has_avx512 and bit_size <= 512) return .{ + .integer, .integer, .integer, .integer, + .integer, .integer, .integer, .integer, + }; + if (has_avx512 and bit_size <= 256) return .{ + .integer, .integer, .integer, .integer, + .none, .none, .none, .none, + }; + return memory_class; + } if (bit_size > 80) return .{ .integer, .integer, .none, .none, .none, .none, .none, .none, @@ -181,7 +192,8 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { .sse, .sseup, .sseup, .sseup, .sseup, .sseup, .sseup, .none, }; - if (bits <= 512) return .{ + // LLVM always returns vectors byval + if (bits <= 512 or ctx == .ret) return .{ .sse, .sseup, .sseup, .sseup, .sseup, .sseup, .sseup, .sseup, }; @@ -219,7 +231,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { } } const field_size = field.ty.abiSize(target); - const field_class_array = classifySystemV(field.ty, target, .arg); + const field_class_array = classifySystemV(field.ty, target, .other); const field_class = std.mem.sliceTo(&field_class_array, .none); if (byte_i + field_size <= 8) { // Combine this field with the previous one. @@ -333,7 +345,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class { } } // Combine this field with the previous one. - const field_class = classifySystemV(field.ty, target, .arg); + const field_class = classifySystemV(field.ty, target, .other); for (result) |*result_item, i| { const field_item = field_class[i]; // "If both classes are equal, this is the resulting class." diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 2355ec645b..47f0455744 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -808,10 +808,6 @@ extern fn c_ret_big_vec() BigVec; test "big simd vector" { if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest; - if (true) { - // https://github.com/ziglang/zig/issues/13629 - return error.SkipZigTest; - } c_big_vec(.{ 1, 2, 3, 4, 5, 6, 7, 8 });