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

📄 cccse.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 3 页
字号:
	    isindex[q->Pr2] = maxcse + 1; /* treat mem reg as index */
	    break;

	case PTA_BYTEPOINT:
	case PTV_IINDEXED:
	case PTA_MINDEXED:
	    isindex[q->Pindex] = maxcse + 1;	/* extract index register */
	    break;				/* accept */

	case PTV_IMMED:
	case PTA_ONEREG:
	case PTA_FCONST:
	case PTA_DCONST:
	case PTA_DCONST1:
	case PTA_DCONST2:
	    break;

	default:
	    return 0;
	}

	/*
	** An opcode making it this far has also passed the opcode type test.
	** Add it to the codes we are looking to match and either continue
	** looking for such ops or break out now that we are done looking.
	*/

	target[maxcse++] = q;		/* remember op we found */
	if (i) break;			/* break out of while loop */
	if (maxcse >= MAXCSE) return 0;	/* too much, give up */
	q = before (q);			/* or skip back and try for more */
    }					/* end while(1) */

    /*
    ** We have discovered complete expression, now set up register
    ** match machines.  If a register is still assigned, we ignore it
    ** to save later confusion in code generation.
    */
    for (i = 0; i < NREGS; i++) {
	if ((rfree(i) || safedouble) && isindex[i] < 0)
	    matchedto[i] = 0;	/* OK to check this reg, set initial match */
	else matchedto[i] = -1;	/* Not OK, don't use it */

/*
	if ((!rfree(i) && !safedouble) || isindex[i] >= 0)
	    matchedto[i] = -1;
	else matchedto[i] = 0;
*/
	regret[i] = i;			/* reg starts returning self */
    }
    if (isindex[r] >= 0)	/* If R used (as index) in its own */
	return 0;		/* calculation, give up... */
    matchedto[r] = 0;		/* OK to re-use main reg */

    if (maxflush < 0) maxflush = maxcse; /* remember top flush margin */
    else if (maxflush == 0) return 0;	/* If nothing to flush, give up */
    isindex[0] = isindex[R_SP] = -1;	/* ignore zero as index */
    stkoffset = 0;			/* no stack hackery yet */
    return 1;				/* OK, say target is ready! */
}

/* FINDCSE() - Fold common subexpressions
*/

