public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* double address to long word pointer cast -O2 optimization bug
@ 2010-03-01 18:22 Kevin Yohe
  2010-03-01 18:27 ` Brian Budge
  0 siblings, 1 reply; 2+ messages in thread
From: Kevin Yohe @ 2010-03-01 18:22 UTC (permalink / raw)
  To: gcc-help

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




^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: double address to long word pointer cast -O2 optimization bug
  2010-03-01 18:22 double address to long word pointer cast -O2 optimization bug Kevin Yohe
@ 2010-03-01 18:27 ` Brian Budge
  0 siblings, 0 replies; 2+ messages in thread
From: Brian Budge @ 2010-03-01 18:27 UTC (permalink / raw)
  To: Kevin Yohe; +Cc: gcc-help

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@ssc-nh.com> 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
>
>
>
>
>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2010-03-01 18:27 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-01 18:22 double address to long word pointer cast -O2 optimization bug Kevin Yohe
2010-03-01 18:27 ` Brian Budge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).