Skip to content

Commit e9b0912

Browse files
committed
AstGen: use {field,elem}_val when they don't cause unnecessary loads
1 parent 48d14b8 commit e9b0912

File tree

1 file changed

+45
-25
lines changed

1 file changed

+45
-25
lines changed

lib/std/zig/AstGen.zig

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6080,6 +6080,9 @@ fn fieldAccess(
60806080
.ref, .ref_coerced_ty => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node),
60816081
.pseudo_ref => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .pseudo_ref }, node),
60826082
else => {
6083+
if ((gz.is_comptime and gz.astgen.fn_block != null) or !nodeAccessesIdentifier(gz.astgen.tree, node)) {
6084+
return rvalue(gz, ri, try addFieldAccess(.field_val, gz, scope, .{ .rl = .none }, node), node);
6085+
}
60836086
const ptr = try addFieldAccess(.field_ptr, gz, scope, .{ .rl = .pseudo_ref }, node);
60846087
const result = try gz.addUnNode(.load, ptr, node);
60856088
return rvalue(gz, ri, result, node);
@@ -6122,40 +6125,32 @@ fn arrayAccess(
61226125
) InnerError!Zir.Inst.Ref {
61236126
const tree = gz.astgen.tree;
61246127
const node_datas = tree.nodes.items(.data);
6125-
switch (ri.rl) {
6126-
.ref, .ref_coerced_ty => {
6127-
const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
6128-
6129-
const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
6130-
6131-
const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
6132-
try emitDbgStmt(gz, cursor);
6133-
6134-
return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
6135-
},
6136-
.pseudo_ref => {
6137-
const lhs = try expr(gz, scope, .{ .rl = .pseudo_ref }, node_datas[node].lhs);
6128+
const lhs_result: ResultInfo, const need_load = switch (ri.rl) {
6129+
.ref, .ref_coerced_ty => .{ .{ .rl = .ref }, false },
6130+
.pseudo_ref => .{ .{ .rl = .pseudo_ref }, false },
6131+
else => if ((gz.is_comptime and gz.astgen.fn_block != null) or !nodeAccessesIdentifier(tree, node)) {
6132+
const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
61386133

61396134
const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
61406135

61416136
const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
61426137
try emitDbgStmt(gz, cursor);
61436138

6144-
return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
6145-
},
6146-
else => {
6147-
const lhs = try expr(gz, scope, .{ .rl = .pseudo_ref }, node_datas[node].lhs);
6139+
return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);
6140+
} else .{ .{ .rl = .pseudo_ref }, true },
6141+
};
6142+
const lhs = try expr(gz, scope, lhs_result, node_datas[node].lhs);
61486143

6149-
const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
6144+
const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
61506145

6151-
const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
6152-
try emitDbgStmt(gz, cursor);
6146+
const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
6147+
try emitDbgStmt(gz, cursor);
61536148

6154-
const ptr = try gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
6155-
const result = try gz.addUnNode(.load, ptr, node);
6156-
return rvalue(gz, ri, result, node);
6157-
},
6158-
}
6149+
const ptr = try gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
6150+
if (!need_load) return ptr;
6151+
6152+
const loaded = try gz.addUnNode(.load, ptr, node);
6153+
return rvalue(gz, ri, loaded, node);
61596154
}
61606155

61616156
fn simpleBinOp(
@@ -10953,6 +10948,31 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
1095310948
}
1095410949
}
1095510950

10951+
/// Returns `true` if field/array access chain ultimately refers to an identifier.
10952+
fn nodeAccessesIdentifier(tree: *const Ast, start_node: Ast.Node.Index) bool {
10953+
const node_tags = tree.nodes.items(.tag);
10954+
const node_datas = tree.nodes.items(.data);
10955+
10956+
var node = start_node;
10957+
while (true) {
10958+
switch (node_tags[node]) {
10959+
.identifier => return true,
10960+
10961+
// Forward the question to the LHS sub-expression.
10962+
.grouped_expression,
10963+
.@"try",
10964+
.@"nosuspend",
10965+
.unwrap_optional,
10966+
.deref,
10967+
.field_access,
10968+
.array_access,
10969+
=> node = node_datas[node].lhs,
10970+
10971+
else => return false,
10972+
}
10973+
}
10974+
}
10975+
1095610976
/// Applies `rl` semantics to `result`. Expressions which do not do their own handling of
1095710977
/// result locations must call this function on their result.
1095810978
/// As an example, if `ri.rl` is `.ptr`, it will write the result to the pointer.

0 commit comments

Comments
 (0)