[4bsd-f77 #37] f77 sometimes rewrites register variables incorrectly
4.2 BSD f77 bug reports
4bsd-f77 at utah-cs.UUCP
Fri Aug 31 07:19:53 AEST 1984
From: Donn Seeley <donn at utah-cs.arpa>
Subject: f77 sometimes rewrites register variables incorrectly
Index: usr.bin/f77/src/f77pass1/regalloc.c 4.2BSD
Description:
When an f77 subroutine is passed another subroutine as an
argument (I'll call the latter 'EXTERNAL' subroutines although
this is not entirely accurate), the compiler sometimes fails to
keep straight the information that is in memory and the
information that has been written out to register when
processing calls to the EXTERNAL subroutine. The effect is
that when an EXTERNAL subroutine is called from inside a loop,
some of its parameters may appear to have the value they had
outside the loop. This bug was found and fixed by Jerry
Berkman and friends.
Repeat-By:
This is really several bugs with a common nature; the following
two programs from Jerry Berkman illustrate different features of
the bugs. Compile this program with the optimizer on:
----------------------------------------------------------------
c in loop in d01anw, i is in a register, but in computing x(i-1),
c the value of i from storage is used
double precision a, b
external dfct
a = 1.0d0
b = 2.0d0
call d01anw(dfct, a, b )
end
double precision function dfct( dx )
double precision dx
dfct = dx
end
subroutine d01anw(f, a, b)
double precision a, b, f
external f
double precision centre, hlgth, fval(8), x(8)
data x / 0.1d0, 0.2d0, 0.3d0, 0.4d0, 0.5d0, 0.6d0, 0.7d0, 0.8d0 /
centre = (b+a)
hlgth = (b-a)
do 260 i=2,8
fval(i) = f(hlgth*x(i-1)+centre)
260 continue
print 8010, fval
8010 format(4f8.4)
end
----------------------------------------------------------------
When you run the program you get the result:
----------------------------------------------------------------
0. 3.0000 3.0000 3.0000
3.0000 3.0000 3.0000 3.0000
----------------------------------------------------------------
But you should see instead:
----------------------------------------------------------------
0. 3.1000 3.2000 3.3000
3.4000 3.5000 3.6000 3.7000
----------------------------------------------------------------
The second program is more of the same. Compile it with the
optimizer on:
----------------------------------------------------------------
c when calling subroutine which is an argument,
c optimizer sometimes forgets to transfer arguments to
c memory (if in registers)
external sub
data ia/1/, ib/2/
call d01anw(sub, ia, ib )
end
subroutine sub( ii )
ii = 2 * ii
end
subroutine d01anw(subr, ii, jj )
external subr
integer fval(4)
ic = (jj+ii)
id = (jj-ii)
do 260 i=1,4
call subr( ic )
fval(i) = ic * ( id + ic )
260 continue
print *, fval
end
----------------------------------------------------------------
If you didn't install the previous fix for EXTERNAL subroutines
('F77 sometimes does improper code motion'), then you get the
following when you run the program:
----------------------------------------------------------------
24 48 96 192
----------------------------------------------------------------
If you were conscientious and installed the earlier fix, the
output is still wrong:
----------------------------------------------------------------
12 12 12 12
----------------------------------------------------------------
The answer you want is:
----------------------------------------------------------------
42 156 600 2352
----------------------------------------------------------------
Fix:
There are a couple problems here. One is that variables are
not being updated from register when they need to be. The
other, related problem is that f77 is making a distinction
between subroutines that can change their arguments and
subroutines that can't, and it mistakenly lumps EXTERNAL
procedures with the latter group. These problems are easily
fixed by adding a missing call to regwrite() and changing
all tests of the form 'ap->vstg == STGEXT' to 'ap->vstg !=
STGINTR'; this last change has the effect of making f77
think that any subroutine other than an intrinsic subroutine
may alter its arguments, and completes the change that was
started on with the earlier 'improper code motion' article.
The changes are in scancall(), countrefs() and regwrite()
in regalloc.c:
----------------------------------------------------------------
*** /tmp/,RCSt1028628 Mon Aug 20 16:43:57 1984
--- regalloc.c Wed Aug 15 17:44:14 1984
***************
*** 1100,1106
if (ep->rightp == NULL) return;
! if (lhs->vstg == STGEXT)
{
args = ep->rightp->listblock.listp;
for (; args; args = args->nextp)
--- 1103,1109 -----
if (ep->rightp == NULL) return;
! if (lhs->vstg != STGINTR)
{
args = ep->rightp->listblock.listp;
for (; args; args = args->nextp)
***************
*** 1173,1179
countrefs(p->exprblock.leftp->addrblock.vleng);
countrefs(p->exprblock.leftp->addrblock.memoffset);
! if (p->exprblock.leftp->addrblock.vstg == STGEXT)
{
if (!commonunusable)
if (linearcode)
--- 1176,1182 -----
countrefs(p->exprblock.leftp->addrblock.vleng);
countrefs(p->exprblock.leftp->addrblock.memoffset);
! if (p->exprblock.leftp->addrblock.vstg != STGINTR)
{
if (!commonunusable)
if (linearcode)
***************
*** 1342,1348
ap = (Addrp) p->exprblock.leftp;
regwrite(sp, ap->vleng);
regwrite(sp, ap->memoffset);
! if (ap->vstg == STGEXT)
{
if (linearcode)
{
--- 1345,1351 -----
ap = (Addrp) p->exprblock.leftp;
regwrite(sp, ap->vleng);
regwrite(sp, ap->memoffset);
! if (ap->vstg != STGINTR)
{
if (linearcode)
{
***************
*** 1416,1421
ap->vstg = STGPREG;
ap->memno = regnum[i];
}
}
}
return;
--- 1419,1428 -----
ap->vstg = STGPREG;
ap->memno = regnum[i];
}
+ }
+ else
+ {
+ regwrite(sp, args->datap);
}
}
return;
----------------------------------------------------------------
Donn Seeley University of Utah CS Dept donn at utah-cs.arpa
40 46' 6"N 111 50' 34"W (801) 581-5668 decvax!utah-cs!donn
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list