?? optim.c
字號:
}
if (ins->Flags & (ISCALL|CHANGED)) return(0);
if (ins->DstReg == ECX || ins->DstReg == EDX)
return(0);
if (ins->SrcReg == ECX || ins->SrcReg == EDX)
return(0);
if (ins->Name[2] == 'q' && ins->Name[1] == 'd')
return(0);
if (ins->Name[0] == 'r' && ins->Name[1] == 'e' && ins->Name[2] == 'p')
return(0);
if (ins->Name[0] == 's' && ins->Name[1] == 'h' && ins->Name[3] == 'l')
return(0);
if (ins->src[0] == '%' && ins->src[1] == 'c')
return(0);
if (ins->dst[0] == '%' && (ins->Flags & ISGENERICMOVE) && ins->DstReg == aReg) {
if (ins->SrcReg != aReg)
break;
}
ins++;
idxInstruction++;
}
return(result);
}
static int TestIfReturnFalse(Instruction *nextIns,int regNum)
{
nextIns++;
if (*(unsigned long *)(nextIns->Name) == JNE_CODE) {
nextIns++;
if (nextIns->Flags & ISMOVL) {
if (nextIns->src[0] == '$' && nextIns->src[1] == '0'
&& nextIns->src[2] == 0) {
if (nextIns->dst[0] == '%' && nextIns->DstReg == regNum) {
nextIns->Flags |= DELETED;
Printf1("Optimization 12\n");
return(1);
}
}
}
}
return(0);
}
static void ChangeRedundantLoad(Instruction *ins,int regNum,BasicBlock *bb,int idxInstruction)
{
unsigned char *regname,tbuf[60];
Instruction *insDst,*nextIns;
nextIns = &InstructionTable[idxInstruction+1];
regname = RegisterNames[regNum];
if (strlen(ins->src) <4) return;
if (ins->DstReg > EBP) return;
if (*(unsigned long *)(ins->Name) != MOVL_CODE) {
/*
We can use this byte widening instructions only with memory
references. I assume that the compiler widens the arguments always
before loading a register with a 16 or 8 bit value, a safe
assumption I suppose.
*/
// strcpy(insDst->Name,"movl"); /*++++++++++++++++++*/
return;
}
insDst = GetNextChangedInstruction(ins,bb);
strcpy(insDst->Name,ins->Name);
/* Print the regname into the source of the changed instruction */
sprintf(tbuf,"%%%s",regname);
strcpy(insDst->src,tbuf);
/* The destination doesn't change */
strcpy(insDst->dst,ins->dst);
/* Update flags etc */
ins->SrcReg = regNum;
Printf1("Optimization 5\n");
}
static int ReadValue(unsigned char *src)
{
int result,r;
if (src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) {
r = sscanf(src+2,"%x",&result);
}
else {
r = sscanf(src,"%d",&result);
}
if (r) return(result);
return(0);
}
static Instruction *GetLastInstruction(int idxInstruction)
{
int li = idxInstruction;
Instruction *lastIns = NULL;
do {
li--;
lastIns = &InstructionTable[li];
} while (li >= 0 && (lastIns->Flags & DELETED));
if (li >= 0) return(lastIns);
return(NULL);
}
static int CheckValueAlreadyLoaded(unsigned char *p)
{
if (State[EAX] && !strcmp(State[EAX],p)) {
return(EAX);
}
if (State[EBX] && !strcmp(State[EBX],p)) {
return(EBX);
}
if (State[ECX] && !strcmp(State[ECX],p)) {
return(ECX);
}
if (State[EDX] && !strcmp(State[EDX],p)) {
return(EDX);
}
if (State[ESI] && !strcmp(State[ESI],p)) {
return(ESI);
}
if (State[EDI] && !strcmp(State[EDI],p)) {
return(EDI);
}
return(0);
}
void FixCalls(Instruction *ins,BasicBlock *bb,int idxInstruction)
{
int last,i,first;
ins->Flags &= ~ISCALL;
if (idxInstruction == bb->LastCall) {
if (bb->FirstCall == idxInstruction) {
bb->FirstCall = bb->LastCall = 0;
return;
}
last = bb->FirstCall;
for (i=bb->FirstCall+1;i<idxInstruction-1;i++) {
if (InstructionTable[i].Flags & ISCALL)
last = i;
}
if (last == bb->FirstCall) {
bb->FirstCall = bb->LastCall = 0;
return;
}
bb->LastCall = last;
return;
}
if (idxInstruction == bb->FirstCall) {
if (bb->LastCall == idxInstruction) {
bb->FirstCall = bb->LastCall = 0;
return;
}
first = 0;
for (i=bb->FirstCall+1;i<bb->LastCall;i++) {
if (InstructionTable[i].Flags & ISCALL) {
first = i;
break;
}
}
bb->FirstCall = first;
if (first == 0) bb->LastCall = 0;
return;
}
}
static char tbuf[70];
static unsigned char *src;
static unsigned char *dst;
static unsigned char *opcode;
static unsigned char *old,*savesrc;
static int regdst,regsrc,isImmediate;
static int aReg,isMovl,isRedundant;
static Instruction *insDst,*lastIns,*changedInstruction,*nextIns;
static Instruction *ins;
static BasicBlock *bb;
static int idxInstruction;
static int RegToRegCopy(void)
{
/* Replace
movl %eax,%edi
movl %edi,-24(%ebp)
with
movl %eax,-24(%ebp)
*/
if (nextIns->Flags & CHANGED) return 0;
if (nextIns->SrcReg == ins->DstReg) {
if (ins->DstReg != EAX &&
*(unsigned long *)(ins->Name) == MOVL_CODE &&
*(unsigned long *)(nextIns->Name) == MOVL_CODE &&
nextIns->SrcReg != nextIns->DstReg &&
nextIns->src[0] == '%') {
if (!IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
insDst = ChangeInstruction(nextIns,bb,nextIns->Name,ins->src,nextIns->dst);
nextIns->SrcReg = ins->SrcReg;
ins->Flags |= DELETED;
deleted++;
Printf1("Optimization 18\n");
// printf("1:\t%s\t%s\t%s\n2:\t%s\t%s\t%s\n3:\t%s\t%s\t%s\n",ins->Name,ins->src,ins->dst,
// nextIns->Name,nextIns->src,nextIns->dst,insDst->Name,insDst->src,insDst->dst);
State[ins->SrcReg] = nextIns->dst;
return 2;
}
}
if (!strcmp(ins->dst,nextIns->src) &&
*(unsigned long *)(nextIns->Name) == PUSH_CODE &&
!IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
ChangeInstruction(nextIns,bb,nextIns->Name,ins->src,"");
ins->Flags |= DELETED;
deleted++;
return 2;
}
}
/* Try to catch sequences like
movl %eax,%edi
cmpl $45, %edi
and replace them with
cmpl $45,%eax
*/
if ((nextIns->Flags & ISCOMPARE) &&
nextIns->src[0] == '$' && nextIns->dst[0] == '%' &&
nextIns->DstReg != EAX &&
!strcmp(nextIns->dst,ins->dst) &&
!IsAliveValue(bb,idxInstruction+2,ins->DstReg)) {
insDst = ChangeInstruction(nextIns,bb,nextIns->Name,nextIns->src,ins->src);
ins->Flags |= DELETED;
nextIns->DstReg = ins->SrcReg;
Printf1("Optimization 17\n");
deleted++;
return 2;
}
return 0;
}
static int ImproveSetEqual(int islong)
{
int wasxchg=0,condition;
Instruction *next = nextIns;
// if (recursion) return 0;
if (!strcmp(nextIns->Name,"xchgl")) {
wasxchg = 1;
next++;
}
if (next->Name[0] == 's' && next->Name[1] == 'e') {
int idx = idxInstruction+2;
Instruction *i1 = &InstructionTable[idx+wasxchg*2];
char *pdst = i1->dst;
if (i1->src[0] == '$' && i1->src[1] == '1' &&
(*(unsigned long *)(i1->Name) == ANDL_CODE)) {
if (islong)
condition = (!strstr(ins->src,pdst)) && (!strstr(ins->dst,pdst));
else {
char tmpregname[5];
tmpregname[0] = '%';
tmpregname[1] = pdst[2];
tmpregname[2] = pdst[3];
tmpregname[3] = 0;
condition = (!strstr(tmpregname,ins->src) && !strstr(tmpregname,ins->dst));
if (condition && tmpregname[2] != 'i') {
tmpregname[2] = 'l';
condition = (condition &&
(!strstr(tmpregname,ins->src) && !strstr(tmpregname,ins->dst)));
}
}
if (condition) {
Instruction *changedIns = GetNextChangedInstruction(ins,bb);
Instruction *i2 = GetNextChangedInstruction(changedIns,bb);
sprintf(i2->Name,"\t%s\t",ins->Name);
strcpy(i2->src,ins->src);
sprintf(i2->dst,",%s\n",ins->dst);
changedIns->Flags &= ~ CHANGED;
changedIns->Flags |= ADDED;
strcpy(changedIns->Name,"xorl");
strcpy(changedIns->src,pdst);
strcpy(changedIns->dst,pdst);
i1->Flags |= DELETED;
deleted++;
State[i1->DstReg] = Nullst;
// printf("cmpl %s %s -> %s\n",ins->src,ins->dst,pdst);
i1++;
if (!strcmp(i1->Name,"cmpl") && !strcmp(i1->src,"$0") &&
!strcmp(i1->dst,pdst)) {
i1->Flags |= DELETED;
deleted++;
return 4;
}
return 3;
}
}
return 0;
}
int TestIfFlagsAlreadySet(Instruction *tmpins)
{
int idx = idxInstruction;
unsigned long opcodeCode = *(unsigned long *)(tmpins->Name);
if (tmpins) {
while (idx > 0 &&
(opcodeCode == MOVL_CODE || opcodeCode == MOVW_CODE) &&
strcmp(tmpins->dst,ins->dst)) {
idx--;
tmpins--;
opcodeCode = *(unsigned long *)(tmpins->Name);
}
if ((opcodeCode == SUBL_CODE
|| opcodeCode == ADDL_CODE
|| opcodeCode == SARL_CODE
|| opcodeCode == ANDL_CODE) &&
!strcmp(tmpins->dst,ins->dst)) {
ins->Flags |= DELETED;
deleted++;
// printf("redundant compare deleted: last ins:%s\n",tmpins->Name);
return 1;
}
}
return 0;
}
#if 0
static int OptimizeImul(void)
{
char *p = strchr(ins->dst,',');
int reg1,reg2,val,val3,val5,val9,n;
char tregname[10],tbuf0[50],tbuf1[50];
Instruction *ChangedIns,*addedIns;
if (p == NULL)
return 0;
if (ins->dst[0] != '%')
return 0;
*p = 0;
strcpy(tregname,ins->dst);
*p++ = ',';
if (*p != '%')
return 0;
reg1 = GetRegNumber(tregname+1);
reg2 = GetRegNumber(p+1);
if (reg1 > EBP || reg2 > EBP)
return 0;
val = ReadValue(ins->src+1);
if (val < 0)
return 0;
if ((val % 5) != 0 && (val % 9) != 0 && (val % 3) != 0)
return 0;
if ((val % 5) == 0) {
val5 = val/5;
n = ispow2(val5);
if (n || val == 5) {
sprintf(tbuf0,"(%s,%s,4)",tregname,tregname);
ChangedIns = ChangeInstruction(ins,bb,"leal",tbuf0,p);
State[reg2] = Nullst;
if (val == 5)
return 1;
commonTail:
addedIns = GetNextChangedInstruction(ChangedIns,bb);
ChangedIns->Flags &= ~CHANGED;
ChangedIns->Flags |= ADDED;
strcpy(addedIns->Name,"\tshll\t");
sprintf(tbuf1,"$%d,",n);
strcpy(addedIns->src,tbuf1);
sprintf(addedIns->dst,"%s\n",p);
return 1;
}
}
if ((val % 9) == 0) {
val9 = val/9;
n = ispow2(val9);
if (n || val == 9) {
sprintf(tbuf0,"(%s,%s,8)",tregname,tregname);
ChangedIns = ChangeInstruction(ins,bb,"leal",tbuf0,p);
State[reg2] = Nullst;
if (val == 9)
return 1;
goto commonTail;
}
}
if ((val % 3) == 0) {
val3 = val/3;
n = ispow2(val3);
if (n || val == 3) {
sprintf(tbuf0,"(%s,%s,2)",tregname,tregname);
ChangedIns = ChangeInstruction(ins,bb,"leal",tbuf0,p);
State[reg2] = Nullst;
if (val == 3)
return 1;
goto commonTail;
}
}
return 0;
}
#endif
static int compare(void)
{
int reg;
if (ins->Flags & (CHANGED|DELETED))
return 1;
reg = ImproveSetEqual(1);
if (reg) return reg;
/*
replace
cmpl $0,reg
by
or reg,reg
*/
if (regdst && !regsrc && isImmediate && src[1] == '0' && src[2] == 0) {
if (TestIfFlagsAlreadySet(lastIns))
return 1;
sprintf(tbuf,"%%%s",dst);
ChangeInstruction(ins,bb,"or",tbuf,tbuf);
Printf1("compl->or\n");
TestIfReturnFalse(ins,ins->DstReg);
}
lastIns = GetLastInstruction(idxInstruction);
if (!regdst /*&& isImmediate*/ && ins->Name[3] == 'l') {
reg = CheckValueAlreadyLoaded(ins->dst);
if (reg) {
sprintf(tbuf,"%%%s",RegisterNames[reg]);
if (isImmediate && ins->src[1] == '0' && ins->src[2] == 0) {
ChangeInstruction(ins,bb,"orl",tbuf,tbuf);
}
else ChangeInstruction(ins,bb,ins->Name,ins->src,tbuf);
Printf1("Optimization 44\n");
return 1;
}
}
/*
Try to change a sequence of dword compares into a sequence of byte compares
*/
if (idxInstruction > 1 &&
regdst && isImmediate && ins->Name[3] == 'l' &&
(lastIns->Flags & (CHANGED|DELETED)) == 0) {
if (!strcmp(lastIns->Name,"movsbl") ||
!strcmp(lastIns->Name,"movzbl")) {
if (!strcmp(lastIns->dst,ins->dst) &&
isByteValue(ins->src)) {
Instruction *i1,*i2;
int idx,alive,changeAll,toChange,i,val;
char dstByteReg[10];
val = ReadValue(&ins->src[1]);
if (val > 127 || val < 0) return 1;
if (nextIns->Name[0] != 'j') {
ChangeInstruction(ins,bb,"cmpb",ins->src,ins->dst);
return 1;
}
if (ins->DstReg != EAX && ins->DstReg != EDX && ins->DstReg != EBX
&& ins->DstReg != ECX) return 1;
idx = idxInstruction+2;
i1 = &InstructionTable[idx];
changeAll = 1;
while (idx < bb->NrOfInstructions && (i1->Flags & ISCOMPARE)) {
if (i1->src[0] != '$') break;
if (strcmp(ins->dst,i1->dst)) break;
val = ReadValue(&i1->src[1]);
if (val > 127 || val < 0)
break;
idx++;
i1++;
if (i1->Name[0] != 'j') { changeAll = 0; break; }
idx++;
i1++;
}
alive = IsAliveValue(bb,idx,ins->DstReg);
toChange = idx - idxInstruction;
dstByteReg[0] = '%';
dstByteReg[1] = ins->dst[2];
dstByteReg[2] = 'l';
dstByteReg[3] = 0;
if (changeAll) {
if (!alive)
ChangeInstruction(lastIns,bb,"movb",lastIns->src,dstByteReg);
i2 = &InstructionTable[idxInstruction];
for (i=idxInstruction;i < idx;i+=2,i2 += 2) {
ChangeInstruction(i2,bb,"cmpb",i2->src,dstByteReg);
}
return toChange;
}
return 1;
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -