⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccopt.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
					}
				    continue;

				default:
				    if ((q->Ptype&PTF_ADRMODE) == PTA_MINDEXED
				      && q->Preg == q->Pindex)
					return;
				    if (q->Pop != P_MOVE || p->Pindex == 0)
					continue;
				    p->Pop = q->Pop;	/* turn P_MOVE+XP_ADDI into */
				    q->Pop = P_ADD;	/* P_MOVEI+P_ADD to save one */
				    swappseudo(p, q);	/* instruction... */
				    p = q;		/* look at correct one next loop */
				}
			    continue;		/* fall through goes back */

			case PTA_REGIS:
			    if (q->Ptype == PTV_IINDEXED && q->Pindex == 0)
				{

		    /*
		    ** fold:  P_MOVEI R,x
		    **        P_ADD    R,S
		    **
		    ** into:  P_MOVEI R,x(S)
		    */
				q->Pindex = p->Pr2;	/* new index */
				foldidx(q);		/* Attempt to optimize index reg */
				dropinstr(p);	/* drop now useless move */
				return;		/* not likely any more to do */
				}
			    if ((q->Ptype & PTF_ADRMODE) == PTA_MINDEXED
			      && q->Pindex == r)
				{
				if (!(q->Ptype & PTF_IMM) || q->Pop != P_MOVE)
				    break;

		    /*
		    ** fold:  P_MOVEI R,x(R)
		    **        P_ADD    R,S
		    **
		    ** into:  P_ADD    R,S
		    **	      P_MOVEI R,x(R)
		    **
		    ** (avoid silly checks and opcode switches below
		    */
				}
			    else if (q->Ptype == PTA_REGIS && q->Pop == P_MOVE)
				{
		    /*
		    ** fold:  P_MOVE  R,S
		    **	      P_ADD   R,T
		    **
		    ** into:  P_ADD   S,T
		    **	      P_MOVE  R,S
		    */
				if (q->Pr2 == R_SP)
				    return; /* don't break stack */
				p->Preg = (char) (q->Pr2);	/* set register */ // FW KCC-NT
				}
			    else
				{

		    /*
		    ** fold:  P_MOVE R,x
		    **        P_ADD  R,S
		    **
		    ** into:  P_MOVE R,S
		    **        P_ADD  R,x
		    */
				if ((q->Ptype&PTF_ADRMODE) == PTA_MINDEXED
				  && q->Preg == q->Pindex)
				    return;
				p->Pop = q->Pop;	/* set opcode */
				q->Pop = P_ADD;	/* to swap them */
				}
			    swappseudo(p,q);	/* opcodes hacked, swap ops */
			    foldplus (q);		/* try again lower down */
			    if (p->Ptype == PTA_REGIS)
				return; /* avoid infinite loop */
			    q = p;			/* start after the swap */
			    continue;		/* try loop again */

			default:
			    switch (q->Ptype)
				{
				case PTV_IINDEXED:
				    if (q->Pindex != 0)
					continue; /* bad swap */
				case PTV_IMMED:		/* swap order of immed and */
				    p->Pop = q->Pop;	/* memory P_MOVE/P_ADD so that */
				    q->Pop = P_ADD;	/* P_ADDI can be optimized */
				    swappseudo(p, q);	/* even further. */
				    break;		/* not likely to find any more */

				case PTA_REGIS:
				    if (q->Pop == P_MOVE)
					{
			/*
			** fold:  P_MOVE  R,S
			**        P_ADDI  R,x
			**
			** into:  P_ADDI  S,x
			**        P_MOVE  R,S
			*/
					swappseudo(p, q); /* swap the ops */
					r = q->Preg = (char) (p->Pr2); /* fix reg in P_ADDI */ // FW KCC-NT
					p = q;	/* move back over it */
					}			/* end PTA_REGIS: if (q->Pop==P_MOVE) */

				default:
				    if (q->Pop == P_ADD)
					continue;
				}			/* end default: switch(q->Ptype) */
			}				/* end switch(p->Ptype) */
		}				/* end switch(p->Pop) */
	    break;				/* default: dont keep looping */
	    }					/* end while(q->Preg == p->Preg) */

    switch (p->Ptype &~ (PTF_IND + PTF_SKIPPED))
	{
	case PTV_IMMED:

	/*
	** fold:  P_ADDI  R,[-n]
	** into:  P_SUBI  R,n
	*/

	    if (p->Pvalue < 0)
		{
		switch (p->Pop)
		    {
		    case P_ADD:
			p->Pop = P_SUB;
			break;

		    case P_MOVE:
			p->Pop = P_MOVN;
			break;

		    case P_SUB:
			p->Pop = P_ADD;
			break;

		    case P_MOVN:
			p->Pop = P_MOVE;
			break;

		    default:
			return;
		    }
		p->Pvalue = - p->Pvalue;
		}
	    else if (p->Pvalue == 0)
		{
		switch (p->Pop)
		    {
		    case P_ADD:
		    case P_SUB:
			dropinstr(p);		/* fold: P_ADDI R,0 */
			return;			/* into: nothing */

		    case P_MOVN:
		    case P_MOVE:
			p->Pop = P_SETZ;		/* fold: P_MOVEI R,0 */
			p->Ptype = PTA_ONEREG;	/* into: P_SETZ  R, */
			return;
		    }
		}
	    if (p->Pvalue == 1 && p->Pop == P_MOVN)
		{
		p->Pop = P_SETO;		/* fold: P_MOVNI R,1 */
		p->Ptype = PTA_ONEREG;		/* into: P_SETO  R, */
		return;
		}
	    break;

	case PTV_IINDEXED:
	    if (p->Pop == P_ADD && p->Pindex == 0)
		{

	    /*
	    ** fold:  P_ADDI   R,addr
	    ** into:  P_MOVEI  R,addr(R)
	    */
		p->Pop = P_MOVE;		/* make P_MOVEI */
		p->Pindex = p->Preg;	/* with index same as reg */
		if ((q = before(p)) != NULL && q->Ptype == PTA_REGIS
		  && q->Pop == P_MOVE
		/* !prevskips (p or q) */ && q->Preg == p->Pindex)
		    {

		/*
		** fold:  P_MOVE  R,S
		**        P_MOVEI R,addr(R)
		**
		** into:  P_MOVEI R,addr(S)
		*/
		    p->Pindex = q->Pr2;	/* flatten index calculation */
		    q->Pop = P_NOP;		/* flush useless P_MOVE */
		    }
		foldidx(p);			/* try to optimize index reg */
		}
	    break;

	case PTA_MINDEXED:
	    if (p->Pop != P_ADD+POF_BOTH || (q = before (p)) == NULL ||
		prevskips (p) || prevskips (q) || q->Preg != p->Preg)
		break;
	    if (unsetz(q))
		{
		if (q->Pop != P_MOVE || q->Ptype != PTV_IMMED)
		    {
		    foldplus(q);		/* Restore more efficient op */
		    break;			/* (ie undo what unsetz did) */
		    }
	    /* Previous instr should now be a P_MOVEI */
		switch ((int) q->Pvalue)
		    {
		    case -1:
			q->Pop = P_NOP;		/* fold:  P_MOVNI R,1 */
			p->Pop = P_SOS;		/*        P_ADDB  R,x */
			foldinc(p);			/* into:  P_SOS   R,x */
			break;
		    case 0:
			q->Pop = P_NOP;		/* fold:  P_MOVEI R,0 */
			p->Pop = P_MOVE;		/*        P_ADDB  R,x */
			foldmove(p);		/* into:  P_MOVE  R,x */
			break;
		    case 1:
			q->Pop = P_NOP;		/* fold:  P_MOVEI R,1 */
			p->Pop = P_AOS;		/*        P_ADDB  R,x */
			foldinc(p);			/* into:  P_AOS   R,x */
			break;
		    default:
			foldplus (q);	/* put back more efficient op */
		    }
		}
	}
}

