authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-20 15:40:48-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-20 16:17:16-07:00
log1417698c111e7f75d1c6959c7af8cd1a4d5231f6
treef66c94d9c97d231dc5a32fb815f57f420912ad7a
parent4fccc95b0152aefeb40912768ec045b57a2fdc2b

Sema: storePtr optimization for tuples

To generate better code for tuples, we detect a tuple operand in storePtr, and analyze field loads and stores directly. This avoids an extra allocation + memcpy which would occur if we used `coerce`.

1 files changed, 21 insertions(+), 3 deletions(-)

src/Sema.zig+21-3
...@@ -14012,7 +14012,7 @@ fn coerce(...@@ -14012,7 +14012,7 @@ fn coerce(
14012 if (inst == .empty_struct) {14012 if (inst == .empty_struct) {
14013 return arrayInitEmpty(sema, dest_ty);14013 return arrayInitEmpty(sema, dest_ty);
14014 }14014 }
14015 if (inst_ty.tag() == .tuple) {14015 if (inst_ty.isTuple()) {
14016 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);14016 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);
14017 }14017 }
14018 },14018 },
...@@ -14384,12 +14384,30 @@ fn storePtr2(...@@ -14384,12 +14384,30 @@ fn storePtr2(
14384 uncasted_operand: Air.Inst.Ref,14384 uncasted_operand: Air.Inst.Ref,
14385 operand_src: LazySrcLoc,14385 operand_src: LazySrcLoc,
14386 air_tag: Air.Inst.Tag,14386 air_tag: Air.Inst.Tag,
14387) !void {14387) CompileError!void {
14388 const ptr_ty = sema.typeOf(ptr);14388 const ptr_ty = sema.typeOf(ptr);
14389 if (ptr_ty.isConstPtr())14389 if (ptr_ty.isConstPtr())
14390 return sema.fail(block, src, "cannot assign to constant", .{});14390 return sema.fail(block, ptr_src, "cannot assign to constant", .{});
1439114391
14392 const elem_ty = ptr_ty.childType();14392 const elem_ty = ptr_ty.childType();
14393
14394 // To generate better code for tuples, we detect a tuple operand here, and
14395 // analyze field loads and stores directly. This avoids an extra allocation + memcpy
14396 // which would occur if we used `coerce`.
14397 const operand_ty = sema.typeOf(uncasted_operand);
14398 if (operand_ty.castTag(.tuple)) |payload| {
14399 const tuple_fields_len = payload.data.types.len;
14400 var i: u32 = 0;
14401 while (i < tuple_fields_len) : (i += 1) {
14402 const elem_src = operand_src; // TODO better source location
14403 const elem = try tupleField(sema, block, uncasted_operand, i, operand_src, elem_src);
14404 const elem_index = try sema.addIntUnsigned(Type.usize, i);
14405 const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src);
14406 try sema.storePtr2(block, src, elem_ptr, elem_src, elem, elem_src, .store);
14407 }
14408 return;
14409 }
14410
14393 const operand = try sema.coerce(block, elem_ty, uncasted_operand, operand_src);14411 const operand = try sema.coerce(block, elem_ty, uncasted_operand, operand_src);
14394 if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null)14412 if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null)
14395 return;14413 return;