Ghastly f77 bug in common subexpression elimination -- IMPORTANT

donn at sdchema.UUCP donn at sdchema.UUCP
Tue Mar 27 17:18:12 AEST 1984


Subject: Ghastly f77 bug in common subexpression elimination -- IMPORTANT
Index:	usr.bin/f77/src/f77pass1/optcse.c 4.2BSD

Description:
	F77 considers two variables from the same COMMON block to be
	the same variable for the purposes of common subexpression
	elimination.  This is almost always wrong.

Repeat-By:
	Copy the following program into a file com.f.  Compile it with
	the optimizer turned on.

	----------------------------------------------------------------
		program com

		common /x/ a, b, c, d
		integer result, a, b, c, d

		a = 2
		b = 3
		c = 4
		d = 5

		result = a * b + c * d

		print *, result

		stop
		end
	----------------------------------------------------------------

	The expected result of running the program is '26'.  What the
	program actually prints is '12'.  To see why, here is the code
	produced (comments and other prettification added):

	----------------------------------------------------------------
		.globl	_MAIN_
		.set	LF1,4
	_MAIN_:
		.word	LWM1
		subl2	$LF1,sp
		jmp	L12
	L13:
		movl	$2,_x_
		movl	$3,_x_+4
		movl	$4,_x_+8
		movl	$5,_x_+12
		mull3	_x_+4,_x_,-4(fp)
		addl3	-4(fp),-4(fp),{result}	# Mistake!
		pushal	v.3
		calls	$1,_s_wsle
		pushl	$4
		pushab	{result}
		pushal	{1}
		pushal	{3}
		calls	$4,_do_lio
		calls	$0,_e_wsle
		pushl	$0
		pushal	{00,00}
		calls	$2,_s_stop
		ret
		.align	1
	_com_:
		.word	LWM1
	L12:
		moval	v.1,r11
		jmp	L13
	----------------------------------------------------------------

	The two multiplies were treated as common subexpressions, and
	the same temporary [-4(fp)] was used to store both results.

Fix:
	I agonized over this one.  Since this is a very urgent problem
	I have decided to can my earlier inconclusive changes and make
	a single, one-line change that has the effect of making COMMON
	variables pretty much ineligible for CSE (actually it gives
	them the status of arrays, which is convenient since COMMON
	blocks look just like arrays to the compiler).  This is fast
	and has the advantage of introducing few new bugs.  The change
	is to optcse.c in routine scantree():

	----------------------------------------------------------------
	***************
	*** 564,570
					ap = (Addrp) p->exprblock.leftp;
					idp = findid(ap);
					killdepnodes(idp);
	! 				if( ! ap->isarray ) {
						if(rnode->is_dead)idp->assgnval=idp->initval;
						else idp->assgnval = rnode;
					}

	--- 584,590 -----
					ap = (Addrp) p->exprblock.leftp;
					idp = findid(ap);
					killdepnodes(idp);
	! 				if( ! (ap->isarray || ap->vstg == STGCOMMON) ) {
						if(rnode->is_dead)idp->assgnval=idp->initval;
						else idp->assgnval = rnode;
					}
	----------------------------------------------------------------

	This bug is responsible for many seemingly unrelated errors,
	such as the previously reported 'exponentiation' error where
	'x1 ** alpha + x2 ** alpha + x3 ** alpha' always turned out
	to be '3 * x1 ** alpha'.  You should fix this as soon as you
	can...

Donn Seeley    UCSD Chemistry Dept.       ucbvax!sdcsvax!sdchema!donn
32 52' 30"N 117 14' 25"W  (619) 452-4016  sdcsvax!sdchema!donn at nosc.ARPA



More information about the Comp.bugs.4bsd.ucb-fixes mailing list