x86_64: rewrite scalar and vector int @divTrunc

This commit is contained in:
Jacob Young 2025-02-13 17:28:33 -05:00
parent 9f121ec8fb
commit 8c48376d64
7 changed files with 2865 additions and 1139 deletions

View file

@ -230,6 +230,7 @@ comptime {
_ = @import("compiler_rt/trunc.zig");
// BigInt. Alphabetically sorted.
_ = @import("compiler_rt/divmodei4.zig");
_ = @import("compiler_rt/udivmodei4.zig");
_ = @import("compiler_rt/udivmodti4.zig");

View file

@ -0,0 +1,50 @@
const std = @import("std");
const builtin = @import("builtin");
const common = @import("common.zig");
const udivmod = @import("udivmodei4.zig").divmod;
comptime {
@export(&__divei4, .{ .name = "__divei4", .linkage = common.linkage, .visibility = common.visibility });
@export(&__modei4, .{ .name = "__modei4", .linkage = common.linkage, .visibility = common.visibility });
}
const endian = builtin.cpu.arch.endian();
inline fn limb(x: []u32, i: usize) *u32 {
return if (endian == .little) &x[i] else &x[x.len - 1 - i];
}
inline fn neg(x: []u32) void {
var ov: u1 = 1;
for (0..x.len) |limb_index| {
const l = limb(x, limb_index);
l.*, ov = @addWithOverflow(~l.*, ov);
}
}
/// Mutates the arguments!
fn divmod(q: ?[]u32, r: ?[]u32, u: []u32, v: []u32) !void {
const u_sign: i32 = @bitCast(u[u.len - 1]);
const v_sign: i32 = @bitCast(v[v.len - 1]);
if (u_sign < 0) neg(u);
if (v_sign < 0) neg(v);
try @call(.always_inline, udivmod, .{ q, r, u, v });
if (q) |x| if (u_sign ^ v_sign < 0) neg(x);
if (r) |x| if (u_sign < 0) neg(x);
}
pub fn __divei4(r_q: [*]u32, u_p: [*]u32, v_p: [*]u32, bits: usize) callconv(.C) void {
@setRuntimeSafety(builtin.is_test);
const u = u_p[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
const v = v_p[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
const q = r_q[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
@call(.always_inline, divmod, .{ q, null, u, v }) catch unreachable;
}
pub fn __modei4(r_p: [*]u32, u_p: [*]u32, v_p: [*]u32, bits: usize) callconv(.C) void {
@setRuntimeSafety(builtin.is_test);
const u = u_p[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
const v = v_p[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
const r = r_p[0 .. std.math.divCeil(usize, bits, 32) catch unreachable];
@call(.always_inline, divmod, .{ null, r, u, v }) catch unreachable;
}

View file

@ -27,8 +27,8 @@ inline fn limb_set(x: []u32, i: usize, v: u32) void {
}
}
// Uses Knuth's Algorithm D, 4.3.1, p. 272.
fn divmod(q: ?[]u32, r: ?[]u32, u: []const u32, v: []const u32) !void {
/// Uses Knuth's Algorithm D, 4.3.1, p. 272.
pub fn divmod(q: ?[]u32, r: ?[]u32, u: []const u32, v: []const u32) !void {
if (q) |q_| @memset(q_[0..], 0);
if (r) |r_| @memset(r_[0..], 0);

File diff suppressed because it is too large Load diff

View file

@ -17978,8 +17978,8 @@ fn binary(comptime op: anytype, comptime opts: struct { compare: Compare = .rela
-0x12, -0x1e, 0x18, 0x6e, 0x31, 0x53, -0x6a, -0x34, 0x13, 0x4d, 0x30, -0x7d, -0x31, 0x1e, -0x24, 0x32,
-0x1e, -0x01, 0x55, 0x33, -0x75, -0x44, -0x57, 0x2b, -0x66, 0x19, 0x7f, -0x28, -0x3f, -0x7e, -0x5d, -0x06,
}, .{
0x05, -0x23, 0x43, -0x54, -0x41, 0x7f, -0x6a, -0x31, 0x04, 0x15, -0x7a, -0x37, 0x6d, 0x16, 0x00, 0x4a,
0x15, 0x55, -0x4a, 0x16, -0x73, -0x0c, 0x1c, -0x26, -0x14, 0x00, 0x55, 0x7b, 0x16, -0x2e, -0x5f, -0x67,
0x05, -0x23, 0x43, -0x54, -0x41, 0x7f, -0x6a, -0x31, 0x04, 0x15, -0x7a, -0x37, 0x6d, 0x16, 0x01, 0x4a,
0x15, 0x55, -0x4a, 0x16, -0x73, -0x0c, 0x1c, -0x26, -0x14, -0x01, 0x55, 0x7b, 0x16, -0x2e, -0x5f, -0x67,
});
try testArgs(@Vector(64, i8), .{
-0x05, 0x76, 0x4e, -0x5c, 0x7b, -0x1a, -0x38, -0x2e, 0x3d, 0x36, 0x01, 0x30, -0x02, -0x71, -0x24, 0x24,
@ -18008,7 +18008,7 @@ fn binary(comptime op: anytype, comptime opts: struct { compare: Compare = .rela
0x23, 0x3b, 0x0a, 0x7a, 0x19, 0x14, 0x65, -0x1d, 0x2b, 0x65, 0x33, 0x2a, 0x52, -0x63, 0x57, 0x10,
-0x1b, 0x26, -0x46, -0x7e, -0x25, 0x79, -0x01, -0x0d, -0x49, -0x4d, 0x74, 0x03, 0x77, 0x16, 0x03, -0x3d,
0x1c, 0x25, 0x5a, -0x2f, -0x16, -0x5f, -0x36, -0x55, -0x44, -0x0c, -0x0f, 0x7b, -0x15, -0x1d, 0x32, 0x31,
0x6e, -0x44, -0x4a, -0x64, 0x67, 0x04, 0x47, 0x00, 0x3c, -0x0a, -0x79, 0x3d, 0x48, 0x5a, 0x61, -0x2c,
0x6e, -0x44, -0x4a, -0x64, 0x67, 0x04, 0x47, -0x02, 0x3c, -0x0a, -0x79, 0x3d, 0x48, 0x5a, 0x61, -0x2c,
0x6d, -0x68, -0x71, -0x6b, -0x11, 0x44, -0x75, -0x55, -0x67, -0x52, 0x64, -0x3d, -0x05, -0x76, -0x6d, -0x44,
});
@ -18035,7 +18035,7 @@ fn binary(comptime op: anytype, comptime opts: struct { compare: Compare = .rela
try testArgs(@Vector(16, u8), .{
0xea, 0x80, 0xbb, 0xe8, 0x74, 0x81, 0xc8, 0x66, 0x7b, 0x41, 0x90, 0xcb, 0x30, 0x70, 0x4b, 0x0f,
}, .{
0x61, 0x26, 0xbe, 0x47, 0x00, 0x9c, 0x55, 0xa5, 0x59, 0xf0, 0xb2, 0x20, 0x30, 0xaf, 0x82, 0x3e,
0x61, 0x26, 0xbe, 0x47, 0x02, 0x9c, 0x55, 0xa5, 0x59, 0xf0, 0xb2, 0x20, 0x30, 0xaf, 0x82, 0x3e,
});
try testArgs(@Vector(32, u8), .{
0xa1, 0x88, 0xc4, 0xf4, 0x77, 0x0b, 0xf5, 0xbb, 0x09, 0x03, 0xbf, 0xf5, 0xcc, 0x7f, 0x6b, 0x2a,
@ -18976,12 +18976,12 @@ test addUnsafe {
inline fn subUnsafe(comptime Type: type, lhs: Type, rhs: Type) AddOneBit(Type) {
@setRuntimeSafety(false);
switch (@typeInfo(Scalar(Type))) {
else => @compileError(@typeName(Type)),
.int => |int| switch (int.signedness) {
.signed => {},
.unsigned => return @as(AddOneBit(Type), @max(lhs, rhs)) - @min(lhs, rhs),
},
.float => {},
else => @compileError(@typeName(Type)),
}
return @as(AddOneBit(Type), lhs) - rhs;
}
@ -19024,42 +19024,51 @@ test divide {
try test_divide.testFloatVectors();
}
// workaround https://github.com/ziglang/zig/issues/22748
// TODO: @TypeOf(@divTrunc(lhs, rhs))
inline fn divTrunc(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs / rhs) {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
return @trunc(lhs / rhs);
inline fn divTrunc(comptime Type: type, lhs: Type, rhs: Type) Type {
switch (@typeInfo(Scalar(Type))) {
else => @compileError(@typeName(Type)),
.int => return @divTrunc(lhs, rhs),
.float => {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
return @trunc(lhs / rhs);
}
// workaround https://github.com/ziglang/zig/issues/22748
// workaround https://github.com/ziglang/zig/issues/22749
// TODO: return @divTrunc(lhs, rhs);
var rt_lhs = lhs;
var rt_rhs = rhs;
_ = .{ &rt_lhs, &rt_rhs };
return @divTrunc(rt_lhs, rt_rhs);
},
}
// workaround https://github.com/ziglang/zig/issues/22748
// workaround https://github.com/ziglang/zig/issues/22749
// TODO: return @divTrunc(lhs, rhs);
var rt_lhs = lhs;
var rt_rhs = rhs;
_ = .{ &rt_lhs, &rt_rhs };
return @divTrunc(rt_lhs, rt_rhs);
}
test divTrunc {
const test_div_trunc = binary(divTrunc, .{ .compare = .approx_int });
try test_div_trunc.testInts();
try test_div_trunc.testIntVectors();
try test_div_trunc.testFloats();
try test_div_trunc.testFloatVectors();
}
// workaround https://github.com/ziglang/zig/issues/22748
// TODO: @TypeOf(@divFloor(lhs, rhs))
inline fn divFloor(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs / rhs) {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
return @floor(lhs / rhs);
inline fn divFloor(comptime Type: type, lhs: Type, rhs: Type) Type {
switch (@typeInfo(Scalar(Type))) {
else => @compileError(@typeName(Type)),
.int => return @divFloor(lhs, rhs),
.float => {
if (@inComptime()) {
// workaround https://github.com/ziglang/zig/issues/22748
return @floor(lhs / rhs);
}
// workaround https://github.com/ziglang/zig/issues/22748
// workaround https://github.com/ziglang/zig/issues/22749
// TODO: return @divFloor(lhs, rhs);
var rt_lhs = lhs;
var rt_rhs = rhs;
_ = .{ &rt_lhs, &rt_rhs };
return @divFloor(rt_lhs, rt_rhs);
},
}
// workaround https://github.com/ziglang/zig/issues/22748
// workaround https://github.com/ziglang/zig/issues/22749
// TODO: return @divFloor(lhs, rhs);
var rt_lhs = lhs;
var rt_rhs = rhs;
_ = &rt_lhs;
_ = &rt_rhs;
return @divFloor(rt_lhs, rt_rhs);
}
test divFloor {
const test_div_floor = binary(divFloor, .{ .compare = .approx_int });

View file

@ -18,5 +18,5 @@ fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
return @divTrunc(a, b);
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -19,5 +19,5 @@ fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) {
return @divTrunc(a, b);
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native