diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2023-09-21 21:06:32 +0100 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-09-22 14:42:27 -0700 |
| commit | e011c31ee8e49bda4052ac9b74d088667dc310ba (patch) | |
| tree | c93088472d3871c3054aeefad72a3957d96b0c6c /src | |
| parent | 272a57eeedb9593f06434b59a8765c4a2b715792 (diff) | |
| download | zig-e011c31ee8e49bda4052ac9b74d088667dc310ba.tar.gz zig-e011c31ee8e49bda4052ac9b74d088667dc310ba.zip | |
Sema: optimize comptime @memset by setting all elements at once
Previously, @memset at comptime performed N pointer stores. This is less
efficient than just storing a whole array of values at once. The
difference can be quite drastic when reinterpreting memory - a test case
which is 40s on master branch now takes under a second on a debug
compiler build.
Resolves: #17214
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 54 |
1 files changed, 24 insertions, 30 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 89a8f74bf6..c6cc93db90 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -24406,10 +24406,12 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void }); }; - const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: { + const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src); + + const runtime_src = rs: { + const ptr_val = try sema.resolveDefinedValue(block, dest_src, dest_ptr) orelse break :rs dest_src; const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, "len"), dest_src); - const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse - break :rs dest_src; + const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src; const len_u64 = (try len_val.getUnsignedIntAdvanced(mod, sema)).?; const len = try sema.usizeCast(block, dest_src, len_u64); if (len == 0) { @@ -24418,33 +24420,25 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void } if (!ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src; - if (try sema.resolveMaybeUndefVal(uncoerced_elem)) |_| { - for (0..len) |i| { - const elem_index = try mod.intRef(Type.usize, i); - const elem_ptr = try sema.elemPtrOneLayerOnly( - block, - src, - dest_ptr, - elem_index, - src, - true, // init - false, // oob_safety - ); - try sema.storePtr2( - block, - src, - elem_ptr, - dest_src, - uncoerced_elem, - value_src, - .store, - ); - } - return; - } else break :rs value_src; - } else dest_src; - - const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src); + const elem_val = try sema.resolveMaybeUndefVal(elem) orelse break :rs value_src; + const array_ty = try mod.arrayType(.{ + .child = dest_elem_ty.toIntern(), + .len = len_u64, + }); + const array_val = (try mod.intern(.{ .aggregate = .{ + .ty = array_ty.toIntern(), + .storage = .{ .repeated_elem = elem_val.toIntern() }, + } })).toValue(); + const array_ptr_ty = ty: { + var info = dest_ptr_ty.ptrInfo(mod); + info.flags.size = .One; + info.child = array_ty.toIntern(); + break :ty try mod.ptrType(info); + }; + const raw_ptr_val = if (dest_ptr_ty.isSlice(mod)) ptr_val.slicePtr(mod) else ptr_val; + const array_ptr_val = try mod.getCoerced(raw_ptr_val, array_ptr_ty); + return sema.storePtrVal(block, src, array_ptr_val, array_val, array_ty); + }; try sema.requireRuntimeBlock(block, src, runtime_src); _ = try block.addInst(.{ |
