@@ -14562,8 +14562,9 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1456214562
1456314563 const mutable_alloc = try block.addTy(.alloc, alloc_ty);
1456414564
14565- // if both the source and destination are arrays
14566- // we can hotpath via a memcpy.
14565+ // there's nothing to copy
14566+ if (result_len == 0 and res_sent_val == null) return mutable_alloc;
14567+
1456714568 if (lhs_ty.zigTypeTag(zcu) == .pointer and
1456814569 rhs_ty.zigTypeTag(zcu) == .pointer)
1456914570 {
@@ -14576,48 +14577,83 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1457614577 });
1457714578
1457814579 const many_ty = slice_ty.slicePtrFieldType(zcu);
14579- const many_alloc = try block.addBitCast (many_ty, mutable_alloc );
14580+ const many_ty_ref = Air.internedToRef (many_ty.toIntern() );
1458014581
14581- // lhs_dest_slice = dest[0..lhs.len]
14582- const slice_ty_ref = Air.internedToRef(slice_ty.toIntern());
1458314582 const lhs_len_ref = try pt.intRef(.usize, lhs_len);
14584- const lhs_dest_slice = try block.addInst(.{
14585- .tag = .slice,
14586- .data = .{ .ty_pl = .{
14587- .ty = slice_ty_ref,
14588- .payload = try sema.addExtra(Air.Bin{
14589- .lhs = many_alloc,
14590- .rhs = lhs_len_ref,
14591- }),
14592- } },
14593- });
1459414583
14595- _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs);
14584+ // @memcpy(@as(*[lhs.len]T, dst[0..lhs.len]), lhs.ptr)
14585+ if (lhs_len != 0) {
14586+ const lhs_dest_slice = switch (rhs_len) {
14587+ 0 => mutable_alloc,
14588+ else => s: {
14589+ // [lhs.len]T
14590+ const array_ty = try pt.arrayType(.{
14591+ .child = resolved_elem_ty.toIntern(),
14592+ .len = lhs_len,
14593+ });
14594+ // *[lhs.len]T
14595+ const mutable_ty = try pt.ptrTypeSema(.{
14596+ .child = array_ty.toIntern(),
14597+ .flags = .{ .address_space = ptr_as },
14598+ });
14599+ break :s try block.addBitCast(mutable_ty, mutable_alloc);
14600+ },
14601+ };
14602+ const lhs_src_pointer = if (lhs_ty.isSlice(zcu))
14603+ try block.addInst(.{
14604+ .tag = .slice_ptr,
14605+ .data = .{ .ty_op = .{
14606+ .ty = many_ty_ref,
14607+ .operand = lhs,
14608+ } },
14609+ })
14610+ else
14611+ lhs;
14612+ _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs_src_pointer);
14613+ }
14614+
14615+ if (rhs_len != 0) {
14616+ const rhs_dest_slice = switch (lhs_len) {
14617+ 0 => mutable_alloc,
14618+ else => s: {
14619+ const many_alloc = try block.addBitCast(many_ty, mutable_alloc);
14620+ const rhs_dest_offset = try block.addInst(.{
14621+ .tag = .ptr_add,
14622+ .data = .{ .ty_pl = .{
14623+ .ty = many_ty_ref,
14624+ .payload = try sema.addExtra(Air.Bin{
14625+ .lhs = many_alloc,
14626+ .rhs = lhs_len_ref,
14627+ }),
14628+ } },
14629+ });
1459614630
14597- // rhs_dest_slice = dest[lhs.len..][0..rhs.len]
14598- const rhs_len_ref = try pt.intRef(.usize, rhs_len);
14599- const rhs_dest_offset = try block.addInst(.{
14600- .tag = .ptr_add,
14601- .data = .{ .ty_pl = .{
14602- .ty = Air.internedToRef(many_ty.toIntern()),
14603- .payload = try sema.addExtra(Air.Bin{
14604- .lhs = many_alloc,
14605- .rhs = lhs_len_ref,
14606- }),
14607- } },
14608- });
14609- const rhs_dest_slice = try block.addInst(.{
14610- .tag = .slice,
14611- .data = .{ .ty_pl = .{
14612- .ty = slice_ty_ref,
14613- .payload = try sema.addExtra(Air.Bin{
14614- .lhs = rhs_dest_offset,
14615- .rhs = rhs_len_ref,
14616- }),
14617- } },
14618- });
14631+ // [rhs.len]T
14632+ const array_ty = try pt.arrayType(.{
14633+ .child = resolved_elem_ty.toIntern(),
14634+ .len = lhs_len,
14635+ });
14636+ // *[rhs.len]T
14637+ const mutable_ty = try pt.ptrTypeSema(.{
14638+ .child = array_ty.toIntern(),
14639+ .flags = .{ .address_space = ptr_as },
14640+ });
1461914641
14620- _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs);
14642+ break :s try block.addBitCast(mutable_ty, rhs_dest_offset);
14643+ },
14644+ };
14645+ const rhs_src_pointer = if (rhs_ty.isSlice(zcu))
14646+ try block.addInst(.{
14647+ .tag = .slice_ptr,
14648+ .data = .{ .ty_op = .{
14649+ .ty = many_ty_ref,
14650+ .operand = rhs,
14651+ } },
14652+ })
14653+ else
14654+ rhs;
14655+ _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs_src_pointer);
14656+ }
1462114657
1462214658 if (res_sent_val) |sent_val| {
1462314659 const elem_index = try pt.intRef(.usize, result_len);
0 commit comments