📄 ccopt.c
字号:
}
continue;
default:
if ((q->Ptype&PTF_ADRMODE) == PTA_MINDEXED
&& q->Preg == q->Pindex)
return;
if (q->Pop != P_MOVE || p->Pindex == 0)
continue;
p->Pop = q->Pop; /* turn P_MOVE+XP_ADDI into */
q->Pop = P_ADD; /* P_MOVEI+P_ADD to save one */
swappseudo(p, q); /* instruction... */
p = q; /* look at correct one next loop */
}
continue; /* fall through goes back */
case PTA_REGIS:
if (q->Ptype == PTV_IINDEXED && q->Pindex == 0)
{
/*
** fold: P_MOVEI R,x
** P_ADD R,S
**
** into: P_MOVEI R,x(S)
*/
q->Pindex = p->Pr2; /* new index */
foldidx(q); /* Attempt to optimize index reg */
dropinstr(p); /* drop now useless move */
return; /* not likely any more to do */
}
if ((q->Ptype & PTF_ADRMODE) == PTA_MINDEXED
&& q->Pindex == r)
{
if (!(q->Ptype & PTF_IMM) || q->Pop != P_MOVE)
break;
/*
** fold: P_MOVEI R,x(R)
** P_ADD R,S
**
** into: P_ADD R,S
** P_MOVEI R,x(R)
**
** (avoid silly checks and opcode switches below
*/
}
else if (q->Ptype == PTA_REGIS && q->Pop == P_MOVE)
{
/*
** fold: P_MOVE R,S
** P_ADD R,T
**
** into: P_ADD S,T
** P_MOVE R,S
*/
if (q->Pr2 == R_SP)
return; /* don't break stack */
p->Preg = (char) (q->Pr2); /* set register */ // FW KCC-NT
}
else
{
/*
** fold: P_MOVE R,x
** P_ADD R,S
**
** into: P_MOVE R,S
** P_ADD R,x
*/
if ((q->Ptype&PTF_ADRMODE) == PTA_MINDEXED
&& q->Preg == q->Pindex)
return;
p->Pop = q->Pop; /* set opcode */
q->Pop = P_ADD; /* to swap them */
}
swappseudo(p,q); /* opcodes hacked, swap ops */
foldplus (q); /* try again lower down */
if (p->Ptype == PTA_REGIS)
return; /* avoid infinite loop */
q = p; /* start after the swap */
continue; /* try loop again */
default:
switch (q->Ptype)
{
case PTV_IINDEXED:
if (q->Pindex != 0)
continue; /* bad swap */
case PTV_IMMED: /* swap order of immed and */
p->Pop = q->Pop; /* memory P_MOVE/P_ADD so that */
q->Pop = P_ADD; /* P_ADDI can be optimized */
swappseudo(p, q); /* even further. */
break; /* not likely to find any more */
case PTA_REGIS:
if (q->Pop == P_MOVE)
{
/*
** fold: P_MOVE R,S
** P_ADDI R,x
**
** into: P_ADDI S,x
** P_MOVE R,S
*/
swappseudo(p, q); /* swap the ops */
r = q->Preg = (char) (p->Pr2); /* fix reg in P_ADDI */ // FW KCC-NT
p = q; /* move back over it */
} /* end PTA_REGIS: if (q->Pop==P_MOVE) */
default:
if (q->Pop == P_ADD)
continue;
} /* end default: switch(q->Ptype) */
} /* end switch(p->Ptype) */
} /* end switch(p->Pop) */
break; /* default: dont keep looping */
} /* end while(q->Preg == p->Preg) */
switch (p->Ptype &~ (PTF_IND + PTF_SKIPPED))
{
case PTV_IMMED:
/*
** fold: P_ADDI R,[-n]
** into: P_SUBI R,n
*/
if (p->Pvalue < 0)
{
switch (p->Pop)
{
case P_ADD:
p->Pop = P_SUB;
break;
case P_MOVE:
p->Pop = P_MOVN;
break;
case P_SUB:
p->Pop = P_ADD;
break;
case P_MOVN:
p->Pop = P_MOVE;
break;
default:
return;
}
p->Pvalue = - p->Pvalue;
}
else if (p->Pvalue == 0)
{
switch (p->Pop)
{
case P_ADD:
case P_SUB:
dropinstr(p); /* fold: P_ADDI R,0 */
return; /* into: nothing */
case P_MOVN:
case P_MOVE:
p->Pop = P_SETZ; /* fold: P_MOVEI R,0 */
p->Ptype = PTA_ONEREG; /* into: P_SETZ R, */
return;
}
}
if (p->Pvalue == 1 && p->Pop == P_MOVN)
{
p->Pop = P_SETO; /* fold: P_MOVNI R,1 */
p->Ptype = PTA_ONEREG; /* into: P_SETO R, */
return;
}
break;
case PTV_IINDEXED:
if (p->Pop == P_ADD && p->Pindex == 0)
{
/*
** fold: P_ADDI R,addr
** into: P_MOVEI R,addr(R)
*/
p->Pop = P_MOVE; /* make P_MOVEI */
p->Pindex = p->Preg; /* with index same as reg */
if ((q = before(p)) != NULL && q->Ptype == PTA_REGIS
&& q->Pop == P_MOVE
/* !prevskips (p or q) */ && q->Preg == p->Pindex)
{
/*
** fold: P_MOVE R,S
** P_MOVEI R,addr(R)
**
** into: P_MOVEI R,addr(S)
*/
p->Pindex = q->Pr2; /* flatten index calculation */
q->Pop = P_NOP; /* flush useless P_MOVE */
}
foldidx(p); /* try to optimize index reg */
}
break;
case PTA_MINDEXED:
if (p->Pop != P_ADD+POF_BOTH || (q = before (p)) == NULL ||
prevskips (p) || prevskips (q) || q->Preg != p->Preg)
break;
if (unsetz(q))
{
if (q->Pop != P_MOVE || q->Ptype != PTV_IMMED)
{
foldplus(q); /* Restore more efficient op */
break; /* (ie undo what unsetz did) */
}
/* Previous instr should now be a P_MOVEI */
switch ((int) q->Pvalue)
{
case -1:
q->Pop = P_NOP; /* fold: P_MOVNI R,1 */
p->Pop = P_SOS; /* P_ADDB R,x */
foldinc(p); /* into: P_SOS R,x */
break;
case 0:
q->Pop = P_NOP; /* fold: P_MOVEI R,0 */
p->Pop = P_MOVE; /* P_ADDB R,x */
foldmove(p); /* into: P_MOVE R,x */
break;
case 1:
q->Pop = P_NOP; /* fold: P_MOVEI R,1 */
p->Pop = P_AOS; /* P_ADDB R,x */
foldinc(p); /* into: P_AOS R,x */
break;
default:
foldplus (q); /* put back more efficient op */
}
}
}
}
/* FINDRSET(p, r) - Find the instruction that sets R, searching backwards
** starting at P. It is OK to attempt starting at NULL; this
** facilitates constructs like findrset(before(p),r).
**
** NOTE: the instruction found may not actually SET the register
** or alter its value; it only USES it in its AC field. Thus the caller
** must apply further checks on the exact opcode.
**
** The instr is assumed to be the most recent one with the register
** field set to R, provided R is not referenced in any way by intervening
** instructions. This includes being used in an address calculation,
** or being the 2nd reg of a double-word op, or finding a PUSHJ.
** Note that the instruction found may be either a double-word or
** single-word op. Also, we don't bother checking the skipped flag while
** moving back, as whether an instr is skipped is irrelevant to whether it
** might use or set the register in question. The instr found (if any) is
** checked for this, however.
*/
PCODE *
findrset(p, reg)
PCODE *p; /* Start looking here */
int reg; /* Register to look for */
{
#if SYS_CSI /* Reg linkage */
if (Register_Preserve(reg))
return NULL; /* avoid faulty opts */
#endif
/* Loop until break out or no instrs left */
for (; p; p = before(p))
{
switch (rinreg(p, reg))
{
default: /* Unknown changes, give up */
return NULL;
case 0: /* Not used in this instr, continue loop */
break;
case 1: /* Win, found single-word op that uses it */
case 2: /* Win, found double-word op that uses it */
/* Found an op that uses this register! Done, unless this instr
** might be skipped over (in which case we can't be sure what it
** will contain and must give up).
*/
if (prevskips(p)) /* Is prev instr a skip? */
return NULL; /* Sigh */
return p; /* Won, found instr that sets reg! */
}
if (rinaddr(p, reg)) /* If reg used in address somehow, */
return NULL; /* stop looking immediately */
}
return NULL; /* No more instrs to look at */
}
/* FINDCONST(p) - Turn register to register op into register immediate.
** Looks back through peephole buffer for op setting second
** register to a constant value. If found, replaces the register reference
** with an immediate operand.
** Only called by rrpop2() in CCCODE, after instruction added to buffer.
** Does not flush the instruction, although it may modify it and may
** flush a preceding instruction.
*/
int
findconst(p)
PCODE *p;
{
PCODE *q;
int op, rused;
if (p->Ptype != PTA_REGIS)
return 0; /* Verify is reg-reg op */
rused = 0; /* Clear flag */
for (q = before (p); q != NULL; q = before (q)) /* look back in buf */
{
switch (q->Pop) /* see what op is */
{
case P_MOVE: /* Move, */
case P_CAI+POF_ISSKIP+POS_SKPE: /* or compare acting like move */
if ((q->Ptype & PTF_ADRMODE) != PTA_RCONST)
break; /* must be immediate */
case P_SETZ: /* Zero makers */
case P_JUMP+POS_SKPN:
case P_AOJ+POS_SKPN:
case P_SOJ+POS_SKPN:
case P_SKIP+POF_ISSKIP+POS_SKPE:
if (q->Preg != p->Pr2)
break; /* but not the reg we want */
if ((isskip (q->Pop) || prevskips (q)) && !dropsout (after (q)))
break; /* or skips, or skipped */
/* Won! Found constant value for this reg */
p->Ptype = PTV_IMMED; /* set immediate instruction */
if ((op = immedop (p->Pop)) != 0) /* except for P_CAM */
{
p->Pop = op; /* which becomes P_CAI */
p->Ptype = PTA_RCONST; /* with constant type */
}
p->Pvalue = (q->Ptype & PTF_ADRMODE) == PTA_RCONST
? q->Pvalue : 0; /* Set to value or zero */
if (q->Pop == P_MOVE && rused == 0) /* If simple set, and safe, */
q->Pop = P_NOP; /* Simply flush the setting instr. */
return 1; /* made const, win! */
}
/* Not found, make sure reg not munged */
if (rrchg(q, p->Pr2))
return 0; /* Fail if reg modified */
/* See if our reg is used for anything within an instruction,
** so we know whether it's OK to flush the
** instruction that sets it (if we find one)
*/
switch (p->Ptype & PTF_ADRMODE)
{
case PTA_MINDEXED: /* These two use index reg */
case PTA_BYTEPOINT:
if ((p->Pindex == q->Pindex)
|| (p->Pindex == q->Preg))
rused++;
break;
case PTA_REGIS:
if (p->Pr2 == q->Pr2)
rused++; /* Drop thru */
default:
if (p->Pr2 == q->Preg)
rused++;
}
}
return 0;
}
/* FOLDBOTH() - Make ops of type POF_BOTH.
**
** looks at the last instruction in the peephole buffer,
** and if it is a MOVEM tries to fold it into an opB.
**
** KLH: This is yet another BIG MESS that badly needs to be cleaned up
** someday!!
*/
void
foldboth()
{
PCODE *p, *b, *q;
int badidx;
int ramask_p, rrmask_p;
foldmove(previous); /* maybe it's a P_MOVE or P_LDB */
if (prevskips (previous))
return; /* skipped over, can't hack */
if (previous->Pop == P_ADD+POF_BOTH) /* try += into ++ */
foldplus (previous);
/*
** fold: P_ADJSP 17,n
** ...
** P_MOVEM R,1-n(17)
**
** into: ...
** P_PUSH 17,R
** P_ADJSP 17,n-1
*/
if ( previous->Pop == P_MOVEM
&& previous->Ptype == PTA_MINDEXED
&& previous->Pindex == R_SP) /* if P_MOVEM onto stack */
for (p = before (previous); p != NULL; p = before (p)) /* looking back */
switch (p->Pop & POF_OPCODE) /* through opcodes... */
{
case P_JRST:
case P_JUMP:
case P_AOJ:
case P_SOJ: /* control flow mungage */
case P_PUSH:
case P_POP:
case P_POPJ: /* or stack mungage */
p = NULL; /* give up */
break;
case P_ADJSP: /* the one we want */
if (prevskips (p) || previous->Poffset != 1 - p->Pvalue)
{
p = NULL; /* wrong number or skipped */
break; /* lose lose */
}
while ((q = after(p)) != previous) /* until right before it */
{
if (q->Pindex == R_SP)
switch (q->Ptype & PTF_ADRMODE)
{
case PTA_MINDEXED:
case PTA_BYTEPOINT: /* indexed types */
q->Poffset += p->Pvalue; /* adjust for hacked stack */
}
swappseudo (p, q); /* bubble P_ADJSP forward */
p = q; /* point to where it is now */
}
swappseudo (p, previous); /* now swap P_MOVEM and P_ADJSP */
p->Pop = P_PUSH; /* make P_PUSH in place of P_MOVEM */
p->Ptype = PTA_REGIS; /* this is now a register op */
p->Pr2 = p->Preg; /* with second reg old first */
p->Preg = R_SP; /* and first reg stack */
if ((-- previous->Pvalue) == 0) /* diminish P_ADJSP by one; if gone, */
dropinstr(previous); /* flush it and fix up "previous" */
if ((q = before (p)) != NULL && q->Preg == p->Pr2 && !prevskips (q))
switch (q->Pop)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -