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

📄 ccopt.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
			    {
			    case P_SETZ:
			    case P_SETO:
			    case P_MOVN:
				if (!unsetz (q))
				    break;	/* turn P_SETZ into P_MOVE */
			    case P_MOVE:

	    /*
	    ** fold:  P_MOVE  R,x
	    **	      P_PUSH  17,R
	    **
	    ** into:  P_PUSH  17,x
	    **	      P_MOVE  R,0(17)
	    **
	    ** in hope that genrelease() will flush the P_MOVE.
	    */

				if (q->Ptype == PTV_IINDEXED)
				    break; /* no XP_PUSHI */
				p->Pop = P_MOVE;		/* get different P_MOVE instr */
				p->Ptype = PTA_MINDEXED;	/* from memory, no indirection */
				p->Preg = q->Preg;		/* into destination register */
				p->Pindex = R_SP;		/* from stack */
				p->Pptr = 0;		/* not global variable space */
				p->Poffset = 0;		/* top of stack */
				q->Pop = P_PUSH;		/* now make old P_MOVE into P_PUSH */
				q->Preg = R_SP;		/* onto stack */
			    }
		    return;				/* no more to do here */

		default:
		    switch (p->Ptype & PTF_ADRMODE)
			{
			case PTA_MINDEXED:
			case PTA_BYTEPOINT:
			    if (p->Pindex == R_SP)
				{
				if (p->Poffset < previous->Poffset)
				    continue;		/* arg, safe */
				p = NULL;		/* Not safe */
				}
			    break;
			case PTA_REGIS:
			    if (p->Pr2 == R_SP)
				p = NULL;			/* OP R,17 loses big */
			    break;
			}
		}

    /*--------------------------------------*/

    if ((b = before(previous)) != NULL
#if SYS_CSI		/*  Reg linkage, avoid faulty optimizations */
	&& Register_Nopreserve (b->Pr2)
#endif
	&& b->Ptype == PTA_REGIS /* !prevskips */
	&& b->Pop == P_MOVE && b->Preg == previous->Preg
#if SYS_CSI
	&& (previous->Pr2 != b->Preg)	/* FEW, 2A(37) 17-Jul-92 (SPR 9877) */
					/* Cannot perform this fold if 2d   */
					/* operand of 2d instr ('x' below)  */
					/* refers to common register ('R'). */
#endif
	&& rfree(b->Pr2)		/* Ensure OK to clobber S */
	&& snglop(previous->Pop))	/* Single-word op */
/*
	&& p->Pop != P_IDIV && p->Pop != P_UIDIV) {
*/
/* BUG!  This call is known to swap an IDIVI and zap its reg!
*/
	/*
	** fold:  MOVE  R,S
	**        OP    R,x
	**
	** into:  OP    S,x
	**        MOVE  R,S
	*/
	{
	previous->Preg = (char) (b->Pr2);	/* flatten the register change */ // FW KCC-NT
	swappseudo(b, previous);	/* switch the two ops */
	p = b;				/* forget about the P_MOVE */
	}
    else
	b = p = previous;		/* no move, start at the top */

    if (p->Ptype != PTA_MINDEXED)
	return;
    switch (p->Pop)
	{
	case P_AOS:
	case P_SOS:
#if 0	/* BAD STUFF!  KLH: This code loses (and has caused actual lossage in
	** compiled code of the form "++I * ++I") because it generates a
	** MOVE S,R which causes the peepholer to think that it is safe
	** to throw R away completely -- which is NOT what the original code
	** wanted to do or imply!
	*/
	    if ((b = before (p)) != NULL && b->Pop == P_MOVEM &&
		b->Ptype == PTA_MINDEXED /* !prevskips */ && b->Pptr == p->Pptr &&
		b->Pindex == p->Pindex && b->Poffset == p->Poffset)
		{

	    /*
	    ** fold:  P_MOVEM R,x
	    **        P_AOS   S,x
	    **
	    ** into:  P_ADDI  R,1
	    **        P_MOVEM R,x
	    **        P_MOVE  S,R
	    */
		b->Pop = P_ADD;		/* make P_ADD */
		b->Ptype = PTV_IMMED;		/* immediate quantity */
		b->Pvalue = (p->Pop == P_AOS)? 1 : -1; /* by one */
		s = p->Preg;		/* remember the reg we want */
		p->Pop = P_MOVEM;		/* now make P_MOVEM */
		r = p->Preg = b->Preg;	/* using old register */
		foldplus(b);		/* fix up addition */
		code00(P_MOVE, s, r);		/* and fix up registers */
		}
	    else