/* FINDRSET(p, r) - Find the instruction that sets R, searching backwards
**	starting at P.  It is OK to attempt starting at NULL; this
**	facilitates constructs like findrset(before(p),r).
**
**	NOTE: the instruction found may not actually SET the register
** or alter its value; it only USES it in its AC field.  Thus the caller
** must apply further checks on the exact opcode.
**
**	The instr is assumed to be the most recent one with the register
** field set to R, provided R is not referenced in any way by intervening
** instructions.  This includes being used in an address calculation,
** or being the 2nd reg of a double-word op, or finding a PUSHJ.
**	Note that the instruction found may be either a double-word or
** single-word op.  Also, we don't bother checking the skipped flag while
** moving back, as whether an instr is skipped is irrelevant to whether it
** might use or set the register in question.  The instr found (if any) is
** checked for this, however.
*/
PCODE *
findrset(p, reg)
PCODE *p;		/* Start looking here */
int reg;		/* Register to look for */
{
#if SYS_CSI			/* Reg linkage */
    if (Register_Preserve(reg))
	return NULL;		/* avoid faulty opts */
#endif

    /* Loop until break out or no instrs left */
    for (; p; p = before(p))
	{
	switch (rinreg(p, reg))
	    {
	    default:		/* Unknown changes, give up */
		return NULL;
	    case 0:		/* Not used in this instr, continue loop */
		break;

	    case 1:		/* Win, found single-word op that uses it */
	    case 2:		/* Win, found double-word op that uses it */
	    /* Found an op that uses this register!  Done, unless this instr
	    ** might be skipped over (in which case we can't be sure what it
	    ** will contain and must give up).
	    */
		if (prevskips(p))	/* Is prev instr a skip? */
		    return NULL;	/* Sigh */
		return p;		/* Won, found instr that sets reg! */
	    }
	if (rinaddr(p, reg))	/* If reg used in address somehow, */
	    return NULL;	/* stop looking immediately */
	}
    return NULL;			/* No more instrs to look at */
}

