Commit c8b0d4d149

Andrew Kelley <andrew@ziglang.org>
2023-05-27 06:14:18
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.
1 parent fc35843
Changed files (2)
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
+    };
+}
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 {