📄 cccse.c
字号:
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 + -