/* FINDCONST(p) - Turn register to register op into register immediate.
**	Looks back through peephole buffer for op setting second
** register to a constant value.  If found, replaces the register reference
** with an immediate operand.
** Only called by rrpop2() in CCCODE, after instruction added to buffer.
** Does not flush the instruction, although it may modify it and may
** flush a preceding instruction.
*/
int
findconst(p)
PCODE *p;
{
    PCODE *q;
    int op, rused;

    if (p->Ptype != PTA_REGIS)
	return 0;	/* Verify is reg-reg op */
    rused = 0;				/* Clear flag */
    for (q = before (p); q != NULL; q = before (q)) /* look back in buf */
	{
	switch (q->Pop)			/* see what op is */
	    {
	    case P_MOVE:			/* Move, */
	    case P_CAI+POF_ISSKIP+POS_SKPE: /* or compare acting like move */
		if ((q->Ptype & PTF_ADRMODE) != PTA_RCONST)
		    break;			/* must be immediate */

	    case P_SETZ:			/* Zero makers */
	    case P_JUMP+POS_SKPN:
	    case P_AOJ+POS_SKPN:
	    case P_SOJ+POS_SKPN:
	    case P_SKIP+POF_ISSKIP+POS_SKPE:
		if (q->Preg != p->Pr2)
		    break;	/* but not the reg we want */
		if ((isskip (q->Pop) || prevskips (q)) && !dropsout (after (q)))
		    break;				/* or skips, or skipped */

	    /* Won!  Found constant value for this reg */
		p->Ptype = PTV_IMMED;		/* set immediate instruction */
		if ((op = immedop (p->Pop)) != 0)	/* except for P_CAM */
		    {
		    p->Pop = op;		/* which becomes P_CAI */
		    p->Ptype = PTA_RCONST;	/* with constant type */
		    }
		p->Pvalue = (q->Ptype & PTF_ADRMODE) == PTA_RCONST
			    ? q->Pvalue : 0;	/* Set to value or zero */

		if (q->Pop == P_MOVE && rused == 0)	/* If simple set, and safe, */
		    q->Pop = P_NOP;		/* Simply flush the setting instr. */

		return 1;			/* made const, win! */
	    }

	/* Not found, make sure reg not munged */
	if (rrchg(q, p->Pr2))
	    return 0;	/* Fail if reg modified */

	/* See if our reg is used for anything within an instruction,
	** so we know whether it's OK to flush the
	** instruction that sets it (if we find one)
	*/
	switch (p->Ptype & PTF_ADRMODE)
	    {
	    case PTA_MINDEXED:		/* These two use index reg */
	    case PTA_BYTEPOINT:
		if ((p->Pindex == q->Pindex)
		    || (p->Pindex == q->Preg))
		    rused++;
		break;
	    case PTA_REGIS:
		if (p->Pr2 == q->Pr2)
		    rused++;	/* Drop thru */
	    default:
		if (p->Pr2 == q->Preg)
		    rused++;
	    }
	}
    return 0;
}