static int
findcse(r, p, safedouble)
PCODE *p;
{
    PCODE *q;
    int i, flushfound;

    if (!cseinit(r, p, safedouble))
	return 0;

    /*
    ** Now all the preliminaries are done, we can go look for a match.
    ** We go back through all the ops, advancing the state machine of
    ** the register of the op until we find a complete match.
    ** This is the second loop and the big one.
    */

    q = p;				/* start again */
    flushfound = 0;			/* haven't found flushes yet */
    while (1) {				/* until we match or give up */
	if (q == NULL) return 0;	/* nothing there, give up */
	if (flushfound < maxflush && target[flushfound] == q) {
	    flushfound++;		/* going to go away, move marker on */
	    q = before (q);		/* ignore this one */
	    continue;			/* try something more substantial */
	}

	switch (q->Pop & (POF_OPCODE | POF_BOTH)) {

	/*
	** Byte instructions.  P_LDB doesn't change memory, but the
	** rest do (the pointer, the contents, or both).
	** We also handle folding P_IBP + P_LDB => P_ILDB here.
	*/

	case P_LDB:
	    if ((r = safematch (q, P_LDB)) != 0) 
		break; /* matched, return */
	    q = before (q);		/* not, back one */
	    continue;			/* and try again */

	case P_DPB:
	    if (q == target[0]) {	/* are we looking for P_IDPB fold? */
		q = before (q);		/* yes, just skip over the P_DPB */
		continue;		/* and look for a real match */
	    }
	case P_IDPB:
	    /* This used to drop through to the ILDB case.  However, this
	    ** caused lossage because it's unsafe to assume that the DPB
	    ** operand is correctly masked off, thus the register contents
	    ** don't necessarily correspond to what an LDB would get.  Someday
	    ** this could be improved to check for masking instructions.
	    */
	    return 0;

	case P_ILDB:
	    if (match (q, P_LDB)) {
		r = q->Preg;		/* matched, set reg */
		break;			/* and return success */
	    }
	    if (flushalias (q)) return 0;
	    q = before (q);		/* back up */
	    continue;			/* and try again */

	case P_IBP:

/* Bug here, the sequence
**		IBP x ? MOVEM x,addr ? LDB r,x
** becomes zapped into
**		MOVEM x,addr ? ILDB r,x
** which is real wrong.
** Until this is figured out and protected against, we enforce a
** restriction that the IBP must immediately precede the DPB/LDB.
*/
	    if (match (q, P_IBP)) switch(target[0]->Pop) {
	    case P_LDB:			/* turn P_IBP x + P_LDB R,x */
/* Temp fix */	if (q != before(target[0]))
/* Temp fix */	    break;
		target[0]->Pop = P_ILDB;	/* into P_ILDB R,x */
		q->Pop = P_NOP;
		return 0;
	    case P_DPB:			/* same with P_DPB */
/* Temp fix */	if (q != before(target[0]))
/* Temp fix */	    break;
		target[0]->Pop = P_IDPB;
		q->Pop = P_NOP;
		return 0;
	    default:
	        ;	/* do nothing */
	    }

	    if (flushalias (q)) return 0;
	    q = before (q);		/* back up */
	    continue;			/* try again */

	/*
	** Binary operations.  If they are not of type POF_BOTH, then
	** they must match the individual op, and if it matches
	** keep looking for the instruction before that in the sequence.
	**
	** If they are POF_BOTH explicitly or implicitly, then they can
	** only match a P_MOVE, and we have to be careful about mem changes.
	*/

	case P_IDIV:	case P_UIDIV:
/* 3/92 SPR-9774 avoid faulty register-pair opt when one is '/' and the
 * the other is '%', as in a[x%y][x/y]; Later, fix ismod[] in cccse.c
 */
#if SYS_CSI
    return 0;
#endif
	case P_DFMP:	case P_DFDV:	case P_DFSB:	case P_DFAD:
	case P_DMOVE:	case P_DMOVN:
	    flushreg(q->Preg + 1);
	case P_FADR:	case P_FSBR:	case P_FMPR:	case P_FDVR:
	case P_ADD:	case P_IMUL:	case P_SUB:
	case P_AND:	case P_IOR:	case P_XOR:
	case P_TRO:   	case P_TRZ:   	case P_TRC:
	case P_TDO:   	case P_TDZ:   	case P_TDC:
	case P_ADJBP:	case P_LSH:
	    if ((r = safematch(q, q->Pop)) != 0)
		matchedto[r]++;
	    q = before (q);		/* whether or no success, back one */
	    continue;			/* and try again */

	case P_SETO+POF_BOTH:	case P_SETZ+POF_BOTH:
	    if ((r = match (q, q->Pop &~ POF_BOTH)) != 0) break;
	case P_MOVEM:	case P_DMOVEM:
	case P_AOS:   	case P_SOS:
	case P_MOVN+POF_BOTH:	case P_MOVM+POF_BOTH:
	case P_ADD+POF_BOTH:	case P_IMUL+POF_BOTH:
	case P_FADR+POF_BOTH:	case P_FSBR+POF_BOTH:
	case P_FMPR+POF_BOTH:	case P_FDVR+POF_BOTH:
	case P_XOR+POF_BOTH:	case P_IOR+POF_BOTH:	case P_AND+POF_BOTH:
	case P_SETCM+POF_BOTH:
	case P_IDIV+POF_BOTH:
	    if ((r = match (q, P_MOVE)) != 0) 
		break; /* matched, set reg and return */
	    if (flushalias (q)) return 0;
	    if (q->Pop != P_MOVEM) flushreg (q->Preg);
	    if (q->Pop == P_DMOVEM) flushreg (q->Preg + 1);
	    q = before (q);		/* back one */
	    continue;			/* and try again */

	/*
	** Unary operations.  These are treated the same as binary ops,
	** except that a successful match means we have found the whole
	** common subexpression.
	*/

	case P_SETCM:	case P_MOVN:	case P_SETO:	case P_SETZ:
	case P_HRRZ:	case P_HLRZ:	case P_HRRE:	case P_HLRE:
	case P_FIX:	case P_FLTR:
	    if ((r = safematch (q, q->Pop)) != 0) break; /* matched, return */
	    q = before (q);		/* move back */
	    continue;			/* try again */

#if 1   /* erroneous code generated by this optimization! assumes
	 * left half of register is insignificant! 
	 */
	case P_HRRM:
	case P_HRLM:
	    if (match (q, (q->Pop == P_HRRM)? P_HRRZ : P_HLRZ)) {
		r = q->Preg;
		break;
	    }
	    if (flushalias (q)) return 0;
	    flushreg (q->Preg);
	    q = before (q);
	    continue;
#endif

	/*
	** Simple moves.  The moves cause the subexpression finder to
	** succeed as above with the unary operations.
	**
	** The !dropsout(q) check is in case this is a P_SKIPA to a P_JRST
	** or P_POPJ, in which case it would still be safe to check for a match
	** but we don't want deadjump() spoiling a perfectly good register
	** when we find that there isn't the match we want.
	*/

	case P_SKIP:
	    if (q->Pop == P_SKIP+POF_ISSKIP+POS_SKPE 
		&& dropsout (after (q)) 
		&& (r = match (q, P_SETZ)) != 0) 
		    break; /* P_SKIPE+P_JRST leaves 0 in reg */
	case P_MOVE:
	    if (!dropsout (q) && (r = safematch (q, P_MOVE)) != 0) break;
	    q = before (q);		/* not, move back */
	    continue;			/* try again */

	/*
	** Jumps.  These cause the flow of control to split, so we can't
	** pull P_IBPs across them.  Also, we remember unconditional jumps
	** in case they are preceded by a P_CAME or cascaded P_SKIP.
	*/

	case P_JRST: case P_POPJ: case P_JUMP:
	    if (q->Pop == P_JUMP+POS_SKPN && (r = match (q, P_SETZ)) != 0) 
		break;
	    jumped = 1;			/* can't fold P_IBP before here */
	    q = before (q);		/* move back */
	    continue;

	case P_AOJ: case P_SOJ:
	    if ((q->Pop & POF_OPSKIP) == POS_SKPN 
		&& (r = match (q, P_SETZ)) != 0) 
		    break;
	    jumped = 1;			/* this is a jump */
	    flushreg (q->Preg);		/* we can't deal with the reg change */
	    q = before (q);		/* so just move back */
	    continue;			/* and try again */

	/*
	** We handle here P_PUSH and P_ADJSP, which effectively change only the
	** stack pointer.
	*/
	case P_PUSH:
	    if ((r = match (q, P_MOVE)) != 0)
		break; /* register pushed matches 0(17) */
	    if (chgpush (q))		/* change refs to here into pushed x */
		return findcse (target[0]->Preg, p, safedouble); /* retry */
	    stkoffset++;		/* remember change to stack */
	    q = before (q);		/* move back */
	    continue;			/* try for another */

	case P_ADJSP:
	    stkoffset += q->Pvalue;	/* remember change to stack */
	    q = before (q);		/* move back */
	    continue;			/* try for another */

	/*
	** Comparisons
	**
	** We already did P_SKIP; these ones don't change their register.
	** But if we are past a P_CAME / P_JRST, we know the P_CAME skipped
	** and therefore the register contains the value compared to.
	*/

	case P_CAI: case P_CAM:
	    if (dropsout (after (q)) && (q->Pop & POF_OPSKIP) == POS_SKPE &&
		match (q, P_MOVE)) {	/* P_CAME+P_JRST is like P_MOVE */
		r = q->Preg;		/* (except that reg not munged) */
		break;
	    }
	case P_TRN: case P_TDN:
	    q = before (q);		/* innocuous op, move back */
	    continue;			/* and look for more */

	default:
	    return 0;			/* unknown op, give up */
	}
	break;				/* propagate escape */
    }

    /*
    ** Here when we've found a complete match.  The register containing
    ** the match is now in R instead of the initial register.
    ** Eliminate the old ops and return success.
    */

    for (i = 0; i < maxflush; i++) target[i]->Pop = P_NOP; /* drop op */
    fixprev();				/* update previous from drop */
    return regret[r];			/* return the successful register */
}

/*
** Test two instructions to see if they refer to the same place
*/
int
sameaddr(p, q, stkoffset)
INT stkoffset;
PCODE *p, *q;
{
    if ( (p->Ptype &~ (PTF_IMM + PTF_SKIPPED))
      != (q->Ptype &~ (PTF_IMM + PTF_SKIPPED)))
	return 0;

⌨️ 快捷键说明

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