#endif /* End of bad stuff */
		foldinc(p);

	default:
	    return;
	case P_MOVEM:
	    break;
	}

    /*
    ** At this point we know that p = previous points to a MOVEM R,X.
    ** Search back to find the last instruction that uses R, to see if we
    ** can fold it with the MOVEM.
    */
    badidx = 0;
    ramask_p = rbinaddr(p);		/* Remember regs used in X */
    rrmask_p = rbits[p->Preg];		/* And in R (for completeness) */
    while (1)
	{
	int rrmask_b;

	b = before(b);			/* skip over unlikely candidate */
	if (b == NULL)
	    return;		/* ran out of them */
	if (rbinaddr(b) & rrmask_p)	/* Can't hack if its addr uses R */
	    return;
	rrmask_b = rbinreg(b);		/* Find mask of regs that Preg uses */
	if (rrmask_b & ramask_p)	/* If reg used in X, then */
	    badidx = 1;			/* can't fold unless SETZ */
	if (rrmask_b & rrmask_p)	/* If both use same Preg, */
	    break;			/* done with loop! */
	}
    if (prevskips(b))
	return;		/* skipped over, lose */

    switch (b->Pop)
	{
	case P_FMPR:
	case P_IMUL:
	    if ((q = findmove(b, p)) != NULL && q->Pop == P_MOVN && !badidx)
		{
	    /*
	    ** fold:  P_MOVN  R,x
	    **        P_IMUL  R,y
	    **        P_MOVEM R,x
	    **
	    ** into:  P_MOVN  R,y
	    **        P_IMULB R,x
	    */
		p->Pop = b->Pop | POF_BOTH;	/* move mply op over */
		b->Pop = P_MOVN;		/* make old add into negated move */
		q->Pop = P_NOP;		/* flush the first move */
		foldplus(p);		/* maybe we can turn it into an AOS */
		break;
		}

	case P_FADR:
	case P_FSBR:
	case P_ADD:
	case P_SUB:
	case P_AND:
	case P_IOR:
	case P_XOR:
	    if ((q = findmove(b, p)) != NULL && q->Pop == P_MOVE && !badidx)
		{
	    /* fold:	MOVE R,x
	    **		ADD R,y
	    **		MOVEM R,x
	    ** into:
	    **		MOVE R,y
	    **		ADDB R,x
	    */
		if (b->Pop == P_SUB)
		    {
		    p->Pop = P_ADD+POF_BOTH;	/* make ADDB */
		    b->Pop = P_MOVN;		/* and MOVN */
		    }
		else if (b->Pop == P_FSBR)
		    {
		    p->Pop = P_FADR+POF_BOTH;	/* make floating add */
		    b->Pop = P_MOVN;		/* and floating MOVN (same as int) */
		    }
		else
		    {
		    p->Pop = b->Pop | POF_BOTH;	/* move add op over */
		    b->Pop = P_MOVE;		/* make old add into move */
		    }
		q->Pop = P_NOP;		/* flush the first move */
		if (b->Ptype == PTA_REGIS
		    && (b->Pop == P_MOVE || pushneg(b->Pr2, before (b))))
		    {
		    b->Pop = P_NOP;
		    p->Preg = (char) (b->Pr2);	// FW KCC-NT
		    code00(P_MOVE, b->Preg, b->Pr2);
		    }
		foldplus(p);		/* maybe we can turn it into an AOS */
		break;
		}
	/* If didn't have preceding MOVE, check following optimization */

	case P_MOVE:
	case P_MOVN:
	case P_MOVM:
	case P_SETCM:
	case P_FDVR:
	case P_IDIV:		/* yes, P_IDIVB works */
	    if (b->Ptype == p->Ptype
	      && b->Poffset == p->Poffset
	      && b->Pindex == p->Pindex
	      && b->Pptr == p->Pptr
	      && !badidx)
		{

	    /*
	    ** fold:  OP    R,addr
	    **        MOVEM R,addr
	    **
	    ** into:  OPB   R,addr
	    */
		p->Pop = b->Pop;		/* move opcode across */
		if (b->Pop != P_MOVE)
		    p->Pop |= POF_BOTH;
		b->Pop = P_NOP;		/* flush old instruction */
		foldplus(p);		/* maybe we can turn it into an AOS */
		}
	    break;

	case P_SETZ:
	case P_SETO:
	    if (b->Ptype == PTA_ONEREG)
		{

	    /*
	    ** fold:  SETZ  R,
	    **        MOVEM R,x
	    **
	    ** into:  SETZB R,x
	    */
		p->Pop = b->Pop+POF_BOTH;	/* move opcode across, make both */
		b->Pop = P_NOP;		/* flush old instruction */
		}
	}
}

