V9/jerq/sgs/optim/w3opt.c

Compare this file to the similar file:
Show the results in this format:

/* @(#) w3opt.c: 1.4 3/27/84				*/
/* w3opt.c
**
**	3B20S three-instruction window improver
**
**
**
** This module contains improvements for three instruction windows,
** of which there aren't many.
*/

/* #include "defs" -- optim.h takes care of this */
#include "optim.h"
#include "optutil.h"
/* w3opt -- 3-instruction peephole window */

boolean					/* true if changes made */
w3opt(pf,pl)
register NODE * pf;			/* pointer to first inst. in window */
register NODE * pl;			/* pointer to last inst. in window */
{
    register NODE * pm = pf->forw;	/* point at middle node */

    int cop1 = pf->op;			/* op code number of first inst. */
    int cop2 = pm->op;			/* op code number of second */
    int cop3 = pl->op;			/* ... of third */

    int src1 ;				/* size (bytes) of source of move */
    int dst1;				/* size of destination of move */
/* *p++ improvement
**
** This improvement rearranges things to facilitate a later 2-instruction
** improvement.  We're looking for the kind of code the compiler generates
** (naively) for *p++.  We want to make an indirect reference possible:
**
**	movw	O1,R		->	movw O1,R
**	addw2	&n,O1		->	movX 0(R),O2
**	movX	0(R),O2		->	addw2 &n,O1
**
** or
**	movw	O1,R		->	movw O1,R
**	addw2	&n,O1		->	movX O2,0(R)
**	movX	O2,0(R)		->	addw2 &n,O1
**
**	if O1 is not a register used by O2
**	if instruction following movX is not conditional branch, since
**	  we're setting different condition codes than before
**	in the first case, O2 cannot be a register used by O1.
**
** Note that this transformation is always correct because:
**
**	1.  O1 could not use R, or the first 2 instructions wouldn't work.
**	2.  O2 can use or set R without problems.
*/

    if (
	    cop1 == MOVW
	&&  cop2 == ADDW2
	&&  ismove(pl,&src1,&dst1)
	&&  isreg(pf->op2)
	&&  *pm->op1 == '&'		/* immediate operand */
	&&  strcmp(pf->op1,pm->op2) == 0
	&&  isdeadcc( pl )
	&&  ! usesvar(pm->op2,pl->op2)	/* O1 can't use O2 */
	)
    {
	char * R = pf->op2;		/* point at register string */
	char * O1 = pf->op1;		/* point at first operand */
	char * O2;			/* second operand */

	if (
		(   ( O2 = pl->op2, iszoffset(pl->op1,R) ) /* test 0(R) */
		||  ( O2 = pl->op1, iszoffset(pl->op2,R) )
		)
	    &&  ! usesvar(O2,O1)	/* O2 can't use O1 */
	    &&  ( isiros( O1 ) || isiros( O2 ) )
					/* safe for mmio */
	    )
	{
	    wchange();			/* change the window */
	    lexchin(pm,pl);		/* preserve line number info */
	    exchange(pm);		/* exchange the last two nodes */
	    swplivecc(pm,pl);       /* swap live/dead info on condtion codes */
	    return(true);
	}
    }
/* Remove redundant compares (see, also w2opt)
**
** On the 3B20S, some instructions do not set all of the result
** indicators correctly.  Consequently it is only safe to remove
** a compare against zero if the following conditional jump only
** tests those bits which are set.  The canonical 3 instruction
** sequence is:
**
**	op O1,O2[,O3]
**	cmpX O[2|3],&0
**	jcond foo
**
** For the instructions we test here, the only valid conditions to
** jump on are equal (zero) and not equal (non-zero).
** Note that signed tests are picked up correctly in w2opt for those
** instructions that generate correct result indicators.
*/

    if (
	    (cop2 == CMPW || cop2 == CMPH || cop2 == CMPB)
	&&  strcmp(pm->op2,"&0") == 0
	&&  strcmp(dst(pf),pm->op1) == 0
	&&  (cop3 == JE || cop3 == JZ || cop3 == JNE || cop3 == JNZ)
	&&  (MCOMB <= cop1 && cop1 <= UMODW3)
	&&  stype(cop1) == stype(cop2)
	&&  isiros(pm->op1)		/* safe from mmio */
	)
    {
	wchange();
	ldelin2(pm);			/* preserve line number info */
	mvlivecc(pm);       /* preserve live/dead info on condtion codes */
	DELNODE(pm);			/* delete the compare */
	return(true);
    }
    return(false);
}