📄 ccopt.c
字号:
p->Pop = P_MOVE; /* into P_MOVE R,x + P_IBP R */
r = p->Preg;
foldmove(p); /* optimize the P_MOVE */
/* make P_IBP without optimization */
p = newcode(PTA_REGIS, P_IBP, 0);
p->Pr2 = r;
return;
}
#endif
foldplus(n); /* all optimization failed, fix up the # */
foldmove(p); /* and try to improve the ADJBP memory reference */
}
/* OPTLSH(p) - Attempt to optimize LSH usage.
** We often get combinations of LSH and AND when dealing with
** PDP10 compability code. Someday this could be spiffed up to
** do LDBs or DPBs.
*/
void
optlsh(p)
PCODE *p;
{
PCODE *q;
unsigned long mask;
if (p->Pop == P_LSH /* Must be a LSH */
/* && !prevskips(p) */ /* that isn't skipped */
&& p->Ptype == PTA_RCONST /* and has constant operand */
&& p->Pvalue < 0 /* and is doing right shift */
&& (q = findrset(before(p), p->Preg)) != NULL) /* Find instr that sets R */
{
if (q->Pop == P_AND /* If it's AND (we know not skipped) */
&& q->Ptype == PTV_IMMED /* with immediate const operand */
&& (mask = ((unsigned INT)q->Pvalue >> (-p->Pvalue))) <= 0777777L)
{
/* Fold: into:
** AND R,[const] LSH R,-n
** ... ...
** LSH R,-n AND R,[const>>n]
** If const>>n will be small enough to fit in the RH, so we can
** generate ANDI instead of AND.
*/
swappseudo(p,q); /* Swap AND with LSH */
p->Pvalue = mask; /* Make AND's mask be shifted one */
}
}
}
/* FOLDINC(p) - Push P_AOS up into the loop it comes from.
**
** Often a for() loop will have a AOS/SOS (and possibly a test) at the bottom.
** The variable is likely to be used in the body of the loop, so for simple
** loops we can merge the AOS in with a previous P_MOVE of the same variable
** (sort of like a reverse common subexpression elimination).
**
** Fold: MOVE R,<E> to: AOS/SOS R,<E>
** ... ...
** AOS/SOS S,<E> --
**
** Intervening instructions must be checked to make sure that
** they do not modify the variable at <E> or the register R,
** and if R is used as an index reg, the offsets need to be fixed up.
** Stack level changes must be tracked so we can be sure whether an
** address reference is to <E> or not.
*/
static void
foldinc(p)
PCODE *p;
{
INT i;
int usedreg;
INT stkoff;
PCODE *q, *b;
if (prevskips(p))
return;
/* <E> must be something plausible. Initialize the used-reg mask;
** bits which are 0 are safe for use as R.
*/
switch (p->Ptype & PTF_ADRMODE)
{
#if 0 /* This isn't supported (probably never called with this anyway) */
case PTA_REGIS:
usedreg = rbits[p->Pr2];
break;
#endif
case PTA_MINDEXED:
usedreg = rbits[p->Pindex];
break;
default:
return;
}
switch (p->Pop)
{
case P_AOS:
i = -1;
break;
case P_SOS:
i = 1;
break;
default:
return;
}
stkoff = 0;
q = p;
while ((q = before(q)) != NULL)
switch (q->Pop)
{
case P_PUSH:
if (q->Preg != R_SP)
return;
++stkoff;
break;
case P_ADJSP: /* Stack adjustment */
if (p->Preg == R_SP)
stkoff += q->Pvalue;
break;
case P_MOVE:
if (sameaddr(p, q, stkoff)) /* found what we want? */
{
if (prevskips(q) || (usedreg&(rbits[q->Preg])))
return;
q->Pop = p->Pop;
b = q;
do
{
b = after(b);
if ((b->Ptype&PTF_ADRMODE) == PTA_MINDEXED
&& b->Pindex == q->Preg)
b->Poffset += i;
else if (b->Ptype == PTV_IMMED
&& b->Preg == q->Preg
&& b->Pop == P_IMUL)
i *= b->Pvalue;
}
while (b != p)
;
i = p->Preg;
dropinstr(p); /* drop extra P_AOS and fix up */
code00(P_MOVE, (int) i, q->Preg);
return;
}
if (q->Preg == p->Pindex)
return;
usedreg |= rbits[q->Preg];
continue;
/* Ops that change a register (or two) */
case P_DFAD:
case P_DFSB:
case P_DFMP:
case P_DFDV:
case P_DMOVE:
case P_DMOVN:
case P_IDIV:
case P_UIDIV:
case P_DFIX:
case P_SUBBP:
case P_MUL:
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_ADJBP:
case P_LSH:
case P_SETCM:
case P_MOVN:
case P_SETO:
case P_SETZ:
case P_HRRZ:
case P_HLRZ:
case P_FIX:
case P_FLTR:
case P_LDB:
if ((q->Ptype & PTF_ADRMODE) != PTA_MINDEXED)
{
usedreg |= rbincode(q);
continue;
}
if (q->Preg == p->Pindex || sameaddr(p, q, stkoff))
return;
usedreg |= rbinreg(q);
continue;
/* Ops that change memory */
case P_POP:
if (q->Preg != R_SP)
return;
--stkoff;
/* Fall thru since op changes mem */
case P_MOVEM:
case P_DPB:
case P_ILDB:
case P_IDPB:
case P_IBP:
case P_FADR+POF_BOTH:
case P_FSBR+POF_BOTH:
case P_FMPR+POF_BOTH:
case P_FDVR+POF_BOTH:
case P_ADD+POF_BOTH:
case P_IMUL+POF_BOTH:
case P_AND+POF_BOTH:
case P_XOR+POF_BOTH:
case P_IOR+POF_BOTH:
case P_AOS:
case P_SOS:
case P_HRRM:
case P_HRLM:
case P_MOVN+POF_BOTH:
case P_MOVE+POF_BOTH:
case P_SETZ+POF_BOTH:
case P_SETO+POF_BOTH:
case P_SETCM+POF_BOTH:
if ((q->Ptype & PTF_ADRMODE) != PTA_MINDEXED)
{
usedreg |= rbincode(q);
continue;
}
if (q->Preg == p->Pindex
|| sameaddr(p, q, stkoff) || alias (p, q, stkoff))
return;
usedreg |= rbinreg(q);
continue;
/* Some op type we don't know?
** Jumps, in particular, come here to simply return and give up the
** optimization attempt.
*/
default:
return;
}
}
/* FOLDPLUS(p) - Improve instruction used to do addition.
**
** takes an addition operation (P_ADD, P_ADDB, etc) in the peephole buffer
** and folds it in with previous instructions, as well as just improving
** it in itself.
*/
void
foldplus(p)
PCODE *p;
{
PCODE *q, *b;
int r;
#if SYS_CSI /* Reg linkage */
if (Register_Preserve (p->Pr2))
return; /* avoid faulty optimizations */
if (p->Pop == P_SUB) /* Reg linkage optimization */
if (p->Ptype == PTV_IMMED)
{
p->Pop = P_ADD; /* make P_SUBI R,i into P_ADDI R,-i */
p->Pvalue = - p->Pvalue; /* so it can be folded later */
} /* in any case treat like P_ADD here*/
#endif
if (p->Pop == P_ADD && p->Ptype == PTA_REGIS /* !prevskips */ &&
(q = before(p)) != NULL && q->Preg == p->Pr2 && !prevskips (q))
switch (q->Pop)
{
case P_SUB:
if (q->Ptype == PTV_IMMED)
{
q->Pop = P_ADD; /* make P_SUBI R,i into P_ADDI R,-i */
q->Pvalue = - q->Pvalue; /* so it can be folded later */
} /* in any case treat like P_ADD here */
case P_ADD:
/*
** fold: P_ADD S,x
** P_ADD R,S
**
** into: P_ADD R,S
** P_ADD R,x
*/
if ((q->Ptype&PTF_ADRMODE) == PTA_MINDEXED
&& q->Preg == q->Pindex)
return;
q->Preg = p->Preg; /* fix up operation */
swappseudo(p,q); /* swap the two */
foldplus(q); /* optimize earlier code some more */
q = before(p); /* pick it up again */
if (q != NULL && q->Pop == P_MOVE && q->Ptype == PTA_REGIS &&
q->Preg == p->Preg)
{
/*
** fold: P_MOVE R,S
** P_ADD R,x
**
** into: P_ADD S,x
** P_MOVE R,S
*/
p->Preg = (char) (q->Pr2); /* fix up register again */ // FW KCC-NT
swappseudo(p,q); /* switch them around again */
p = q; /* forget the move, hack the add */
}
break; /* end case P_ADD, P_SUB */
case P_AOS:
case P_SOS:
case P_MOVE:
case P_MOVN:
if (((q->Ptype & PTF_ADRMODE) == PTA_MINDEXED
&& q->Pindex == p->Preg) ||
(q->Ptype & PTF_IND) || (b = before(q)) == NULL ||
((r = rchange (b->Pop)) != PRC_RCHG && r != PRC_RSET) ||
b->Preg != p->Preg || !(b->Ptype & PTF_IMM) || prevskips (b) ||
((b->Ptype & PTF_ADRMODE) == PTA_MINDEXED && q->Preg == b->Pindex))
break;
/*
** fold: P_ADDI R,x
** P_AOS S,y
** P_ADD R,S
**
** into: P_AOS S,y
** P_ADDI R,x
** P_ADD R,S
**
** so the immediate add can propagate to the list start...
*/
swappseudo (b, q); /* thats all folks! */
} /* end switch(q->Pop) */
r = p->Preg; /* remember register */
q = p; /* start up just before op */
if (!prevskips (p))
while ((q = before(q)) != NULL
&& !prevskips (q)
&& q->Preg == r
&& p->Pop == P_ADD)
{
switch (q->Pop)
{
case P_MOVN:
case P_SUB:
case P_SETO:
case P_SETZ:
if (!unsetz (q))
break; /* turn into P_MOVE or P_ADD */
case P_MOVE:
case P_ADD:
switch (p->Ptype)
{
case PTV_IMMED:
switch (q->Ptype)
{
case PTV_IINDEXED:
case PTV_IMMED:
/*
** fold: P_MOVEI R,addr(i)
** P_ADDI R,c
**
** into: P_MOVEI R,addr+c(i)
*/
/* 8/91 ensure addr+c is a legal offset */
if((q->Poffset + p->Pvalue) < (1 << 18))
{
q->Poffset += p->Pvalue;
dropinstr(p); /* poof! */
p = q;
}
continue;
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
*/
if ((q->Ptype&PTF_ADRMODE) == PTA_MINDEXED
&& q->Preg == q->Pindex)
return;
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 */
}
default:
if (q->Pop == P_ADD)
continue;
} /* end switch(q->Ptype) */
break; /* propagate break to escape loop */
case PTV_IINDEXED:
switch (q->Ptype)
{
case PTV_IINDEXED:
if ((q->Pptr != NULL && p->Pptr != NULL) ||
(q->Pindex != 0 && p->Pindex != 0))
continue;
case PTV_IMMED:
/*
** fold: P_MOVEI R,c
** P_ADDI R,addr(i)
**
** into: P_MOVEI R,addr+c(i)
*/
/* 8/91 ensure addr+c is a legal offset */
if((p->Poffset + q->Poffset) < (1 << 18))
{
p->Pop = q->Pop;
q->Pop = P_NOP;
p->Poffset += q->Poffset;
if (q->Ptype == PTV_IINDEXED)
{
if (p->Pptr == NULL)
p->Pptr = q->Pptr;
if (p->Pindex == 0)
p->Pindex = q->Pindex;
}
}
continue;
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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -