authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2025-04-25 03:02:20+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2025-04-28 10:42:33+03:30
log296b17f37b5c2c28dc909e37d0bb15853338eb79
treea620dc77dcd602618629d2b191438b48d25946a6
parentfc55c1b7a1b62f0ffa4de5dfcfba03c84feb1ca5

spirv: allow `offset_and_cast` for vectors when possible


1 files changed, 29 insertions(+), 15 deletions(-)

src/codegen/spirv.zig+29-15
......@@ -1065,6 +1065,7 @@ const NavGen = struct {
10651065
10661066 fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef {
10671067 const pt = self.pt;
1068 const zcu = pt.zcu;
10681069 switch (derivation) {
10691070 .comptime_alloc_ptr, .comptime_field_ptr => unreachable,
10701071 .int => |int| {
......@@ -1104,23 +1105,36 @@ const NavGen = struct {
11041105 .offset_and_cast => |oac| {
11051106 const parent_ptr_id = try self.derivePtr(oac.parent.*);
11061107 const parent_ptr_ty = try oac.parent.ptrType(pt);
1107 disallow: {
1108 if (oac.byte_offset != 0) break :disallow;
1109 // Allow changing the pointer type child only to restructure arrays.
1110 // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T.
1111 const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);
1112 const result_ptr_id = self.spv.allocId();
1113 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
1114 .id_result_type = result_ty_id,
1115 .id_result = result_ptr_id,
1116 .operand = parent_ptr_id,
1117 });
1118 return result_ptr_id;
1108 const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);
1109
1110 if (oac.byte_offset != 0) {
1111 const child_size = oac.new_ptr_ty.childType(zcu).abiSize(zcu);
1112 if (oac.byte_offset % child_size != 0) {
1113 return self.fail("cannot perform pointer cast: '{}' to '{}'", .{
1114 parent_ptr_ty.fmt(pt),
1115 oac.new_ptr_ty.fmt(pt),
1116 });
1117 }
1118
1119 // Vector element ptr accesses are derived as offset_and_cast.
1120 // We can just use OpAccessChain.
1121 assert(parent_ptr_ty.childType(zcu).zigTypeTag(zcu) == .vector);
1122 return self.accessChain(
1123 result_ty_id,
1124 parent_ptr_id,
1125 &.{@intCast(@divExact(oac.byte_offset, child_size))},
1126 );
11191127 }
1120 return self.fail("cannot perform pointer cast: '{}' to '{}'", .{
1121 parent_ptr_ty.fmt(pt),
1122 oac.new_ptr_ty.fmt(pt),
1128
1129 // Allow changing the pointer type child only to restructure arrays.
1130 // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T.
1131 const result_ptr_id = self.spv.allocId();
1132 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
1133 .id_result_type = result_ty_id,
1134 .id_result = result_ptr_id,
1135 .operand = parent_ptr_id,
11231136 });
1137 return result_ptr_id;
11241138 },
11251139 }
11261140 }