aboutsummaryrefslogtreecommitdiff
path: root/src/Module.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-05-30 20:23:51 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-06-10 20:47:57 -0700
commit82f6f164a1af6557451e580dcf3197ad94e5437e (patch)
tree6a88050cac9da741c2ae8434ef0fe2989c411ee5 /src/Module.zig
parentc7d65fa3685a5f48cfedaa7a1adf758e1dc6d219 (diff)
downloadzig-82f6f164a1af6557451e580dcf3197ad94e5437e.tar.gz
zig-82f6f164a1af6557451e580dcf3197ad94e5437e.zip
InternPool: improve hashing performance
Key.PtrType is now an extern struct so that hashing it can be done by reinterpreting bytes directly. It also uses the same representation for type_pointer Tag encoding and the Key. Accessing pointer attributes now requires packed struct access, however, many operations are now a copy of a u32 rather than several independent fields. This function moves the top two most used Key variants - pointer types and pointer values - to use a single-shot hash function that branches for small keys instead of calling memcpy. As a result, perf against merge-base went from 1.17x ± 0.04 slower to 1.12x ± 0.04 slower. After the pointer value hashing was changed, total CPU instructions spent in memcpy went from 4.40% to 4.08%, and after additionally improving pointer type hashing, it further decreased to 3.72%.
Diffstat (limited to 'src/Module.zig')
-rw-r--r--src/Module.zig69
1 files changed, 38 insertions, 31 deletions
diff --git a/src/Module.zig b/src/Module.zig
index b1a74932d3..862025d8f9 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -6430,8 +6430,10 @@ pub fn populateTestFunctions(
// func
try mod.intern(.{ .ptr = .{
.ty = try mod.intern(.{ .ptr_type = .{
- .elem_type = test_decl.ty.toIntern(),
- .is_const = true,
+ .child = test_decl.ty.toIntern(),
+ .flags = .{
+ .is_const = true,
+ },
} }),
.addr = .{ .decl = test_decl_index },
} }),
@@ -6466,9 +6468,11 @@ pub fn populateTestFunctions(
{
const new_ty = try mod.ptrType(.{
- .elem_type = test_fn_ty.toIntern(),
- .is_const = true,
- .size = .Slice,
+ .child = test_fn_ty.toIntern(),
+ .flags = .{
+ .is_const = true,
+ .size = .Slice,
+ },
});
const new_val = decl.val;
const new_init = try mod.intern(.{ .ptr = .{
@@ -6681,65 +6685,68 @@ pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!
pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {
var canon_info = info;
- const have_elem_layout = info.elem_type.toType().layoutIsResolved(mod);
+ const have_elem_layout = info.child.toType().layoutIsResolved(mod);
- if (info.size == .C) canon_info.is_allowzero = true;
+ if (info.flags.size == .C) canon_info.flags.is_allowzero = true;
// Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
// type, we change it to 0 here. If this causes an assertion trip because the
// pointee type needs to be resolved more, that needs to be done before calling
// this ptr() function.
- if (info.alignment.toByteUnitsOptional()) |info_align| {
- if (have_elem_layout and info_align == info.elem_type.toType().abiAlignment(mod)) {
- canon_info.alignment = .none;
+ if (info.flags.alignment.toByteUnitsOptional()) |info_align| {
+ if (have_elem_layout and info_align == info.child.toType().abiAlignment(mod)) {
+ canon_info.flags.alignment = .none;
}
}
- switch (info.vector_index) {
+ switch (info.flags.vector_index) {
// Canonicalize host_size. If it matches the bit size of the pointee type,
// we change it to 0 here. If this causes an assertion trip, the pointee type
// needs to be resolved before calling this ptr() function.
- .none => if (have_elem_layout and info.host_size != 0) {
- const elem_bit_size = info.elem_type.toType().bitSize(mod);
- assert(info.bit_offset + elem_bit_size <= info.host_size * 8);
- if (info.host_size * 8 == elem_bit_size) {
- canon_info.host_size = 0;
+ .none => if (have_elem_layout and info.packed_offset.host_size != 0) {
+ const elem_bit_size = info.child.toType().bitSize(mod);
+ assert(info.packed_offset.bit_offset + elem_bit_size <= info.packed_offset.host_size * 8);
+ if (info.packed_offset.host_size * 8 == elem_bit_size) {
+ canon_info.packed_offset.host_size = 0;
}
},
.runtime => {},
- _ => assert(@enumToInt(info.vector_index) < info.host_size),
+ _ => assert(@enumToInt(info.flags.vector_index) < info.packed_offset.host_size),
}
return (try intern(mod, .{ .ptr_type = canon_info })).toType();
}
pub fn singleMutPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
- return ptrType(mod, .{ .elem_type = child_type.toIntern() });
+ return ptrType(mod, .{ .child = child_type.toIntern() });
}
pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
- return ptrType(mod, .{ .elem_type = child_type.toIntern(), .is_const = true });
+ return ptrType(mod, .{
+ .child = child_type.toIntern(),
+ .flags = .{
+ .is_const = true,
+ },
+ });
}
pub fn manyConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
- return ptrType(mod, .{ .elem_type = child_type.toIntern(), .size = .Many, .is_const = true });
+ return ptrType(mod, .{
+ .child = child_type.toIntern(),
+ .flags = .{
+ .size = .Many,
+ .is_const = true,
+ },
+ });
}
pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {
const info = Type.ptrInfoIp(&mod.intern_pool, ptr_ty.toIntern());
return mod.ptrType(.{
- .elem_type = new_child.toIntern(),
-
+ .child = new_child.toIntern(),
.sentinel = info.sentinel,
- .alignment = info.alignment,
- .host_size = info.host_size,
- .bit_offset = info.bit_offset,
- .vector_index = info.vector_index,
- .size = info.size,
- .is_const = info.is_const,
- .is_volatile = info.is_volatile,
- .is_allowzero = info.is_allowzero,
- .address_space = info.address_space,
+ .flags = info.flags,
+ .packed_offset = info.packed_offset,
});
}