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

📄 cccse.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 3 页
字号:
    switch (p->Ptype & PTF_ADRMODE) {
    case PTA_REGIS:
	return (p->Pr2 == q->Pr2);

    case PTA_BYTEPOINT:
	if (p->Pbsize != q->Pbsize) return 0;
    case PTA_MINDEXED:
	if ((p->Ptype & PTF_IMM) != (q->Ptype & PTF_IMM)) return 0;
	if (p->Pindex != q->Pindex || p->Pptr != q->Pptr) return 0;
	if (p->Pindex == R_SP) return (p->Poffset == q->Poffset - stkoffset);
	else return (p->Poffset == q->Poffset);

    case PTA_FCONST:
	return (p->Pfloat == q->Pfloat);

    case PTA_DCONST:
	return (p->Pdouble == q->Pdouble);
    case PTA_DCONST1:
	return (p->Pdouble1 == q->Pdouble1);
    case PTA_DCONST2:
	return (p->Pdouble2 == q->Pdouble2);

    case PTA_RCONST:
	return (p->Pvalue == q->Pvalue);
    case PTA_PCONST:
	return (   p->Pptr == q->Pptr
		&& p->Pbsize == q->Pbsize
		&& p->Poffset == q->Poffset);

    case PTA_ONEREG:
	return 1;
    default:
	int_error("sameaddr: bad Ptype");
	return 0;
    }
}

/*
** See if two ops can possibly refer to the same place
**
** We know they aren't exactly the same address, but maybe they're
** aliases of each other, in which case we want to know so we can
** be careful around ops that change memory.
*/
int
alias (p, q, soff)
PCODE *p, *q;
INT soff;		/* Stack offset */
{
    int pt, qt;

    /* Only need to check further if both instrs reference memory */
    if ( (  (p->Ptype&PTF_ADRMODE) == PTA_BYTEPOINT
	 || (p->Ptype&PTF_ADRMODE) == PTA_MINDEXED)
      && (  (q->Ptype&PTF_ADRMODE) == PTA_BYTEPOINT
	 || (q->Ptype&PTF_ADRMODE) == PTA_MINDEXED)) {
	pt = p->Ptype;
	qt = q->Ptype;

	/* Duplicate sameaddr() checking here, since we want to test
	** for either a PTA_MINDEXED and PTA_BYTEPOINT reference, and
	** sameaddr() only does this if both are the same type.
	*/
	if (p->Pindex == q->Pindex && p->Pptr == q->Pptr) {
	    if (p->Pindex == R_SP) {
		if (p->Poffset == (q->Poffset - soff))
		    return 1;		/* Same location on stack */
	    } else if (p->Poffset == q->Poffset)
		return 1;
	}

	/* If either has the indirect bit set, give up. */
	if ((pt | qt) & PTF_IND) return 1;	/* May alias */

#if 0 /* Old stuff, flush */
	/* P_MOVEI != P_MOVEM != P_DPB */
	if ( (q->Ptype &~ (PTF_IMM + PTF_SKIPPED))
	  != (p->Ptype &~ (PTF_IMM + PTF_SKIPPED)))
	    return 0;
#endif
#if 0	/* Finish coding this later */
	/* Byte ptrs to different parts of a word? */
	if ( (pt&PTF_ADRMODE) == PTA_BYTEPOINT
	  && (pt&PTF_ADRMODE) == PTA_BYTEPOINT) {
	    /* Check to see if bytes overlap or not */
	    return 0;			/* If no overlap */
	}
#endif
	/* stack can't alias with much */
	if (p->Pindex == R_SP && !(pt & PTF_IMM)) {
	    if (!stackrefs) return 0;
	    if (q->Pindex == R_SP && !(qt & PTF_IMM)) return 0;
	    return (q->Pptr == NULL || (qt & PTF_IMM));
	}

	/* same for other word from stack */
	if (q->Pindex == R_SP && !(qt & PTF_IMM)) {
	    if (!stackrefs) return 0;
	    return (p->Pptr == NULL || (pt & PTF_IMM));
	}

	/* non-indirect with same index or with different symbols */
	if (!(pt & PTF_IMM) && !(qt & PTF_IMM)) {
	    if (p->Pindex == q->Pindex) return 0;
	    if (p->Pptr != NULL && q->Pptr != NULL && p->Pptr != q->Pptr)
		return 0;
	}

	/* none of the above, it can alias */
	return 1;
    }
    return 0;			/* Not mem refs, can't alias with anything */
}

