diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig index 083813a799..2ea23046f4 100644 --- a/lib/std/crypto/benchmark.zig +++ b/lib/std/crypto/benchmark.zig @@ -7,6 +7,7 @@ const builtin = @import("builtin"); const std = @import("std"); +const mem = std.mem; const time = std.time; const Timer = time.Timer; const crypto = std.crypto; @@ -21,14 +22,6 @@ const Crypto = struct { name: []const u8, }; -fn blackBox(x: anytype) void { - asm volatile ("" - : - : [x] "rm" (x) - : "memory" - ); -} - const hashes = [_]Crypto{ Crypto{ .ty = crypto.hash.Md5, .name = "md5" }, Crypto{ .ty = crypto.hash.Sha1, .name = "sha1" }, @@ -54,7 +47,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 while (offset < bytes) : (offset += block.len) { h.update(block[0..]); } - blackBox(&h); + mem.forceEval(&h); const end = timer.read(); const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; @@ -89,7 +82,7 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 { const start = timer.lap(); while (offset < bytes) : (offset += in.len) { Mac.create(mac[0..], in[0..], key[0..]); - blackBox(&mac); + mem.forceEval(&mac); } const end = timer.read(); @@ -116,7 +109,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c var i: usize = 0; while (i < exchange_count) : (i += 1) { _ = DhKeyExchange.create(out[0..], out[0..], in[0..]); - blackBox(&out); + mem.forceEval(&out); } } const end = timer.read(); @@ -141,7 +134,7 @@ pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count var i: usize = 0; while (i < signatures_count) : (i += 1) { const s = try Signature.sign(&msg, key_pair, null); - blackBox(&s); + mem.forceEval(&s); } } const end = timer.read(); @@ -177,7 +170,7 @@ pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64 Aead.encrypt(in[0..], tag[0..], in[0..], &[_]u8{}, nonce, key); Aead.decrypt(in[0..], in[0..], tag, &[_]u8{}, nonce, key) catch unreachable; } - blackBox(&in); + mem.forceEval(&in); const end = timer.read(); const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; diff --git a/lib/std/math.zig b/lib/std/math.zig index a76f0a391d..7b2d897379 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -5,6 +5,7 @@ // and substantial portions of the software. const std = @import("std.zig"); const assert = std.debug.assert; +const mem = std.mem; const testing = std.testing; /// Euler's number (e) @@ -108,34 +109,8 @@ pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) bool { return fabs(x - y) < epsilon; } -// TODO: Hide the following in an internal module. pub fn forceEval(value: anytype) void { - const T = @TypeOf(value); - switch (T) { - f16 => { - var x: f16 = undefined; - const p = @ptrCast(*volatile f16, &x); - p.* = x; - }, - f32 => { - var x: f32 = undefined; - const p = @ptrCast(*volatile f32, &x); - p.* = x; - }, - f64 => { - var x: f64 = undefined; - const p = @ptrCast(*volatile f64, &x); - p.* = x; - }, - f128 => { - var x: f128 = undefined; - const p = @ptrCast(*volatile f128, &x); - p.* = x; - }, - else => { - @compileError("forceEval not implemented for " ++ @typeName(T)); - }, - } + mem.forceEval(value); } pub fn raiseInvalid() void { diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 36fc27984d..0ac12c1212 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -2158,6 +2158,17 @@ pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T { return alignBackwardGeneric(T, addr + (alignment - 1), alignment); } +/// Force an evaluation of the expression; this tries to prevent +/// the compiler from optimizing the computation away even if the +/// result eventually gets discarded. +pub fn forceEval(val: anytype) void { + asm volatile ("" + : + : [val] "rm" (val) + : "memory" + ); +} + test "alignForward" { testing.expect(alignForward(1, 1) == 1); testing.expect(alignForward(2, 1) == 2);