This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Optimization Bug in g77


I have run into a strange problem with g77 when run with the -O or -O1
option but NOT with -O2, -O3, or no optimization.  Below is piece
of Fortran code (removed from a larger program) which illustrates the
problem.  The basic function of the code is to go through a list
of data (the RAW array) and accumulate an average and uncertainty
in the average, excluding "outlier points".  This is done iteratively
by calculating an average and standard deviation using only points
that differ by less than some number (NSIG) of standard deviations
from the average calculated by the previous iteration (in the first
iteration all points are accumulated).  The iteration is repeted until
the average does not change between two iterations or until some
maximum number of iterations is reached.  In the program below, some
fake data is first generated.  For technical reasons, the number of
"rejected points" and the number of iterations (normally integers) are
accumulated in double precision reals.

The problem with this code is that when compiled with either the -O or -O1
options, the maximum number of iterations is performed.  When compiled
with -O2, -O3, or no optimization options, only 2 iterations are done.
Some how the check for the averages of two successive iterations is
being disabled when -O or -O1 is selected.

Two other symptoms that I have noticed: if the -ffloat-store option is
used, then the program always works correctly (does only 2 iterations).
And, if the write statement immediately preceding the check for
equal averages is un-commented, the program also works correctly.

-----------Program optimization-test.F CUT HERE--------------------------
C	This program produces two different results depending on
C	the g77 optimization.
	IMPLICIT NONE
C	Maximum number of iterations of the filtering process
	INTEGER NITRMX
	PARAMETER (NITRMX = 50)
C	Number of SIGMA outside of which data is rejected.
	INTEGER NSIG
	PARAMETER (NSIG = 40)
C	Number of data points
	INTEGER NDAT
	PARAMETER (NDAT = 200)
C
	INTEGER I
	REAL RAW(200)
	DOUBLE PRECISION AV,SD,AVOLD,SDOLD,FIL(2),SUM,SUM2
C
	FIL(2) = 1.D0
	SDOLD = 1.D37
	AVOLD = 0.D0
C	Generate some fake data (Gaussian tail with flat-top)
	DO 100 I = 1,NDAT
	    RAW(I) = EXP(-((I-100.)/10.)**2)
100	CONTINUE
	DO 110 I = NDAT/2-20,NDAT/2+20
	    RAW(I) = 1
110	CONTINUE
C
C	Scan data to calculate mean and uncertainty.  Reject
C	any data that is NSIG SIGMA from the mean (unless this
C	is the first iteration).
10	SUM = 0.D0
	SUM2 = 0.D0
	FIL(1) = 0.D0
	DO 70 I = 1,NDAT
	    IF (FIL(2).LE.1.D0.OR.ABS(RAW(I)-AVOLD).LE.NSIG*SDOLD) THEN
	        SUM = SUM+RAW(I)
	        SUM2 = SUM2+RAW(I)**2
	    ELSE
	        FIL(1) = FIL(1)+1.D0
	    ENDIF
70	CONTINUE
C	Calculate a new mean and SIGMA.
	AV = SUM/(NDAT-FIL(1))
C	This is the standard deviation of the mean (which is not the
C	same as the standard deviation of the measurement distribution,
C	i.e. the sample standard deviation.).
	SD = SQRT(SUM2/(NDAT-FIL(1))-AV**2)/SQRT(NDAT-1-FIL(1))
c	write (6,*) av
	IF (FIL(2).LE.1.D0.OR.AV.NE.AVOLD) THEN
	    IF (FIL(2).LT.NITRMX) THEN
C	        If this is the first iteration, or if the process
C	        hasn't converged, go back and re-scan.
	        FIL(2) = FIL(2)+1.D0
	        AVOLD = AV
	        SDOLD = SD
	        GO TO 10
	    ENDIF
	ENDIF
	write (6,*) fil(2),av,fil(1)
	if (fil(2).eq.nitrmx) then
	    write (6,*) 'Wrong answer!'
	else
	    write (6,*) 'Right answer.'
	endif
	STOP 'All done.'
	END
------------------------------------------------------------------------

Here is the Makefile that I use to genererate the executable of the
above program.  It assumes that the above Fortran is in a file
called optimization-test.F.  A number of different choices for
the FFLAGS (most commented out) are divided into a group that doesn't
work and a group that works.

-----------------------Makefile CUT HERE--------------------------------
# This is a make file for optimization-test.  The following commands are
# defined:
# make			Create program on source directory (don't install
#                       in destination)
# make all			"
# make program			"
# make clean		Remove object files from the source directory
# make install		Move the program from the source directory to the
#                       destination
# make update		Combines program creation with installation in
#                       destination directory

# Final result of this make file
PROGRAM=optimization-test

OBJS=optimization-test.o

# Source file names (syntax is the same as SRCS=$(patsubst %.o,%.F,$(OBJS)))
SRCS=$(OBJS:%.o=%.F)

# Place to store the final result (no last /)
DEST=$(HOME)/bin/$(OSNAME)

# Name of this file
MAKEFILE=Makefile

# Library directories 
LIBDIR=

# Libraries to link to (other operating system specific libraries are defined
# by OSLIBS).
LIBS=

# Fortran command
FC=g77

