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

📄 cccode.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
** These are not as well behaved as loop and if labels so we can't do as much.
*/
void
codgolab(lab)
SYMBOL *lab;
{
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	{
	fprintf(fpho, "CODGOLAB: %s\n", lab->Sname);
	}
#endif
    if (optobj)
	optlab(lab);	/* Optimize */
    flushcode();		/* Clear out previous code */
    outlab(lab);		/* and unconditionally emit label */
#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)
	shocum();
#endif
}

/* This code should be flushed eventually,
** and TXO, TXZ, TXC forms substituted for this silly nonsense.
*/

/* ------------------------------------------------------ */
/*	return immediate version of boolean operator      */
/* ------------------------------------------------------ */

immedop(int op)
{
    switch (op & POF_OPCODE)
	{
	case P_CAM:
	    return op ^ (P_CAM ^ P_CAI);
	case P_TDN:
	    return op ^ (P_TDN ^ P_TRN);
	case P_TDO:
	    return op ^ (P_TDO ^ P_TRO);
	case P_TDC:
	    return op ^ (P_TDC ^ P_TRC);
	case P_TDZ:
	    return op ^ (P_TDZ ^ P_TRZ);
	default:
	    return 0;
	}
}

/* PEEPHOLER PSEUDO-OP OPTIMIZATION ROUTINES */

/* CODRRX - Optimization auxiliary for CODE0.
**	Basically intended to help make sense of the gigantic switch
**	statement that previously existed.
**
**	prev - instruction farther back in peephole buffer, which we are
**		looking at.
**	np - instruction we are trying to optimize (normally what was
**		just added; an OP R,S instr).
*/
static void
codrrx(prev, np)
PCODE *prev, *np;
{
    PCODE *q;

    /* Avoids faulty optimizations in the functions: codrrx, rrpre1, rrpre2,
     * rrpre3, rrpopt, rrpop2, localbyte, chkref, chkmref, rincode, rinaddr, 
     * rrchg, foldbyte, foldplus, foldadjbp, foldskip, sameaddr, alias, 
     * inskip, and findconst.
     */
    if (Register_Preserve(np->Pr2))
	return;

    /* If have an unskipped previous instruction to look at,
    ** try to fold: our newly added instr into it.
    */
    if (prev && !prevskips(prev))
	{
	if (prev->Preg != np->Pr2
	  && rrpre1(np))		/* Prev instr R != new S */
	    return;			/* If won, just return. */

	if ((q = findrset(prev, np->Pr2)) != NULL
	  && rrpre2(q, np))		/* Prev instr R == new S */
	    return;			/* If won, just return */
	}
    rrpop2(np);				/* Try standard optimizations */
}

/* RRPRE1 - Auxiliary for CODE0.
**	Does some commutative register-register optimization.
** The constraints for coming here are that:
**	A previous instr exists, which is not skipped,
**		such that its R (register field) is NOT the same as the S
**		of the new instruction we are adding.
**	P points to the newly added instruction, which is always a
**		register-register op.
**
** Returns TRUE if an optimization change was made.
*/
static int
rrpre1(p)
PCODE *p;
{
    PCODE *q;
    int r, s;

    /* See if opcode of new instruction is one we can do something with.
    ** If the operation is commutative or can otherwise have the
    ** ordering of its operands reversed, then see if this can result
    ** in an improvement.
    */
    switch (p->Pop & POF_OPCODE)
	{
	case P_ADD:
	case P_IMUL:		/* Commutative integer ops */
	case P_FADR:
	case P_FMPR:		/* Commutative floating ops */
	case P_IOR:
	case P_AND:
	case P_XOR:	/* Bitwise ops */
	case P_CAM:				/* Invertible test */
	    break;			/* Win, can check further! */
	default:
	    return 0;			/* Something else, so fail */
	}

    /* A recognized op, check further. */
    if (p->Pr2 == R_SP			/* Never mess with stack reg! */
      || (q = findrset(before(p), p->Preg)) == NULL)	/* Find instr setting R */
	return 0;

    switch (q->Pop)			/* Does that instr */
	{
	case P_SETZ:
	case P_SETO:	/* set R in a simple way? */
	case P_MOVE:
	case P_MOVN:
	    break;
	default:			/* No, just give up. */
	    return 0;
	}
    if (q->Ptype == PTV_IINDEXED)	/* Also ignore if imm addr op */
	return 0;

    /* OK, try swapping the operands and see if that helps. */
    r = p->Preg;
    s = p->Pr2;
    p->Preg = s;			/* Reverse order of AC,E in op */
    p->Pr2 = r;
    if ((p->Pop&POF_OPCODE) == P_CAM)
	{
	p->Pop = swapop(p->Pop);	/* Invert the skip test */
	if (rrpre2(q, p))		/* See if this helped optimize */
	    return 1;
	p->Pop = swapop(p->Pop);	/* Nope, restore original test */
	}
    else if (rrpre2(q, p))		/* Re-check optimization now */
	{
	code00(P_MOVE, r, s);		/* Won! Put back in right reg */
	return 1;
	}
    p->Preg = r;	/* Failed, restore original ordering. */
    p->Pr2 = s;
    return 0;		/* Return failure so rrpre2 called */
}

