donn@CS.UTAH.EDU (Donn Seeley) (11/29/89)
Someone on our system (HP 9000 series 300 running 4.3 BSD) noticed a
few weeks ago that 'rn' was doing odd things with their Teleray
terminal. This didn't seem very important at the time, but a few weeks
later I looked into the problem and found that it was really a problem
in 'tset' that caused the termcap processing to screw up.
Specifically, if 'tset' was compiled with -fstrength-reduce, a routine
called cancelled() was compiled incorrectly. I was able to extract the
code from 'tset' and reproduce the problem in a small example:
Script started on Tue Nov 28 18:46:15 1989
% cat cancelled.c
int ncap;
char delcap[128][2];
cancelled(cap)
char *cap;
{
register int i;
for (i = 0; i < ncap; i++)
if (cap[0] == delcap[i][0] && cap[1] == delcap[i][1])
return 1;
++ncap;
return cap[2] == '@';
}
% cc -v -O -S -fstrength-reduce cancelled.c
gcc version 1.36.9
/usr/src/gnu/gcc-1.36.9.utah/cpp -nostdinc -v -I/usr/include -undef -D__GNUC__ -Dmc68000 -Dmc68020 -Dhp300 -Dhp9000 -Dunix -D__mc68000__ -D__mc68020__ -D__hp300__ -D__hp9000__ -D__unix__ -D__OPTIMIZE__ -traditional -D__HAVE_FPU__ cancelled.c /usr/tmp/cc000624.cpp
GNU CPP version 1.36.9
/usr/src/gnu/gcc-1.36.9.utah/cc1 /usr/tmp/cc000624.cpp -quiet -dumpbase cancelled.c -fstrength-reduce -O -traditional -fwritable-strings -fno-defer-pop -version -o cancelled.s
GNU C version 1.36.9 (68k, MIT syntax) compiled by GNU C version 1.36.9.
default target switches: -m68020 -mc68020 -m68881 -mbitfield
% cat cancelled.s
#NO_APP
gcc_compiled.:
.text
.even
.globl _cancelled
_cancelled:
link a6,#0
moveml #0x30,sp@-
movel a6@(8),a3
clrl d1 # loop prologue
cmpl _ncap,d1
jge L7
lea _delcap,a0
movel a0,a1 # initialize GIV: &delcap[i][0]
moveb a3@(1),d0
extbl d0
lea a0@(d0:l:2),a2 # bizarreness: &delcap[cap[1]][0] (!)
movel _ncap,d0
asll #1,d0
addl a0,d0
L6: # body of loop
moveb a3@,d1
cmpb a1@,d1 # correctly test using first GIV
jne L4
cmpl a2,a1 # test GIV against bizarreness
jne L4
moveq #1,d0
jra L1
L4:
addqw #2,a1
cmpl a1,d0
jgt L6
L7: # end of loop
addql #1,_ncap
cmpb #64,a3@(2)
seq d0
moveq #1,d1
andl d1,d0
L1:
moveml a6@(-8),#0xc00
unlk a6
rts
.comm _delcap,256
.comm _ncap,4
% exit
script done on Tue Nov 28 18:47:05 1989
Here's my analysis of the situation... The strength reduction code did
find that &delcap[i][0] was a GIV, but failed to identify a GIV in
&delcap[i][1]. Subsequent code assumes that if a comparison contains a
reference to the BIV 'i' (reg_mentioned_p()), one operand of the
comparison must literally be that BIV; this assumption probably works
most of the time because most occurrences of BIVs are either naked or
in GIVs which in turn are replaced by register references. In the
comparison 'cap[1] == delcap[i][1]', 'cap[1]' gets treated as the BIV
and 'delcap[i][1]' is apparently treated as an invariant, hence the
bizarre substitution seen in the loop prologue.
If can_eliminate_biv_p() is hacked so that it punts when a compare does
not have a BIV as a direct operand, eliminate_biv() won't mangle the
code trying to eliminate it, so I made the following change in loop.c:
------------------------------------------------------------------------
*** /tmp/,RCSt1000773 Tue Nov 28 20:18:59 1989
--- loop.c Tue Nov 28 20:18:45 1989
***************
*** 4821,4831 ****
arg = XEXP (src, 1);
arg_operand = 1;
}
! else
{
arg = XEXP (src, 0);
arg_operand = 0;
}
if (GET_CODE (arg) == CONST_INT)
{
--- 4821,4834 ----
arg = XEXP (src, 1);
arg_operand = 1;
}
! else if ((GET_CODE (XEXP (src, 1)) == REG)
! && (REGNO (XEXP (src, 1)) == bl->regno))
{
arg = XEXP (src, 0);
arg_operand = 0;
}
+ else
+ return 0;
if (GET_CODE (arg) == CONST_INT)
{
------------------------------------------------------------------------
This change makes 'tset' work right, and shows no effect on any of the
regressions I've tried on other sources, including GCC itself.
I'm still a little puzzled by a few aspects of this example, though.
Why wasn't '&delcap[i][0]' pulled out by CSE from '&delcap[i][1]'? Why
wasn't '&delcap[i][1]' considered a suitable GIV candidate? Oh well...
Donn Seeley University of Utah CS Dept donn@cs.utah.edu
40 46' 6"N 111 50' 34"W (801) 581-5668 utah-cs!donn