Subject: bug was introduced in '/lib/c2' a while back Index: lib/c2/c21.c 2.11BSD Description: A bug was introduced in the optimizer a while back. The sequence movb X,rN bic $177400,rN was always being transformed into clr rN bisb X,rN this is not the correct thing to do when 'X' is the same as 'rN': movb r0,r0 bic $177400,r0 was being turned into: clr r0 bisb r0,r0 which is obviously not correct. In the case where 'X' is the same as 'rN' the optimization should be to remove the 'movb' instruction and leave the 'bic' instruction. Another pair of optimizations was seen recently. The sequence sxt X clr X is silly, the 'sxt' is not needed since the operand is cleared in the very next instruction. A fairly common sequence arising from calling a function with two arguments and then testing the return value was noticed recently: The C code: if (foo(a,b) == 0) ... generates the following: mov b,(sp) mov a,-(sp) jsr pc,foo tst (sp)+ tst r0 beq ... Since the 'tst' instruction clears the C and V bits the branch which follows will never rely on those being set. The two 'tst' statements can be combined into a single 'mov' instruction which sets the N and Z condition codes and saves 1 instruction at the same time:L mov b,(sp) mov a,-(sp) jsr pc,foo mov r0,(sp)+ beq ... (in case you're interested this saved 256 bytes of text space in the kernel) Repeat-By: The 'movb r0,r0' bug was noticed when the 'tcsh' was compiled, the bracket9('[ ... ]') construct was causing a core dump in the pattern matching sequence. Run /lib/c2 interactively and type the two lines movb r0,r0 bic $-400,r0 ^D to observe the problem. Fix: Apply the following patch, compile and reinstall 'c2'. ------------------------------------------------------------------------------ *** /usr/src/lib/c2/c21.c.old Sun Dec 29 22:02:02 1991 --- /usr/src/lib/c2/c21.c Mon Feb 3 10:59:37 1992 *************** *** 140,145 **** --- 140,157 ---- if (isreg(regs[RT2]) == r && natural(regs[RT1])) { if (r < 0 && (!xnatural(regs[RT2]) || !equstr(temp, regs[RT2]))) goto out; + /* + * XXX - the sequence "movb rN,rN; bic $-400,rN" can not be transformed + * because the 'clr' would lose all information about 'rN'. The best that can + * be done is to remove the 'movb' instruction and leave the 'bic'. + */ + if (isreg(regs[RT1]) == r) { + p = p->back; + p->forw->back = p->back; + p->back->forw = p->forw; + nchange++; + continue; + } dest(regs[RT1], flt); p->back->op = CLR; p->back->subop = 0; *************** *** 172,177 **** --- 184,199 ---- } continue; + case SXT: + singop(p); + if (p->forw->op == CLR && p->forw->subop != BYTE && + xnatural(regs[RT1]) && !strcmp(p->code, p->forw->code)){ + p->forw->back = p->back; + p->back->forw = p->forw; + nchange++; + continue; + } + goto sngl; case CLRF: case NEGF: flt = NREG; *************** *** 183,189 **** case NEG: case ASR: case ASL: - case SXT: case SWAB: singop(p); sngl: --- 205,210 ---- *************** *** 207,212 **** --- 228,250 ---- singop(p); repladdr(p, 0, flt); source(regs[RT1]); + if (p->back->op == TST && !flt && not_sp(regs[RT1])) { + char rt1[20]; + strcpy(rt1, regs[RT1]); + singop(p->back); + if (!strcmp("(sp)+", regs[RT1])) { + p->back->subop = p->subop; + p->back->forw = p->forw; + p->forw->back = p->back; + p = p->back; + p->op = MOV; + p->code = copy(2, rt1, ",(sp)+"); + nrtst++; + nchange++; + continue; + } + singop(p); + } if (p->back->op == MOV && p->back->subop == BYTE) { dualop(p->back); setcc(regs[RT2]); *************** *** 998,1001 **** --- 1036,1049 ---- if (natural(ap)) return(1); return(equstr("(sp)", ap)); + } + + not_sp(ap) + register char *ap; + { + char c; + + while (c = *ap++) + if (c == '(') return(*ap == 's' && ap[1] == 'p'); + return(1); }