# Fortran (g77) flags for Linux
# -fcase-lower		Map to lower case (case insensitive)
#			(note that most libraries are compiled
#			with lower case symbols).
# -O			Optimize the code -- same as O1 (could be O2 for even
#			beter optimization, or O3 for the best optimization)
# -Wall			Warn when variables are unused (except
#			for declaration) and when uninitialized
# 			variables are used. 
# The following options produce a program that does NOT work
# FFLAGS=-W -Wall -fcase-lower -O
# FFLAGS=-W -Wall -fcase-lower -O1
#
# The following options produce a program that works:
# FFLAGS=-W -Wall -fcase-lower -O2
# FFLAGS=-W -Wall -fcase-lower -O3
# FFLAGS=-W -Wall -fcase-lower -ffloat-store -O1
# FFLAGS=-W -Wall -fcase-lower -ffloat-store -O
# FFLAGS=-W -Wall -fcase-lower -ffloat-store
# FFLAGS=-W -Wall -fcase-lower -ffloat-store -O2
# FFLAGS=-W -Wall -fcase-lower -ffloat-store -O3
FFLAGS=-W -Wall -fcase-lower

# Loader options for Linux
# -L <directory>        Look in <directory> for libraries
LDFLAGS=

# Libraries required on this operating system
OSLIBS=

# "make all" and "make program" are the same as "make"
all:		$(PROGRAM)
program:        $(PROGRAM)
$(PROGRAM):     $(OBJS)
		$(FC) $(LDFLAGS) $(OBJS) $(LIBS) $(OSLIBS) -o $(PROGRAM)

# "make install" transfers the program to the destination directory
install:	$(PROGRAM)
		mv $(PROGRAM) $(DEST)

# "make update" combines the creation of the program with its installation.
update:		$(DEST)/$(PROGRAM)
$(DEST)/$(PROGRAM): $(SRCS)
		@make -f $(MAKEFILE) DEST=$(DEST) install

# "make clean" removes all old object files.  This uses a "phony target"
# (ie target without dependencies)
.PHONY:		clean
clean:
		rm -f $(OBJS)

Here is the result of doing g77 -v on my system:


------------------------------------------------------------------------
>g77 -v
g77 version 2.95.4 20011002 (Debian prerelease) (from FSF-g77 version
0.5.25 20010319 (prerelease))
Driving: g77 -v -c -xf77-version /dev/null -xnone
Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.4/specs
gcc version 2.95.4 20011002 (Debian prerelease)
 /usr/lib/gcc-lib/i386-linux/2.95.4/cpp0 -lang-c -v -D__GNUC__=2
-D__GNUC_MINOR__=95 -D__ELF__ -D__unix__ -D__i386__ -D__linux__ -D__unix
-D__linux -Asystem(posix) -D_LANGUAGE_FORTRAN -traditional
-Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ /dev/null /dev/null
GNU CPP version 2.95.4 20011002 (Debian prerelease) (i386 Linux/ELF)
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /usr/lib/gcc-lib/i386-linux/2.95.4/include
 /usr/include
End of search list.
The following default directories have been omitted from the search path:
 /usr/lib/gcc-lib/i386-linux/2.95.4/../../../../include/g++-3
 /usr/lib/gcc-lib/i386-linux/2.95.4/../../../../i386-linux/include
End of omitted list.
 /usr/lib/gcc-lib/i386-linux/2.95.4/f771 -fnull-version -quiet -dumpbase
g77-version.f -version -fversion -o /tmp/ccCss7xb.s /dev/null
GNU F77 version 2.95.4 20011002 (Debian prerelease) (i386-linux) compiled
by GNU C version 2.95.4 20011002 (Debian prerelease).
GNU Fortran Front End version 0.5.25 20010319 (prerelease)
 as -V -Qy -o /tmp/ccOS8gud.o /tmp/ccCss7xb.s
GNU assembler version 2.12.90.0.1 (i386-linux) using BFD version
2.12.90.0.1 20020307 Debian/GNU Linux
 ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o /tmp/cc8iVYBd
/tmp/ccOS8gud.o /usr/lib/crt1.o /usr/lib/crti.o
/usr/lib/gcc-lib/i386-linux/2.95.4/crtbegin.o
-L/usr/lib/gcc-lib/i386-linux/2.95.4 -lg2c -lm -lgcc -lc -lgcc
/usr/lib/gcc-lib/i386-linux/2.95.4/crtend.o /usr/lib/crtn.o
 /tmp/cc8iVYBd
__G77_LIBF77_VERSION__: 0.5.25 20010319 (prerelease)
@(#)LIBF77 VERSION 19990503
__G77_LIBI77_VERSION__: 0.5.25 20010319 (prerelease)
@(#) LIBI77 VERSION pjw,dmg-mods 19990503
__G77_LIBU77_VERSION__: 0.5.25 20010319 (prerelease)
@(#) LIBU77 VERSION 19980709
-----------------------------------------------------------------------

Obvously I have a work-around to make my code do what I want it to do,
but this makes me worry that there are other programs, compiled with
-O, that are not really doing what they are supposed to do.

Thank you for any help (patches, suggestions).  Let me know if I can
supply more information.

				Steve Williamson
				Physics Dept.
				University of Illinois


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]