Optimizer handles double incorrectly
john@jupiter.com
john@jupiter.com
Mon Nov 29 12:05:00 GMT 1999
Platform:
Pentium II PC, Red Hat Linux 6.0, X11R6.4 @ Patch Level 3, compiled -m486 -g2 -ansi -pedantic
gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
Description:
There is a bug in the gcc optimizer's handling of "double". It also
occurs with gcc version 2.95.1 19990816 (release). Unfortunately,
it depends on things that are compiled with something. Which is to
say, while I can reproduce it by compiling the whole X Server,
I can not extract the routine and reproduce it as a separate program.
I have encountered two such bugs, one in our hardware initialization
code and one in the font libraries. Neither is extractable, i.e. the below,
compiled with the same options run fine as separate programs but not as
parts of the X Server (see below).
--John
Timing Bug:
As part of the X Server, af is corrupted by the assignment ef = df immediately
following.
/*
gcc -c -m486 -g2 -O2 -ansi -pedantic -Dlinux -D__i386__ -D_POSIX_S
OURCE -D_BSD_SOURCE -D_SVID_SOURCE -DX_LOCALE -DSHAPE -DXCSECURITY
-DTOGCUP -DDPMSExtension -DGCCUSESGAS -DSTATIC_COLOR -DAVOID_GLYP
HBLT -DPIXPRIV -DXV -DFORCE_SEPARATE_PRIVATE -DNDEBUG -DFUNCPROTO=1
5 -DNARROWPROTO optbug.c
gcc -o optbug -m486 -g2 -O2 -ansi -pedantic optbug.c
*/
typedef struct {
unsigned int PixelClk;
unsigned int DesiredFrequency;
unsigned int ActualFrequency;
unsigned char Numerator;
unsigned char Denominator;
unsigned char PostScale;
} ClkRegSet, *ClkRegSetPtr;
void
calculate_int_vclks(ClkRegSet *CP)
{
double f, af, ef, df, e;
double rf = 14318.18;
int i, j, n, d, s, p, on, od, os;
df = (double )CP->DesiredFrequency;
af = (double )0.0;
ef = df;
for (s = 1; s >= 0; s--)
{
p = s + 1;
for (i = 1; i < 128; i++)
{
if (i & 1)
n = 64 - ((i - 1) / 2);
else
n = 64 + (i / 2);
for (j = 1; j < 128; j++)
{
if (j & 1)
d = 64 - ((j - 1) / 2);
else
d = 64 + (j / 2);
f = (rf * (double) n) / ((double) (d * p));
e = abs(f - df);
if (e < ef)
{
af = f;
on = n;
od = d;
os = s;
ef = e;
}
}
}
}
CP->ActualFrequency = (int )af;
CP->Numerator = on;
CP->Denominator = od;
CP->PostScale = os;
}
==================================================================================================
Font Bug:
Font:
courb.pfa, -adobe-courier-bold-r-normal--14-*-*-*-*-*-*-*.
This did not seem to be library bug, since the font server, compiled in the same tree with
identical defines and libraries, including libfont.a, opens the font without problems.
It was thought to be an initialization error, since the Jupiter X Server is quite complex,
supporting multiple screens, Virtual Screen and multiple depths. Several instances of memory
being allocated in one place, freed in another and reallocated in yet another had been
encountered during implementation.
With the aid of Electric Fence, it was found that the Bresenham algorithm was violating its
allocated memory space (t1_Bresenham at lines.c:182) due to out of bound (x,y) coordinates.
(By setting EF_PROTECT_FREE, efence also eliminated the possibility of memory allocation
errors as initially suspected.) The origin of the problem was traced to the MatrixMultiply
procedure (t1_MMultiply at spaces.c:860).
Workaround:
The anomalous calculations were eliminated by removing the \""register\"" declarations from the
input parameters and working variables.
Comments:
Why this should correct anything is not understood. MatrixMultiply is a very simple procedure,
(see below). The same code in the same file and same library running on the same machine at
the same time with the same input parameters yields correct computations when linked with the
Font Server and incorrect computations when linked with the X Server. It may be a compiler bug
or perhaps there is some register initialization done by the font server that is not done by the
X Server.
/*
* :h3.MatrixMultiply() - Implements Multiplication of Two Matrices
* Implements matrix multiplication, A * B = C.
* To remind myself, matrix multiplication goes rows of A times columns of B.
* The output matrix may be the same as one of the input matrices.
*/
void MatrixMultiply(A, B, C)
register double A[2][2],B[2][2]; /* input matrices */
register double C[2][2]; /* output matrix */
{
register double txx,txy,tyx,tyy;
txx = A[0][0] * B[0][0] + A[0][1] * B[1][0];
txy = A[1][0] * B[0][0] + A[1][1] * B[1][0];
tyx = A[0][0] * B[0][1] + A[0][1] * B[1][1];
tyy = A[1][0] * B[0][1] + A[1][1] * B[1][1];
C[0][0] = txx;
C[1][0] = txy;
C[0][1] = tyx;
C[1][1] = tyy;
}
Dump of assembler code for function t1_MMultiply:
0x808a260 <t1_MMultiply>: pushl ëp
0x808a261 <t1_MMultiply+1>: movl %esp,ëp
0x808a263 <t1_MMultiply+3>: movl 0x8(ëp),ÃÂx
0x808a266 <t1_MMultiply+6>: movl 0xc(ëp),ìx
0x808a269 <t1_MMultiply+9>: movl 0x10(ëp),êx
0x808a26c <t1_MMultiply+12>: fldl (ÃÂx)
0x808a26e <t1_MMultiply+14>: fmull (ìx)
0x808a270 <t1_MMultiply+16>: fldl 0x8(ÃÂx)
0x808a273 <t1_MMultiply+19>: fmull 0x10(ìx)
0x808a276 <t1_MMultiply+22>: faddp %st,%st(1)
0x808a278 <t1_MMultiply+24>: fldl 0x10(ÃÂx)
0x808a27b <t1_MMultiply+27>: fmull (ìx)
0x808a27d <t1_MMultiply+29>: fldl 0x18(ÃÂx)
0x808a280 <t1_MMultiply+32>: fmull 0x10(ìx)
0x808a283 <t1_MMultiply+35>: faddp %st,%st(1)
0x808a285 <t1_MMultiply+37>: fldl (ÃÂx)
0x808a287 <t1_MMultiply+39>: fmull 0x8(ìx)
0x808a28a <t1_MMultiply+42>: fldl 0x8(ÃÂx)
0x808a28d <t1_MMultiply+45>: fmull 0x18(ìx)
0x808a290 <t1_MMultiply+48>: faddp %st,%st(1)
0x808a292 <t1_MMultiply+50>: fldl 0x10(ÃÂx)
0x808a295 <t1_MMultiply+53>: fmull 0x8(ìx)
0x808a298 <t1_MMultiply+56>: fldl 0x18(ÃÂx)
0x808a29b <t1_MMultiply+59>: fmull 0x18(ìx)
0x808a29e <t1_MMultiply+62>: faddp %st,%st(1)
0x808a2a0 <t1_MMultiply+64>: fxch %st(3)
0x808a2a2 <t1_MMultiply+66>: fstpl (êx)
0x808a2a4 <t1_MMultiply+68>: fxch %st(1)
0x808a2a6 <t1_MMultiply+70>: fstpl 0x10(êx)
0x808a2a9 <t1_MMultiply+73>: fstpl 0x8(êx)
0x808a2ac <t1_MMultiply+76>: fstpl 0x18(êx)
0x808a2af <t1_MMultiply+79>: movl ëp,%esp
0x808a2b1 <t1_MMultiply+81>: popl ëp
0x808a2b2 <t1_MMultiply+82>: ret
End of assembler dump.
Fix:
void MatrixMultiply(A, B, C)
double A[2][2],B[2][2]; /* input matrices */
double C[2][2]; /* output matrix */
{
double txx,txy,tyx,tyy;
txx = A[0][0] * B[0][0] + A[0][1] * B[1][0];
txy = A[1][0] * B[0][0] + A[1][1] * B[1][0];
tyx = A[0][0] * B[0][1] + A[0][1] * B[1][1];
tyy = A[1][0] * B[0][1] + A[1][1] * B[1][1];
C[0][0] = txx;
C[1][0] = txy;
C[0][1] = tyx;
C[1][1] = tyy;
}
======================================================================
More information about the Gcc-bugs
mailing list