Thread overview
Preventing the Compiler from Optimizing Away Benchmarks
Mar 13, 2023
jmh530
Mar 13, 2023
user1234
Mar 13, 2023
jmh530
March 13, 2023

I was looking at [1] for ways to prevent the compiler from optimizing away code when trying to benchmark.

It has the following C++ code as a simpler version:

inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
    asm volatile("" : "+r,m"(value) : : "memory");
}

I made an attempt to make a D version of it, but failed. Apparently DMD doesn't like the "" in the first part of the asm instruction. I'm also not sure the volatileLoad command is right, but I didn't know of any other way to have volatile work in D (and I couldn't figure out how it actually worked from looking at the code).

void DoNotOptimize(T)(T* ptr)
{
    import core.volatile: volatileLoad;
    T value = volatileLoad(ptr);
    asm {"" : "+r,m"(value) : : "memory";}
}

[1] https://theunixzoo.co.uk/blog/2021-10-14-preventing-optimisations.html

March 13, 2023

On Monday, 13 March 2023 at 14:17:57 UTC, jmh530 wrote:

>

I was looking at [1] for ways to prevent the compiler from optimizing away code when trying to benchmark.

It has the following C++ code as a simpler version:

inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
    asm volatile("" : "+r,m"(value) : : "memory");
}

I made an attempt to make a D version of it, but failed. Apparently DMD doesn't like the "" in the first part of the asm instruction. I'm also not sure the volatileLoad command is right, but I didn't know of any other way to have volatile work in D (and I couldn't figure out how it actually worked from looking at the code).

void DoNotOptimize(T)(T* ptr)
{
    import core.volatile: volatileLoad;
    T value = volatileLoad(ptr);
    asm {"" : "+r,m"(value) : : "memory";}
}

[1] https://theunixzoo.co.uk/blog/2021-10-14-preventing-optimisations.html

that's illegal code. You mix GCC/LLVM syntax with D asm block and the front-end wont recognize that.

LDC recognizes a syntax similar to what is described in your link, see https://wiki.dlang.org/LDC_inline_assembly_expressions. GDC has it too (since that the syntax invented by GCC in first place) but I cant find the documentation ATM.

March 13, 2023

On Monday, 13 March 2023 at 15:23:25 UTC, user1234 wrote:

>

[snip]

>

[1] https://theunixzoo.co.uk/blog/2021-10-14-preventing-optimisations.html

that's illegal code. You mix GCC/LLVM syntax with D asm block and the front-end wont recognize that.

LDC recognizes a syntax similar to what is described in your link, see https://wiki.dlang.org/LDC_inline_assembly_expressions. GDC has it too (since that the syntax invented by GCC in first place) but I cant find the documentation ATM.

Thanks, that helps. Below seems to be working...(with LDC and -O) when I include the DoNotOptimize, it takes around 300-500us, but when I comment it out, then it takes about 5us. It would still take some work to figure out how to get it to work with DMD.

void DoNotOptimize(T)(T* ptr)
{
    import ldc.llvmasm;
    import core.volatile: volatileLoad;
    T value = volatileLoad(ptr);

    __asm("", "*mr,~{memory}", &value, );
}

void main() {
    import std.algorithm.iteration: sum;
    import std.array: uninitializedArray;
    import std.datetime.stopwatch;
    import std.random: uniform;
    import std.stdio: writeln;

    auto testData = uninitializedArray!(long[])(600_000);
    foreach(ref el; testData) el = uniform(0, 10);

    ulong seed = 0;
    ulong output = 0;
    StopWatch sw;
    sw.start();

    DoNotOptimize(&seed);
    output = testData.sum(seed);
    DoNotOptimize(&output);
    sw.stop();
    writeln("time: ", sw.peek);
}