-1

I have a library, which does heavy loop-unrolling on compile-time. I am also using a Bench-marking tool, which works by instantiating a struct inside a scope, and at destruction it measures the time between creation and destruction and returns the values collected. Now, by inserting some function-call inside there, it can measure the time for the function call. what i would like to know is, can the compiler jump scopes?(see my code below)

PerfEvent ev;
{
    PerfEventBlock bl(ev, countPE);
    ev.setParam("name","FTensor3D");
    res(l,m,n,o) = t1(l,m,k)*t2(k,n,o);
}

Or in other words: can the compiler "outsource" work to the outside of the scope(i got weird results back and am wondering)

Clebo Sevic
  • 581
  • 1
  • 7
  • 17
  • 1
    Can you please clarify what you mean, and tell us what's exactly going wrong with a [mcve]. – πάντα ῥεῖ Apr 05 '19 at 15:50
  • 1
    If you are getting weird results youshould post a [mcve] and we can tell you why. Asking they question in this format is too broad and you'll get generic answers like you have below. – NathanOliver Apr 05 '19 at 15:50
  • 1
    Why not just look at the generated code? – melpomene Apr 05 '19 at 15:55
  • 3
    @CleboSevic You are taking the downvotes too personally. Aside from the fact that you _did_ get comments how to improve your question, the downvote button says itself that it applies to _unclear_ questions. And I can't deny that, while I kind of get the gist of what you want (which is why I wasn't moved to vote down), it's simply cloudy wording. "outsource" and "jump scopes" have no particular meaning, whereas you probably meant something like "running the constructor/destructor further outside the scope". – Max Langhof Apr 05 '19 at 16:05

2 Answers2

4

As long as the observable result (as defined by the standard) of the code is the same - before and after an optimization, the compiler is allowed to do whatever transformation it wants.

Note: Execution speed, for example, is not considered an observable result. Also, if your program contains Undefined Behaviour then any result is acceptable.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • 1
    It's worth clarifying that execution speed is *not* considered an observable result. – Quentin Apr 05 '19 at 15:54
  • 1
    But it's also worth noting that a call to any kind of timing facility will generally be opaque to the compiler, so it cannot be proven to be side-effect free. Hence the compiler cannot reorder the timing calls wherever it likes. – Max Langhof Apr 05 '19 at 16:06
  • 1
    @MaxLanghof You are correct, but if I was to list *everything* that's not considered an observable side effect, then I may as well quote the standard. And to list everything that's opaque to the compiler is also going to be a looong list. I believe I have mentioned everything that is *relevant* to OP with the current question. So I'll leave it at that. – Jesper Juhl Apr 05 '19 at 16:11
2

If your PerfEventBlock constructor and destructor perform a system call then the compiler should not be able to prove that it has no observable side effects. However, it could still (in theory) reorder your intermittent code before or after these, as long as it can prove that doing so doesn't change observable behavior from the perspective of the abstract machine. See also e.g. here.

Example:

void inc(int& a) { ++a; }

void foo();

int bar()
{
    int a = 1;
    foo();
    inc(a);
    foo();
    return a;
}

https://godbolt.org/z/gOr7aU

The compiler doesn't know what foo() does so it has to assume there are observable side effects. Still, you can see in the assembly that inc is so trivial, the compiler inlined (and constant-folded) it. There is no obligation to perform whatever is involved in inc(a) between the two side effects, because inc itself has no outside observable effect itself.

So it is possible that the compiler moves the code you want to profile out from between the constructor and destructor of PerfEventBlock. In fact, with link-time optimizations, this option can remain on the table further than you think (a function call into another compilation unit - such as foo() here - might be opaque to the compiler but not the linker).

Max Langhof
  • 23,383
  • 5
  • 39
  • 72