x86_64: implement integer @reduce(.Add)

This commit is contained in:
Jacob Young 2025-05-21 12:15:03 -04:00
parent d69f4c48fc
commit 1f6f8b0ffe
16 changed files with 3088 additions and 112 deletions

View File

@ -607,7 +607,7 @@ const Date = struct {
while (month < date.month) : (month += 1) { while (month < date.month) : (month += 1) {
const days: u64 = std.time.epoch.getDaysInMonth( const days: u64 = std.time.epoch.getDaysInMonth(
date.year, date.year,
@as(std.time.epoch.Month, @enumFromInt(month)), @enumFromInt(month),
); );
sec += days * std.time.epoch.secs_per_day; sec += days * std.time.epoch.secs_per_day;
} }
@ -623,15 +623,13 @@ const Date = struct {
}; };
pub fn parseTimeDigits(text: *const [2]u8, min: u8, max: u8) !u8 { pub fn parseTimeDigits(text: *const [2]u8, min: u8, max: u8) !u8 {
const result = if (use_vectors) result: {
const nn: @Vector(2, u16) = .{ text[0], text[1] }; const nn: @Vector(2, u16) = .{ text[0], text[1] };
const zero: @Vector(2, u16) = .{ '0', '0' }; const zero: @Vector(2, u16) = .{ '0', '0' };
const mm: @Vector(2, u16) = .{ 10, 1 }; const mm: @Vector(2, u16) = .{ 10, 1 };
break :result @reduce(.Add, (nn -% zero) *% mm); const result = @reduce(.Add, (nn -% zero) *% mm);
} else std.fmt.parseInt(u8, text, 10) catch return error.CertificateTimeInvalid;
if (result < min) return error.CertificateTimeInvalid; if (result < min) return error.CertificateTimeInvalid;
if (result > max) return error.CertificateTimeInvalid; if (result > max) return error.CertificateTimeInvalid;
return @truncate(result); return @intCast(result);
} }
test parseTimeDigits { test parseTimeDigits {
@ -647,14 +645,12 @@ test parseTimeDigits {
} }
pub fn parseYear4(text: *const [4]u8) !u16 { pub fn parseYear4(text: *const [4]u8) !u16 {
const result = if (use_vectors) result: {
const nnnn: @Vector(4, u32) = .{ text[0], text[1], text[2], text[3] }; const nnnn: @Vector(4, u32) = .{ text[0], text[1], text[2], text[3] };
const zero: @Vector(4, u32) = .{ '0', '0', '0', '0' }; const zero: @Vector(4, u32) = .{ '0', '0', '0', '0' };
const mmmm: @Vector(4, u32) = .{ 1000, 100, 10, 1 }; const mmmm: @Vector(4, u32) = .{ 1000, 100, 10, 1 };
break :result @reduce(.Add, (nnnn -% zero) *% mmmm); const result = @reduce(.Add, (nnnn -% zero) *% mmmm);
} else std.fmt.parseInt(u16, text, 10) catch return error.CertificateTimeInvalid;
if (result > 9999) return error.CertificateTimeInvalid; if (result > 9999) return error.CertificateTimeInvalid;
return @truncate(result); return @intCast(result);
} }
test parseYear4 { test parseYear4 {
@ -858,7 +854,7 @@ pub const der = struct {
pub fn parse(bytes: []const u8, index: u32) Element.ParseError!Element { pub fn parse(bytes: []const u8, index: u32) Element.ParseError!Element {
var i = index; var i = index;
const identifier = @as(Identifier, @bitCast(bytes[i])); const identifier: Identifier = @bitCast(bytes[i]);
i += 1; i += 1;
const size_byte = bytes[i]; const size_byte = bytes[i];
i += 1; i += 1;
@ -872,7 +868,7 @@ pub const der = struct {
}; };
} }
const len_size = @as(u7, @truncate(size_byte)); const len_size: u7 = @truncate(size_byte);
if (len_size > @sizeOf(u32)) { if (len_size > @sizeOf(u32)) {
return error.CertificateFieldHasInvalidLength; return error.CertificateFieldHasInvalidLength;
} }
@ -1244,5 +1240,3 @@ pub const rsa = struct {
return res; return res;
} }
}; };
const use_vectors = @import("builtin").zig_backend != .stage2_x86_64;