/* FOLDBOTH() - Make ops of type POF_BOTH.
**
**    looks at the last instruction in the peephole buffer,
**    and if it is a MOVEM tries to fold it into an opB.
**
** KLH: This is yet another BIG MESS that badly needs to be cleaned up
**	someday!!
*/

void
foldboth()
{
    PCODE *p, *b, *q;
    int badidx;
    int ramask_p, rrmask_p;

    foldmove(previous);			/* maybe it's a P_MOVE or P_LDB */
    if (prevskips (previous))
	return;	/* skipped over, can't hack */
    if (previous->Pop == P_ADD+POF_BOTH) /* try += into ++ */
	foldplus (previous);

    /*
    ** fold:  P_ADJSP 17,n
    **	      ...
    **	      P_MOVEM R,1-n(17)
    **
    ** into:  ...
    **	      P_PUSH  17,R
    **	      P_ADJSP 17,n-1
    */

    if ( previous->Pop == P_MOVEM
      && previous->Ptype == PTA_MINDEXED
      && previous->Pindex == R_SP)		/* if P_MOVEM onto stack */
	for (p = before (previous); p != NULL; p = before (p)) /* looking back */
	    switch (p->Pop & POF_OPCODE)		/* through opcodes... */
		{

		case P_JRST:
		case P_JUMP:
		case P_AOJ:
		case P_SOJ:			/* control flow mungage */
		case P_PUSH:
		case P_POP:
		case P_POPJ:	/* or stack mungage */
		    p = NULL;				/* give up */
		    break;

		case P_ADJSP:			/* the one we want */
		    if (prevskips (p) || previous->Poffset != 1 - p->Pvalue)
			{
			p = NULL;			/* wrong number or skipped */
			break;			/* lose lose */
			}

		    while ((q = after(p)) != previous) /* until right before it */
			{
			if (q->Pindex == R_SP)
			    switch (q->Ptype & PTF_ADRMODE)
				{
				case PTA_MINDEXED:
				case PTA_BYTEPOINT: /* indexed types */
				    q->Poffset += p->Pvalue; /* adjust for hacked stack */
				}
			swappseudo (p, q);		/* bubble P_ADJSP forward */
			p = q;			/* point to where it is now */
			}
		    swappseudo (p, previous);	/* now swap P_MOVEM and P_ADJSP */
		    p->Pop = P_PUSH;		/* make P_PUSH in place of P_MOVEM */
		    p->Ptype = PTA_REGIS;		/* this is now a register op */
		    p->Pr2 = p->Preg;		/* with second reg old first */
		    p->Preg = R_SP;			/* and first reg stack */

		    if ((-- previous->Pvalue) == 0)	/* diminish P_ADJSP by one; if gone, */
			dropinstr(previous);	/* flush it and fix up "previous" */

		    if ((q = before (p)) != NULL && q->Preg == p->Pr2 && !prevskips (q))
			switch (q->Pop)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -