My Home on the Internet

Main menu

Monthly Archives: July 2011

Like a good boy I did my apt-get update / apt-get upgrade the other day and thought everything was ok. It pulled down some x.org updates and a new nvidia-current (yes, running Ubuntu with some development ppa’s). Upon rebooting I noticed compositing in kwin had stopped. I thought maybe the sequence of updates had messed something up because there was one xorg update that came in after nvidia-current.

So I ran glxinfo and log and behold I had no GL extensions whatsoever. Hrm, this is a problem I thought. I also ran nvidia-settings to see what it said and the OpenGL tab also said nothing was there. Did a quick web check and no one else was reporting problems with the version of the nvidia driver I had.

I then did a quick ldd `which glxinfo` to see what was up, thinking that one of the xorg updates might have sneaked in some mesa configs. Sure enough, glxinfo was pulling libGL.so from mesa instead of the nvidia binary. I looked in /etc/ld.so.conf.d and found a i386-linux-gnu_GL.conf file that indeed placed mesa in ldconfig’s path higher than the nvidia one. A quick rm i386-linux-gnu_GL.conf and restarting of X fixed things.

The moral of the story is, if you’re like me and have the xorg edgers ppa installed and have suddenly lost OpenGL acceleration, check your /etc/ld.so.conf.d dir.

I came across this article on the Daily WTF and it reminded me of the many issues I have with Microsoft compilers. For example, back in the VB 6 days, I remember how variables in a structure would disappear if the field they referenced in a database was NULL. This made things oh so much fun.

I also remember how Visual C++ decided to screw with new so it wouldn’t throw std::bad_alloc on allocation failure. I had a bunch of code where I had to put in things like foo = new(nothrow) all throughout my code to help it be cross platform. Or having two separate and incompatible iostreams implementations where neither was really feature complete but I needed to find a way to use both to get things to work.

For my second post about compilers, I thought I’d show what happens with various optimization levels in GCC. Note I’m still focusing on gcc because I’m too lazy to fire up VirtualBox and Windows right now.

As a reminder from the first, here’s my wonderfully useless sample program. All it does is go through a loop and does not use the output.

int main(int argc, char* argv[]){ int i = 0; int loop;

for (loop = 0; loop < 50; loop++) ++i; return 0;}

So last time they were purposely compiled without optimization as I just wanted a quick and dirty assembler output. Below we’ll examine the assembly output at different optimization levels of just the main function, as that’s the one we’re more interested in (there are actually more sections in an ELF executable, but that’s a story for another day).

The option flag -O1 turns on the first level of optimizations in gcc/g++. Instead of copying them here, I’ll refer you to the GNU manpage for optimizations for gcc/g++.

Compared to the previous post (no optimization), we see here that the assembly is better optimized. This version does not allocate space for the local variables i and loop,set them to zero, and increment loop and i at each pass. Instead, it loads 50 into the EAX register, subtracts 1, and checks if the zero flag is set. If not, it loops back to the subtraction and continues until it reaches zero. It then nukes it’s local stack and returns while being padded out (again, I’ll go over that another day). As we turn more optimization on, the compiler does more analysis and realizes that it doesn’t need to increment the variables since we’re not doing anything with them. For brevity, note that the assembly output from g++ is identical to the main function from gcc.

gcc -O2 main.c -o main_c1

At -O2, the compiler does even more analysis and has more “smarts” turned on. Let’s look at the assembler output below.

Here the compiler realized that nothing is done with the variables, and nothing was done with the output. So, the compiler doesn’t even do the loop any more. It still pushes the stack frame pointer. It moves 0 into EAX (the xor eax,eax generates shorter op codes and is a touch faster than actually pushing zero there). It still sets up the stack frame (main is a function after all) and then brings back the previous frame and returns. Again, with optimization the g++ assembly matches the gcc output for main(). gcc/g++ -O3 generates the same output as -O2.

You might ask yourself “Why do the compilers even set up the stack frame for the main function?” The answer is, they have to. main() HAS to exist in a C or C++ program, even if it really doesn’t do anything.