How smart is the compiler?

Started by
24 comments, last by Conner McCloud 17 years, 6 months ago
Quote:Original post by ToohrVyk
Quote:Original post by Way Walker
But if x is a const bool, then any program that modifies it is malformed.


Oops, I overlooked the const. The compiler can make this optimization safely.
bool* ptr = (bool*) &x *ptr = <value>;
This is C(++), after all -- we can do whatever the hell we want.

If the compiler doesn't correctly perform the optimization, you could try copying the value of the flag to a local variable, which will demonstrate to the compiler that no non-local modifications can be made. I'd only do that after reading the assembly listing and seeing that the compiler wasn't doing the optimization, though.

On the other hand, if you assume a desktop processor, you've got a branch predictor to save your ass here. Even if the compiler doesn't optimize, that compare will be free every single time after the first run through the loop.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Advertisement
If you always know the value of x before the while loop starts, and it's never modified during the loop, why don't you do the optimisation yourself? In fact, I don't understand why your code is doing such a thing as a test on a const bool.
To win one hundred victories in one hundred battles is not the acme of skill. To subdue the enemy without fighting is the acme of skill.
Quote:Original post by Way Walker
Quote:Origianl post by daerid
If x is a const bool, then possibly. Or if x is a #define.


Actually, in this case, a #define would not allow this optimization since it's a function call which, so far as we can tell, might not always return the same value.

Stop whatever you're doing right now, and go look up the word "pre-processor".
daerid@gmail.com
Quote:Original post by daerid
Quote:Original post by Way Walker
Quote:Origianl post by daerid
If x is a const bool, then possibly. Or if x is a #define.


Actually, in this case, a #define would not allow this optimization since it's a function call which, so far as we can tell, might not always return the same value.

Stop whatever you're doing right now, and go look up the word "pre-processor".


Thats what he's saying - a define cannot be assigned to a function call.
Quote:Original post by King of Men
If you always know the value of x before the while loop starts, and it's never modified during the loop, why don't you do the optimisation yourself?


OP: I have a professor and several computer hardware engineering friends who would repeat this sentiment. Usually loudly, at the top of their lungs. They seem to be a bit touchy about keeping such if comparisons out of loops.

As far as the compiler, I'm not sure if VS 2005 knows to optimize it out. But if you're aware that such a thing should be optimized (which you obviously are), why wouldn't you just do it yourself?
Considering you can use the values of such const bool variables as template arguments, I'd say it's safe to say that any modern compiler will optimize the loop away.

#include <iostream>namespace{  bool const x = false;  template<bool T>  void p()  {    std::cout << "true\n";  }  template<>  void p<false>()  {    std::cout << "false\n";  }}int main(){  p<x>();}
Quote:Original post by Promit
bool* ptr = (bool*) &x *ptr = <value>;
This is C(++), after all -- we can do whatever the hell we want.


To the best of my knowledge, in C++, 4.4 [conv.qual] disagrees with this pointer conversion because it removes cv-qualifiers. A const_cast might have been possible, but it is only guaranteed to work if the referenced rvalue is defined as non-const (which is not the case here).

Well he did use a C-style cast, so all bets are off.
It looks like the compiler isn't as smart as you'd like it to be. At least mine isn't:

I compiled the following code under MSVC++ 2003 with full optimisations on:

void ConstCall() {	OutputDebugStringA("ConstCall\n");	const bool x = GetSomeBool();	while (running) {		if (x) FuncA();		FuncB();	}}void NotConstCall() {	OutputDebugStringA("NotConstCall\n");	bool x = GetSomeBool();	while (running) {		if (x) FuncA();		FuncB();	}}

The debug strings are just there to aid my disassembler. The compiler was hell-bent on inlining everything in sight, so some bullying was necessary (__declspec(noinline)), but I don't see how that would affect the test. The two functions came out identical.

Here's the assembly (edited for readability), for anyone who cares:

00401080 push    ebx00401081 push    ("ConstCall")00401086 call    (OutputDebugStringA)0040108C call    (GetSomeBool)00401091 mov     bl, al00401093 mov     al, (running)00401098 test    al, al0040109A jz      short 4010B70040109C lea     esp, [esp+0]004010A0 test    bl, bl004010A2 jz      short 4010A9004010A4 call    (FuncA)004010A9 call    (FuncB)004010AE mov     al, (running)004010B3 test    al, al004010B5 jnz     short 4010A0004010B7 pop     ebx004010B8 retn


Regards
Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
The reason I asked the question is my actual case is that the while is a little more complex with 4 or 5 ifs and longer code segments. Coding out every of the 16 or so combinations would take up a lot of code, and being a programmer, I don't like the feel of copy-paste programming nor the verbosity of it; I appreciate the conciseness and logical layout of a while loop written like so. The question is, with speed favoured over size, would the compiler perform this expansion for me?

I don't really know Assembly, I'm not sure I could tell if the optimisation was done from assembly listings. Also this is specific to VS2005.

edit: post timing conflict, thanks for investigating theAdmiral - I'll save the expansion for the end of my project.
Construct (Free open-source game creator)

This topic is closed to new replies.

Advertisement