Subject: C optimizer fixes
Index:	lib/c2/c21.c 2.11BSD

Description:
	The C optimizer misses some easy optimizations. In particular
	double 'tst' instructions are not reduced to a single 'tst' and
	the condition codes are not paid attention to when set by 
	instructions such as 'add', 'sub', 'inc', 'bic', etc.

Repeat-By:
	Compile the following test program and examine the generated
	code.  Annontated generated code is included.

	int	x, y;
main()
	{

	if	(x > 3 * y / 2)
		exit();
	x += y;
	if	(x)
		exit();
	x &= 7;
	if	(x)
		exit();
	}
/* generated code from above program */
_main:
	jsr	r5,csv
	mov	_y,r1
	mul	$3,r1
	tst	r1
	tst	r1		<----- redundant 'tst'
	sxt	r0
	div	$2,r0
	cmp	_x,r0
	jle	L4
	jsr	pc,_exit
L4:	add	_y,_x
	tst	_x		<----- unneeded 'tst'.  the 'add' just above
				       sets the condition codes - an explicit
				       'tst' is not necessary.
	jeq	L5
	jsr	pc,_exit
L5:	bic	$-10,_x
	tst	_x		<----- another example of an extra 'tst'.
				       'bic' sets the condition codes - an
				       explicit 'tst' is not needed.
	jeq	L3
	jsr	pc,_exit
L3:	jmp	cret

Fix:
	Apply the patch below, recompile and install 'c2'.  Testing has
	been quite thorough, including a recompile of /lib/libc.a and
	the kernel - no problems have been encountered.
--------------------------------------------------------------------------
*** c21.c.old	Tue Oct 21 01:23:50 1986
--- c21.c	Fri Oct  4 08:39:10 1991
***************
*** 94,100 ****
  		dest(regs[RT2], flt);
  		if (p->op==DIV && (r = isreg(regs[RT2])>=0))
  			regs[r+1][0] = 0;
! 		ccloc[0] = 0;
  		continue;
  
  	case CLRF:
--- 94,111 ----
  		dest(regs[RT2], flt);
  		if (p->op==DIV && (r = isreg(regs[RT2])>=0))
  			regs[r+1][0] = 0;
! 		switch	(p->op)
! 			{
! 			case	ADD:
! 			case	SUB:
! 			case	BIC:
! 			case	BIS:
! 			case	ASH:
! 				setcc(regs[RT2]);
! 				break;
! 			default:
! 				ccloc[0] = 0;
! 			}
  		continue;
  
  	case CLRF:
***************
*** 113,123 ****
  	sngl:
  		dest(regs[RT1], flt);
  		if (p->op==CLR && flt==0)
  			if ((r = isreg(regs[RT1])) >= 0)
  				savereg(r, "$0");
  			else
  				setcon("$0", regs[RT1]);
! 		ccloc[0] = 0;
  		continue;
  
  	case TSTF:
--- 124,138 ----
  	sngl:
  		dest(regs[RT1], flt);
  		if (p->op==CLR && flt==0)
+ 			{
  			if ((r = isreg(regs[RT1])) >= 0)
  				savereg(r, "$0");
  			else
  				setcon("$0", regs[RT1]);
! 			ccloc[0] = 0;
! 			}
! 		else
! 			setcc(regs[RT1]);
  		continue;
  
  	case TSTF:
***************
*** 134,139 ****
--- 149,156 ----
  			nrtst++;
  			nchange++;
  		}
+ 		else
+ 			setcc(regs[RT1]); /* XXX - double TST in a row */
  		continue;
  
  	case CMPF:
***************
*** 328,333 ****
--- 345,351 ----
  }
  
  abs(x)
+ register int x;
  {
  	return(x<0? -x: x);
  }
***************
*** 367,373 ****
  
  struct node *
  nonlab(p)
! struct node *p;
  {
  	CHECK(10);
  	while (p && p->op==LABEL)
--- 385,391 ----
  
  struct node *
  nonlab(p)
! register struct node *p;
  {
  	CHECK(10);
  	while (p && p->op==LABEL)
***************
*** 782,788 ****
  equstr(ap1, ap2)
  char *ap1, *ap2;
  {
! 	char *p1, *p2;
  
  	p1 = ap1;
  	p2 = ap2;
--- 800,806 ----
  equstr(ap1, ap2)
  char *ap1, *ap2;
  {
! 	register char *p1, *p2;
  
  	p1 = ap1;
  	p2 = ap2;
