Commit 83dcd9f038

Jacob G-W <jacoblevgw@gmail.com>
2021-10-01 03:31:46
stage2: emit Value.repeated for `**` where the array size is one
This takes advantage of the repeated value.
1 parent b0e89ee
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -6189,16 +6189,22 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
             try Type.Tag.array.create(anon_decl.arena(), .{ .len = final_len, .elem_type = mulinfo.elem_type });
         const buf = try anon_decl.arena().alloc(Value, final_len);
 
-        // the actual loop
-        var i: u64 = 0;
-        while (i < tomulby) : (i += 1) {
-            var j: u64 = 0;
-            while (j < mulinfo.len) : (j += 1) {
-                const val = try lhs_sub_val.elemValue(sema.arena, j);
-                buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena());
+        // handles the optimisation where arr.len == 0 : [_]T { X } ** N
+        const val = if (mulinfo.len == 1) blk: {
+            const copied_val = try (try lhs_sub_val.elemValue(sema.arena, 0)).copy(anon_decl.arena());
+            break :blk try Value.Tag.repeated.create(anon_decl.arena(), copied_val);
+        } else blk: {
+            // the actual loop
+            var i: u64 = 0;
+            while (i < tomulby) : (i += 1) {
+                var j: u64 = 0;
+                while (j < mulinfo.len) : (j += 1) {
+                    const val = try lhs_sub_val.elemValue(sema.arena, j);
+                    buf[mulinfo.len * i + j] = try val.copy(anon_decl.arena());
+                }
             }
-        }
-        const val = try Value.Tag.array.create(anon_decl.arena(), buf);
+            break :blk try Value.Tag.array.create(anon_decl.arena(), buf);
+        };
         if (lhs_ty.zigTypeTag() == .Pointer) {
             return sema.analyzeDeclRef(try anon_decl.finish(final_ty, val));
         } else {
test/behavior/array.zig
@@ -32,4 +32,9 @@ test "array init with mult" {
     const a = 'a';
     var i: [8]u8 = [2]u8{ a, 'b' } ** 4;
     try expect(std.mem.eql(u8, &i, "abababab"));
+
+    // this should cause a Value.repeated to be emitted in AIR.
+    // TODO: find a way to test that this is actually getting emmited
+    var j: [4]u8 = [1]u8{'a'} ** 4;
+    try expect(std.mem.eql(u8, &j, "aaaa"));
 }