/* --------------------------- */
/*      see if op matches      */
/* --------------------------- */

static int
match (q, op)
PCODE *q;
{
    int i;

    /* make sure not possible to skip over this one */
    if (prevskips (q) && !dropsout (after (q))) return 0;

    /* do funny matches */
    switch (q->Pop & POF_OPCODE) {
    case P_IBP:			/* no useful reg, but fold into P_DPB */
	return (!jumped && sameaddr(target[0], q, stkoffset));

    case P_PUSH:				/* might be push of register */
	return ((q->Ptype &~ PTF_SKIPPED) == PTA_REGIS && (i = matchedto[q->Pr2]) >= 0
		&& target[i]->Pop == op && stktop (target[i]))?
	    q->Pr2 : 0;			/* ret pushed reg if success, else 0 */

    case P_IDIV: case P_UIDIV:
	i = matchedto[q->Preg + 1];	/* save target */
	flushreg (q->Preg + 1);		/* from certain destruction */

	/* see if construable as used as mod, if not treat normally */
	/* do not check matchedto[q->Preg] -- will unnecessarily lose */
	if (i < 0 || !ismod[i] || !sameaddr (target[i], q, stkoffset)) break;

	matchedto[q->Preg] = i;		/* set match to other reg */
	regret[q->Preg] = regret[q->Preg + 1]; /* chain return val */
	return q->Preg;			/* return success */
    default:
	;	/* do nothing */
    }

    /* now the boring cases */
    if ((i = matchedto[q->Preg]) < 0 || ismod[i]) return 0; /* get target */
    if (op == P_SETZ && target[i]->Pop == P_SETZ) return q->Preg;
    if (target[i]->Pop == op && sameaddr(target[i], q, stkoffset)) /* match */
	return q->Preg;			/* success! return with reg */

    /* Maybe MOVEI matches MOVNI */
    if (((op == P_MOVN && target[i]->Pop == P_MOVE)
	|| (op == P_MOVE && target[i]->Pop == P_MOVN))
      && (q->Ptype & PTF_ADRMODE) == PTA_RCONST
      && (target[i]->Ptype & PTF_ADRMODE) == PTA_RCONST
      && q->Pvalue == - target[i]->Pvalue)
	return q->Preg;			/* Yes, win! */

    return 0;				/* not even that, give up */
}

/* ------------------------------------ */
/*      jacket routine for match ()      */
/* ------------------------------------ */

static int
safematch (q, op)
PCODE *q;
{
    int r;
    if ((r = match (q, op)) == 0) flushreg (q->Preg); /* fail, give up reg */
    return r;				/* return result of match */
}

/*
** See if op refers to the top of the stack.
** Should be safe to fail for non-stack-top-refs.
*/

static int
stktop (p)
PCODE *p;
{
    return p->Ptype == PTA_MINDEXED && p->Pptr == NULL &&
	   p->Poffset == - stkoffset && p->Pindex == R_SP;
}

/* CHGPUSH - Replace refs to thing PUSHed on top of stack with pushed value.
**	 Returns 1 if anything changed.
** Only called from one place in findcse().
*/

