From c8b0d4d149c891ed83db57fe6986d10c5dd654af Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 26 May 2023 21:14:18 -0700 Subject: [PATCH] InternPool: optimize zigTypeTag() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a particularly hot function, so we operate directly on encodings rather than the more straightforward implementation of calling `indexToKey`. I measured this as 1.05 ± 0.04 times faster than the previous commit with a ReleaseFast build against hello world (which includes std.debug and formatted printing). I also profiled the function and found that zigTypeTag() went from being a major caller of `indexToKey` to being completely insignificant due to being so fast. --- src/InternPool.zig | 201 +++++++++++++++++++++++++++++++++++++++++++++ src/type.zig | 87 +------------------- 2 files changed, 202 insertions(+), 86 deletions(-) diff --git a/src/InternPool.zig b/src/InternPool.zig index 07e74ffe35..fdc0a9af3a 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -4899,3 +4899,204 @@ pub fn isNoReturn(ip: InternPool, ty: Index) bool { }, }; } + +/// This is a particularly hot function, so we operate directly on encodings +/// rather than the more straightforward implementation of calling `indexToKey`. +pub fn zigTypeTagOrPoison(ip: InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId { + return switch (index) { + .u1_type, + .u8_type, + .i8_type, + .u16_type, + .i16_type, + .u29_type, + .u32_type, + .i32_type, + .u64_type, + .i64_type, + .u80_type, + .u128_type, + .i128_type, + .usize_type, + .isize_type, + .c_char_type, + .c_short_type, + .c_ushort_type, + .c_int_type, + .c_uint_type, + .c_long_type, + .c_ulong_type, + .c_longlong_type, + .c_ulonglong_type, + => .Int, + + .c_longdouble_type, + .f16_type, + .f32_type, + .f64_type, + .f80_type, + .f128_type, + => .Float, + + .anyopaque_type => .Opaque, + .bool_type => .Bool, + .void_type => .Void, + .type_type => .Type, + .anyerror_type => .ErrorSet, + .comptime_int_type => .ComptimeInt, + .comptime_float_type => .ComptimeFloat, + .noreturn_type => .NoReturn, + .anyframe_type => .AnyFrame, + .null_type => .Null, + .undefined_type => .Undefined, + .enum_literal_type => .EnumLiteral, + + .atomic_order_type, + .atomic_rmw_op_type, + .calling_convention_type, + .address_space_type, + .float_mode_type, + .reduce_op_type, + .call_modifier_type, + => .Enum, + + .prefetch_options_type, + .export_options_type, + .extern_options_type, + => .Struct, + + .type_info_type => .Union, + + .manyptr_u8_type, + .manyptr_const_u8_type, + .manyptr_const_u8_sentinel_0_type, + .single_const_pointer_to_comptime_int_type, + .slice_const_u8_type, + .slice_const_u8_sentinel_0_type, + => .Pointer, + + .anyerror_void_error_union_type => .ErrorUnion, + .empty_struct_type => .Struct, + + .generic_poison_type => return error.GenericPoison, + + // values, not types + .undef => unreachable, + .zero => unreachable, + .zero_usize => unreachable, + .zero_u8 => unreachable, + .one => unreachable, + .one_usize => unreachable, + .one_u8 => unreachable, + .four_u8 => unreachable, + .negative_one => unreachable, + .calling_convention_c => unreachable, + .calling_convention_inline => unreachable, + .void_value => unreachable, + .unreachable_value => unreachable, + .null_value => unreachable, + .bool_true => unreachable, + .bool_false => unreachable, + .empty_struct => unreachable, + .generic_poison => unreachable, + + .var_args_param_type => unreachable, // special tag + + _ => switch (ip.items.items(.tag)[@enumToInt(index)]) { + .type_int_signed, + .type_int_unsigned, + => .Int, + + .type_array_big, + .type_array_small, + => .Array, + + .type_vector => .Vector, + + .type_pointer, + .type_slice, + => .Pointer, + + .type_optional => .Optional, + .type_anyframe => .AnyFrame, + .type_error_union => .ErrorUnion, + + .type_error_set, + .type_inferred_error_set, + => .ErrorSet, + + .type_enum_auto, + .type_enum_explicit, + .type_enum_nonexhaustive, + => .Enum, + + .simple_type => unreachable, // handled via Index tag above + + .type_opaque => .Opaque, + + .type_struct, + .type_struct_ns, + .type_struct_anon, + .type_tuple_anon, + => .Struct, + + .type_union_tagged, + .type_union_untagged, + .type_union_safety, + => .Union, + + .type_function => .Fn, + + // values, not types + .undef, + .runtime_value, + .simple_value, + .ptr_mut_decl, + .ptr_decl, + .ptr_int, + .ptr_eu_payload, + .ptr_opt_payload, + .ptr_comptime_field, + .ptr_elem, + .ptr_field, + .ptr_slice, + .opt_payload, + .opt_null, + .int_u8, + .int_u16, + .int_u32, + .int_i32, + .int_usize, + .int_comptime_int_u32, + .int_comptime_int_i32, + .int_small, + .int_positive, + .int_negative, + .int_lazy_align, + .int_lazy_size, + .error_set_error, + .error_union_error, + .error_union_payload, + .enum_literal, + .enum_tag, + .float_f16, + .float_f32, + .float_f64, + .float_f80, + .float_f128, + .float_c_longdouble_f80, + .float_c_longdouble_f128, + .float_comptime_float, + .variable, + .extern_func, + .func, + .only_possible_value, + .union_value, + .bytes, + .aggregate, + .repeated, + => unreachable, + }, + .none => unreachable, // special tag + }; +} diff --git a/src/type.zig b/src/type.zig index cb455d5ebe..a9ad8b94fd 100644 --- a/src/type.zig +++ b/src/type.zig @@ -23,92 +23,7 @@ pub const Type = struct { } pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId { - return switch (mod.intern_pool.indexToKey(ty.toIntern())) { - .int_type => .Int, - .ptr_type => .Pointer, - .array_type => .Array, - .vector_type => .Vector, - .opt_type => .Optional, - .error_union_type => .ErrorUnion, - .error_set_type, .inferred_error_set_type => .ErrorSet, - .struct_type, .anon_struct_type => .Struct, - .union_type => .Union, - .opaque_type => .Opaque, - .enum_type => .Enum, - .func_type => .Fn, - .anyframe_type => .AnyFrame, - .simple_type => |s| switch (s) { - .f16, - .f32, - .f64, - .f80, - .f128, - .c_longdouble, - => .Float, - - .usize, - .isize, - .c_char, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - => .Int, - - .anyopaque => .Opaque, - .bool => .Bool, - .void => .Void, - .type => .Type, - .anyerror => .ErrorSet, - .comptime_int => .ComptimeInt, - .comptime_float => .ComptimeFloat, - .noreturn => .NoReturn, - .null => .Null, - .undefined => .Undefined, - .enum_literal => .EnumLiteral, - - .atomic_order, - .atomic_rmw_op, - .calling_convention, - .address_space, - .float_mode, - .reduce_op, - .call_modifier, - => .Enum, - - .prefetch_options, - .export_options, - .extern_options, - => .Struct, - - .type_info => .Union, - - .generic_poison => return error.GenericPoison, - }, - - // values, not types - .undef, - .runtime_value, - .simple_value, - .variable, - .extern_func, - .func, - .int, - .err, - .error_union, - .enum_literal, - .enum_tag, - .float, - .ptr, - .opt, - .aggregate, - .un, - => unreachable, - }; + return mod.intern_pool.zigTypeTagOrPoison(ty.toIntern()); } pub fn baseZigTypeTag(self: Type, mod: *Module) std.builtin.TypeId {