optimizer bug

Mark van Doesburg m.j.s.vandoesburg@student.utwente.nl
Wed Jun 24 04:10:00 GMT 1998


When compiling the attached program with:

	gcc -O test.ii

Executing a.out causes a segmentation fault.
Without the -O it runs without errors. 

The following function is translated

	void SetTransformation(int const &M)
	{
		coord<fract,3> corner[8];
		corner[0][0]=corner[0][1]=corner[0][2]=0;
	}

into:

test.o:     file format elf32-i386

Disassembly of section .text:

00000000 <SetTransformation(int const &)>:
   0:	55             	pushl  %ebp
   1:	89 e5          	movl   %esp,%ebp
   3:	83 ec 60       	subl   $0x60,%esp
   6:	53             	pushl  %ebx
   7:	b9 07 00 00 00 	movl   $0x7,%ecx
   c:	8d 74 26 00    	leal   0x0(%esi,1),%esi
  10:	ba 02 00 00 00 	movl   $0x2,%edx
  15:	83 ea 01       	subl   $0x1,%edx
  18:	73 fb          	jae    15 <SetTransformation(int const &)+0x15>
  1a:	83 e9 01       	subl   $0x1,%ecx
  1d:	73 f1          	jae    10 <SetTransformation(int const &)+0x10>
  1f:	c7 45 a8 00 00 	movl   $0x0,0xffffffa8(%ebp)
  24:	00 00 
  26:	8b 00          	movl   (%eax),%eax		<---------- ?
  28:	89 45 a4       	movl   %eax,0xffffffa4(%ebp)
  2b:	8b 03          	movl   (%ebx),%eax		<---------- ?
  2d:	89 45 a0       	movl   %eax,0xffffffa0(%ebp)
  30:	8b 5d 9c       	movl   0xffffff9c(%ebp),%ebx
  33:	89 ec          	movl   %ebp,%esp
  35:	5d             	popl   %ebp
  36:	c3             	ret    
  37:	90             	nop    

Which is obviously(?) incorrect since eax and ebx are never initialized.

The system used:

	Linux 2.0.34
	libc 5.4.33
	Intel pentium/AMD K5
	binutils 2.9.1 

Reading specs from /usr/local/lib/gcc-lib/i586-pc-linux-gnulibc1/egcs-2.91.42/specs
gcc version egcs-2.91.42 19980621 (gcc2 ss-980502 experimental)

If you need more information you can mail me directly or via the egcs mailing
list (not egcs-bugs).

greetings, Mark.

-------------------------- test.ii ----------------------------------------
# 1 "test.cpp"
# 1 "coord.h" 1



# 1 "fract.h" 1



typedef int int32;
typedef long long int64;

class fract {
	static const int shift=16;
	int32 d; 
public:
	fract() {}
	fract(int i) { d=i<<shift; }
	fract(double o) { d=(int)((1<<shift)*o+0.5); }

	operator bool() const { return d; }
	operator int() const { return d>>shift; }
	operator double() const { return (double)d/(1<<shift); }

	int32 &direct() { return d; }
	int32 fp() const { return d&((1<<shift)-1); }

	fract &operator=(fract f) { d=f.d; }
	fract &operator=(int f) { d=f<<shift; }
	fract &operator=(double f) { d=(int)((1<<shift)*f+0.5); }

	fract operator+(fract f) const { fract t; t.d=d+f.d; return t; }
	fract operator+(int f) const { fract t; t=*this+(fract)f; return t; }
	fract operator+(double f) const { fract t; t=*this+(fract)f; return t; }
	fract operator-(fract f) const { fract t; t.d=d-f.d; return t; }
	fract operator-(int f) const { fract t; t=*this-(fract)f; return t; }
	fract operator-(double f) const { fract t; t=*this-(fract)f; return t; }
	fract operator*(fract) const;
	fract operator*(int32 i) const { fract t; t.d=d*i; return t; }
	fract operator*(double i) const;
	fract operator/(fract f) const;
	fract operator/(int i) const { fract t; t.d=d/i; return t; }
	fract operator/(double i) const;
	fract operator-() const { fract t; t.d=-d; return t; }

	fract &operator+=(fract f) { d+=f.d; return *this; }
	fract &operator-=(fract f) { d-=f.d; return *this; }

