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) {
const days: u64 = std.time.epoch.getDaysInMonth(
date.year,
@as(std.time.epoch.Month, @enumFromInt(month)),
@enumFromInt(month),
);
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 {
const result = if (use_vectors) result: {
const nn: @Vector(2, u16) = .{ text[0], text[1] };
const zero: @Vector(2, u16) = .{ '0', '0' };
const mm: @Vector(2, u16) = .{ 10, 1 };
break :result @reduce(.Add, (nn -% zero) *% mm);
} else std.fmt.parseInt(u8, text, 10) catch return error.CertificateTimeInvalid;
const nn: @Vector(2, u16) = .{ text[0], text[1] };
const zero: @Vector(2, u16) = .{ '0', '0' };
const mm: @Vector(2, u16) = .{ 10, 1 };
const result = @reduce(.Add, (nn -% zero) *% mm);
if (result < min) return error.CertificateTimeInvalid;
if (result > max) return error.CertificateTimeInvalid;
return @truncate(result);
return @intCast(result);
}
test parseTimeDigits {
@ -647,14 +645,12 @@ test parseTimeDigits {
}
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 zero: @Vector(4, u32) = .{ '0', '0', '0', '0' };
const mmmm: @Vector(4, u32) = .{ 1000, 100, 10, 1 };
break :result @reduce(.Add, (nnnn -% zero) *% mmmm);
} else std.fmt.parseInt(u16, text, 10) catch return error.CertificateTimeInvalid;
const nnnn: @Vector(4, u32) = .{ text[0], text[1], text[2], text[3] };
const zero: @Vector(4, u32) = .{ '0', '0', '0', '0' };
const mmmm: @Vector(4, u32) = .{ 1000, 100, 10, 1 };
const result = @reduce(.Add, (nnnn -% zero) *% mmmm);
if (result > 9999) return error.CertificateTimeInvalid;
return @truncate(result);
return @intCast(result);
}
test parseYear4 {
@ -858,7 +854,7 @@ pub const der = struct {
pub fn parse(bytes: []const u8, index: u32) Element.ParseError!Element {
var i = index;
const identifier = @as(Identifier, @bitCast(bytes[i]));
const identifier: Identifier = @bitCast(bytes[i]);
i += 1;
const size_byte = bytes[i];
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)) {
return error.CertificateFieldHasInvalidLength;
}
@ -1244,5 +1240,3 @@ pub const rsa = struct {
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 Allocator = mem.Allocator;
const assert = std.debug.assert;
const use_vectors = builtin.zig_backend != .stage2_x86_64;
const Client = @This();
const proto = @import("protocol.zig");
@ -594,13 +593,10 @@ pub const Response = struct {
}
fn parseInt3(text: *const [3]u8) u10 {
if (use_vectors) {
const nnn: @Vector(3, u8) = text.*;
const zero: @Vector(3, u8) = .{ '0', '0', '0' };
const mmm: @Vector(3, u10) = .{ 100, 10, 1 };
return @reduce(.Add, @as(@Vector(3, u10), nnn -% zero) *% mmm);
}
return std.fmt.parseInt(u10, text, 10) catch unreachable;
const nnn: @Vector(3, u8) = text.*;
const zero: @Vector(3, u8) = .{ '0', '0', '0' };
const mmm: @Vector(3, u10) = .{ 100, 10, 1 };
return @reduce(.Add, (nnn -% zero) *% mmm);
}
test parseInt3 {
@ -1796,5 +1792,6 @@ pub fn fetch(client: *Client, options: FetchOptions) !FetchResult {
}
test {
_ = Response;
_ = &initDefaultProxies;
}

View File

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

View File

@ -3091,7 +3091,6 @@ test "std.zon free on error" {
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_x86_64) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15329
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" {
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_arm) return error.SkipZigTest; // TODO
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" {
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_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" {
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_arm) 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" {
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_arm) return error.SkipZigTest; // TODO
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" {
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_arm) return error.SkipZigTest; // TODO
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" {
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_arm) return error.SkipZigTest; // TODO
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" {
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_arm) return error.SkipZigTest; // TODO
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" {
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_arm) return error.SkipZigTest; // TODO
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" {
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_arm) return error.SkipZigTest; // TODO
@ -1905,7 +1904,6 @@ test "array of structs inside struct initialized with undefined" {
}
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_arm) return error.SkipZigTest; // TODO
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" {
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_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" {
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_arm) 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" {
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_arm) return error.SkipZigTest; // TODO
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" {
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_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;

View File

@ -89,7 +89,6 @@ test "type name of undefined" {
var buf: []u8 = undefined;
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_arm) return error.SkipZigTest; // TODO
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)" {
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_arm) return error.SkipZigTest; // TODO
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" {
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_arm) return error.SkipZigTest; // TODO
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" {
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_aarch64) 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" {
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_arm) return error.SkipZigTest; // TODO

View File

@ -4881,6 +4881,14 @@ test reduceXor {
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 {
return @splat(rhs[0]);
}