static int
chgpush (p)
PCODE *p;
{
    PCODE *q;
    int found, i, sop, sreg;
    INT so;

    /* see if this push uses a bad register */
    switch (p->Ptype) {
	case PTV_IMMED:			/* Immediate RCONST is OK */
	case PTA_FCONST:
	case PTA_DCONST1:
	case PTA_DCONST2:
	    break;
	case PTA_REGIS:			/* Not sure about this --KLH */
	    if (p->Pr2 == 0
		|| p->Pr2 == R_SP
		|| matchedto[p->Pr2] == 0)
		break;			/* Check that 2nd reg OK */
	    return 0;			/* Else fail */
	case PTA_MINDEXED:
	    if (p->Pindex == 0
		|| p->Pindex == R_SP
		|| matchedto[p->Pindex] == 0)
		break;			/* Check that index reg OK */
					/* Else drop thru to fail */

	case PTA_BYTEPOINT:	/* Shouldn't be pushing this anyway */
	default:
	    return 0;
    }

    /* maybe it uses a killed value */
    for (so = 0, q = target[0]; q != p; q = before(q))
	switch (q->Pop & POF_OPCODE) {
	    case P_ADJSP:		/* stack adjustment */
		if (q->Preg == R_SP)
		    so += q->Pvalue;
		continue;		/* No mem change */

	    /* This one can screw up if we PUSH through an AC that isn't R_SP,
	    ** since we can't know for sure where the AC is pointing.  Oh well.
	    */
	    case P_PUSH:		/* ignorable mem chg, also stk adj */
		if (q->Preg == R_SP) {
		    so++;
		    continue;
		}
		return 0;		/* Unknown change */

	    case P_POP:		/* Stack adj, must also check mem change */
		if (q->Preg == R_SP)
		    so--;	/* Adjust, then drop through */

	    default:			/* non-stack-change op */
		if ( ((q->Pop & POF_BOTH)		/* If op changes mem */
		      || (popflg[q->Pop&POF_OPCODE]&PF_MEMCHG))
		  && (sameaddr(p, q, stkoffset + 1 - so)	/* same mem? */
		      || alias (p, q, stkoffset + 1 - so)))
			return 0;		/* Then fail */
	}

    /* it is ok, change the targets to reflect it */
    found = 0;				/* none hacked up yet */
    for (i = 0; i < maxcse; i++) if (stktop (target[i])) { /* find stack ref */
	sop = target[i]->Pop;	/* Save op and reg of target */
	sreg = target[i]->Preg;
	*(target[i]) = *p;	/* Copy entire pseudo-code struct */
	target[i]->Pop = sop;	/* Then restore old op and reg */
	target[i]->Preg = sreg;

	/* Verify index reg value is valid before checking it -- then adjust to
	** proper stack offset if necessary.
	*/
	if ( (((target[i]->Ptype)&PTF_ADRMODE) == PTA_MINDEXED
	     || ((target[i]->Ptype)&PTF_ADRMODE) == PTA_BYTEPOINT)
	    && target[i]->Pindex == R_SP)
		target[i]->Poffset -= 1 + stkoffset;
	found = 1;			/* remember we got one */
    }
    return found;
}

/* -------------------------------- */
/*      get rid of useless reg      */
/* -------------------------------- */

static void
flushreg(r)
{
    flushtarget(isindex[r]);
    matchedto[r] = -1;
}

/* ----------------------------------------------- */
/*      get rid of obsoleted target registers      */
/* ----------------------------------------------- */

static void
flushtarget(i)
{
    int r;
    for (r = 0; r < NREGS; r++) if (matchedto[r] < i) matchedto[r] = -1;
}

/* ----------------------------------------- */
/*      get rid of ops with same memory      */
/* Returns 1 if we should give up and quit findcse immediately.
*/

static int
flushalias (q)
PCODE *q;
{
    int i, pregmatch, flushtop;

    if ((q->Ptype & PTF_ADRMODE) == PTA_REGIS) flushreg (q->Pr2);
    flushtop = -1;
    for (i = 0; i < maxcse; i++)
	if (sameaddr(target[i], q, stkoffset)
	  || alias(target[i], q, stkoffset))
	    flushtop = i + 1;
/* KLH 1/29/87 Not sure if this is right fix, but don't have time to
** figure it all out.
** If this op (which is assumed to change memory) has an address which
** matches anything in the target subexpr and this op is also
** conditionalized (prev instr is a skip) then give up immediately,
** since we can't know whether the op changed memory or not.
*/
    if (flushtop >= 0 && prevskips(q)) return 1;
/* End of hasty fix */

    pregmatch = matchedto[q->Preg];
    flushtarget(flushtop);
    if (q->Pop != P_MOVEM) pregmatch = -1;
    else matchedto[q->Preg] = pregmatch;
    return (flushtop == maxcse && pregmatch < 0);
}

⌨️ 快捷键说明

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