This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: help interpreting gcc 4.1.1 optimisation bug
andrew@walrond.org writes:
> On Mon, Jun 12, 2006 at 12:32:36PM +0100, Andrew Haley wrote:
> > andrew@walrond.org writes:
> > > I want a reduced test case for this problem for bugzilla, but don't
> > > really know the exact cause. I _think_ code is being improperly
> > > optimized away, but I don't know. This function is part of a
> > > BigInteger library, and works perfectly upto and including -O2, but
> > > produces bogus results at -O3, unless I uncomment the debug_msg()
> > > line, which just dumps the contents of 'i' to the screen. I'm
> > > guessing that without it, the compiler fails to notice that i's
> > > contents are being accessed via the _front8/_back8 pointers, and
> > > throws the preceeding 'i' related code away. Heres the code:
> > >
> > > void Integer::export_bytes(Data& _buffer, PortMode _mode) const
> > > {
> > > debug_scope("export_bytes(Data&)");
> > >
> > > Integer i(*this,1);
> > >
> > > if (_mode==SIGNED) {
> > > if (*mBack & TOP_BIT)
> > > i.grow(1,0);
> > > if (sign()<0)
> > > i.twoscomplement();
> > > }
> > >
> > > for (UnsignedW* p=i.mFront; p<=i.mBack; p++)
> > > *p = host2little(*p);
> > >
> > > Unsigned8* _front8 = reinterpret_cast<Unsigned8*>(i.mFront);
> > > Unsigned8* _back8 = _front8+(i.mSize*WORD_BYTES)-1;
> > > if (_mode==UNSIGNED)
> > > while (_back8!=_front8 and *_back8==0)
> > > _back8--;
> > > else if (mSign==1)
> > > while (_back8!=_front8 and *_back8==0 and
> > > !(*(_back8-1)&0x80))
> > > _back8--;
> > > else
> > > while (_back8!=_front8 and *_back8==0xff and
> > > *(_back8-1)&0x80)
> > > _back8--;
> > >
> > > //debug_msg(String("Force i\n")+i.dump());
> > >
> > > _buffer.assign(_front8, _back8+1);
> > > }
> > >
> > > Any thoughts on how to proceed?
> >
> > I think your code is broken. A reinterpret_cast from foo* to bar* is
> > only well-defined if foo and bar are compatible types or one of
> > {foo,bar} is type char. I can't be sure from your code, but I'm
> > guessing that i.mFront is not declared as a pointer to Unsigned8, but
> > as a pointer to an incompatible type UnsignedW.
>
> typedef unsigned long UnsignedW;
> typedef unsigned char Unsigned8;
> typdef std::vector<Unsigned8> Data;
>
> mFront is defined as UnsignedW*, an array of words constituting the
> big integer.
OK. That should be fine, then.
> Having converted the words from host to little endian with
> host2little(), I am simply reading (exporting) the bytes out into a
> vector using std::vector::assign(InputIter first, InputIter last)
>
> Seems legit, no?
The only likely significant difference with -O3 is that small
functions get inlined.
I'm starting to be a little suspicious about host2little(). I wonder
if that's well-defined.
I'm just guessing here becasue I can't see the code. Is it possible
for you to turn this into a small test case that anyone can run?
Andrew.