authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-26 21:14:18-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:56-07:00
logc8b0d4d149c891ed83db57fe6986d10c5dd654af
tree80074b404e9d6b425e233e534f43ffa2c7d96ba9
parentfc358435cb5cbcc21967af438b190d4e18bba9ae

InternPool: optimize zigTypeTag()

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.

2 files changed, 202 insertions(+), 86 deletions(-)

src/InternPool.zig+201
......@@ -4899,3 +4899,204 @@ pub fn isNoReturn(ip: InternPool, ty: Index) bool {
48994899 },
49004900 };
49014901}
4902
4903/// This is a particularly hot function, so we operate directly on encodings
4904/// rather than the more straightforward implementation of calling `indexToKey`.
4905pub fn zigTypeTagOrPoison(ip: InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId {
4906 return switch (index) {
4907 .u1_type,
4908 .u8_type,
4909 .i8_type,
4910 .u16_type,
4911 .i16_type,
4912 .u29_type,
4913 .u32_type,
4914 .i32_type,
4915 .u64_type,
4916 .i64_type,
4917 .u80_type,
4918 .u128_type,
4919 .i128_type,
4920 .usize_type,
4921 .isize_type,
4922 .c_char_type,
4923 .c_short_type,
4924 .c_ushort_type,
4925 .c_int_type,
4926 .c_uint_type,
4927 .c_long_type,
4928 .c_ulong_type,
4929 .c_longlong_type,
4930 .c_ulonglong_type,
4931 => .Int,
4932
4933 .c_longdouble_type,
4934 .f16_type,
4935 .f32_type,
4936 .f64_type,
4937 .f80_type,
4938 .f128_type,
4939 => .Float,
4940
4941 .anyopaque_type => .Opaque,
4942 .bool_type => .Bool,
4943 .void_type => .Void,
4944 .type_type => .Type,
4945 .anyerror_type => .ErrorSet,
4946 .comptime_int_type => .ComptimeInt,
4947 .comptime_float_type => .ComptimeFloat,
4948 .noreturn_type => .NoReturn,
4949 .anyframe_type => .AnyFrame,
4950 .null_type => .Null,
4951 .undefined_type => .Undefined,
4952 .enum_literal_type => .EnumLiteral,
4953
4954 .atomic_order_type,
4955 .atomic_rmw_op_type,
4956 .calling_convention_type,
4957 .address_space_type,
4958 .float_mode_type,
4959 .reduce_op_type,
4960 .call_modifier_type,
4961 => .Enum,
4962
4963 .prefetch_options_type,
4964 .export_options_type,
4965 .extern_options_type,
4966 => .Struct,
4967
4968 .type_info_type => .Union,
4969
4970 .manyptr_u8_type,
4971 .manyptr_const_u8_type,
4972 .manyptr_const_u8_sentinel_0_type,
4973 .single_const_pointer_to_comptime_int_type,
4974 .slice_const_u8_type,
4975 .slice_const_u8_sentinel_0_type,
4976 => .Pointer,
4977
4978 .anyerror_void_error_union_type => .ErrorUnion,
4979 .empty_struct_type => .Struct,
4980
4981 .generic_poison_type => return error.GenericPoison,
4982
4983 // values, not types
4984 .undef => unreachable,
4985 .zero => unreachable,
4986 .zero_usize => unreachable,
4987 .zero_u8 => unreachable,
4988 .one => unreachable,
4989 .one_usize => unreachable,
4990 .one_u8 => unreachable,
4991 .four_u8 => unreachable,
4992 .negative_one => unreachable,
4993 .calling_convention_c => unreachable,
4994 .calling_convention_inline => unreachable,
4995 .void_value => unreachable,
4996 .unreachable_value => unreachable,
4997 .null_value => unreachable,
4998 .bool_true => unreachable,
4999 .bool_false => unreachable,
5000 .empty_struct => unreachable,
5001 .generic_poison => unreachable,
5002
5003 .var_args_param_type => unreachable, // special tag
5004
5005 _ => switch (ip.items.items(.tag)[@enumToInt(index)]) {
5006 .type_int_signed,
5007 .type_int_unsigned,
5008 => .Int,
5009
5010 .type_array_big,
5011 .type_array_small,
5012 => .Array,
5013
5014 .type_vector => .Vector,
5015
5016 .type_pointer,
5017 .type_slice,
5018 => .Pointer,
5019
5020 .type_optional => .Optional,
5021 .type_anyframe => .AnyFrame,
5022 .type_error_union => .ErrorUnion,
5023
5024 .type_error_set,
5025 .type_inferred_error_set,
5026 => .ErrorSet,
5027
5028 .type_enum_auto,
5029 .type_enum_explicit,
5030 .type_enum_nonexhaustive,
5031 => .Enum,
5032
5033 .simple_type => unreachable, // handled via Index tag above
5034
5035 .type_opaque => .Opaque,
5036
5037 .type_struct,
5038 .type_struct_ns,
5039 .type_struct_anon,
5040 .type_tuple_anon,
5041 => .Struct,
5042
5043 .type_union_tagged,
5044 .type_union_untagged,
5045 .type_union_safety,
5046 => .Union,
5047
5048 .type_function => .Fn,
5049
5050 // values, not types
5051 .undef,
5052 .runtime_value,
5053 .simple_value,
5054 .ptr_mut_decl,
5055 .ptr_decl,
5056 .ptr_int,
5057 .ptr_eu_payload,
5058 .ptr_opt_payload,
5059 .ptr_comptime_field,
5060 .ptr_elem,
5061 .ptr_field,
5062 .ptr_slice,
5063 .opt_payload,
5064 .opt_null,
5065 .int_u8,
5066 .int_u16,
5067 .int_u32,
5068 .int_i32,
5069 .int_usize,
5070 .int_comptime_int_u32,
5071 .int_comptime_int_i32,
5072 .int_small,
5073 .int_positive,
5074 .int_negative,
5075 .int_lazy_align,
5076 .int_lazy_size,
5077 .error_set_error,
5078 .error_union_error,
5079 .error_union_payload,
5080 .enum_literal,
5081 .enum_tag,
5082 .float_f16,
5083 .float_f32,
5084 .float_f64,
5085 .float_f80,
5086 .float_f128,
5087 .float_c_longdouble_f80,
5088 .float_c_longdouble_f128,
5089 .float_comptime_float,
5090 .variable,
5091 .extern_func,
5092 .func,
5093 .only_possible_value,
5094 .union_value,
5095 .bytes,
5096 .aggregate,
5097 .repeated,
5098 => unreachable,
5099 },
5100 .none => unreachable, // special tag
5101 };
5102}
src/type.zig+1-86
......@@ -23,92 +23,7 @@ pub const Type = struct {
2323 }
2424
2525 pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId {
26 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
27 .int_type => .Int,
28 .ptr_type => .Pointer,
29 .array_type => .Array,
30 .vector_type => .Vector,
31 .opt_type => .Optional,
32 .error_union_type => .ErrorUnion,
33 .error_set_type, .inferred_error_set_type => .ErrorSet,
34 .struct_type, .anon_struct_type => .Struct,
35 .union_type => .Union,
36 .opaque_type => .Opaque,
37 .enum_type => .Enum,
38 .func_type => .Fn,
39 .anyframe_type => .AnyFrame,
40 .simple_type => |s| switch (s) {
41 .f16,
42 .f32,
43 .f64,
44 .f80,
45 .f128,
46 .c_longdouble,
47 => .Float,
48
49 .usize,
50 .isize,
51 .c_char,
52 .c_short,
53 .c_ushort,
54 .c_int,
55 .c_uint,
56 .c_long,
57 .c_ulong,
58 .c_longlong,
59 .c_ulonglong,
60 => .Int,
61
62 .anyopaque => .Opaque,
63 .bool => .Bool,
64 .void => .Void,
65 .type => .Type,
66 .anyerror => .ErrorSet,
67 .comptime_int => .ComptimeInt,
68 .comptime_float => .ComptimeFloat,
69 .noreturn => .NoReturn,
70 .null => .Null,
71 .undefined => .Undefined,
72 .enum_literal => .EnumLiteral,
73
74 .atomic_order,
75 .atomic_rmw_op,
76 .calling_convention,
77 .address_space,
78 .float_mode,
79 .reduce_op,
80 .call_modifier,
81 => .Enum,
82
83 .prefetch_options,
84 .export_options,
85 .extern_options,
86 => .Struct,
87
88 .type_info => .Union,
89
90 .generic_poison => return error.GenericPoison,
91 },
92
93 // values, not types
94 .undef,
95 .runtime_value,
96 .simple_value,
97 .variable,
98 .extern_func,
99 .func,
100 .int,
101 .err,
102 .error_union,
103 .enum_literal,
104 .enum_tag,
105 .float,
106 .ptr,
107 .opt,
108 .aggregate,
109 .un,
110 => unreachable,
111 };
26 return mod.intern_pool.zigTypeTagOrPoison(ty.toIntern());
11227 }
11328
11429 pub fn baseZigTypeTag(self: Type, mod: *Module) std.builtin.TypeId {