authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-02 16:05:12-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-10-02 16:05:12-04:00
log468ed7ada50c743eabe01b36d0ee9f090d80e00a
treefc5a703aaf6211db25355fcf79a945696564f3df
parent05d36fce9c7fde223e6657b3dc47105fbf065695
parent83dcd9f0386a6bd70cf8d7dee3892f3b8d31d506
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #9875 from g-w1/timestimes

stage2: emit Value.repeated for `**` with array len 1

3 files changed, 38 insertions(+), 10 deletions(-)

src/Sema.zig+15-9
...@@ -6189,16 +6189,22 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr...@@ -6189,16 +6189,22 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
6189 try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type });6189 try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type });
6190 const buf = try anon_decl.arena().alloc(Value, final_len);6190 const buf = try anon_decl.arena().alloc(Value, final_len);
61916191
6192 // the actual loop6192 // handles the optimisation where arr.len == 0 : [_]T { X } ** N
6193 var i: u64 = 0;6193 const val = if (mulinfo.len == 1) blk: {
6194 while (i < tomulby) : (i += 1) {6194 const copied_val = try (try lhs_sub_val.elemValue(sema.arena, 0)).copy(anon_decl.arena());
6195 var j: u64 = 0;6195 break :blk try Value.Tag.repeated.create(anon_decl.arena(), copied_val);
6196 while (j < mulinfo.len) : (j += 1) {6196 } else blk: {
6197 const val = try lhs_sub_val.elemValue(sema.arena, j);6197 // the actual loop
6198 buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena());6198 var i: u64 = 0;
6199 while (i < tomulby) : (i += 1) {
6200 var j: u64 = 0;
6201 while (j < mulinfo.len) : (j += 1) {
6202 const val = try lhs_sub_val.elemValue(sema.arena, j);
6203 buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena());
6204 }
6199 }6205 }
6200 }6206 break :blk try Value.Tag.array.create(anon_decl.arena(), buf);
6201 const val = try Value.Tag.array.create(anon_decl.arena(), buf);6207 };
6202 if (lhs_ty.zigTypeTag() == .Pointer) {6208 if (lhs_ty.zigTypeTag() == .Pointer) {
6203 return sema.analyzeDeclRef(try anon_decl.finish(final_ty, val));6209 return sema.analyzeDeclRef(try anon_decl.finish(final_ty, val));
6204 } else {6210 } else {
src/codegen/llvm.zig+18-1
...@@ -1024,6 +1024,7 @@ pub const DeclGen = struct {...@@ -1024,6 +1024,7 @@ pub const DeclGen = struct {
1024 else => |tag| return self.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }),1024 else => |tag| return self.todo("implement const of pointer type '{}' ({})", .{ tv.ty, tag }),
1025 },1025 },
1026 .Array => {1026 .Array => {
1027 const gpa = self.gpa;
1027 if (tv.val.castTag(.bytes)) |payload| {1028 if (tv.val.castTag(.bytes)) |payload| {
1028 const zero_sentinel = if (tv.ty.sentinel()) |sentinel| blk: {1029 const zero_sentinel = if (tv.ty.sentinel()) |sentinel| blk: {
1029 if (sentinel.tag() == .zero) break :blk true;1030 if (sentinel.tag() == .zero) break :blk true;
...@@ -1037,7 +1038,6 @@ pub const DeclGen = struct {...@@ -1037,7 +1038,6 @@ pub const DeclGen = struct {
1037 );1038 );
1038 }1039 }
1039 if (tv.val.castTag(.array)) |payload| {1040 if (tv.val.castTag(.array)) |payload| {
1040 const gpa = self.gpa;
1041 const elem_ty = tv.ty.elemType();1041 const elem_ty = tv.ty.elemType();
1042 const elem_vals = payload.data;1042 const elem_vals = payload.data;
1043 const sento = tv.ty.sentinel();1043 const sento = tv.ty.sentinel();
...@@ -1053,6 +1053,23 @@ pub const DeclGen = struct {...@@ -1053,6 +1053,23 @@ pub const DeclGen = struct {
1053 @intCast(c_uint, llvm_elems.len),1053 @intCast(c_uint, llvm_elems.len),
1054 );1054 );
1055 }1055 }
1056 if (tv.val.castTag(.repeated)) |payload| {
1057 const val = payload.data;
1058 const elem_ty = tv.ty.elemType();
1059 const len = tv.ty.arrayLen();
1060
1061 const llvm_elems = try gpa.alloc(*const llvm.Value, len);
1062 defer gpa.free(llvm_elems);
1063 var i: u64 = 0;
1064 while (i < len) : (i += 1) {
1065 llvm_elems[i] = try self.genTypedValue(.{ .ty = elem_ty, .val = val });
1066 }
1067 const llvm_elem_ty = try self.llvmType(elem_ty);
1068 return llvm_elem_ty.constArray(
1069 llvm_elems.ptr,
1070 @intCast(c_uint, llvm_elems.len),
1071 );
1072 }
1056 return self.todo("handle more array values", .{});1073 return self.todo("handle more array values", .{});
1057 },1074 },
1058 .Optional => {1075 .Optional => {
test/behavior/array.zig+5
...@@ -32,4 +32,9 @@ test "array init with mult" {...@@ -32,4 +32,9 @@ test "array init with mult" {
32 const a = 'a';32 const a = 'a';
33 var i: [8]u8 = [2]u8{ a, 'b' } ** 4;33 var i: [8]u8 = [2]u8{ a, 'b' } ** 4;
34 try expect(std.mem.eql(u8, &i, "abababab"));34 try expect(std.mem.eql(u8, &i, "abababab"));
35
36 // this should cause a Value.repeated to be emitted in AIR.
37 // TODO: find a way to test that this is actually getting emmited
38 var j: [4]u8 = [1]u8{'a'} ** 4;
39 try expect(std.mem.eql(u8, &j, "aaaa"));
35}40}