1

I'm looking for a compiler flag that will allow me to prevent the compiler optimising away the loop in code like this:

void func() {
    std::unique_ptr<int> up1(new int(0)), up2;
    up2 = move(up1);
    for(int i = 0; i < 1000000000; i++) {
        if(up2) {
            *up2 += 1;
        }
    }
    if(up2)
        printf("%d", *up2);
}

in both C++ and Rust code. I'm trying to compare similar sections of code in terms of speed and running this loop rather than just evaluating the overall result is important. Since Rust statically guarantees that the pointer ownership hasn't been moved, it doesn't need the null pointer checks on each iteration of the loop and I would imagine therefore it would produce faster code if the loop couldn't be optimised out for whatever reason.

Rust compiles using an LLVM backend, so I would preferably be using that for C++ as well.

Harvey Adcock
  • 929
  • 1
  • 7
  • 16
  • 1
    Try `volatile int i`. – Unimportant Apr 19 '16 at 12:51
  • Another option would be to put it in a separate module and compile with `-O0` – Devolus Apr 19 '16 at 12:53
  • 2
    And what is the intention? If compiler can optimize the theoretical result of such tests are absolute useless. So why spend time on this hypothetical issues? – Klaus Apr 19 '16 at 12:57
  • This question cannot have one answer for both Rust and C++. Please pick one and adjust the question as appropriate. – Shepmaster Apr 19 '16 at 13:03
  • 2
    This question is unfortunately quite incomplete. Measuring the performance of unoptimized code is pointless, so what do you want to measure here if not the loop? The cost of `*up2 += 1;`? – Matthieu M. Apr 19 '16 at 13:04
  • go watch this video on microbenchmarking. It's long, but it's very informative and entertaining as well. It has a lot of good info as well as a very specific, very good answer to your question involving inserting 0-instruction inline assembly. https://www.youtube.com/watch?v=nXaxk27zwlk – xaxxon Apr 19 '16 at 13:06
  • Have you seen [Tuning C++: Benchmarks, and CPUs, and Compilers! Oh My!](https://www.youtube.com/watch?v=nXaxk27zwlk) by Chandler Carruth (CppCon 2015)? Highly informational. – Matthieu M. Apr 19 '16 at 13:07
  • 1
    @MatthieuM. beat you – xaxxon Apr 19 '16 at 13:08
  • @xaxxon: I see no link in your comment, but might you be talking about the video I linked? Okay I NOW see a link in your comment, cheater :P – Matthieu M. Apr 19 '16 at 13:08
  • @user1320881: `volatile` is likely to prevent vectorization, so unless we know what the OP wishes to measure, it may or may not be the right answer. – Matthieu M. Apr 19 '16 at 13:15
  • @Klaus I'm trying to measure the difference between Rust and C++ code when something that's statically checked at compile time in Rust has to be manually checked in C++. This has to be checked on each access of the pointer in C++ so I want multiple accesses of the pointer to happen, hence the loop that I don't want optimised out. – Harvey Adcock Apr 19 '16 at 13:46
  • @HarveyAdcock: What's `up2`? Can we get a [MCVE](http://stackoverflow.com/help/mcve)? Do you want to measure the performance of the `*up2 += 1;` statement? – Matthieu M. Apr 19 '16 at 13:47
  • @Shepmaster but if there's a solution for LLVM wouldn't that be applicable to both Rust and C++? The only reason I didn't phrase this as a solely LLVM question is in case there was a decent way without changing optimisation settings. – Harvey Adcock Apr 19 '16 at 13:51
  • You'd have to be able to pass LLVM options to both compilers and doing that would require compiler-specific options, making the answer specific to one compiler or another. If someone provides a great answer for C++ and another person a great answer for Rust, which will you accept? – Shepmaster Apr 19 '16 at 13:56
  • @MatthieuM. Have updated the question to show the relevant parts of the question to what I'm looking at in terms of performance improvement in Rust. So it's essentially what the overhead of checking for null-ness would be that I'm interested in. – Harvey Adcock Apr 19 '16 at 13:58
  • 2
    @HarveyAdcock: Thanks for the update :) Are you trying to check the overhead of null checks specifically? And if so, are you interested in null checks in loops? Or null checks in "straight" code (no loop)? Because of branch prediction the "overhead" might vary between both cases. – Matthieu M. Apr 19 '16 at 14:20
  • @MatthieuM. Ah, I hadn't thought about branch prediction, I was mainly thinking about in straight code, which is probably what's making any attempts I've made at forcing the loop end up similar times for both! Although the check would still need to be processed, so I would've imagined at least a small slowdown. – Harvey Adcock Apr 19 '16 at 14:24

2 Answers2

2

In Rust you can use test::black_box.

In C++ (using gcc) asm volatile("" : "+r" (datum));. See this.

Community
  • 1
  • 1
malbarbo
  • 10,717
  • 1
  • 42
  • 57
1

One typical way to avoid having the compiler optimize away loops is to make their bounds indeterminate at compile time. In this example, rather than looping up to 10000000, loop up to a count which is read from stdin or argv.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 1
    @MatthieuM.: Right, but the OP seems to be interested in "running this loop rather than just evaluating the overall result" which unrolling doesn't harm. – John Zwinck Apr 19 '16 at 13:05
  • 1
    It's the "seems" that I'm trying to unravel. It's not clear to me what they are trying to measure here... – Matthieu M. Apr 19 '16 at 13:10