authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-06-20 13:44:24-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-06-20 14:02:09-04:00
logd7bd4f339c90b9ce07283600cb7ef129912ceef3
treeff3d181923df575edd51562397f60c93eff8d8e7
parent6b56f4ff0bf9ac9c5e0b4a11cf0536472447bc4a

Sema: optimize value resolution


3 files changed, 53 insertions(+), 44 deletions(-)

src/InternPool.zig+33
...@@ -622,6 +622,8 @@ pub const Key = union(enum) {...@@ -622,6 +622,8 @@ pub const Key = union(enum) {
622 len: Index = .none,622 len: Index = .none,
623623
624 pub const Addr = union(enum) {624 pub const Addr = union(enum) {
625 const Tag = @typeInfo(Addr).Union.tag_type.?;
626
625 decl: Module.Decl.Index,627 decl: Module.Decl.Index,
626 mut_decl: MutDecl,628 mut_decl: MutDecl,
627 comptime_field: Index,629 comptime_field: Index,
...@@ -5702,10 +5704,18 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {...@@ -5702,10 +5704,18 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
5702 };5704 };
5703}5705}
57045706
5707pub fn isUndef(ip: *const InternPool, val: Index) bool {
5708 return val == .undef or ip.items.items(.tag)[@intFromEnum(val)] == .undef;
5709}
5710
5705pub fn isRuntimeValue(ip: *const InternPool, val: Index) bool {5711pub fn isRuntimeValue(ip: *const InternPool, val: Index) bool {
5706 return ip.items.items(.tag)[@intFromEnum(val)] == .runtime_value;5712 return ip.items.items(.tag)[@intFromEnum(val)] == .runtime_value;
5707}5713}
57085714
5715pub fn isVariable(ip: *const InternPool, val: Index) bool {
5716 return ip.items.items(.tag)[@intFromEnum(val)] == .variable;
5717}
5718
5709pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalIndex {5719pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalIndex {
5710 var base = @intFromEnum(val);5720 var base = @intFromEnum(val);
5711 while (true) {5721 while (true) {
...@@ -5730,6 +5740,29 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalInd...@@ -5730,6 +5740,29 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalInd
5730 }5740 }
5731}5741}
57325742
5743pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag {
5744 var base = @intFromEnum(val);
5745 while (true) {
5746 switch (ip.items.items(.tag)[base]) {
5747 .ptr_decl => return .decl,
5748 .ptr_mut_decl => return .mut_decl,
5749 .ptr_comptime_field => return .comptime_field,
5750 .ptr_int => return .int,
5751 inline .ptr_eu_payload,
5752 .ptr_opt_payload,
5753 .ptr_elem,
5754 .ptr_field,
5755 => |tag| base = ip.extra.items[
5756 ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "base").?
5757 ],
5758 inline .ptr_slice => |tag| base = ip.extra.items[
5759 ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "ptr").?
5760 ],
5761 else => return null,
5762 }
5763 }
5764}
5765
5733/// This is a particularly hot function, so we operate directly on encodings5766/// This is a particularly hot function, so we operate directly on encodings
5734/// rather than the more straightforward implementation of calling `indexToKey`.5767/// rather than the more straightforward implementation of calling `indexToKey`.
5735pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId {5768pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId {
src/Sema.zig+19-38
...@@ -1898,13 +1898,10 @@ fn resolveConstMaybeUndefVal(...@@ -1898,13 +1898,10 @@ fn resolveConstMaybeUndefVal(
1898 reason: []const u8,1898 reason: []const u8,
1899) CompileError!Value {1899) CompileError!Value {
1900 if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| {1900 if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| {
1901 switch (val.toIntern()) {1901 if (val.isGenericPoison()) return error.GenericPoison;
1902 .generic_poison => return error.GenericPoison,1902 if (sema.mod.intern_pool.isVariable(val.toIntern()))
1903 else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {1903 return sema.failWithNeededComptime(block, src, reason);
1904 .variable => return sema.failWithNeededComptime(block, src, reason),1904 return val;
1905 else => return val,
1906 },
1907 }
1908 }1905 }
1909 return sema.failWithNeededComptime(block, src, reason);1906 return sema.failWithNeededComptime(block, src, reason);
1910}1907}
...@@ -1919,15 +1916,11 @@ fn resolveConstValue(...@@ -1919,15 +1916,11 @@ fn resolveConstValue(
1919 reason: []const u8,1916 reason: []const u8,
1920) CompileError!Value {1917) CompileError!Value {
1921 if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {1918 if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {
1922 switch (val.toIntern()) {1919 if (val.isGenericPoison()) return error.GenericPoison;
1923 .generic_poison => return error.GenericPoison,1920 if (val.isUndef(sema.mod)) return sema.failWithUseOfUndef(block, src);
1924 .undef => return sema.failWithUseOfUndef(block, src),1921 if (sema.mod.intern_pool.isVariable(val.toIntern()))
1925 else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {1922 return sema.failWithNeededComptime(block, src, reason);
1926 .undef => return sema.failWithUseOfUndef(block, src),1923 return val;
1927 .variable => return sema.failWithNeededComptime(block, src, reason),
1928 else => return val,
1929 },
1930 }
1931 }1924 }
1932 return sema.failWithNeededComptime(block, src, reason);1925 return sema.failWithNeededComptime(block, src, reason);
1933}1926}
...@@ -1971,14 +1964,9 @@ fn resolveMaybeUndefVal(...@@ -1971,14 +1964,9 @@ fn resolveMaybeUndefVal(
1971 inst: Air.Inst.Ref,1964 inst: Air.Inst.Ref,
1972) CompileError!?Value {1965) CompileError!?Value {
1973 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;1966 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
1974 switch (val.ip_index) {1967 if (val.isGenericPoison()) return error.GenericPoison;
1975 .generic_poison => return error.GenericPoison,1968 if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null;
1976 .none => return val,1969 return val;
1977 else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {
1978 .variable => return null,
1979 else => return val,
1980 },
1981 }
1982}1970}
19831971
1984/// Value Tag `variable` causes this function to return `null`.1972/// Value Tag `variable` causes this function to return `null`.
...@@ -2002,20 +1990,13 @@ fn resolveMaybeUndefValIntable(...@@ -2002,20 +1990,13 @@ fn resolveMaybeUndefValIntable(
2002 inst: Air.Inst.Ref,1990 inst: Air.Inst.Ref,
2003) CompileError!?Value {1991) CompileError!?Value {
2004 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;1992 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
2005 var check = val;1993 if (val.isGenericPoison()) return error.GenericPoison;
2006 while (true) switch (check.ip_index) {1994 if (val.ip_index == .none) return val;
2007 .generic_poison => return error.GenericPoison,1995 if (sema.mod.intern_pool.isVariable(val.toIntern())) return null;
2008 .none => break,1996 if (sema.mod.intern_pool.getBackingAddrTag(val.toIntern())) |addr| switch (addr) {
2009 else => switch (sema.mod.intern_pool.indexToKey(check.toIntern())) {1997 .decl, .mut_decl, .comptime_field => return null,
2010 .variable => return null,1998 .int => {},
2011 .ptr => |ptr| switch (ptr.addr) {1999 .eu_payload, .opt_payload, .elem, .field => unreachable,
2012 .decl, .mut_decl, .comptime_field => return null,
2013 .int => break,
2014 .eu_payload, .opt_payload => |base| check = base.toValue(),
2015 .elem, .field => |base_index| check = base_index.base.toValue(),
2016 },
2017 else => break,
2018 },
2019 };2000 };
2020 return try sema.resolveLazyValue(val);2001 return try sema.resolveLazyValue(val);
2021}2002}
src/value.zig+1-6
...@@ -1991,12 +1991,7 @@ pub const Value = struct {...@@ -1991,12 +1991,7 @@ pub const Value = struct {
1991 }1991 }
19921992
1993 pub fn isUndef(val: Value, mod: *Module) bool {1993 pub fn isUndef(val: Value, mod: *Module) bool {
1994 if (val.ip_index == .none) return false;1994 return val.ip_index != .none and mod.intern_pool.isUndef(val.toIntern());
1995 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1996 .undef => true,
1997 .simple_value => |v| v == .undefined,
1998 else => false,
1999 };
2000 }1995 }
20011996
2002 /// TODO: check for cases such as array that is not marked undef but all the element1997 /// TODO: check for cases such as array that is not marked undef but all the element