/* RRPRE2 - (another) Auxiliary for CODE0.
**	Checks previous instruction for optimization with the one we're
** currently adding.  The constraints for coming here are that:
**	P points to a previous instr, which is not skipped,
**		such that its R (register field) is the SAME as the S
**		of the new instruction we are adding.
**	NP points to the newly added instruction, which is an OP R,S.
**		(register-register op)
**		Note that S is NOT referenced by anything between P and NP,
**		which makes various things safe.
*/
static int
rrpre2(p, np)
PCODE *p, *np;		/* An existing instruction being examined */
{
    int op = np->Pop;	/* OP R,S of new instruction we just added */
    int r = np->Preg;
    int s = np->Pr2;
    PCODE *q;

    /* Check opcode of PREVIOUS instr.
    ** Breaking out of the switch statement simply leaves new instr alone
    ** and returns failure.
    */
    switch (p->Pop & (POF_OPCODE | POF_BOTH))
	{
	case P_IMUL:
		{
		PCODE *b, *bb;

		if (p != before(np))
		    break;	/* For now */

		if (op != P_SUB || (q = before (p)) == NULL || q->Pop != P_IDIV ||
		    q->Preg != p->Preg || !sameaddr (p, q, 0) ||
		    (b = before (q)) == NULL || b->Pop != P_MOVE ||
		    b->Preg != p->Preg)
		    break;
		if (b->Ptype == PTA_REGIS && b->Pr2 == r)
		    bb = NULL;
		else if ((bb = before (b)) == NULL || bb->Preg != r ||
			 bb->Pop != P_MOVE || prevskips (bb) ||
			 !sameaddr (b, bb, 0))
		    break;

	/*
	** fold:  MOVE R,x
	**	  MOVE S,x
	**	  IDIV S,y
	**	  IMUL S,y
	**	  SUB R,S
	**
	** into:  MOVE S,x
	**	  IDIV S,y	;error if S is preserve reg.
	**	  MOVE R,S+1
	**
	** for ignorant Pascal programmers.
	*/

		if (bb != NULL)
		    bb->Pop = P_NOP; /* drop first move */
		p->Pop = P_NOP;			/* drop P_IMUL */
		dropinstr(np);			/* Drop new instr, fix up previous */
		code00(P_MOVE, r, s+1);		/* put result in right reg */
		return 1;
		}

	case P_DMOVN:			/* similar to P_MOVN below */
	    switch (op)
		{
		case P_DMOVE:			/* move over for optimization */
		    p->Pop = P_DMOVE;
		    op = P_DMOVN;
		    break;
		case P_DMOVN:			/* cancel double DMOVN */
		    p->Pop = P_DMOVE;
		    op = P_DMOVE;
		    break;
		case P_DFAD:			/* R + -X is same as R - X */
		    p->Pop = P_DMOVE;
		    op = P_DFSB;
		    break;
		case P_DFSB:			/* R - -X is same as R + X */
		    p->Pop = P_DMOVE;
		    op = P_DFAD;
		    break;
		default:
		    return 0;		/* Give up, failed to add instr */
		}
	    np->Pop = op;
	/* Then drop through to following case */

	case P_DMOVE:
	    switch (op)
		{
		case P_DFAD:
		case P_DFSB:
		case P_DFDV:
		case P_DFMP:
		case P_DMOVE:
		case P_DMOVN:
		/* Optimize	DMOVE S,x /.../ Dop R,S
		** into		Dop R,x
		*/
		    rrpre3(p, np, op);
		    return 1;

	/* Try to fold: DMOVE R,M / PUSH x,R / PUSH x,R+1
	** into PUSH x,M / PUSH x,M+1
	** We come here when the current instr is DMOVE and we are adding
	** a PUSH.
	*/
		case P_PUSH:
		    if (p != before(np))
			break;	/* For now */

	    /* Check out addressing mode, and forget it unless
	    ** it's a plain vanilla REGIS, MINDEXED, or DCONST.
	    ** Indirection, immediateness, or skippedness all cause failure.
	    */
		    switch (p->Ptype)
			{
			case PTA_REGIS:
			case PTA_MINDEXED:
			case PTA_DCONST:
			    break;
			default:
			    return 0;		/* Give up, no optimization done */
			}

	    /* First turn DMOVE R,M / PUSH P,R
	    ** into MOVE R+1,M+1 / PUSH P,M
	    */
		    p->Pop = P_MOVE;		/* fold: the DMOVE R,M */
		    p->Preg++;			/* into MOVE R+1,M */
		    switch (p->Ptype)		/* Now fix up memory operand */
			{
			case PTA_REGIS:
			    p->Pr2++;			/* MOVE R+1,R2+1 */
						/* PUSH P,R2 */
			    break;
			case PTA_MINDEXED:
			    dropinstr(np);			/* Flush new instr */
			    codemdx(P_PUSH, r, p->Pptr,		/* MOVE R+1,M+1 */
				    p->Poffset++, p->Pindex);	/* PUSH P,M */
			    np = previous;
			    break;
			case PTA_DCONST:
			    p->Ptype = PTA_DCONST2;		/* MOVE R+1,1+[const] */
			    np->Ptype = PTA_DCONST1;	/* PUSH R,[const] */
			    np->Pdouble = p->Pdouble;
			    break;
			}

	    /* Now try to rearrange the MOVE / PUSH into PUSH / MOVE
	    ** if we still know where things are (not always true).
	    ** np should point to the PUSH.
	    */
		    if (np->Pop != P_PUSH)
			return 1;	/* If not, forget it */
		    if ((p = before(np)) != NULL	/* See if prev instr is */
		      && (p->Pop == P_MOVE))		/* still MOVE */
		/* Yep, swap 'em */
			{
			if ((p->Ptype&PTF_ADRMODE)==PTA_MINDEXED
			  && p->Pindex == R_SP)
			    p->Poffset--;
			swappseudo(p, np);		/* into PUSH / MOVE */
			}
		    return 1;
		}
	    break;

	case P_IOR:				/* Prev instr was IOR of possible BP */
	case P_ADJBP:			/* or ADJBP of known BP */
	    if (op == P_LDB || op == P_DPB)	/* If one-time use of BP, */
		{
		if (localbyte(p, np))	/* try to make it local-fmt */
		    return 1;		/* Won, folded. */
		}
	    break;

	case P_SETZ:
	    switch (op)
		{
		case P_MOVE:		/* fold:  SETZ S, ; error if S preserve reg */
		case P_FMPR:		/*	    ...		*/
		case P_IMUL:		/*        MOVE/etc R,S  */
		case P_MOVN:		/* into:  SETZ R,   */
		case P_FLTR:
		    np->Pop = P_SETZ;	/* Replace this op with a SETZ R, */
		    np->Ptype = PTA_ONEREG;
		    dropinstr(p);		/* Flush the old SETZ */
		    return 1;

		case P_ADD:		/* fold:  SETZ S, error if S preserve reg */
		case P_FADR:		/*	   ...		*/
		case P_SUB:		/*        ADD  R,S	*/
		case P_FSBR:		/* into:  null		*/
		    dropinstr(np);		/* Flush the new op */
		    dropinstr(p);		/* and flush the SETZ */
		    return 1;
		}

	case P_SETO:			/* fall in from P_SETZ above */
	/* fold: SETZ/SETO S, to MOVNI S,0/1 */
	    p->Pvalue = (p->Pop == P_SETO ? 1 : 0);
	    p->Pop = P_MOVN;
	    p->Ptype = PTV_IMMED;		/* then drop through */

	case P_MOVN:
	/* invert MOVN(*) to MOVE(*) for following optimization */

	    switch(op & POF_OPCODE)
		{
		case P_MOVE:
		    p->Pop = P_MOVE;	/* move P_MOVN over for optimization */
		    np->Pop = P_MOVN;
		    break;
		case P_MOVN:
		    p->Pop = P_MOVE;	/* cancel double P_MOVN */
		    np->Pop = P_MOVE;
		    if (changereg (r, s, p))
			{
			dropinstr(np);	/* Flush pointless MOVE */
			return 1;
			}
		    break;
		case P_ADD:		/* R + -X is same as R - X */
		    p->Pop = P_MOVE;
		    np->Pop = P_SUB;
		    break;
		case P_SUB:		/* R - -X is same as R + X */
		    p->Pop = P_MOVE;
		    np->Pop = P_ADD;
		    break;
		case P_FADR:		/* R + -X is same as R - X */
		    p->Pop = P_MOVE;
		    np->Pop = P_FSBR;
		    break;
		case P_FSBR:		/* R - -X is same as R + X */
		    p->Pop = P_MOVE;
		    np->Pop = P_FADR;
		    break;

		case P_CAM:
		case P_IMUL:
		case P_FMPR:
		case P_FDVR:
		    if (p->Ptype != PTV_IMMED
		      && (q = before(p)) != NULL
		      && q->Preg == r
		      && !prevskips (q))
			switch (q->Pop)
			    {
			    case P_MOVE:	/* a <= -b is same as -a >= b */
				q->Pop = P_MOVN;
				p->Pop = P_MOVE;
				np->Pop = swapop(np->Pop);
				codrrx(p, np);		/* Continue looking back */
				return 1;

			    case P_MOVN:	/* -a <= -b is same as a >= b */
				q->Pop = P_MOVE;
				p->Pop = P_MOVE;
				np->Pop = swapop(np->Pop);
				codrrx(p, np);		/* Continue looking back */
				return 1;
			    }
		default:
		    if (p->Ptype == PTV_IMMED)
			{
			p->Pop = P_MOVE;	/* unknown const case, make P_MOVE */
			p->Pvalue = - p->Pvalue; /* with negated value */
			}
		    else
			{
			return 0;		/* Give up, no optimization done */
			}
		}	/* Drop through to following case */

	case P_MOVE:
	    rrpre3(p, np, np->Pop);		/* Always takes care of everything */
	    return 1;

	case P_HRRZ:
	case P_HLRZ:
	/* Turn HLRZ/HRRZ S,X
	**	...
	**	HRRE R,S
	** into:
	**	HLRE/HRRE R,X
	*/
	    if (op == P_HRRE)
		{
		rrpre3(p, np, (p->Pop == P_HRRZ ? P_HRRE : P_HLRE));
		return 1;
		}
	    break;

	case P_ADD:
	case P_SUB:
	/*
	** fold:  ADD/SUB S,x
	**		...
	**        ADD/SUB R,S
	**
	** into:  ADD/SUB R,x
	**		...
	**        ADD/SUB R,S
	**
	** and keep looking back for further optimization.
	*/

	/* Ensure that new instr is ADD or SUB before wasting more time */
	    if (op != P_ADD && op != P_SUB)
		break;

	/* Make sure the old ADD/SUB doesn't use its own reg as index */
	    if (rinaddr(p, p->Preg))
		break;

	/* See whether new instr's reg is otherwise referenced.
	** It is OK to skip over references of the form ADD/SUB R,M as
	** the result doesn't depend on the order of the instrs, and this
	** allows us to convert things like (a - (b+c+d)) into (a-b-c-d).
	*/
	    for (q = before(np); (q = chkref(p, q, r)) != NULL; q = before(q))
		{
	    /* Found a reference, see if it's OK to pass by. */
		if ((q->Pop == P_ADD || q->Pop == P_SUB)	/* ADD or SUB? */
		  && r == q->Preg && !rinaddr(q, r))	/* R ref reg-only? */
		    continue;				/* Win, skip over */
		return 0;			/* Failed, no optimization. */
		}

⌨️ 快捷键说明

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