View File

@ -13,7 +13,6 @@ const net = std.net;
const Uri = std.Uri; const Uri = std.Uri;
const Allocator = mem.Allocator; const Allocator = mem.Allocator;
const assert = std.debug.assert; const assert = std.debug.assert;
const use_vectors = builtin.zig_backend != .stage2_x86_64;
const Client = @This(); const Client = @This();
const proto = @import("protocol.zig"); const proto = @import("protocol.zig");
@ -594,13 +593,10 @@ pub const Response = struct {
} }
fn parseInt3(text: *const [3]u8) u10 { fn parseInt3(text: *const [3]u8) u10 {
if (use_vectors) {
const nnn: @Vector(3, u8) = text.*; const nnn: @Vector(3, u8) = text.*;
const zero: @Vector(3, u8) = .{ '0', '0', '0' }; const zero: @Vector(3, u8) = .{ '0', '0', '0' };
const mmm: @Vector(3, u10) = .{ 100, 10, 1 }; const mmm: @Vector(3, u10) = .{ 100, 10, 1 };
return @reduce(.Add, @as(@Vector(3, u10), nnn -% zero) *% mmm); return @reduce(.Add, (nnn -% zero) *% mmm);
}
return std.fmt.parseInt(u10, text, 10) catch unreachable;
} }
test parseInt3 { test parseInt3 {
@ -1796,5 +1792,6 @@ pub fn fetch(client: *Client, options: FetchOptions) !FetchResult {
} }
test { test {
_ = Response;
_ = &initDefaultProxies; _ = &initDefaultProxies;
} }

View File

@ -109,27 +109,21 @@ pub fn feed(p: *HeadParser, bytes: []const u8) usize {
continue; continue;
}, },
else => { else => {
const chunk = bytes[index..][0..vector_len];
const matches = if (use_vectors) matches: {
const Vector = @Vector(vector_len, u8); const Vector = @Vector(vector_len, u8);
// const BoolVector = @Vector(vector_len, bool); // const BoolVector = @Vector(vector_len, bool);
const BitVector = @Vector(vector_len, u1); const BitVector = @Vector(vector_len, u1);
const SizeVector = @Vector(vector_len, u8); const SizeVector = @Vector(vector_len, u8);
const chunk = bytes[index..][0..vector_len];
const v: Vector = chunk.*; const v: Vector = chunk.*;
const matches_r: BitVector = @bitCast(v == @as(Vector, @splat('\r'))); // depends on https://github.com/ziglang/zig/issues/19755
const matches_n: BitVector = @bitCast(v == @as(Vector, @splat('\n'))); // const matches_r: BitVector = @bitCast(v == @as(Vector, @splat('\r')));
// const matches_n: BitVector = @bitCast(v == @as(Vector, @splat('\n')));
const matches_r: BitVector = @select(u1, v == @as(Vector, @splat('\r')), @as(Vector, @splat(1)), @as(Vector, @splat(0)));
const matches_n: BitVector = @select(u1, v == @as(Vector, @splat('\n')), @as(Vector, @splat(1)), @as(Vector, @splat(0)));
const matches_or: SizeVector = matches_r | matches_n; const matches_or: SizeVector = matches_r | matches_n;
break :matches @reduce(.Add, matches_or); const matches = @reduce(.Add, matches_or);
} else matches: {
var matches: u8 = 0;
for (chunk) |byte| switch (byte) {
'\r', '\n' => matches += 1,
else => {},
};
break :matches matches;
};
switch (matches) { switch (matches) {
0 => {}, 0 => {},
1 => switch (chunk[vector_len - 1]) { 1 => switch (chunk[vector_len - 1]) {
@ -357,7 +351,6 @@ inline fn intShift(comptime T: type, x: anytype) T {
const HeadParser = @This(); const HeadParser = @This();
const std = @import("std"); const std = @import("std");
const use_vectors = builtin.zig_backend != .stage2_x86_64;
const builtin = @import("builtin"); const builtin = @import("builtin");
test feed { test feed {

View File

@ -3091,7 +3091,6 @@ test "std.zon free on error" {
test "std.zon vector" { test "std.zon vector" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15330 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15330
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15329
const gpa = std.testing.allocator; const gpa = std.testing.allocator;

File diff suppressed because it is too large Load Diff

View File

@ -970,7 +970,6 @@ test "store array of array of structs at comptime" {
} }
test "accessing multidimensional global array at comptime" { test "accessing multidimensional global array at comptime" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;

View File

@ -2714,7 +2714,6 @@ test "result type is preserved into comptime block" {
} }
test "bitcast vector" { test "bitcast vector" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO

View File

@ -1164,7 +1164,6 @@ test "assignment to non-byte-aligned field in packed struct" {
} }
test "packed struct field pointer aligned properly" { test "packed struct field pointer aligned properly" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO

View File

@ -326,7 +326,6 @@ test "lazy abi size used in comparison" {
} }
test "peer type resolution with @TypeOf doesn't trigger dependency loop check" { test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;

View File

@ -994,7 +994,6 @@ test "modify slice length at comptime" {
} }
test "slicing zero length array field of struct" { test "slicing zero length array field of struct" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
@ -1011,7 +1010,6 @@ test "slicing zero length array field of struct" {
} }
test "slicing slices gives correct result" { test "slicing slices gives correct result" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
@ -1026,7 +1024,6 @@ test "slicing slices gives correct result" {
} }
test "get address of element of zero-sized slice" { test "get address of element of zero-sized slice" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
@ -1040,7 +1037,6 @@ test "get address of element of zero-sized slice" {
} }
test "sentinel-terminated 0-length slices" { test "sentinel-terminated 0-length slices" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;

View File

@ -1835,7 +1835,6 @@ test "tuple with comptime-only field" {
} }
test "extern struct fields are aligned to 1" { test "extern struct fields are aligned to 1" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
@ -1905,7 +1904,6 @@ test "array of structs inside struct initialized with undefined" {
} }
test "runtime call in nested initializer" { test "runtime call in nested initializer" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
@ -1938,7 +1936,6 @@ test "runtime call in nested initializer" {
} }
test "runtime value in nested initializer passed as pointer to function" { test "runtime value in nested initializer passed as pointer to function" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
@ -1963,7 +1960,6 @@ test "runtime value in nested initializer passed as pointer to function" {
} }
test "struct field default value is a call" { test "struct field default value is a call" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO

View File

@ -47,7 +47,6 @@ test "try then not executed with assignment" {
} }
test "`try`ing an if/else expression" { test "`try`ing an if/else expression" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
@ -69,7 +68,6 @@ test "`try`ing an if/else expression" {
} }
test "'return try' of empty error set in function returning non-error" { test "'return try' of empty error set in function returning non-error" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;

View File

@ -89,7 +89,6 @@ test "type name of undefined" {
var buf: []u8 = undefined; var buf: []u8 = undefined;
test "reslice of undefined global var slice" { test "reslice of undefined global var slice" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;

View File

@ -2129,7 +2129,6 @@ test "copied union field doesn't alias source" {
} }
test "create union(enum) from other union(enum)" { test "create union(enum) from other union(enum)" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
@ -2254,7 +2253,6 @@ test "matching captures causes union equivalence" {
} }
test "signed enum tag with negative value" { test "signed enum tag with negative value" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;

View File

@ -1548,7 +1548,6 @@ test "index into comptime-known vector is comptime-known" {
} }
test "arithmetic on zero-length vectors" { test "arithmetic on zero-length vectors" {
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@ -1567,7 +1566,6 @@ test "arithmetic on zero-length vectors" {
test "@reduce on bool vector" { test "@reduce on bool vector" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO

View File

@ -4881,6 +4881,14 @@ test reduceXor {
try test_reduce_xor.testIntVectors(); try test_reduce_xor.testIntVectors();
} }
inline fn reduceAdd(comptime Type: type, rhs: Type) @typeInfo(Type).vector.child {
return @reduce(.Add, rhs);
}
test reduceAdd {
const test_reduce_add = unary(reduceAdd, .{});
try test_reduce_add.testIntVectors();
}
inline fn splat(comptime Type: type, rhs: Type) Type { inline fn splat(comptime Type: type, rhs: Type) Type {
return @splat(rhs[0]); return @splat(rhs[0]);
} }