Hi Kevin - This is an example of breaking the strict aliasing rules of C++. You should use unions to perform these kind of manipulations. Brian On Mon, Mar 1, 2010 at 10:22 AM, Kevin Yohe <kevin@xxxxxxxxxx> wrote: > I have recently come across what appears to be an optimization bug. I am > using gcc version 4.3.1 configured for a powerpc 750. I am using -O2 > optimization. The bug is related to passing a double defined as a local > variable into a trace function which takes 8 32-bit unsigned integers of > auxiliary data. The trace function is using the c++ default arguments (not > varargs). When I want to trace my local double I am performing the > following cast conversions to map the upper and lower data words into 32-bit > aux data parameters. > > double myDouble; > ... > Trace((unsigned int)(*(long long int*)&myDouble) >> 32), > // aux data word 1 myDouble > upper word > (unsigned int)(*(long long int*)&myDouble) & 0xffffffff) ); > // aux data word 2 myDouble > lower word > > The trace method logs the data to a buffer in memory. When I dump the data > logged in my buffer, the values are clearly not 64-bit floating point. They > appear to be 32-bit memory addresses that were residual on the stack. This > only seemed to be a problem with some of the double variables that I passed > into the trace function. For example, in the case below, > > double myDouble1 = func1(); > ... > double myDouble2 = func2(); > > Trace(((unsigned int)(*(long long int*)&myDouble1) >> 32), > (unsigned int)(*(long long int*)&myDouble1) & 0xffffffff), > (((unsigned int)(*(long long int*)&myDouble2) >> 32), > (unsigned int)(*(long long int*)&myDouble2) & 0xffffffff)); > > > The "myDouble1" value looks correct but the "myDouble2" value is incorrect. > I was able to fix the problem 3 different ways. The first was simply to > remove optimization (i.e -O0). The second was to make the bad double > parameters global as in the example below. > > double myDouble1 = func1(); > ... > static double myDouble2 = func2(); > > Trace(((unsigned int)(*(long long int*)&myDouble1) >> 32), > (unsigned int)(*(long long int*)&myDouble1) & 0xffffffff), > (((unsigned int)(*(long long int*)&myDouble2) >> 32), > (unsigned int)(*(long long int*)&myDouble2) & 0xffffffff)); > > Another thing I tried was to insert a nop instruction just before the call > to Trace as in the example below. > > > double myDouble1 = func1(); > ... > double myDouble2 = func2(); > > asm("nop"); > > Trace(((unsigned int)(*(long long int*)&myDouble1) >> 32), > (unsigned int)(*(long long int*)&myDouble1) & 0xffffffff), > (((unsigned int)(*(long long int*)&myDouble2) >> 32), > (unsigned int)(*(long long int*)&myDouble2) & 0xffffffff)); > > I am not sure why the last example worked. The only thing I can think of is > that the "asm" call prevents the method from being optimized. Let me know > if this is a known issue or if you need more details. > > Thanks, > > Kevin > > > > >