Commit d7bd4f339c

Jacob Young <jacobly0@users.noreply.github.com>
2023-06-20 19:44:24
Sema: optimize value resolution
1 parent 6b56f4f
Changed files (3)
src/InternPool.zig
@@ -622,6 +622,8 @@ pub const Key = union(enum) {
         len: Index = .none,
 
         pub const Addr = union(enum) {
+            const Tag = @typeInfo(Addr).Union.tag_type.?;
+
             decl: Module.Decl.Index,
             mut_decl: MutDecl,
             comptime_field: Index,
@@ -5702,10 +5704,18 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
     };
 }
 
+pub fn isUndef(ip: *const InternPool, val: Index) bool {
+    return val == .undef or ip.items.items(.tag)[@intFromEnum(val)] == .undef;
+}
+
 pub fn isRuntimeValue(ip: *const InternPool, val: Index) bool {
     return ip.items.items(.tag)[@intFromEnum(val)] == .runtime_value;
 }
 
+pub fn isVariable(ip: *const InternPool, val: Index) bool {
+    return ip.items.items(.tag)[@intFromEnum(val)] == .variable;
+}
+
 pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalIndex {
     var base = @intFromEnum(val);
     while (true) {
@@ -5730,6 +5740,29 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalInd
     }
 }
 
+pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag {
+    var base = @intFromEnum(val);
+    while (true) {
+        switch (ip.items.items(.tag)[base]) {
+            .ptr_decl => return .decl,
+            .ptr_mut_decl => return .mut_decl,
+            .ptr_comptime_field => return .comptime_field,
+            .ptr_int => return .int,
+            inline .ptr_eu_payload,
+            .ptr_opt_payload,
+            .ptr_elem,
+            .ptr_field,
+            => |tag| base = ip.extra.items[
+                ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "base").?
+            ],
+            inline .ptr_slice => |tag| base = ip.extra.items[
+                ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "ptr").?
+            ],
+            else => return null,
+        }
+    }
+}
+
 /// 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: *const InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId {
src/Sema.zig
@@ -1898,13 +1898,10 @@ fn resolveConstMaybeUndefVal(
     reason: []const u8,
 ) CompileError!Value {
     if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| {
-        switch (val.toIntern()) {
-            .generic_poison => return error.GenericPoison,
-            else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {
-                .variable => return sema.failWithNeededComptime(block, src, reason),
-                else => return val,
-            },
-        }
+        if (val.isGenericPoison()) return error.GenericPoison;
+        if (sema.mod.intern_pool.isVariable(val.toIntern()))
+            return sema.failWithNeededComptime(block, src, reason);
+        return val;
     }
     return sema.failWithNeededComptime(block, src, reason);
 }
@@ -1919,15 +1916,11 @@ fn resolveConstValue(
     reason: []const u8,
 ) CompileError!Value {
     if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {
-        switch (val.toIntern()) {
-            .generic_poison => return error.GenericPoison,
-            .undef => return sema.failWithUseOfUndef(block, src),
-            else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {
-                .undef => return sema.failWithUseOfUndef(block, src),
-                .variable => return sema.failWithNeededComptime(block, src, reason),
-                else => return val,
-            },
-        }
+        if (val.isGenericPoison()) return error.GenericPoison;
+        if (val.isUndef(sema.mod)) return sema.failWithUseOfUndef(block, src);
+        if (sema.mod.intern_pool.isVariable(val.toIntern()))
+            return sema.failWithNeededComptime(block, src, reason);
+        return val;
     }
     return sema.failWithNeededComptime(block, src, reason);
 }
@@ -1971,14 +1964,9 @@ fn resolveMaybeUndefVal(
     inst: Air.Inst.Ref,
 ) CompileError!?Value {
     const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
-    switch (val.ip_index) {
-        .generic_poison => return error.GenericPoison,
-        .none => return val,
-        else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {
-            .variable => return null,
-            else => return val,
-        },
-    }
+    if (val.isGenericPoison()) return error.GenericPoison;
+    if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null;
+    return val;
 }
 
 /// Value Tag `variable` causes this function to return `null`.
@@ -2002,20 +1990,13 @@ fn resolveMaybeUndefValIntable(
     inst: Air.Inst.Ref,
 ) CompileError!?Value {
     const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
-    var check = val;
-    while (true) switch (check.ip_index) {
-        .generic_poison => return error.GenericPoison,
-        .none => break,
-        else => switch (sema.mod.intern_pool.indexToKey(check.toIntern())) {
-            .variable => return null,
-            .ptr => |ptr| switch (ptr.addr) {
-                .decl, .mut_decl, .comptime_field => return null,
-                .int => break,
-                .eu_payload, .opt_payload => |base| check = base.toValue(),
-                .elem, .field => |base_index| check = base_index.base.toValue(),
-            },
-            else => break,
-        },
+    if (val.isGenericPoison()) return error.GenericPoison;
+    if (val.ip_index == .none) return val;
+    if (sema.mod.intern_pool.isVariable(val.toIntern())) return null;
+    if (sema.mod.intern_pool.getBackingAddrTag(val.toIntern())) |addr| switch (addr) {
+        .decl, .mut_decl, .comptime_field => return null,
+        .int => {},
+        .eu_payload, .opt_payload, .elem, .field => unreachable,
     };
     return try sema.resolveLazyValue(val);
 }
src/value.zig
@@ -1991,12 +1991,7 @@ pub const Value = struct {
     }
 
     pub fn isUndef(val: Value, mod: *Module) bool {
-        if (val.ip_index == .none) return false;
-        return switch (mod.intern_pool.indexToKey(val.toIntern())) {
-            .undef => true,
-            .simple_value => |v| v == .undefined,
-            else => false,
-        };
+        return val.ip_index != .none and mod.intern_pool.isUndef(val.toIntern());
     }
 
     /// TODO: check for cases such as array that is not marked undef but all the element