Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
321 views
in Technique[技术] by (71.8m points)

c++ - How not to optimize away - mechanics of a folly function

I was searching for a programming technique that would ensure variables used for benchmarking (without observable side effects) won't be optimized away by the compiler

This gives some info, but I ended up using folly and the following function

/**
 * Call doNotOptimizeAway(var) against variables that you use for
 * benchmarking but otherwise are useless. The compiler tends to do a
 * good job at eliminating unused variables, and this function fools
 * it into thinking var is in fact needed.
 */
#ifdef _MSC_VER

#pragma optimize("", off)

template <class T>
void doNotOptimizeAway(T&& datum) {
  datum = datum;
}

#pragma optimize("", on)

#else
template <class T>
void doNotOptimizeAway(T&& datum) {
  asm volatile("" : "+r" (datum));
}
#endif

I want to use the above, but I have little understanding of its workings. I'm mostly interested in the non VC++ portion and why/how the line

asm volatile("" : "+r" (datum));

creates a non optimizable context or why is this something one would choose to implement such a thing. Also a comparison between the 2 methods would be interesting (I don't know how pragma optimize works but it looks like a cleaner solution - non portable though)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There is no standard way to disable optimisations, so if you need to disable optimisations, you're limited to whatever your implementation happens to provide. It doesn't make sense to compare the two approaches unless you find a compiler that supports them both.

Anyway, in GCC,

asm volatile("" : "+r" (datum));

means that unverified assembly code supplied by the user is embedded into the assembly generated by GCC. The first string literal ("") contains the assembly code to inject. It's empty, so there isn't actually any code that gets emitted at all.

The part after the : informs GCC about the effect of the assembly code. "+r" (datum) means that GCC should assume that the assembly code reads and modifies datum. Even though it doesn't. The reason for that is that any earlier calculations that end up storing a value in datum cannot be discarded as unnecessary. At the same time, the assembly code itself cannot be discarded as unnecessary, because of the potential modification to datum. volatile also marks the assembly code as code that must not be optimised away, as documented here:

GCC's optimizers sometimes discard asm statements if they determine there is no need for the output variables. Also, the optimizers may move code out of loops if they believe that the code will always return the same result (i.e. none of its input values change between calls). Using the volatile qualifier disables these optimizations. [...]

It seems a bit much to use two different approaches to prevent the assembly code from being removed, really, but I guess it's best to be sure.

The r constraint means that the code does not care all that much which register GCC makes available for the assembly code to use, and is documented here:

‘r’
? ? A register operand is allowed provided that it is in a general register.

The + modifier means that the code may read from and write to datum, and is documented here:

‘+’
? ? Means that this operand is both read and written by the instruction. [...]


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...