mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
x86_64: rewrite vector @intCast
This commit is contained in:
parent
f0ac14ce97
commit
4c5abe5ac6
@ -450,7 +450,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
.skip_non_native = skip_non_native,
|
.skip_non_native = skip_non_native,
|
||||||
.skip_libc = skip_libc,
|
.skip_libc = skip_libc,
|
||||||
.use_llvm = use_llvm,
|
.use_llvm = use_llvm,
|
||||||
.max_rss = 1 * 1024 * 1024 * 1024,
|
.max_rss = 1.25 * 1024 * 1024 * 1024,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
test_modules_step.dependOn(tests.addModuleTests(b, .{
|
test_modules_step.dependOn(tests.addModuleTests(b, .{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -203,8 +203,8 @@ test "@min/@max notices vector bounds" {
|
|||||||
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
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
||||||
|
|
||||||
var x: @Vector(2, u16) = .{ 140, 40 };
|
var x: @Vector(2, u16) = .{ 140, 40 };
|
||||||
const y: @Vector(2, u64) = .{ 5, 100 };
|
const y: @Vector(2, u64) = .{ 5, 100 };
|
||||||
@ -257,8 +257,8 @@ test "@min/@max notices bounds from vector types" {
|
|||||||
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
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
||||||
|
|
||||||
var x: @Vector(2, u16) = .{ 30, 67 };
|
var x: @Vector(2, u16) = .{ 30, 67 };
|
||||||
var y: @Vector(2, u32) = .{ 20, 500 };
|
var y: @Vector(2, u32) = .{ 20, 500 };
|
||||||
@ -301,8 +301,7 @@ test "@min/@max notices bounds from vector types when element of comptime-known
|
|||||||
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
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
||||||
!comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
|
|
||||||
|
|
||||||
var x: @Vector(2, u32) = .{ 1_000_000, 12345 };
|
var x: @Vector(2, u32) = .{ 1_000_000, 12345 };
|
||||||
_ = &x;
|
_ = &x;
|
||||||
|
|||||||
@ -24,27 +24,32 @@ inline fn runtime(comptime Type: type, comptime value: Type) Type {
|
|||||||
}.variable;
|
}.variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn Scalar(comptime Type: type) type {
|
||||||
|
return switch (@typeInfo(Type)) {
|
||||||
|
else => Type,
|
||||||
|
.vector => |info| info.child,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// inline to avoid a runtime `@splat`
|
||||||
|
inline fn splat(comptime Type: type, scalar: Scalar(Type)) Type {
|
||||||
|
return switch (@typeInfo(Type)) {
|
||||||
|
else => scalar,
|
||||||
|
.vector => @splat(scalar),
|
||||||
|
};
|
||||||
|
}
|
||||||
fn sign(rhs: anytype) switch (@typeInfo(@TypeOf(rhs))) {
|
fn sign(rhs: anytype) switch (@typeInfo(@TypeOf(rhs))) {
|
||||||
else => bool,
|
else => bool,
|
||||||
.vector => |vector| @Vector(vector.len, bool),
|
.vector => |vector| @Vector(vector.len, bool),
|
||||||
} {
|
} {
|
||||||
switch (@typeInfo(@TypeOf(rhs))) {
|
const ScalarInt = @Type(.{ .int = .{
|
||||||
else => {
|
.signedness = .unsigned,
|
||||||
const I = @Type(.{ .int = .{
|
.bits = @bitSizeOf(Scalar(@TypeOf(rhs))),
|
||||||
.signedness = .unsigned,
|
} });
|
||||||
.bits = @bitSizeOf(@TypeOf(rhs)),
|
const VectorInt = switch (@typeInfo(@TypeOf(rhs))) {
|
||||||
} });
|
else => ScalarInt,
|
||||||
return @as(I, @bitCast(rhs)) & @as(I, 1) << (@bitSizeOf(I) - 1) != 0;
|
.vector => |vector| @Vector(vector.len, ScalarInt),
|
||||||
},
|
};
|
||||||
.vector => |vector| {
|
return @as(VectorInt, @bitCast(rhs)) & splat(VectorInt, @as(ScalarInt, 1) << @bitSizeOf(ScalarInt) - 1) != splat(VectorInt, 0);
|
||||||
const I = @Type(.{ .int = .{
|
|
||||||
.signedness = .unsigned,
|
|
||||||
.bits = @bitSizeOf(vector.child),
|
|
||||||
} });
|
|
||||||
const V = @Vector(vector.len, I);
|
|
||||||
return @as(V, @bitCast(rhs)) & @as(V, @splat(@as(I, 1) << (@bitSizeOf(I) - 1))) != @as(V, @splat(0));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn boolAnd(lhs: anytype, rhs: @TypeOf(lhs)) @TypeOf(lhs) {
|
fn boolAnd(lhs: anytype, rhs: @TypeOf(lhs)) @TypeOf(lhs) {
|
||||||
switch (@typeInfo(@TypeOf(lhs))) {
|
switch (@typeInfo(@TypeOf(lhs))) {
|
||||||
@ -1648,12 +1653,12 @@ fn cast(comptime op: anytype, comptime opts: struct { strict: bool = false }) ty
|
|||||||
comptime imm_arg: Type,
|
comptime imm_arg: Type,
|
||||||
mem_arg: Type,
|
mem_arg: Type,
|
||||||
) !void {
|
) !void {
|
||||||
const expected = comptime op(Result, Type, imm_arg);
|
const expected = comptime op(Result, Type, imm_arg, imm_arg);
|
||||||
var reg_arg = mem_arg;
|
var reg_arg = mem_arg;
|
||||||
_ = .{®_arg};
|
_ = .{®_arg};
|
||||||
try checkExpected(expected, op(Result, Type, reg_arg), opts.strict);
|
try checkExpected(expected, op(Result, Type, reg_arg, imm_arg), opts.strict);
|
||||||
try checkExpected(expected, op(Result, Type, mem_arg), opts.strict);
|
try checkExpected(expected, op(Result, Type, mem_arg, imm_arg), opts.strict);
|
||||||
try checkExpected(expected, op(Result, Type, imm_arg), opts.strict);
|
try checkExpected(expected, op(Result, Type, imm_arg, imm_arg), opts.strict);
|
||||||
}
|
}
|
||||||
// noinline for a more helpful stack trace
|
// noinline for a more helpful stack trace
|
||||||
noinline fn testArgs(comptime Result: type, comptime Type: type, comptime imm_arg: Type) !void {
|
noinline fn testArgs(comptime Result: type, comptime Type: type, comptime imm_arg: Type) !void {
|
||||||
@ -5218,6 +5223,39 @@ fn cast(comptime op: anytype, comptime opts: struct { strict: bool = false }) ty
|
|||||||
try testArgs(f128, f128, nan(f128));
|
try testArgs(f128, f128, nan(f128));
|
||||||
}
|
}
|
||||||
fn testIntVectors() !void {
|
fn testIntVectors() !void {
|
||||||
|
try testArgs(@Vector(1, i8), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, u8), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, i16), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, u16), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, i32), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, u32), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, i64), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, u64), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, i128), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, u128), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, i256), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, u256), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, i512), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, u512), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, i1024), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, u1024), @Vector(1, i1), .{-1});
|
||||||
|
try testArgs(@Vector(1, i8), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, u8), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, i16), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, u16), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, i32), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, u32), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, i64), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, u64), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, i128), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, u128), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, i256), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, u256), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, i512), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, u512), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, i1024), @Vector(1, u1), .{1});
|
||||||
|
try testArgs(@Vector(1, u1024), @Vector(1, u1), .{1});
|
||||||
|
|
||||||
try testArgs(@Vector(2, i8), @Vector(2, i1), .{ -1, 0 });
|
try testArgs(@Vector(2, i8), @Vector(2, i1), .{ -1, 0 });
|
||||||
try testArgs(@Vector(2, u8), @Vector(2, i1), .{ -1, 0 });
|
try testArgs(@Vector(2, u8), @Vector(2, i1), .{ -1, 0 });
|
||||||
try testArgs(@Vector(2, i16), @Vector(2, i1), .{ -1, 0 });
|
try testArgs(@Vector(2, i16), @Vector(2, i1), .{ -1, 0 });
|
||||||
@ -9917,21 +9955,18 @@ test clz {
|
|||||||
try test_clz.testIntVectors();
|
try test_clz.testIntVectors();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn intCast(comptime Result: type, comptime Type: type, rhs: Type) Result {
|
inline fn intCast(comptime Result: type, comptime Type: type, rhs: Type, comptime ct_rhs: Type) Result {
|
||||||
|
@setRuntimeSafety(false); // TODO
|
||||||
const res_info = switch (@typeInfo(Result)) {
|
const res_info = switch (@typeInfo(Result)) {
|
||||||
.int => |info| info,
|
.int => |info| info,
|
||||||
.vector => |info| @typeInfo(info.child).int,
|
.vector => |info| @typeInfo(info.child).int,
|
||||||
else => @compileError(@typeName(Result)),
|
else => @compileError(@typeName(Result)),
|
||||||
};
|
};
|
||||||
const rhs_info = switch (@typeInfo(Type)) {
|
const rhs_info = @typeInfo(Scalar(Type)).int;
|
||||||
.int => |info| info,
|
|
||||||
.vector => |info| @typeInfo(info.child).int,
|
|
||||||
else => @compileError(@typeName(Type)),
|
|
||||||
};
|
|
||||||
const min_bits = @min(res_info.bits, rhs_info.bits);
|
const min_bits = @min(res_info.bits, rhs_info.bits);
|
||||||
return @intCast(switch (@as(union(enum) {
|
return @intCast(switch (@as(union(enum) {
|
||||||
shift: std.math.Log2Int(Type),
|
shift: std.math.Log2Int(Scalar(Type)),
|
||||||
mask: std.math.Log2IntCeil(Type),
|
mask: std.math.Log2IntCeil(Scalar(Type)),
|
||||||
}, switch (res_info.signedness) {
|
}, switch (res_info.signedness) {
|
||||||
.signed => switch (rhs_info.signedness) {
|
.signed => switch (rhs_info.signedness) {
|
||||||
.signed => .{ .shift = rhs_info.bits - min_bits },
|
.signed => .{ .shift = rhs_info.bits - min_bits },
|
||||||
@ -9943,21 +9978,34 @@ inline fn intCast(comptime Result: type, comptime Type: type, rhs: Type) Result
|
|||||||
},
|
},
|
||||||
})) {
|
})) {
|
||||||
// TODO: if (bits == 0) rhs else rhs >> bits,
|
// TODO: if (bits == 0) rhs else rhs >> bits,
|
||||||
.shift => |bits| if (bits == 0)
|
.shift => |bits| if (bits == 0) rhs else switch (@typeInfo(Type)) {
|
||||||
rhs
|
.int => if (ct_rhs < 0)
|
||||||
else if (rhs < 0)
|
rhs | std.math.minInt(Type) >> bits
|
||||||
rhs | std.math.minInt(Type) >> bits
|
else
|
||||||
else
|
rhs & std.math.maxInt(Type) >> bits,
|
||||||
rhs & std.math.maxInt(Type) >> bits,
|
.vector => rhs | @select(
|
||||||
.mask => |bits| if (bits == rhs_info.bits) rhs else rhs & (1 << bits) - 1,
|
Scalar(Type),
|
||||||
|
ct_rhs < splat(Type, 0),
|
||||||
|
splat(Type, std.math.minInt(Scalar(Type)) >> bits),
|
||||||
|
splat(Type, 0),
|
||||||
|
) & ~@select(
|
||||||
|
Scalar(Type),
|
||||||
|
ct_rhs >= splat(Type, 0),
|
||||||
|
splat(Type, std.math.minInt(Scalar(Type)) >> bits),
|
||||||
|
splat(Type, 0),
|
||||||
|
),
|
||||||
|
else => comptime unreachable,
|
||||||
|
},
|
||||||
|
.mask => |bits| if (bits == rhs_info.bits) rhs else rhs & splat(Type, (1 << bits) - 1),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
test intCast {
|
test intCast {
|
||||||
const test_int_cast = cast(intCast, .{});
|
const test_int_cast = cast(intCast, .{});
|
||||||
try test_int_cast.testInts();
|
try test_int_cast.testInts();
|
||||||
|
try test_int_cast.testIntVectors();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn floatCast(comptime Result: type, comptime Type: type, rhs: Type) Result {
|
inline fn floatCast(comptime Result: type, comptime Type: type, rhs: Type, comptime _: Type) Result {
|
||||||
return @floatCast(rhs);
|
return @floatCast(rhs);
|
||||||
}
|
}
|
||||||
test floatCast {
|
test floatCast {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user