Skip to content

Commit a3b1ba8

Browse files
committed
spirv: new vectorization helper
The old vectorization helper (WipElementWise) was clunky and a bit annoying to use, and it wasn't really flexible enough. This introduces a new vectorization helper, which uses Temporary and Operation types to deduce a Vectorization to perform the operation in a reasonably efficient manner. It removes the outer loop required by WipElementWise so that implementations of AIR instructions are cleaner. This helps with sanity when we start to introduce support for composite integers. airShift, convertToDirect, convertToIndirect, and normalize are initially implemented using this new method.
1 parent 4e7159a commit a3b1ba8

File tree

7 files changed

+1647
-1067
lines changed

7 files changed

+1647
-1067
lines changed

src/codegen/spirv.zig

Lines changed: 1578 additions & 1017 deletions
Large diffs are not rendered by default.

src/codegen/spirv/Module.zig

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ cache: struct {
155155
void_type: ?IdRef = null,
156156
int_types: std.AutoHashMapUnmanaged(std.builtin.Type.Int, IdRef) = .{},
157157
float_types: std.AutoHashMapUnmanaged(std.builtin.Type.Float, IdRef) = .{},
158+
// This cache is required so that @Vector(X, u1) in direct representation has the
159+
// same ID as @Vector(X, bool) in indirect representation.
160+
vector_types: std.AutoHashMapUnmanaged(struct { IdRef, u32 }, IdRef) = .{},
158161
} = .{},
159162

160163
/// Set of Decls, referred to by Decl.Index.
@@ -194,6 +197,7 @@ pub fn deinit(self: *Module) void {
194197

195198
self.cache.int_types.deinit(self.gpa);
196199
self.cache.float_types.deinit(self.gpa);
200+
self.cache.vector_types.deinit(self.gpa);
197201

198202
self.decls.deinit(self.gpa);
199203
self.decl_deps.deinit(self.gpa);
@@ -474,13 +478,17 @@ pub fn floatType(self: *Module, bits: u16) !IdRef {
474478
}
475479

476480
pub fn vectorType(self: *Module, len: u32, child_id: IdRef) !IdRef {
477-
const result_id = self.allocId();
478-
try self.sections.types_globals_constants.emit(self.gpa, .OpTypeVector, .{
479-
.id_result = result_id,
480-
.component_type = child_id,
481-
.component_count = len,
482-
});
483-
return result_id;
481+
const entry = try self.cache.vector_types.getOrPut(self.gpa, .{ child_id, len });
482+
if (!entry.found_existing) {
483+
const result_id = self.allocId();
484+
entry.value_ptr.* = result_id;
485+
try self.sections.types_globals_constants.emit(self.gpa, .OpTypeVector, .{
486+
.id_result = result_id,
487+
.component_type = child_id,
488+
.component_count = len,
489+
});
490+
}
491+
return entry.value_ptr.*;
484492
}
485493

486494
pub fn constUndef(self: *Module, ty_id: IdRef) !IdRef {

test/behavior/abs.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ test "@abs int vectors" {
152152
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
153153
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
154154
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
155-
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
156155

157156
try comptime testAbsIntVectors(1);
158157
try testAbsIntVectors(1);

test/behavior/floatop.zig

Lines changed: 0 additions & 34 deletions
Large diffs are not rendered by default.

test/behavior/math.zig

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,6 @@ test "division" {
440440
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
441441
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
442442
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
443-
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
444443
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
445444
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
446445
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
@@ -530,7 +529,6 @@ test "division half-precision floats" {
530529
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
531530
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
532531
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
533-
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
534532
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
535533
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
536534

@@ -622,7 +620,6 @@ test "negation wrapping" {
622620
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
623621
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
624622
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
625-
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
626623

627624
try expectEqual(@as(u1, 1), negateWrap(u1, 1));
628625
}
@@ -1031,6 +1028,60 @@ test "@mulWithOverflow bitsize > 32" {
10311028
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10321029
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10331030

1031+
{
1032+
var a: u40 = 3;
1033+
var b: u40 = 0x55_5555_5555;
1034+
var ov = @mulWithOverflow(a, b);
1035+
1036+
try expect(ov[0] == 0xff_ffff_ffff);
1037+
try expect(ov[1] == 0);
1038+
1039+
// Check that overflow bits in the low-word of wide-multiplications are checked too.
1040+
// Intermediate result is less than 2**64
1041+
b = 0x55_5555_5556;
1042+
ov = @mulWithOverflow(a, b);
1043+
try expect(ov[0] == 2);
1044+
try expect(ov[1] == 1);
1045+
1046+
// Check that overflow bits in the high-word of wide-multiplications are checked too.
1047+
// Intermediate result is more than 2**64 and bits 40..64 are not set.
1048+
a = 0x10_0000_0000;
1049+
b = 0x10_0000_0000;
1050+
ov = @mulWithOverflow(a, b);
1051+
try expect(ov[0] == 0);
1052+
try expect(ov[1] == 1);
1053+
}
1054+
1055+
{
1056+
var a: i40 = 3;
1057+
var b: i40 = -0x2a_aaaa_aaaa;
1058+
var ov = @mulWithOverflow(a, b);
1059+
1060+
try expect(ov[0] == -0x7f_ffff_fffe);
1061+
try expect(ov[1] == 0);
1062+
1063+
// Check that the sign bit is properly checked
1064+
b = -0x2a_aaaa_aaab;
1065+
ov = @mulWithOverflow(a, b);
1066+
try expect(ov[0] == 0x7f_ffff_ffff);
1067+
try expect(ov[1] == 1);
1068+
1069+
// Check that the low-order bits above the sign are checked.
1070+
a = 6;
1071+
ov = @mulWithOverflow(a, b);
1072+
try expect(ov[0] == -2);
1073+
try expect(ov[1] == 1);
1074+
1075+
// Check that overflow bits in the high-word of wide-multiplications are checked too.
1076+
// high parts and sign of low-order bits are all 1.
1077+
a = 0x08_0000_0000;
1078+
b = -0x08_0000_0001;
1079+
ov = @mulWithOverflow(a, b);
1080+
1081+
try expect(ov[0] == -0x8_0000_0000);
1082+
try expect(ov[1] == 1);
1083+
}
1084+
10341085
{
10351086
var a: u62 = 3;
10361087
_ = &a;
@@ -1580,7 +1631,6 @@ test "@round f16" {
15801631
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15811632
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15821633
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1583-
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15841634
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
15851635
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15861636

@@ -1592,7 +1642,6 @@ test "@round f32/f64" {
15921642
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15931643
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15941644
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1595-
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15961645
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
15971646
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15981647

test/behavior/select.zig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ test "@select vectors" {
88
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
99
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1010
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11-
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1211
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1312

1413
try comptime selectVectors();
@@ -39,7 +38,6 @@ test "@select arrays" {
3938
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
4039
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
4140
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
42-
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
4341
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
4442
if (builtin.zig_backend == .stage2_x86_64 and
4543
!comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx2)) return error.SkipZigTest;

test/behavior/vector.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,6 @@ test "vector division operators" {
548548
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
549549
if (builtin.zig_backend == .stage2_llvm and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
550550
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
551-
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
552551
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
553552

554553
const S = struct {

0 commit comments

Comments
 (0)