#if 0 /* Old stuff from last part of foldboth() */
	switch (rchange (b->Pop))
{
    case PRC_RSAME:		 /* nice single word op? */
    case PRC_RSET:
    case PRC_RCHG:
    case PRC_RCHG_DSAME:
	if (b->Preg == p->Preg)
	    break; /* the one we want */
	continue;			/* else look back some more */

    case PRC_DSAME:		/* nasty double word op? */
    case PRC_DSET:
    case PRC_DSET_RSAME:
    case PRC_DCHG:
    case PRC_DCHG_RSAME:
	if (!prevskips(b)
	  && (b->Pop == P_DFMP || b->Pop == P_DFDV)
	  && b->Preg == p->Preg
	  && (q = before(b))
	  && !prevskips(q)
	  && q->Pop == P_SETZ
	  && q->Preg == p->Preg + 1)
	    {

		/*
		** fold:  SETZ  R+1,
		**	  DFMP R,y	(or DFDV R,y)
		**	  MOVEM R,x
		**
		** into:  FMPR  R,y	(or FDVR R,y)
		**	  MOVEM R,x
		**
		** so that later optimization can turn it into a FMPRB.
		** The low order word of the double can't affect the result,
		** but only for multiply -- this is not safe for DFAD and DFSB!
		*/
	    if (q->Ptype == PTA_ONEREG)
		q->Pop = P_NOP; /* drop P_SETZ */
	    b->Pop = ((b->Pop == P_DFMP)? P_FMPR : P_FDVR); /* make singleword */
		/* Fix up operand if a constant */
	    if ((b->Ptype&PTF_ADRMODE) == PTA_DCONST)
		{
		b->Ptype = (b->Ptype& ~PTF_ADRMODE) | PTA_FCONST;
		b->Pfloat = (float)b->Pdouble;
		}
	    break;			/* escape loop */
	    }
	if ((b->Preg + 1) == p->Pindex)
	    badidx = 1;
	if (b->Preg != p->Preg && (b->Preg + 1) != p->Preg)
	    continue;
    default:			/* P_PUSHJ? */
	return;			/* give up */
}
break;
    }
#endif

static PCODE *
findmove(b, p)
PCODE *b, *p;
    {
    PCODE *q = b;

    /* Scan back from potentially foldable op (B) to set Q for some
    ** cases that might need it.  (KLH: seems dumb)
    */
    while ((q = before(q)) != NULL
      && q->Preg != b->Preg
      && q->Preg != p->Preg
      && q->Preg != p->Pindex)
	{
	    switch (q->Pop)
		{
		case P_FADR:
		case P_FSBR:
		case P_FDVR:
		case P_FMPR:
		case P_ADD:
		case P_IMUL:
		case P_SUB:
		case P_MOVE:
		case P_MOVN:
		case P_SETZ:
		case P_SETO:
		case P_FLTR:
		case P_FIX:
		case P_AND:
		case P_IOR:
		case P_SETCM:
		    continue;
		}
	    return NULL;			/* unknown op, stop */
}
if (q
  && q->Preg == p->Preg
  && q->Ptype == p->Ptype /* !prevskips */
  && q->Pptr == p->Pptr
  && q->Poffset == p->Poffset
  && q->Pindex == p->Pindex)
    return q;
return NULL;
    }


static int
snglop(op)
int op;
    {
    switch (rchange(op))
{
    case PRC_RSAME:
    case PRC_RSET:
    case PRC_RCHG:
    case PRC_RCHG_DSAME:
	return 1;		/* OK single-word operation */
    default:
	return 0;		/* Anything else is assumed not OK */
}
}

/* FOLDSTACK(n) - Optimize previous instructions into P_ADJSP.
**
**    Attempts to pull previous P_ADJSPs, P_PUSHs, etc into a new P_ADJSP
** which would, if no such optimization occurred, have constant n.
** The return value is what the constant should be, taking into
** account any optimization which has been done.
**	This is only called by code8 in CCCODE when about to generate
** an ADJSP.  This is also invoked via code8 when code0 generates
** a PUSH P,R.
**	It is ALWAYS safe to flush an ADJSP P,-n because that just
** leaves some extra junk on the stack and doesn't invalidate any
** following references.
**	The thing to beware of is flushing positive adjustments
** (ADJSP P,+n) because this could leave following code referencing
** places beyond the end of the stack (i.e. indexing through P with
** a positive offset), unless we are careful and
** have made sure that no such references exist.
**	The "maxfold" variable is to ensure that we don't accidentally
** do this.  It is set to the largest positive N that it is safe to
** flush (if an ADJSP P,+N is encountered); this means that no code
** has been seen which references a location higher than -maxfold(P).
** That is, -maxfold(P) is assumed to have a reference.
** Note that 0(P) is a valid reference.  maxfold should never be
** negative!
**	Finally, if we know from "stackrefs" that the current function
** generates an address pointing to something on the stack, then it is
** never safe to flush a positive ADJSP, since we can't tell just from
** the instruction memory references whether a portion of the stack is
** really being used or not.  This is why maxfold is set to 0 in that
** case, which means that as far as is known, all of the current stack is
** referenced.
*/

INT
foldstack(n)
INT n;
    {
    PCODE *p = previous;		/* Start from end of buffer */
    INT maxfold = (stackrefs ? 0 : 1000000L);	/* limit on pos ADJSP fold */

    while (p != NULL)
	switch (p->Pop & POF_OPCODE)
{
    case P_ADJSP:
	/* See if safe to merge this ADJSP in with current one (at end),
	** and if so adjust stack to account for its flushage, and
	** then flush it.
	*/
	if (p->Preg != R_SP		/* Must be ADJSP 17, */
	  || prevskips(p)		/* and not skipped over */
	  || p->Pvalue > maxfold)	/* and not about to invalidate refs */
	    return n;		/* Failed one of above, quit. */
	n += adjstack(p->Pvalue, p);	/* Won, adjust all following refs */
	n += p->Pvalue;
	maxfold -= p->Pvalue;
	dropinstr(p);			/* Flush that ADJSP */
	p = previous;			/* Start loop over */
	break;

    case P_PUSH:
	/* If this PUSH is the last instruction, and "n" is negative
	** (meaning stack being reduced) then we can simply flush the PUSH
	** since the value pushed is never used.
	** Otherwise, OK to look past a PUSH P,[0]/[-1] because
	** adjstack() knows how to convert those to a SETZB/SETOB -n(P)
	** which is more efficient.
	** Likewise, PUSH P,R is ok because adjstack() can change it to

⌨️ 快捷键说明

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