	int operator<(fract f)	const { return d<f.d; }
	int operator<=(fract f)	const { return d<=f.d; }
	int operator>(fract f)	const { return d>f.d; }
	int operator>=(fract f)	const { return d>=f.d; }
	int operator!=(fract f)	const { return d!=f.d; }
	int operator==(fract f)	const { return d==f.d; } 

	int operator<(int i)	const { return *this<fract(i); }
	int operator<=(int i)	const { return *this<=fract(i); }
	int operator>(int i)	const { return *this>fract(i); }
	int operator>=(int i)	const { return *this>=fract(i); }
	int operator!=(int i)	const { return *this!=fract(i); }
	int operator==(int i)	const { return *this==fract(i); } 

	int operator<(double i)		const { return *this<fract(i); }
	int operator<=(double i)	const { return *this<=fract(i); }
	int operator>(double i)		const { return *this>fract(i); }
	int operator>=(double i)	const { return *this>=fract(i); }
	int operator!=(double i)	const { return *this!=fract(i); }
	int operator==(double i)	const { return *this==fract(i); } 
};

inline fract fract::operator*(fract f) const
{
	fract t; 
	t.d=((long long)d*f.d)>>shift; 
	return t; 
}

inline fract fract::operator*(double i) const 
{
	fract t; 
	t.d=(int32)(d*i+0.5); 
	return t; 
}

inline fract fract::operator/(fract f) const 
{
	fract t;
	t.d=(((int64)d<<shift)/f.d); 
	return t;
}

inline fract fract::operator/(double i) const 
{ 
	fract t; 
	t.d=(int)(d/i+0.5); 
	return t; 
}

inline int operator*(int i,fract f)
{
	return i*(int)f;
}

inline double operator*(double i,fract f)
{
	return i*(double)f;
}

inline int operator/(int i,fract f)
{
	return i/(int)f;
}

inline double operator/(double d,fract f)
{
	return d/(double)f;
}

inline int operator+(int i,fract f)
{
	return i+(int)f;
}

inline double operator+(double i,fract f)
{
	return i+(double)f;
}

inline int operator-(int i,fract f)
{
	return i-(int)f;
}

inline double operator-(double i,fract f)
{
	return i-(double)f;
}


# 4 "coord.h" 2


template<class T,int S> 
class coord {
	T c[S];
public: 
	coord() {};

	template<class TT> coord(coord<TT,S> const &o); 
	template<class TT> coord<T,S> &operator=(TT[S]);

	T &operator[](int i) { return c[i]; }
	T const &operator[](int i) const { return c[i]; }
	T get(int i) const { return c[i]; } 

	coord<T,S> operator-() const; 
	coord<T,S> operator+(coord<T,S> const &o) const;
	coord<T,S> operator+=(coord<T,S> const &o) { *this=*this+o; }
	coord<T,S> operator-(coord<T,S> const &o) const;
	coord<T,S> operator-=(coord<T,S> const &o) { *this=*this-o; }
	template<class TT> T operator*(coord<TT,S> const &o) const;

	coord<T,S> &operator*=(int);
	coord<T,S> &operator*=(double);
	coord<T,S> &operator*=(fract);
	coord<T,S> &operator/=(int);
	coord<T,S> &operator/=(double);
	coord<T,S> &operator/=(fract);
	coord<T,S> operator*(int)	const;
	coord<T,S> operator*(double)	const;
	coord<T,S> operator*(fract)	const;
	coord<T,S> operator/(int)	const;
	coord<T,S> operator/(double)	const;
	coord<T,S> operator/(fract)	const;

	int operator==(coord<T,S> const &) const;
	int operator!=(coord<T,S> const&o) const { return !(*this==o); }

	void print();
};

template<class T,int S>
inline void coord<T,S>::print()
{
	printf("(");
	for(int i=0;i<S;i++) {
		printf("%lf",(double)c[i]);
		if(i<S-1)
			printf(",");
	}
	printf(")");
}

template<class T,int S> template<class TT>
inline coord<T,S>::coord(coord<TT,S> const &o)
{
	for(int i=0;i<S;i++) 
		c[i]=o.get(i); 
}

template<class T,int S> template<class TT>
inline coord<T,S> &coord<T,S>::operator=(TT d[S])
{
	for(int i=0;i<S;i++)
		c[i]=d[i];
	return *this;
}

template<class T,int S>
inline coord<T,S> coord<T,S>::operator+(coord<T,S> const &o) const
{
	coord<T,S> t;
	for(int i=0;i<S;i++) 
		t.c[i]=c[i]+o.get(i);
	return t;
}

template<class T,int S>
inline coord<T,S> coord<T,S>::operator-(coord<T,S> const &o) const
{
	coord<T,S> t;
	for(int i=0;i<S;i++) 
		t.c[i]=c[i]-o.c[i]; 
	return t;
}

template<class T,int S>
inline coord<T,S> coord<T,S>::operator-() const
{
	coord<T,S> t;
	for(int i=0;i<S;i++)
		t[i]=-c[i];
	return t;
}

template<class T,int S> template<class TT>
inline T coord<T,S>::operator*(coord<TT,S> const &o) const
{
	T t;
	t=c[0]*o.get(0);
	for(int i=1;i<S;i++) 
		t+=c[i]*o.get(i); 
	return t;
} 

template<class T,int S>
inline coord<T,S> &coord<T,S>::operator*=(int x)
{
	for(int i=0;i<S;i++)
		c[i]*=x;
	return *this;
}

template<class T,int S>
inline coord<T,S> &coord<T,S>::operator*=(double x)
{
	for(int i=0;i<S;i++)
		c[i]*=x;
	return *this;
}

template<class T,int S>
inline coord<T,S> &coord<T,S>::operator*=(fract x)
{
	for(int i=0;i<S;i++)
		c[i]*=x;
	return *this;
}

template<class T,int S>
inline coord<T,S> &coord<T,S>::operator/=(int x)
{
	for(int i=0;i<S;i++)
		c[i]/=x;
	return *this;
}

template<class T,int S>
inline coord<T,S> &coord<T,S>::operator/=(double x)
{
	for(int i=0;i<S;i++)
		c[i]/=x;
	return *this;
}

template<class T,int S>
inline coord<T,S> &coord<T,S>::operator/=(fract x)
{
	for(int i=0;i<S;i++)
		c[i]/=x;
	return *this;
}

template<class T,int S>
inline coord<T,S> coord<T,S>::operator*(int x) const
{
	coord<T,S> t;
	for(int i=0;i<S;i++)
		t[i]=c[i]*x;
	return t;
}

template<class T,int S>
inline coord<T,S> coord<T,S>::operator*(double x) const
{
	coord<T,S> t;
	for(int i=0;i<S;i++)
		t[i]=c[i]*x;
	return t;
}

template<class T,int S>
inline coord<T,S> coord<T,S>::operator*(fract x) const
{
	coord<T,S> t;
	for(int i=0;i<S;i++)
		t[i]=c[i]*x;
	return t;
}

template<class T,int S>
inline coord<T,S> coord<T,S>::operator/(int x) const
{
	coord<T,S> t;
	for(int i=0;i<S;i++)
		t[i]=c[i]/x;
	return t;
}

template<class T,int S>
inline coord<T,S> coord<T,S>::operator/(double x) const
{
	coord<T,S> t;
	for(int i=0;i<S;i++)
		t[i]=c[i]/x;
	return t;
}

template<class T,int S>
inline coord<T,S> coord<T,S>::operator/(fract x) const
{
	coord<T,S> t;
	for(int i=0;i<S;i++)
		t[i]=c[i]/x;
	return t;
}

template<class T,int S>
inline int coord<T,S>::operator==(coord<T,S> const &o) const
{
	for(int i=0;i<S;i++)
		if(c[i]!=o.c[i])
			return 0;
	return 1;
}

template <class T,int S>
inline coord<int,S> operator*(int i,coord<T,S> c)
{
	return c*i;
}

template <class T,int S>
inline coord<double,S> operator*(double i,coord<T,S> c)
{
	return (coord<double,S>)c*i;
}

template <class T,int S>
inline coord<fract,S> operator*(fract i,coord<T,S> c)
{
	return (coord<fract,S>)c*i;
}


# 1 "test.cpp" 2


void SetTransformation(int const &M)
{
	coord<fract,3> corner[8];
	corner[0][0]=corner[0][1]=corner[0][2]=0;
}

main()
{
	int M;
	SetTransformation(M);
}



More information about the Gcc-bugs mailing list