authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2022-12-09 18:22:50+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-09 18:22:50+01:00
logc49e4d534fb8e8ec994a8ffbc62eae8ef1e4e819
tree0194dab2137336a88964fc781f62ea3aa8f0bef0
parent65f35a76f954c30717f641fde341771085abd06e
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Improve and remove duplicate doNotOptimizeAway() implementations (#13790)

* Improve and remove duplicate doNotOptimizeAway() implementations We currently have two doNotOptimizeAway() implementations, one in std.math and the other one in std.mem. Maybe we should deprecate one. In the meantime, the std.math one now just calls the std.mem one. In a comptime environment, just ignore the value. Previously, std.mem.doNotOptimizeAway() did not work at comptime. If the value fits in a CPU register, just tell the compiler we need that value to be computed, without clobbering anything else. Only clobber all possibly escaped memory on pointers or large arrays. Add tests by the way since we didn't had any (we had, but only indirect ones).

2 files changed, 70 insertions(+), 12 deletions(-)

lib/std/math.zig+2-7
......@@ -195,13 +195,8 @@ test "approxEqAbs and approxEqRel" {
195195 }
196196}
197197
198pub fn doNotOptimizeAway(value: anytype) void {
199 // TODO: use @declareSideEffect() when it is available.
200 // https://github.com/ziglang/zig/issues/6168
201 const T = @TypeOf(value);
202 var x: T = undefined;
203 const p = @ptrCast(*volatile T, &x);
204 p.* = x;
198pub fn doNotOptimizeAway(val: anytype) void {
199 return mem.doNotOptimizeAway(val);
205200}
206201
207202pub fn raiseInvalid() void {
lib/std/mem.zig+68-5
......@@ -3559,12 +3559,75 @@ pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T {
35593559/// Force an evaluation of the expression; this tries to prevent
35603560/// the compiler from optimizing the computation away even if the
35613561/// result eventually gets discarded.
3562// TODO: use @declareSideEffect() when it is available - https://github.com/ziglang/zig/issues/6168
35623563pub fn doNotOptimizeAway(val: anytype) void {
3563 asm volatile (""
3564 :
3565 : [val] "rm" (val),
3566 : "memory"
3567 );
3564 var a: u8 = 0;
3565 if (@typeInfo(@TypeOf(.{a})).Struct.fields[0].is_comptime) return;
3566
3567 const max_gp_register_bits = @bitSizeOf(c_long);
3568 const t = @typeInfo(@TypeOf(val));
3569 switch (t) {
3570 .Void, .Null, .ComptimeInt, .ComptimeFloat => return,
3571 .Enum => doNotOptimizeAway(@enumToInt(val)),
3572 .Bool => doNotOptimizeAway(@boolToInt(val)),
3573 .Int => {
3574 const bits = t.Int.bits;
3575 if (bits <= max_gp_register_bits) {
3576 const val2 = @as(
3577 std.meta.Int(t.Int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, bits))),
3578 val,
3579 );
3580 asm volatile (""
3581 :
3582 : [val2] "r" (val2),
3583 );
3584 } else doNotOptimizeAway(&val);
3585 },
3586 .Float => {
3587 if (t.Float.bits == 32 or t.Float.bits == 64) {
3588 asm volatile (""
3589 :
3590 : [val] "rm" (val),
3591 );
3592 } else doNotOptimizeAway(&val);
3593 },
3594 .Pointer => asm volatile (""
3595 :
3596 : [val] "m" (val),
3597 : "memory"
3598 ),
3599 .Array => {
3600 if (t.Array.len * @sizeOf(t.Array.child) <= 64) {
3601 for (val) |v| doNotOptimizeAway(v);
3602 } else doNotOptimizeAway(&val);
3603 },
3604 else => doNotOptimizeAway(&val),
3605 }
3606}
3607
3608test "doNotOptimizeAway" {
3609 comptime doNotOptimizeAway("test");
3610
3611 doNotOptimizeAway(null);
3612 doNotOptimizeAway(true);
3613 doNotOptimizeAway(0);
3614 doNotOptimizeAway(0.0);
3615 doNotOptimizeAway(@as(u1, 0));
3616 doNotOptimizeAway(@as(u3, 0));
3617 doNotOptimizeAway(@as(u8, 0));
3618 doNotOptimizeAway(@as(u16, 0));
3619 doNotOptimizeAway(@as(u32, 0));
3620 doNotOptimizeAway(@as(u64, 0));
3621 doNotOptimizeAway(@as(u128, 0));
3622 doNotOptimizeAway(@as(u13, 0));
3623 doNotOptimizeAway(@as(u37, 0));
3624 doNotOptimizeAway(@as(u96, 0));
3625 doNotOptimizeAway(@as(u200, 0));
3626 doNotOptimizeAway(@as(f32, 0.0));
3627 doNotOptimizeAway(@as(f64, 0.0));
3628 doNotOptimizeAway([_]u8{0} ** 4);
3629 doNotOptimizeAway([_]u8{0} ** 100);
3630 doNotOptimizeAway(@as(std.builtin.Endian, .Little));
35683631}
35693632
35703633test "alignForward" {