This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Optimize flag breaks code on many versions of gcc (not all)
- From: minus <minus at toneby dot com>
- To: gcc at gcc dot gnu dot org
- Date: Sun, 18 Jun 2006 20:10:06 +0200
- Subject: Optimize flag breaks code on many versions of gcc (not all)
This 'little' program behaves bad when compiled with -O. It works fine
when no -O or -O0 is used.
The function is from Graphics Gem I and has been ported from C to C++
http://www.acm.org/pubs/tog/GraphicsGems/gems.html#gems
Woo, Andrew, Fast Ray-Box Intersection, p. 395-396, code: p. 736-737
This is how things went when compiling on my Debian unstable (current as
of 2006-06-18).
The problem has also been encountererd on redhat rhel (3?) but not
investigated there.
No flags were used except -On (The program do compile cleanly with
-Wall -W -pedantic)
-O0 -O1 -O2 -O3
g++-2.95 ok error error error
g++-3.3 ok error error error
g++-3.4 ok ok error error
g++-4.0 ok error error error
g++-4.1 ok error error error
g++ -v output for each compiler it further down.
Have I done something wrong or is this something for the bugzilla?
minus
// ********** Start of program
#include <iostream>
#include <vector>
using namespace std;
class GeoPoint
{
public:
inline GeoPoint(double east, double north, double height)
{elt_[0]=east;elt_[1]=north;elt_[2]=height;}
GeoPoint& operator-=(const GeoPoint& p) {
elt_[0] -= p[0]; elt_[1] -= p[1]; elt_[2] -= p[2];
return *this;
}
GeoPoint& operator-=(const double p) {
elt_[0]-=p; elt_[1]-=p; elt_[2]-=p;
return *this;
}
GeoPoint& operator+=(const double p) {
elt_[0]+=p; elt_[1]+=p; elt_[2]+=p;
return *this;
}
double &operator[](int i) { return elt_[i]; }
const double &operator[](int i) const { return elt_[i]; }
private:
double elt_[3];
private:
friend std::ostream& operator<<(std::ostream& s,const GeoPoint& a);
};
std::ostream& operator<<(std::ostream& s,const GeoPoint& a)
{
s << " ( " << a[0] << " " << a[1] << " " << a[2] << " ) ";
return s;
}
/*********************************************************************/
bool rayBoxIntersection(const GeoPoint& ll,
const GeoPoint& ur,
const GeoPoint& start,
const GeoPoint& end,
GeoPoint& coord)
{
typedef enum {RIGHT,LEFT,MIDDLE} PlaneRelative;
const int NumberOfDimensions=3;
bool inside=true;
PlaneRelative quadrant[NumberOfDimensions];
GeoPoint candidatePlane(0.0,0.0,0.0);
GeoPoint dir(end);
dir-=start;
GeoPoint maxT(-1,-1,-1);
// Find candidate planes
for (int i=0; i<NumberOfDimensions; i++) {
if (start[i]<ll[i]) {
quadrant[i] = LEFT;
candidatePlane[i]=ll[i];
inside=false;
} else if (start[i]>ur[i]) {
quadrant[i] = RIGHT;
candidatePlane[i]=ur[i];
inside=false;;
} else {
quadrant[i] = MIDDLE;
}
}
if (inside) {
coord=start;
return true;
}
// calculate T distances to candidate planes
for (int i=0; i<NumberOfDimensions; i++) {
if (quadrant[i]!=MIDDLE && dir[i] !=0.0) {
maxT[i]=(candidatePlane[i]-start[i])/dir[i];
} else {
maxT[i]=-1.0;
}
}
//get largest maxT for final choice of intersection
int whichPlane=0;
for (int i=1; i<NumberOfDimensions; i++) {
if (maxT[whichPlane]<maxT[i]) {
whichPlane=i;
}
}
if (maxT[whichPlane]<0.0) {
// didn't hit the box
return (false);
}
for (int i=0; i<NumberOfDimensions; i++) {
if (whichPlane==i) {
coord[i]=candidatePlane[i];
} else {
coord[i]=start[i]+maxT[whichPlane]*dir[i];
// **** Uncomment one of these to make the program work.
//sleep(0);
//cerr << "";
if ((coord[i]<ll[i]) || (coord[i]>ur[i])) {
// outside box
return false;
}
}
}
return true;
}
/*********************************************************************/
int main(void)
{
vector<GeoPoint> p;
// define three boxes.
p.push_back(GeoPoint(1.004,1.004,1.004)); // at start of line
p.push_back(GeoPoint(1.020,1.020,1.020)); // middle of line
p.push_back(GeoPoint(1.046,1.046,1.046)); // at end of line
GeoPoint start(1.000,1.000,1.000);
GeoPoint end(1.050,1.050,1.050);
for (vector<GeoPoint>::const_iterator iter=p.begin();
iter!=p.end();
++iter)
{
GeoPoint ll(*iter);
GeoPoint ur(*iter);
ll-=0.005;
ur+=0.005;
GeoPoint hit(-1,-1,-1);
GeoPoint hitreverse(-1,-1,-1);
// find where the first hit inside the box (ll,ur) of the
// line between start and end
bool res1=rayBoxIntersection(ll,ur,start,end,hit);
// find where the first hit inside the box (ll,ur) of the
// line between end and start (the reverse direction compared
// to the previous call)
bool res2=rayBoxIntersection(ll,ur,end,start,hitreverse);
if (res1 && res2) {
cout << "ok: " << endl;
} else {
cout << "error" << endl;
}
}
return 0;
}
// ********** End of program
// ********** output from g++ -v for each compiler used.
Reading specs from /usr/lib/gcc-lib/i486-linux-gnu/2.95.4/specs
gcc version 2.95.4 20011002 (Debian prerelease)
Reading specs from /usr/lib/gcc-lib/i486-linux-gnu/3.3.6/specs
Configured with: ../src/configure -v --enable-languages=c,c++
--prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info
--with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared
--enable-__cxa_atexit --with-system-zlib --enable-nls
--without-included-gettext --enable-clocale=gnu --enable-debug
i486-linux-gnu
Thread model: posix
gcc version 3.3.6 (Debian 1:3.3.6-13)
Reading specs from /usr/lib/gcc/i486-linux-gnu/3.4.6/specs
Configured with: ../src/configure -v --enable-languages=c,c++,f77,pascal
--prefix=/usr --libexecdir=/usr/lib
--with-gxx-include-dir=/usr/include/c++/3.4 --enable-shared
--with-system-zlib --enable-nls --without-included-gettext
--program-suffix=-3.4 --enable-__cxa_atexit --enable-clocale=gnu
--enable-libstdcxx-debug --with-tune=i686 i486-linux-gnu
Thread model: posix
gcc version 3.4.6 (Debian 3.4.6-2)
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c
++,java,f95,objc,ada,treelang --prefix=/usr --enable-shared
--with-system-zlib --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --enable-nls --program-suffix=-4.0
--enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug
--enable-java-awt=gtk-default --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-4.0-1.4.2.0/jre
--enable-mpfr --disable-werror --with-tune=i686
--enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.0.4 20060507 (prerelease) (Debian 4.0.3-3)
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c
++,java,fortran,objc,obj-c++,ada,treelang --prefix=/usr --enable-shared
--with-system-zlib --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --enable-nls --program-suffix=-4.1
--enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug
--enable-java-awt=gtk --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-4.1-1.4.2.0/jre
--enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.2 20060613 (prerelease) (Debian 4.1.1-5)
--