📄 ccjskp.c
字号:
}
p = before(previous);
if (p != NULL && oneinstr(previous) && p->Pop == P_CAI+POF_ISSKIP+POS_SKPE &&
p->Ptype == PTA_RCONST && (q = before(p)) != NULL && q->Pop == P_JRST &&
q->Pptr == lab && (b = before(q)) != NULL && !prevskips (b))
switch(b->Pop) {
/*
** fold: CAIN R,x
** JRST lab
** CAIE R,x+1
** instr
** lab:
**
** into: CAIL R,x
** CAILE R,x+1
** instr
** lab:
*/
case P_AOS+POF_ISSKIP+POS_SKPN:
if (p->Pvalue == 1) {
b->Pop = P_AOS+POF_ISSKIP+POS_SKPL;
dropjump(q);
p->Pop = P_CAI+POF_ISSKIP+POS_SKPLE;
setskip(p);
}
break;
case P_SKIP+POF_ISSKIP+POS_SKPN:
if (p->Pvalue == 1) {
b->Pop = P_SKIP+POF_ISSKIP+POS_SKPL;
dropjump(q);
p->Pop = P_CAI+POF_ISSKIP+POS_SKPLE;
setskip(p);
}
break;
case P_SOS+POF_ISSKIP+POS_SKPN:
if (p->Pvalue == 1) {
b->Pop = P_SOS+POF_ISSKIP+POS_SKPL;
dropjump(q);
p->Pop = P_CAI+POF_ISSKIP+POS_SKPLE;
setskip(p);
}
break;
case P_CAI+POF_ISSKIP+POS_SKPN:
if (b->Ptype != PTA_RCONST) break;
if (b->Pvalue + 1 == p->Pvalue) {
b->Pop = P_CAI+POF_ISSKIP+POS_SKPL;
dropjump(q);
p->Pop = P_CAI+POF_ISSKIP+POS_SKPLE;
setskip(p);
} else if (b->Pvalue == p->Pvalue + 1) {
b->Pop = P_CAI+POF_ISSKIP+POS_SKPL;
b->Pvalue--; /* note foldskip unsafe here! */
dropjump(q); /* might be in a recursive casejump */
setskip(p);
p->Pop = P_CAI+POF_ISSKIP+POS_SKPLE;
p->Pvalue++;
}
} /* end switch(b->Pop) */
foldjump(previous, lab); /* common optimizations with JRST */
if (!oneinstr (previous) || (p = before (previous)) == NULL) return;
/* fold P_JUMPx R,lab / instr / lab:: into P_CAIx R,0 / instr */
if (p->Pptr == lab) {
jumptoskip(p); /* make into skip */
if (isskip(p->Pop)) setskip(previous); /* set instr skipped */
crossjump(previous, lab); /* now retry pulling JUMPx across */
p = before(previous); /* fix up again */
}
/*
** Remaining optimizations work for jumps over two instructions.
** If we don't have that, give up. If (q->Pptr == lab) then q is
** a jump instruction.
*/
if ((q = before (p)) == NULL || (q->Ptype & PTF_ADRMODE) != PTA_MINDEXED
#if SYS_CSI /* Reg linkage */
|| Register_Preserve(p->Preg) /* avoid faulty optimizations */
#endif
|| q->Pptr != lab) return; /* make sure some jump to lab */
/*
** fold: P_JUMPx R,$n
** P_MOVE S,R
** op
** $n::
**
** into: P_SKIPx S,R
** op
*/
if (p->Pop == P_MOVE && p->Ptype == PTA_REGIS && q->Preg == p->Pr2 &&
!prevskips (q)) switch (q->Pop & POF_OPCODE) {
case P_JUMP:
p->Pop = q->Pop ^ (P_JUMP ^ P_SKIP ^ POF_ISSKIP);
dropjump (q);
setskip(previous);
optlab(lab); /* try again */
return; /* tail recursively */
case P_AOJ:
p->Pop = q->Pop ^ (P_AOJ ^ P_AOS ^ POF_ISSKIP);
dropjump (q);
setskip(previous);
optlab(lab); /* try again */
return; /* tail recursively */
case P_SOJ:
p->Pop = q->Pop ^ (P_SOJ ^ P_SOS ^ POF_ISSKIP);
dropjump (q);
setskip(previous);
optlab(lab); /* try again */
return; /* tail recursively */
}
/* A couple of these deal with skipping over P_MOVEMs */
if (previous->Pop == P_MOVEM && p->Pop == P_MOVE && p->Preg == previous->Preg)
{
if (p->Ptype == PTV_IMMED && p->Pvalue == 1 && q->Pop== P_SOJ+POS_SKPN
#if SYS_CSI /* Reg linkage */
&& (Register_Nopreserve (p->Preg)) /*avoid faulty optimizations */
#endif
&& !prevskips (q) && changereg (p->Preg, q->Preg, before (q))) {
/*
** fold: P_SOJN R,$x
** P_MOVEI S,1
** P_MOVEM S,y
** $x::
**
** into: P_CAIN R,1
** P_MOVEM R,y
*/
dropjump (q); /* flush P_SOJN */
p->Pop = P_CAI+POF_ISSKIP+POS_SKPN; /* make skip comparison */
p->Ptype = PTA_RCONST; /* immediate built in to P_CAI */
p->Pvalue = 1; /* against one */
setskip(previous); /* movem is now skipped over */
optlab(lab); /* try again */
return; /* tail recursively */
}
/*
** fold: P_MOVEM R,x
** P_JUMPy S,lab
** P_MOVE T,w
** P_MOVEM T,x
**
** into: P_CAIy S,0
** P_MOVE R,y
** P_MOVEM R,x
*/
/*
* Starting at q (third instruction before label), scan backwards
* for a MOVEM. If we find one BEFORE (not at) q, check it for
* two criteria.
*/
for (b = q; b != NULL; b = before (b))
if (b->Pop == P_MOVEM) { /* Find MOVEM if any */
if (prevskips(b)) b = NULL; /*Forget it if it's skipped */
#if SYS_CSI /* Reg linkage */
if (Register_Preserve (b->Preg))
b = NULL; /* avoid faulty opts */
#endif
break;
}
/*
* Starting after the MOVEM we just found, scan forward checking
* for criteria to proceed. Some opcodes are OK regardless, some
* must be checked to ensure that they don't touch our register,
* and all others are right out.
*/
for (bb = after(b); b != NULL && bb != NULL && bb != p; bb = after(bb))
switch (bb->Pop & POF_OPCODE) {
case P_MOVE: case P_ADD: case P_AOJ: case P_SOJ: case P_SKIP:
case P_SETZ: case P_SETO: case P_IOR: case P_LDB:
if (bb->Preg == b->Preg)
b = NULL; /* unsafe rchange, flush */
case P_TLN: case P_TDN: case P_TRN:
case P_CAI: case P_CAM:
#if !SYS_CSI
/*
* FEW, 2A(37) 22-Jul-92 It seems wrong to include these
* two instruction types in the "good" class, because they
* may jump off anywhere, to code that expects the MOVEM
* to have been done. Ruling out these two instructon types
* resolves SPR 9574.
*/
case P_JUMP:
case P_JRST:
#endif
continue; /* safe or not, try again or break */
default: b = NULL; /* not one we know */
}
if (b != NULL && sameaddr(b, previous, 0)) {
jumptoskip (q); /* turn jump into skip */
p->Preg = previous->Preg = b->Preg; /* set registers */
setskip(p); /* P_MOVE is now skipped over */
b->Pop = P_NOP; /* drop first P_MOVEM */
if (q->Pop == P_TRN+POF_ISSKIP+POS_SKPA && invskip (before (q)))
q->Pop = P_NOP; /* fold P_TRNA into previous */
else foldskip(q, 0); /* else safely fold ex-P_JUMP */
return;
}
} /* end if P_MOVE and P_MOVEM */
/*
** fold: (skips)
** P_JRST lab
** P_MOVE R,y
** instr
**
** into: (inverse skips)
** P_SKIPA R,y
** P_TRNA
** instr
*/
#if SYS_CSI /* Reg linkage */
if (Register_Preserve (p->Preg)) /* avoid faulty opts */
return;
#endif
if (q->Pop != P_JRST || !newskip (p)) return;
if (!invskip (before (q))) {
unskip (p); /* can't flip, undo changes */
return; /* and give up */
}
reflabel (lab, -1); /* drop jump */
setskip(p); /* p skipped */
q->Pop = P_TRN+POF_ISSKIP+POS_SKPA; /* make P_TRNA */
q->Ptype = PTA_ONEREG; /* no mem ref */
setskip(q); /* q skipped */
swappseudo (p, q); /* swap P_TRNA and new P_SKIPA */
setskip(previous); /* previous skipped */
if (!invskip (q)) return; /* rest depends on flipping P_SKIPA */
p->Pop = P_NOP; /* if can flip, no P_TRNA */
/*
** fold: P_SKIPA R,x
** P_TDOA R,$BYTE
** P_IOR R,$BYTE
**
** into: P_MOVE R,x
** P_IOR R,$BYTE
*/
if (previous->Pop != P_IOR || (q = before (previous)) == NULL ||
q->Pop != P_TDO+POF_ISSKIP+POS_SKPA || !sameaddr(q, previous, 0)) return;
unskip(before(q)); /* turn prev skip off */
q->Pop = P_NOP; /* drop P_TDOA */
clrskip(previous); /* P_IOR not skipped over anymore */
}
/* UNJUMP(label) - Get rid of jump so can replace it with jumped-to label
**
** Only called once by CCGEN2's glogical().
**
** Called when we know there will only be one more instruction between
** here and the label, but we can't rely on later optimization because
** we want to emit another label here.
**
** Returns 1 or 0 depending on whether made successful skip.
** In neither case changes PTF_SKIPPED attribute of succeeding instrs.
*/
int
unjump(label lab)
{
if (previous == NULL || previous->Pptr != lab) return 0;
switch (previous->Pop & POF_OPCODE) {
case P_JRST:
dropjump(previous); /* drop it all the way out */
return 1;
case P_JUMP: case P_AOJ: case P_SOJ:
jumptoskip(previous); /* make into P_CAIx */
previous->Pop = revop(previous->Pop); /* with opposite parity */
return 1; /* let optlab() take care of rest */
default:
return 0;
}
}
/* FOLDTRNA(p) - Attempt to get rid of a P_TRNA.
**
** Folds it into instructions ahead of it in the buffer.
** This is called late, by realcode(), to avoid confusion
** in earlier parts of the peepholer.
*/
int
foldtrna(PCODE *p)
{
PCODE *q, *a;
if (p == NULL
|| p->Pop != P_TRN+POF_ISSKIP+POS_SKPA
|| (q = after(p)) == NULL
|| (q->Pop != P_JRST
&& q->Pop != P_POPJ
&& (q->Pop & POF_OPSKIP) != POS_SKPA)
|| (a = after(q)) == NULL
|| !newskip(a))
return 0; /* no good */
/*
** fold: TRNA
** JRST $x
** MOVE R,y
**
** into: SKIPA R,y
** JRST $x
*/
unskip(q); /* turn SKIPA over op into MOVE */
setskip(a); /* op that skipped TRNA now skips it */
swappseudo(q, a); /* switch the jump and new skip */
p->Pop = P_NOP; /* TRNA disappears */
return 1; /* tell realcode() we won */
}
/* INSKIP(p) - Fold test type instruction into previous P_SKIPA+P_MOVE
*/
void
inskip (PCODE *p)
{
PCODE *q, *b;
int skop, compl;
if (p->Ptype != PTA_REGIS) return; /* must be unskipped register op */
switch (p->Pop) { /* see what we want to fold back up */
case P_AND: skop = P_TDZ; compl = 1; break; /* SKIPA+MOVE+AND => TDZA+AND */
case P_IOR: skop = P_TDO; compl = 0; break; /* SKIPA+MOVE+IOR => TDOA+IOR */
case P_XOR: skop = P_TDC; compl = 0; break; /* SKIPA+MOVE+XOR => TDCA+XOR */
default: break; /* can't handle anything else */
}
/* look for P_SKIPA and P_MOVE (with right registers) before op */
/* we save the unsetz for last because it has side effects */
if ((q = before (p)) == NULL || (q->Preg != p->Pr2 && q->Preg != p->Preg)
|| (b = before (q)) == NULL || b->Pop != P_SKIP+POF_ISSKIP+POS_SKPA ||
(compl && b->Ptype != PTV_IMMED+PTF_SKIPPED) || b->Preg != q->Preg ||
!unsetz (q)) return;
/* found them, perform the fold */
b->Pop = skop + POF_ISSKIP + POS_SKPA; /* make always skipping op for P_SKIPA */
if (b->Ptype & PTF_IMM) { /* if immediate quantity */
b->Ptype &=~ PTF_IMM; /* make PTA_RCONST rather than PTV_IMMED */
b->Pop = immedop (b->Pop); /* and use built-in-immed op */
}
if (compl) b->Pvalue = ~ b->Pvalue; /* complement mask if P_TDZA for P_AND */
q->Pop = p->Pop; /* and non-skip for P_MOVE (no compl) */
/* see if result is already in right reg; if not, put it there */
if (q->Preg == p->Pr2 || changereg (p->Preg, p->Pr2, before (b))) {
b->Preg = q->Preg = p->Preg; /* ok or fixed, change regs */
dropinstr(p); /* drop now useless op */
} else {
b->Preg = q->Preg = (char) (p->Pr2); /* pre-op val in wrong reg, fix ops */ // FW KCC-NT
p->Pop = P_MOVE; /* add P_MOVE to put in right place */
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -