From 343aacab2c691f5ba558d43ffdd43df954173604 Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Mon, 25 Feb 2008 23:56:54 +0000
Subject: [PATCH] Emit more dead EFLAGS annotations from functions with global
 EFLAGS uses.

---
 SMPBasicBlock.cpp | 36 +++++++++++++++++++++++++++++++++---
 SMPBasicBlock.h   |  7 +++++++
 SMPInstr.cpp      |  4 ++++
 SMPInstr.h        |  4 ++++
 4 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/SMPBasicBlock.cpp b/SMPBasicBlock.cpp
index 9191aa31..11edc491 100644
--- a/SMPBasicBlock.cpp
+++ b/SMPBasicBlock.cpp
@@ -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);
diff --git a/SMPBasicBlock.h b/SMPBasicBlock.h
index e6ee3d01..2326643d 100644
--- a/SMPBasicBlock.h
+++ b/SMPBasicBlock.h
@@ -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
diff --git a/SMPInstr.cpp b/SMPInstr.cpp
index 0140d728..277280fa 100644
--- a/SMPInstr.cpp
+++ b/SMPInstr.cpp
@@ -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
diff --git a/SMPInstr.h b/SMPInstr.h
index 952a4a7e..4a639dec 100644
--- a/SMPInstr.h
+++ b/SMPInstr.h
@@ -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
-- 
GitLab