C ++ tries to optimize code by replacing tests

I am looking at code written by someone else, and it has many debug sections, like

if(0) { code } 

or if(1) { code }

or if(false) { code }

There is even

 #if(0) #endif 

(which did not turn gray, though - I thought he should)

I was wondering if I replaced them with #if 0 (or #ifdef _DEBUG ), is it possible to optimize the code? - or - it won't make any difference?

I think this can help, since I saw the code that is inside these sections in gray - and I thought this code was removed from the Release executable ... so it makes it faster. It's true?

The code I think of is inside functions that could be called many times ...

Edit: The code I'm talking about runs millions of times. I know that the contents of if (0) will be ignored ...

I also know that you can easily debug the problem by switching the test from 0 to 1 ...

My question was that I add millions of millions of times a test if (0) does not add overhead ... I am trying to figure out that everything that this code can do will take less hours,

+3
c ++ optimization
Feb 02 '13 at 1:20
source share
5 answers

If the expressions inside these IFs are constant and defined at compile time , you can be pretty sure that the compiler has already removed them from the code for you.

Of course, if you compile in Debug-Mode and / or if you have an optimization level of zero, then the compiler can skip this and leave these tests, but with equal values โ€‹โ€‹zero / one / true / false is unlikely.

For compile-time constant branches, you can be sure that the compiler has deleted the dead.

It can even remove complex windows, for example:

 const int x = 5; if( 3 * x * x < 10 ) // ~ 75 < 10 { doBlah(); // skipped } 

However, without this 'const' token in X, the value of the expression may not be determined at compile time, and it may โ€œleakโ€ into the actual final product.

In addition, the value of the expression in the following code is not necessarily a compile-time constant:

 const int x = aFunction(); if( 3 * x * x < 10 ) // ~ 75 < 10 { doBlah(); // skipped } 

X is a constant, but it is initialized with the value from the function. X will most likely not be detected at compile time. At run time, the function can return any value *), so the compiler should assume that X is unknown.

Therefore, if you have the opportunity, use a preprocessor. In trivial cases that will not do much, because the compiler already knew about it. But cases are not always trivial, and you will often notice a change in vrey. When the optimizer does not output a value, it leaves the code, even if it is dead. The preprocessor, on the other hand, ensures that deleted partitions are deleted before they are compiled and optimized. In addition, using a preprocessor for this will at least speed up compilation: the compiler / optimizer will not have to trace constants / calculations / checkbranches, etc.

*) you can write a method / function, the return value can actually be determined at the compilation and optimization stages: if the function is simple and if it is embedded, its result can be optimized along with some branches .. But even if you can rely to some extent on removing if-0 sentences, you cannot rely on inlining as much.

+2
Feb 02 '13 at 1:23
source share
โ€” -

If you have code inside the if (0) block, the code generated by the compiler will be the same as if this block was not present in any reasonable compiler. The code will still be checked for compile-time errors. (Assuming there are no transition labels or something weird in it.)

If you have code inside the if (1) block, the code generated by the compiler will be the same as if the code was only inside curly braces. This is the usual way to provide a code block of your own scope so that local variables are destroyed where needed.

If you ifdef output the code, the compiler completely ignores it. The code can be completely meaningless, contain syntax errors or whatever, but the compiler doesnโ€™t care.

+2
Feb 02 '13 at 1:24
source share

Typically, #if 0 used to delete the code while still saving it - for example, to easily compare with the parameters, I sometimes do:

 #if 1 some sort of code #else some other code #endif 

That way, I can quickly switch between the two alternatives.

In this case, the preprocessor will simply leave one of the two options in the code.

The if(0) or if(1) constructs are similar - the compiler will largely remove the if, and in the case of 0, it will also remove the rest of the if-statement.

I think itโ€™s rather sloppy to leave such things in the โ€œcompletedโ€ code, but it is very useful for debugging / development.

Say, for example, you are trying to create a new method to execute something much faster:

 if (1) { fast_function(); } else { slower_function(); } 

Now, in one of the test tables, the result shows an error. Therefore, you want to quickly return to slower_funcion and see if the result matches or not. If this is the same, then you need to look at what has changed since the last time it went through. If everything is ok with slower_function, you will come back and see why fast_function () does not work as it should in this case.

+2
Feb 02 '13 at 1:27
source share

True (depending on the build and preprocessor settings).

Entering debug code in #ifdef _DEBUG (or similar) is the standard way to completely exclude them from your release versions. Usually the debug build of #define is this, and the release build does not work.

Usually, the compiler should also delete code, for example if (0) , if it is set with the correct optimization flags, but this adds extra work to the compiler and programmer (now you have to change them all!), I would definitely leave this in the preprocessor.

+1
Feb 02 '13 at 1:21
source share

You're right. If you compile with #define DEBUG 0 , you will actually remove all #if DEBUG blocks at compile time. Consequently, there will be much less code, and it will work faster.

Just make sure you release your code after creating #define DEBUG 0 at release time.

A good optimizing compiler (GCC, MSVC) will completely remove if(0) and if(1) from the code ... translating to machine code will NOT check these conditions ...

+1
Feb 02 '13 at 1:25
source share



All Articles