authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-24 19:42:06-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-09-24 19:42:06-07:00
logeb072fa52846c6583b856c8c88d50d65f46b3667
treef1c1f213685f476200562bcc870bc774bd81fa2f
parentdf5f0517b33b5f7bc2a508cf6a0ee62246f02d21
parentc08c0fc6eddf601785abfbc5e5a9ab5c89d7cfbf
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17256 from ziglang/packed-bit-offsets

compiler: packed structs cache bit offsets

4 files changed, 17 insertions(+), 19 deletions(-)

src/InternPool.zig+1-1
...@@ -4195,7 +4195,7 @@ fn extraPackedStructType(ip: *const InternPool, extra_index: u32, inits: bool) K...@@ -4195,7 +4195,7 @@ fn extraPackedStructType(ip: *const InternPool, extra_index: u32, inits: bool) K
4195 .len = fields_len,4195 .len = fields_len,
4196 },4196 },
4197 .field_inits = if (inits) .{4197 .field_inits = if (inits) .{
4198 .start = type_struct_packed.end + fields_len + fields_len,4198 .start = type_struct_packed.end + fields_len * 2,
4199 .len = fields_len,4199 .len = fields_len,
4200 } else .{4200 } else .{
4201 .start = 0,4201 .start = 0,
src/Module.zig+4-4
...@@ -6650,10 +6650,10 @@ pub fn structFieldAlignmentExtern(mod: *Module, field_ty: Type) Alignment {...@@ -6650,10 +6650,10 @@ pub fn structFieldAlignmentExtern(mod: *Module, field_ty: Type) Alignment {
6650 return ty_abi_align;6650 return ty_abi_align;
6651}6651}
66526652
6653/// TODO: avoid linear search by storing these in trailing data of packed struct types6653/// https://github.com/ziglang/zig/issues/17178 explored storing these bit offsets
6654/// then packedStructFieldByteOffset can be expressed in terms of bits / 8, fixing6654/// into the packed struct InternPool data rather than computing this on the
6655/// that one too.6655/// fly, however it was found to perform worse when measured on real world
6656/// https://github.com/ziglang/zig/issues/171786656/// projects.
6657pub fn structPackedFieldBitOffset(6657pub fn structPackedFieldBitOffset(
6658 mod: *Module,6658 mod: *Module,
6659 struct_type: InternPool.Key.StructType,6659 struct_type: InternPool.Key.StructType,
src/Sema.zig+3-2
...@@ -21377,8 +21377,9 @@ fn reifyStruct(...@@ -21377,8 +21377,9 @@ fn reifyStruct(
21377 }21377 }
2137821378
21379 var fields_bit_sum: u64 = 0;21379 var fields_bit_sum: u64 = 0;
21380 for (struct_type.field_types.get(ip)) |field_ty| {21380 for (0..struct_type.field_types.len) |i| {
21381 fields_bit_sum += field_ty.toType().bitSize(mod);21381 const field_ty = struct_type.field_types.get(ip)[i].toType();
21382 fields_bit_sum += field_ty.bitSize(mod);
21382 }21383 }
2138321384
21384 if (backing_int_val.optionalValue(mod)) |backing_int_ty_val| {21385 if (backing_int_val.optionalValue(mod)) |backing_int_ty_val| {
src/type.zig+9-12
...@@ -3021,27 +3021,24 @@ pub const Type = struct {...@@ -3021,27 +3021,24 @@ pub const Type = struct {
3021 };3021 };
3022 }3022 }
30233023
3024 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {3024 pub fn packedStructFieldBitOffset(ty: Type, field_index: usize, mod: *Module) u32 {
3025 const ip = &mod.intern_pool;3025 const ip = &mod.intern_pool;
3026 const struct_type = ip.indexToKey(ty.toIntern()).struct_type;3026 const struct_type = ip.indexToKey(ty.toIntern()).struct_type;
3027 assert(struct_type.layout == .Packed);3027 assert(struct_type.layout == .Packed);
3028 comptime assert(Type.packed_struct_layout_version == 2);3028 comptime assert(Type.packed_struct_layout_version == 2);
30293029
3030 var bit_offset: u16 = undefined;3030 var running_bits: u32 = 0;
3031 var elem_size_bits: u16 = undefined;
3032 var running_bits: u16 = 0;
3033 for (struct_type.field_types.get(ip), 0..) |field_ty, i| {3031 for (struct_type.field_types.get(ip), 0..) |field_ty, i| {
3032 if (i == field_index) break;
3034 if (!field_ty.toType().hasRuntimeBits(mod)) continue;3033 if (!field_ty.toType().hasRuntimeBits(mod)) continue;
30353034 const field_bits: u32 = @intCast(field_ty.toType().bitSize(mod));
3036 const field_bits: u16 = @intCast(field_ty.toType().bitSize(mod));
3037 if (i == field_index) {
3038 bit_offset = running_bits;
3039 elem_size_bits = field_bits;
3040 }
3041 running_bits += field_bits;3035 running_bits += field_bits;
3042 }3036 }
3043 const byte_offset = bit_offset / 8;3037 return running_bits;
3044 return byte_offset;3038 }
3039
3040 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {
3041 return packedStructFieldBitOffset(ty, field_index, mod) / 8;
3045 }3042 }
30463043
3047 pub const FieldOffset = struct {3044 pub const FieldOffset = struct {