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