authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-28 20:33:50-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-28 20:33:50-07:00
log7efc2a06264170632e56256a5fad97e945768056
treef96446fade460810afbdf4ccc003be2069e378de
parent51a40f9a666085b53353f65f017bcf9bf18daaa3

AstGen: improved logic for nodeMayNeedMemoryLocation

* `@as` and `@bitCast` no longer unconditionally return `true` from this function; they forward the question to their sub-expression. * fix `@splat` incorrectly being marked as needing a memory location (this function returns a SIMD vector; it definitely does not want a memory location). Makes AstGen generate slightly nicer ZIR, which in turn generates slightly nicer AIR, generating slightly nicer machine code in debug builds. It also means I can procrastinate implementing the bitcast_result_ptr ZIR instruction semantic analysis :^)

2 files changed, 37 insertions(+), 15 deletions(-)

src/AstGen.zig+20-6
......@@ -8271,17 +8271,31 @@ fn nodeMayNeedMemoryLocation(tree: *const Ast, start_node: Ast.Node.Index) bool
82718271 }
82728272 },
82738273
8274 .builtin_call,
8275 .builtin_call_comma,
8276 .builtin_call_two,
8277 .builtin_call_two_comma,
8278 => {
8274 .builtin_call_two, .builtin_call_two_comma => {
8275 const builtin_token = main_tokens[node];
8276 const builtin_name = tree.tokenSlice(builtin_token);
8277 // If the builtin is an invalid name, we don't cause an error here; instead
8278 // let it pass, and the error will be "invalid builtin function" later.
8279 const builtin_info = BuiltinFn.list.get(builtin_name) orelse return false;
8280 switch (builtin_info.needs_mem_loc) {
8281 .never => return false,
8282 .always => return true,
8283 .forward1 => node = node_datas[node].rhs,
8284 }
8285 },
8286
8287 .builtin_call, .builtin_call_comma => {
8288 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
82798289 const builtin_token = main_tokens[node];
82808290 const builtin_name = tree.tokenSlice(builtin_token);
82818291 // If the builtin is an invalid name, we don't cause an error here; instead
82828292 // let it pass, and the error will be "invalid builtin function" later.
82838293 const builtin_info = BuiltinFn.list.get(builtin_name) orelse return false;
8284 return builtin_info.needs_mem_loc;
8294 switch (builtin_info.needs_mem_loc) {
8295 .never => return false,
8296 .always => return true,
8297 .forward1 => node = params[1],
8298 }
82858299 },
82868300 }
82878301 }
src/BuiltinFn.zig+17-9
......@@ -110,10 +110,19 @@ pub const Tag = enum {
110110 Vector,
111111};
112112
113pub const MemLocRequirement = enum {
114 /// The builtin never needs a memory location.
115 never,
116 /// The builtin always needs a memory location.
117 always,
118 /// The builtin forwards the question to argument at index 1.
119 forward1,
120};
121
113122tag: Tag,
114123
115/// `true` if the builtin call can take advantage of a result location pointer.
116needs_mem_loc: bool = false,
124/// Info about the builtin call's ability to take advantage of a result location pointer.
125needs_mem_loc: MemLocRequirement = .never,
117126/// `true` if the builtin call can be the left-hand side of an expression (assigned to).
118127allows_lvalue: bool = false,
119128/// The number of parameters to this builtin function. `null` means variable number
......@@ -148,7 +157,7 @@ pub const list = list: {
148157 "@as",
149158 .{
150159 .tag = .as,
151 .needs_mem_loc = true,
160 .needs_mem_loc = .forward1,
152161 .param_count = 2,
153162 },
154163 },
......@@ -184,7 +193,7 @@ pub const list = list: {
184193 "@bitCast",
185194 .{
186195 .tag = .bit_cast,
187 .needs_mem_loc = true,
196 .needs_mem_loc = .forward1,
188197 .param_count = 2,
189198 },
190199 },
......@@ -248,7 +257,7 @@ pub const list = list: {
248257 "@call",
249258 .{
250259 .tag = .call,
251 .needs_mem_loc = true,
260 .needs_mem_loc = .always,
252261 .param_count = 3,
253262 },
254263 },
......@@ -410,7 +419,7 @@ pub const list = list: {
410419 "@field",
411420 .{
412421 .tag = .field,
413 .needs_mem_loc = true,
422 .needs_mem_loc = .always,
414423 .param_count = 2,
415424 .allows_lvalue = true,
416425 },
......@@ -699,7 +708,6 @@ pub const list = list: {
699708 "@splat",
700709 .{
701710 .tag = .splat,
702 .needs_mem_loc = true,
703711 .param_count = 2,
704712 },
705713 },
......@@ -714,7 +722,7 @@ pub const list = list: {
714722 "@src",
715723 .{
716724 .tag = .src,
717 .needs_mem_loc = true,
725 .needs_mem_loc = .always,
718726 .param_count = 0,
719727 },
720728 },
......@@ -869,7 +877,7 @@ pub const list = list: {
869877 "@unionInit",
870878 .{
871879 .tag = .union_init,
872 .needs_mem_loc = true,
880 .needs_mem_loc = .always,
873881 .param_count = 3,
874882 },
875883 },