Skip to content
Snippets Groups Projects
Commit 343aacab authored by clc5q's avatar clc5q
Browse files

Emit more dead EFLAGS annotations from functions with global EFLAGS uses.

parent feff40a5
No related branches found
No related tags found
No related merge requests found
......@@ -46,9 +46,17 @@ SMPBasicBlock::SMPBasicBlock(SMPFunction *Func, list<SMPInstr>::iterator First,
this->BlockNum = SMP_BLOCKNUM_UNINIT;
this->FirstAddr = First->GetAddr();
this->MyFunc = Func;
this->FirstFlagsDef = Last->GetAddr() + 1;
this->LastFlagsUse = First->GetAddr() - 1;
this->FlagsDeadAfterLastUse = false;
this->FlagsDeadBeforeFirstKill = false;
list<SMPInstr>::iterator CurrInst = First;
while (CurrInst != Last) {
this->Instrs.push_back(CurrInst);
if (CurrInst->HasFlagsDef() && (CurrInst->GetAddr() < this->FirstFlagsDef))
this->FirstFlagsDef = CurrInst->GetAddr();
if (CurrInst->HasFlagsUse() && (CurrInst->GetAddr() > this->LastFlagsUse))
this->LastFlagsUse = CurrInst->GetAddr();
++CurrInst;
}
Last->SetTerminatesBlock();
......@@ -568,6 +576,17 @@ bool SMPBasicBlock::IsRegDead(ea_t InstAddr, unsigned int RegIndex) const {
return true; // no DEF-USE chains overlapped the instrumentation point
} // end of SMPBasicBlock::IsRegDead()
// For functions in which the flags register is a global name, determine whether the flags
// are dead at the instruction located at addr. Do not call this function unless the
// FlagOp is a global name.
bool SMPBasicBlock::AreGlobalFlagsDead(ea_t addr, op_t FlagOp) {
if (this->FlagsDeadAfterLastUse && (addr > this->LastFlagsUse))
return true;
if (this->FlagsDeadBeforeFirstKill && (addr <= this->FirstFlagsDef))
return true;
return false;
} // end of SMPBasicBlock::AreGlobalFlagsDead()
// Mark the registers that are dead for each instruction in the block.
void SMPBasicBlock::MarkDeadRegs(void) {
// **!!** We will limit ourselves to local names for now. Most of the dead register
......@@ -579,6 +598,12 @@ void SMPBasicBlock::MarkDeadRegs(void) {
FlagsOp.type = o_reg;
FlagsOp.reg = X86_FLAGS_REG;
char DeadString[MAXSTR];
bool GlobalFlags = this->MyFunc->IsGlobalName(FlagsOp);
if (GlobalFlags) {
this->FlagsDeadAfterLastUse = (this->LiveOutSet.find(FlagsOp) == this->LiveOutSet.end());
this->FlagsDeadBeforeFirstKill = ((this->UpExposedSet.find(FlagsOp) == this->UpExposedSet.end())
&& (this->KillSet.find(FlagsOp) != this->KillSet.end()));
}
for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
DeadString[0] = '\0';
// First, put EFLAGS at beginning of string if it is dead.
......@@ -590,11 +615,16 @@ void SMPBasicBlock::MarkDeadRegs(void) {
qstrncat(DeadString, " EFLAGS", sizeof(DeadString) - 1);
}
}
else if (this->MyFunc->IsGlobalName(FlagsOp)) {
;
else if (GlobalFlags) {
if (this->AreGlobalFlagsDead((*InstIter)->GetAddr(), FlagsOp)) {
qstrncat(DeadString, " EFLAGS", sizeof(DeadString) - 1);
}
else {
;
#if SMP_DEBUG_OPTIMIZATIONS
msg("Global EFLAGS in %s\n", this->MyFunc->GetFuncName());
msg("Global EFLAGS in %s\n", this->MyFunc->GetFuncName());
#endif
}
}
else { // EFLAGS are not locally used, but not global either; they are dead here
qstrncat(DeadString, " EFLAGS", sizeof(DeadString) - 1);
......
......@@ -37,6 +37,8 @@ public:
inline int GetNumber(void) const { return BlockNum; }
inline list<list<SMPInstr>::iterator>::iterator GetFirstInstr(void) { return Instrs.begin(); };
inline list<list<SMPInstr>::iterator>::iterator GetLastInstr(void) { return Instrs.end(); };
inline ea_t GetFirstFlagsDef(void) const { return FirstFlagsDef; };
inline ea_t GetLastFlagsUse(void) const { return LastFlagsUse; };
inline list<list<SMPBasicBlock>::iterator>::iterator GetFirstPred(void) {
return Predecessors.begin();
};
......@@ -115,8 +117,13 @@ private:
bool Returns; // contains a return instruction
bool SharedTailChunk; // is part of a code chunk shared among functions
bool IsLiveInStale; // Has LiveOutSet changed since LiveInSet was computed?
ea_t FirstFlagsDef; // addr of first instr that DEFs the flags
ea_t LastFlagsUse; // addr of last instr that USEs the flags
bool FlagsDeadAfterLastUse; // flags global, dead after last use in the block
bool FlagsDeadBeforeFirstKill; // flags global, dead before first DEF in block
// Methods
bool MDAlreadyKilled(op_t) const; // Was op_t killed by something already in KillSet?
bool AreGlobalFlagsDead(ea_t, op_t FlagOp); // Is the flags register FlagOp dead at ea_t?
};
#endif
......@@ -54,6 +54,8 @@ SMPInstr::SMPInstr(ea_t addr) {
this->JumpTarget = false;
this->BlockTerm = false;
this->DeadRegsString[0] = '\0';
this->DefsFlags = false;
this->UsesFlags = false;
return;
}
......@@ -631,9 +633,11 @@ void SMPInstr::MDFixupDefUseLists(void) {
}
if (SMPDefsFlags[this->SMPcmd.itype]) {
this->MDAddRegDef(X86_FLAGS_REG, false);
this->DefsFlags = true;
}
if (SMPUsesFlags[this->SMPcmd.itype]) {
this->MDAddRegUse(X86_FLAGS_REG, false);
this->UsesFlags = true;
}
#if 1
......
......@@ -58,6 +58,8 @@ public:
bool MDIsFrameAllocInstr(void) const;
bool MDIsFrameDeallocInstr(bool UseFP, asize_t LocSize) const;
bool MDUsesCalleeSavedReg(void) const;
inline bool HasFlagsDef(void) const { return DefsFlags; };
inline bool HasFlagsUse(void) const { return UsesFlags; };
// Printing methods
void PrintOperands(void) const;
char *DestString(int OptType);
......@@ -81,6 +83,8 @@ private:
bool JumpTarget; // Is Instr the target of any jumps or branches?
bool BlockTerm; // This instruction terminates a basic block.
char DeadRegsString[MAXSTR]; // Registers that are dead at this instruction
bool DefsFlags; // Instr DEFs the flags
bool UsesFlags; // Instr USEs the flags
// Methods
void BuildSMPDefUseLists(void); // Build DEF and USE lists for instruction
void MDFixupDefUseLists(void); // Machine-dependent ad hoc fixes
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment