Subject: /lib/c2 bug fixes plus enhancements Index: lib/c2/all 2.11BSD Description: The optimizer (/lib/c2) has several bugs and missed several chances to replace code segments with shorter sequences: 1) running as a filter causes a core dump because the 'setbuf' statements were misplaced. 2) the 'div' instruction was missing from the opcode table even though the instruction was checked for in rmove(). the check for 'DIV' also used " + 1" instead of " | 1" when marking the second (odd) register as changed. 3) local and register variable assignments (lines starting with ~ as in "~fs=r4" caused c2 to throw away information about register contents. 4) extracting the high byte of a word (the major() macro for example) generated a "ash $-10,R; bic $-400,R" which should become "clrb R; swab R". a 'clrb' is much faster (as well as shorter) than the "ash $-10". 5) extracting the low byte of a word generated "mov X,R; bic $-400,R" which should have been transformed into "clr R; bisb X,R". 6) the 'changed' flag wasn't set in several places where code was removed/altered. Repeat-By: Examine the generated code from the earlier versions as well as looking over the c2 sources. Fix: Apply the patch below, recompile and install /lib/c2 --------------------------------------------------------------------------- *** /usr/src/lib/c2/c20.c.old Tue Oct 21 01:23:50 1986 --- /usr/src/lib/c2/c20.c Tue Oct 29 17:09:09 1991 *************** *** 37,42 **** --- 37,43 ---- "bic", BIC, "bis", BIS, "mul", MUL, + "div", DIV, "ash", ASH, "xor", XOR, ".text",TEXT, *************** *** 57,62 **** --- 58,64 ---- "cfcc", CFCC, "sob", SOB, "jsr", JSR, + "swab", SWAB, ".end", END, 0, 0}; *************** *** 92,106 **** fprintf(stderr, "C2: can't find %s\n", argv[1]); exit(1); } - setbuf(stdin,buf1); /* sbrk problems */ } if (argc>2) { if (freopen(argv[2], "w", stdout) == NULL) { fprintf(stderr, "C2: can't create %s\n", argv[2]); exit(1); } - setbuf(stdout,buf2); /* sbrk problems */ } lasta = firstr = lastr = sbrk(sizeof(char *)); maxiter = 0; opsetup(); --- 94,108 ---- fprintf(stderr, "C2: can't find %s\n", argv[1]); exit(1); } } + setbuf(stdin,buf1); /* sbrk problems */ if (argc>2) { if (freopen(argv[2], "w", stdout) == NULL) { fprintf(stderr, "C2: can't create %s\n", argv[2]); exit(1); } } + setbuf(stdout,buf2); /* sbrk problems */ lasta = firstr = lastr = sbrk(sizeof(char *)); maxiter = 0; opsetup(); *** /usr/src/lib/c2/c21.c.old Sun Oct 20 16:15:12 1991 --- /usr/src/lib/c2/c21.c Sat Nov 2 19:42:32 1991 *************** *** 31,36 **** --- 31,37 ---- p->forw->back = p->back; p->back->forw = p->forw; redunm++; + nchange++; continue; } } *************** *** 39,44 **** --- 40,46 ---- strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); + nchange++; goto sngl; } repladdr(p, 0, flt); *************** *** 80,85 **** --- 82,88 ---- strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); + nchange++; goto sngl; } if ((p->op==BIC || p->op==BIS) && equstr(regs[RT1], "$0")) { *************** *** 86,99 **** if (p->forw->op!=CBR) { p->back->forw = p->forw; p->forw->back = p->back; continue; } } repladdr(p, 0, flt); source(regs[RT1]); dest(regs[RT2], flt); ! if (p->op==DIV && (r = isreg(regs[RT2])>=0)) ! regs[r+1][0] = 0; switch (p->op) { case ADD: --- 89,163 ---- if (p->forw->op!=CBR) { p->back->forw = p->forw; p->forw->back = p->back; + nchange++; continue; } } + /* + * the next block of code looks for the sequences (which extract the + * high byte of a word or the low byte respectively): + * ash $-10,r + * bic $-400,r + * or + * mov natural,r + * bic $-400,r + * and transforms them into: + * clrb r + * swab r + * or + * clr r + * bisb natural,r + * These constructs occur often enough in the kernel (dealing with major/minor + * device numbers, etc) it's worth a little extra work at compile time. + */ + if (p->op == BIC && (equstr(regs[RT1],"$-400") || + equstr(regs[RT1],"$-177400"))) { + if (p->back->op == ASH) { + r = isreg(regs[RT2]); + dualop(p->back); + if ((equstr(regs[RT1], "$-10") || + equstr(regs[RT1], "$177770")) && + r == isreg(regs[RT2])) { + strcpy(regs[RT1], regs[RT2]); + regs[RT2][0] = 0; + p->back->op = CLR; + p->back->subop = BYTE; + p->back->code = copy(1, regs[RT1]); + p->op = SWAB; + p->code = copy(1, regs[RT1]); + nchange++; + goto sngl; + } + } + else if (p->back->op == MOV && p->forw->op != CBR) { + char temp[50]; + + r = isreg(regs[RT2]); + if (r < 0 && !xnatural(regs[RT2])) + goto out; + strcpy(temp, regs[RT2]); + dualop(p->back); + if (isreg(regs[RT2]) == r && natural(regs[RT1])) { + if (r < 0 && (!xnatural(regs[RT2]) || !equstr(temp, regs[RT2]))) + goto out; + dest(regs[RT1], flt); + p->back->op = CLR; + p->back->subop = 0; + p->back->code = copy(1, regs[RT2]); + p->op = BIS; + p->subop = BYTE; + strcat(regs[RT1], ","); + p->code = copy(2, regs[RT1], regs[RT2]); + nchange++; + } + } + out: dualop(p); /* restore banged up parsed operands */ + } repladdr(p, 0, flt); source(regs[RT1]); dest(regs[RT2], flt); ! if (p->op==DIV && (r = isreg(regs[RT2]))>=0) ! regs[r|1][0] = 0; switch (p->op) { case ADD: *************** *** 120,125 **** --- 184,190 ---- case ASR: case ASL: case SXT: + case SWAB: singop(p); sngl: dest(regs[RT1], flt); *************** *** 253,258 **** --- 318,334 ---- ccloc[0] = 0; continue; + /* + * Unrecognized (unparsed) instructions, assignments (~foo=r2), and + * data arrive here. In order to prevent throwing away information + * about register contents just because a local assignment is done + * we check for the first character being a tilde. + */ + case 0: + if (p->code[0] != '~') + clearreg(); + continue; + case JBR: redunbr(p); *************** *** 676,681 **** --- 752,758 ---- rt1[1] = r + '0'; rt1[2] = 0; nsaddr++; + nchange++; } if (r1>=0) { rt2[1] = 'r'; *************** *** 682,687 **** --- 759,765 ---- rt2[2] = r1 + '0'; rt2[3] = 0; nsaddr++; + nchange++; } p->code = copy(2, rt1, rt2); } *************** *** 907,910 **** --- 985,996 ---- if (*--p == '+' || *p ==')' && *--p != '5') return(0); return(1); + } + + xnatural(ap) + char *ap; + { + if (natural(ap)) + return(1); + return(equstr("(sp)", ap)); } *** /usr/src/lib/c2/c2.h.old Tue Oct 21 01:23:50 1986 --- /usr/src/lib/c2/c2.h Tue Oct 29 17:08:45 1991 *************** *** 53,59 **** #define CFCC 45 #define SOB 46 #define JSR 47 ! #define END 48 #define JEQ 0 #define JNE 1 --- 53,60 ---- #define CFCC 45 #define SOB 46 #define JSR 47 ! #define SWAB 48 ! #define END 49 #define JEQ 0 #define JNE 1