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 {...@@ -1065,6 +1065,7 @@ const NavGen = struct {
10651065
1066 fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef {1066 fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef {
1067 const pt = self.pt;1067 const pt = self.pt;
1068 const zcu = pt.zcu;
1068 switch (derivation) {1069 switch (derivation) {
1069 .comptime_alloc_ptr, .comptime_field_ptr => unreachable,1070 .comptime_alloc_ptr, .comptime_field_ptr => unreachable,
1070 .int => |int| {1071 .int => |int| {
...@@ -1104,23 +1105,36 @@ const NavGen = struct {...@@ -1104,23 +1105,36 @@ const NavGen = struct {
1104 .offset_and_cast => |oac| {1105 .offset_and_cast => |oac| {
1105 const parent_ptr_id = try self.derivePtr(oac.parent.*);1106 const parent_ptr_id = try self.derivePtr(oac.parent.*);
1106 const parent_ptr_ty = try oac.parent.ptrType(pt);1107 const parent_ptr_ty = try oac.parent.ptrType(pt);
1107 disallow: {1108 const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);
1108 if (oac.byte_offset != 0) break :disallow;1109
1109 // Allow changing the pointer type child only to restructure arrays.1110 if (oac.byte_offset != 0) {
1110 // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T.1111 const child_size = oac.new_ptr_ty.childType(zcu).abiSize(zcu);
1111 const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);1112 if (oac.byte_offset % child_size != 0) {
1112 const result_ptr_id = self.spv.allocId();1113 return self.fail("cannot perform pointer cast: '{}' to '{}'", .{
1113 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{1114 parent_ptr_ty.fmt(pt),
1114 .id_result_type = result_ty_id,1115 oac.new_ptr_ty.fmt(pt),
1115 .id_result = result_ptr_id,1116 });
1116 .operand = parent_ptr_id,1117 }
1117 });1118
1118 return result_ptr_id;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 );
1119 }1127 }
1120 return self.fail("cannot perform pointer cast: '{}' to '{}'", .{1128
1121 parent_ptr_ty.fmt(pt),1129 // Allow changing the pointer type child only to restructure arrays.
1122 oac.new_ptr_ty.fmt(pt),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,
1123 });1136 });
1137 return result_ptr_id;
1124 },1138 },
1125 }1139 }
1126 }1140 }