📄 ccjskp.c
字号:
case P_SUB:
if (!safechange) return;
/*
** fold: P_SUB R,addr
** P_CAIN R,0
**
** into: P_CAMN R,addr
**
** (only for P_CAMN or P_CAME, not other comparisons)
*/
if (p->Pop != P_CAI+POF_ISSKIP+POS_SKPE && p->Pop != P_CAI+POF_ISSKIP+POS_SKPN) return;
q->Pop = p->Pop; /* make comparison */
if (q->Ptype & PTF_IMM) q->Ptype &=~ PTF_IMM; /* immediate uses P_CAI form */
else q->Pop ^= (P_CAM ^ P_CAI); /* memory uses P_CAM form */
break;
case P_AOS: case P_SOS:
/*
** fold: P_AOS R,addr
** P_CAIx R,0
**
** into: P_AOSx R,addr
*/
q->Pop |= (p->Pop &~ POF_OPCODE);
break;
default: return;
}
/*
** All the defaults in the previous switch should be return statements,
** so if we made it through we must have made a fold. We should therefore
** flush the P_CAIx so we don't have two skips in a row.
*/
dropinstr(p); /* flush it, making sure previous valid */
}
/* JUMPTOSKIP(p) - Turn a jump into an immediate compare against zero.
**
** Assumes there is one instruction between the jump and its
** label; if only zero the resulting skip should be reversed.
** Doesn't update PTF_SKIPPED in following opcodes.
*/
static void
jumptoskip (p)
PCODE *p;
{
if ((p->Ptype &~ PTF_SKIPPED) == PTA_MINDEXED) switch (p->Pop & POF_OPCODE) {
case P_JRST:
if (invskip(before(p))) { /* can flip previous skips */
dropjump (p); /* so having done it just drop jump */
return;
}
reflabel (p->Pptr, -1); /* fix up reference counts */
p->Pop = P_TRN+POF_ISSKIP+POS_SKPA; /* now turn it into a P_TRNA */
p->Ptype ^= (PTA_MINDEXED ^ PTA_ONEREG); /* no address */
p->Preg = 0; /* no register either */
return;
case P_JUMP:
reflabel (p->Pptr, -1); /* fix up reference counts */
p->Pop ^= (P_CAI ^ P_JUMP ^ POF_ISSKIP); /* make P_CAIx */
p->Ptype ^= (PTA_MINDEXED ^ PTA_RCONST); /* immediate compare */
p->Pvalue = 0; /* against zero */
return;
case P_AOJ:
reflabel (p->Pptr, -1); /* fix up reference counts */
p->Pop ^= (P_AOS ^ P_AOJ ^ POF_ISSKIP); /* make P_AOSx */
p->Ptype ^= (PTA_MINDEXED ^ PTA_REGIS); /* reg to reg */
p->Pr2 = p->Preg; /* both same reg */
return;
case P_SOJ:
reflabel (p->Pptr, -1); /* fix up reference counts */
p->Pop ^= (P_SOS ^ P_SOJ ^ POF_ISSKIP); /* make P_SOSx */
p->Ptype ^= (PTA_MINDEXED ^ PTA_REGIS); /* reg to reg */
p->Pr2 = p->Preg; /* both same reg */
return;
}
}
/* CROSSJUMP(p, label) - Pull JUMPx across skips
**
** Sometimes it can improve code to move a P_JUMPx, P_AOJx, or P_SOJx from one
** side of a set of cascaded skips to the other. We have to be careful
** though in rearranging this sort of thing that we don't get illegal
** memory references or indirection loops.
** KLH: One problem with this code is that the two code sequences
** are not equivalent. That is, the registers may end up with different
** values, since the skips may have modified the regs. The initial sequence
** would not do this modification, whereas the new sequence does.
*/
static void
crossjump(pcur, lab)
PCODE *pcur;
label lab;
{
PCODE *q, *p;
int op;
/*
** fold: JUMPx R,lab ; JUMPx, AOJx, or SOJx
** (any number of skips) ; for JUMP, cannot change R or any mem
** ; also cannot use R in address
** ; for A/SOJ, ditto + can't use R as reg
** pcur-> JRST L2
** lab: (or JRST lab)
**
** into: (the same skips)
** JUMPy R,L2
** lab: (or JRST lab)
*/
if (pcur->Pop != P_JRST) return; /* must be a jump here */
for (q = before(pcur); ; q = before(q)) {
if (q == NULL) return;
if (!isskip(q->Pop)) /* Non-skip instr halts loop */
break;
if ((popflg[q->Pop&POF_OPCODE]&PF_MEMCHG) /* Any mem chg instr */
|| (q->Ptype & PTF_IND)) /* or indirect ref */
return; /* halts the search. */
}
switch (op = (q->Pop & POF_OPCODE)) {
case P_AOJ:
case P_SOJ:
case P_JUMP:
if (q->Pptr != lab || prevskips(q))
return; /* Wrong label or op is skipped */
/* Re-scan the skips to ensure they do not use R unsafely.
** For JUMP, just ensure the skip does not modify R, and does not
** use it in an address.
** For AOJ/SOJ, must ensure R is not referenced at all.
*/
for (p = before(pcur); p != q; p = before(p)) {
if (rinaddr(p, q->Preg) || /* R cannot be in addr */
((op == P_JUMP)
? rrchg(p, q->Preg) /* Cannot modify R */
: rinreg(p, q->Preg))) /* Cannot reference R */
return;
}
/* Won, OK to move and invert the jump. */
pcur->Preg = q->Preg; /* else copy reg to jump on */
pcur->Pop = revop(q->Pop); /* invert jump cond */
dropjump(q); /* drop original JUMPx */
}
}
/* FOLDJUMP(label) - Common optimizations for labels and jumps
**
** Called either when about to emit a jump to the given label, or when about
** to emit the label itself. There are some things we can do in optlab()
** that we can't do here, because (for instance) we don't want to turn a
** jump two before another to the same place into a TRNA to the jump.
*/
void
foldjump(PCODE *prev, label lab)
/* Instr preceding either label or the JRST to label */
{
PCODE *q, *b;
if (!prev || !oneinstr(prev) ||
(q = before(prev)) == NULL || (b = before(q)) == NULL) return;
if (q->Pop == P_JRST
&& q->Pptr == lab
&& !(q->Ptype & PTF_IND)
&& invskip(b)) {
/*
** Fold: skip Into: reverse-skip
** JRST lab --
** op op
** lab: (or JRST lab) lab: (or JRST lab)
*/
dropjump(q); /* already flipped skip, drop jump */
setskip(prev); /* op is now skipped over */
if (prev->Pop == P_MOVN
&& b->Preg == prev->Preg
&& !prevskips(b)
&& (b->Pop == P_SKIP+POF_ISSKIP+POS_SKPG || b->Pop == P_SKIP+POF_ISSKIP+POS_SKPGE)
&& (sameaddr(b, prev, 0)
|| (prev->Ptype == PTF_SKIPPED+PTA_REGIS
&& prev->Preg == prev->Pr2))) {
/*
** fold: SKIPGE R,x into: MOVM R,x
** MOVN R,R --
*/
b->Pop = P_MOVM; /* make MOVM */
dropinstr(prev); /* drop MOVN and fix prev */
prev = b; /* to point to new previous op */
}
} else if (isskip(q->Pop) && oneinstr(q)
&& b->Pop == P_JRST && b->Pptr == lab
&& invskip(before(b))) {
/*
** fold: skip1
** JRST lab
** skip2 (must be skippable)
** op
** lab: (or JRST lab)
**
** into: reverse skip1
** reverse skip2
** JRST lab
** op
** lab: (or JRST lab)
*/
q->Pop = revop(q->Pop); /* reverse the second skip */
setskip(q); /* skip now will be skipped over */
swappseudo(b, q); /* switch the skip and the jump */
clrskip(prev); /* op no longer skipped over */
}
crossjump(prev, lab); /* pull JUMPx across skips */
}
/* NEWSKIP(p) - Turn non-skip op into a skip
**
** I.e. P_MOVE becomes P_SKIPA. Works even if op is skipped over
** (caller must check for that case). Again, afters are not set PTF_SKIPPED.
*/
static int
newskip (p)
PCODE *p;
{
PCODE *q;
if (p != NULL) switch (p->Pop) {
case P_SUB:
if ((p->Ptype &~ PTF_SKIPPED) != PTV_IMMED || p->Pvalue != 1) break;
p->Ptype ^= (PTV_IMMED ^ PTA_REGIS);
p->Pr2 = p->Preg;
case P_SOS:
p->Pop = P_SOS+POF_ISSKIP+POS_SKPA;
return 1;
case P_ADD:
if ((p->Ptype &~ PTF_SKIPPED) != PTV_IMMED || p->Pvalue != 1) break;
p->Ptype ^= (PTV_IMMED ^ PTA_REGIS);
p->Pr2 = p->Preg;
case P_AOS:
p->Pop = P_AOS+POF_ISSKIP+POS_SKPA;
return 1;
case P_IOR:
if (p->Ptype & PTF_IMM) {
p->Pop = P_TRO+POF_ISSKIP+POS_SKPA;
p->Ptype &=~ PTF_IMM;
} else p->Pop = P_TDO+POF_ISSKIP+POS_SKPA;
return 1;
case P_XOR:
if (p->Ptype & PTF_IMM) {
p->Pop = P_TRC+POF_ISSKIP+POS_SKPA;
p->Ptype &=~ PTF_IMM;
} else p->Pop = P_TDC+POF_ISSKIP+POS_SKPA;
return 1;
case P_SETZ:
if ((p->Ptype &~ PTF_SKIPPED) != PTA_ONEREG) break;
p->Pop = P_TDZ+POF_ISSKIP+POS_SKPA;
p->Ptype ^= (PTA_ONEREG ^ PTA_REGIS);
p->Pr2 = p->Preg;
return 1;
case P_SETO: case P_MOVN: case P_MOVE:
if (!unsetz (p) || p->Ptype == PTV_IINDEXED) break; /* no XP_SKIPAI */
p->Pop = P_SKIP+POF_ISSKIP+POS_SKPA;
if ((p->Ptype &~ PTF_SKIPPED) == PTA_REGIS && (q = before (p)) != NULL &&
q->Preg == p->Pr2 && !prevskips (q)) switch (q->Pop & POF_OPCODE) {
case P_SKIP: case P_AOS: case P_SOS:
/*
** fold: P_SKIPx S,x
** P_SKIPA R,S
**
** into: P_SKIPx R,x
*/
q->Pop = revop (q->Pop); /* invert skip */
q->Preg = p->Preg; /* set reg */
dropinstr(p); /* drop extra skip, fix up previous */
}
return 1;
}
return 0;
}
/* UNSKIP(p) - Turn skip back into non-skip
** Undoes the actions of newskip(), and turns off conditional skips.
**
** Safe to be called on non-skip ops like P_JRST and P_POPJ.
*/
void
unskip (p)
PCODE *p;
{
if (!isskip (p->Pop)) return; /* be safe for P_JUMPx */
switch (p->Pop &= POF_OPCODE) {
case P_SOS:
if ((p->Ptype &~ PTF_SKIPPED) != PTA_REGIS || p->Pr2 != p->Preg) return;
p->Pop = P_SUB; /* P_SOSA R,R */
p->Ptype ^= (PTA_REGIS ^ PTV_IMMED); /* becomes P_SUBI R,1 */
p->Pvalue = 1;
return;
case P_AOS:
if ((p->Ptype &~ PTF_SKIPPED) != PTA_REGIS || p->Pr2 != p->Preg) return;
p->Pop = P_ADD; /* P_AOSA R,R */
p->Ptype ^= (PTA_REGIS ^ PTV_IMMED); /* becomes P_ADDI R,1 */
p->Pvalue = 1;
return;
case P_TRO:
p->Ptype |= PTF_IMM;
case P_TDO:
p->Pop = P_IOR;
return;
case P_TRC:
p->Ptype |= PTF_IMM;
case P_TDC:
p->Pop = P_XOR;
return;
case P_TDZ:
if ((p->Ptype &~ PTF_SKIPPED) != PTA_REGIS || p->Pr2 != p->Preg) return;
p->Pop = P_SETZ; /* P_TDZA R,R */
p->Ptype ^= (PTA_REGIS ^ PTA_ONEREG); /* becomes P_SETZ R, */
return;
case P_SKIP:
p->Pop = P_MOVE;
if ((p->Ptype &~ PTF_SKIPPED) != PTV_IMMED || p->Pvalue != -1) return;
p->Pop = P_SETO;
p->Ptype ^= (PTV_IMMED ^ PTA_ONEREG);
return;
case P_TRN: case P_TDN: case P_TLN: case P_CAI: case P_CAM: /* no-ops */
dropinstr(p); /* flush it all the way, fix up previous */
unskip(before(p)); /* make sure no spurious skippage */
}
/* default is safe, just op with no skip part */
}
/* OPTLAB(label) - Optimize code in front of label
**
** If we know the label is coming after the next instruction, we can
** make several changes, mostly turning jumps into skips, that improve
** code and may make it possible to avoid emitting the label.
*/
void
optlab(label lab)
{
PCODE *p, *q, *b, *bb;
/* Fold useless jumps and preceeding skips into nothing */
if ((previous->Pop == P_JRST || (previous->Pop & POF_OPCODE) == P_JUMP) &&
previous->Pptr == lab && !(previous->Ptype & PTF_IND)) {
dropjump(previous); /* drop the jump or skip */
unskip(previous); /* disable the skip before it */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -