From 2db04f4efc7f0866906015d08b70855687878b7a Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Sat, 17 May 2008 03:12:12 +0000
Subject: [PATCH] Treat xor reg,reg as mov reg,0.

---
 SMPInstr.cpp | 61 ++++++++++++++++++++++++++++++++++++++++------------
 SMPInstr.h   |  7 ++++--
 2 files changed, 52 insertions(+), 16 deletions(-)

diff --git a/SMPInstr.cpp b/SMPInstr.cpp
index 6085406d..64bed3c2 100644
--- a/SMPInstr.cpp
+++ b/SMPInstr.cpp
@@ -198,6 +198,7 @@ SMPInstr::SMPInstr(ea_t addr) {
 	this->BlockTerm = false;
 	this->TailCall = false;
 	this->Interrupt = false;
+	this->RegClearIdiom = false;
 	this->DeadRegsString[0] = '\0';
 	this->DefsFlags = false;
 	this->UsesFlags = false;
@@ -710,6 +711,16 @@ void SMPInstr::Analyze(void) {
 
 	this->Interrupt = ((NN_int == cmd.itype) || (NN_into == cmd.itype) || (NN_int3 == cmd.itype));
 
+	// See if instruction is an ASM idiom for clearing a register.
+	if (NN_xor == this->SMPcmd.itype) {
+		ushort FirstReg;
+		if (o_reg == this->SMPcmd.Operands[0].type) {
+			FirstReg = this->SMPcmd.Operands[0].reg;
+			if (this->SMPcmd.Operands[1].is_reg(FirstReg))
+				this->RegClearIdiom = true;
+		}
+	}
+
 	// Build the DEF and USE lists for the instruction.
 	this->BuildSMPDefUseLists();
 	// Fix up machine dependent quirks in the def and use lists.
@@ -781,6 +792,19 @@ void SMPInstr::BuildSMPDefUseLists(void) {
 		}
 	} // end for (OpNum = 0; ...)
 
+	if (this->RegClearIdiom) {
+		// Something like xor eax,eax clears eax but does not really
+		//  use eax. It is the same as mov eax,0 and we don't want to
+		//  extend the prior def-use chain for eax to this instruction
+		//  by treating the instruction as xor eax,eax. Instead, we
+		//  build the DEF and USE lists and RTL as if it were mov eax,0.
+		op_t ImmOp;
+		ImmOp.type = o_imm;
+		ImmOp.value = 0;
+		this->Uses.SetRef(ImmOp, NUMERIC);
+		return;
+	}
+
 	// Now, do the Uses. Uses have special case operations, because
 	//  any memory operand could have register uses in the addressing
 	//  expression, and we must create Uses for those registers. For
@@ -816,7 +840,7 @@ void SMPInstr::BuildSMPDefUseLists(void) {
 } // end of SMPInstr::BuildSMPDefUseLists()
 
 // If DefReg is not already in the DEF list, add a DEF for it.
-void SMPInstr::MDAddRegDef(ushort DefReg, bool Shown) {
+void SMPInstr::MDAddRegDef(ushort DefReg, bool Shown, SMPOperandType Type) {
 	op_t TempDef;
 	TempDef.type = o_reg;
 	TempDef.reg = DefReg;
@@ -824,12 +848,12 @@ void SMPInstr::MDAddRegDef(ushort DefReg, bool Shown) {
 		TempDef.set_showed();
 	else
 		TempDef.clr_showed();
-	this->Defs.SetRef(TempDef);
+	this->Defs.SetRef(TempDef, Type);
 	return;
 } // end of SMPInstr::MDAddRegDef()
 
 // If UseReg is not already in the USE list, add a USE for it.
-void SMPInstr::MDAddRegUse(ushort UseReg, bool Shown) {
+void SMPInstr::MDAddRegUse(ushort UseReg, bool Shown, SMPOperandType Type) {
 	op_t TempUse;
 	TempUse.type = o_reg;
 	TempUse.reg = UseReg;
@@ -837,7 +861,7 @@ void SMPInstr::MDAddRegUse(ushort UseReg, bool Shown) {
 		TempUse.set_showed();
 	else
 		TempUse.clr_showed();
-	this->Uses.SetRef(TempUse);
+	this->Uses.SetRef(TempUse, Type);
 	return;
 } // end of SMPInstr::MDAddRegUse()
 
@@ -948,8 +972,8 @@ void SMPInstr::MDFixupDefUseLists(void) {
 		BaseOpnd.reg = R_cx;
 		BaseOpnd.hasSIB = 0;
 		BaseOpnd.clr_showed();
-		this->Defs.SetRef(BaseOpnd);
-		this->Uses.SetRef(BaseOpnd);
+		this->Defs.SetRef(BaseOpnd, NUMERIC);
+		this->Uses.SetRef(BaseOpnd, NUMERIC);
 	}
 	if ((this->SMPcmd.itype == NN_cmps) || (this->SMPcmd.itype == NN_scas)
 		|| (this->SMPcmd.itype == NN_movs) || (this->SMPcmd.itype == NN_stos)) {
@@ -961,12 +985,12 @@ void SMPInstr::MDFixupDefUseLists(void) {
 		BaseOpnd.clr_showed();
 		if ((this->SMPcmd.itype == NN_cmps) || (this->SMPcmd.itype == NN_movs)) {
 			BaseOpnd.reg = R_si;
-			this->Defs.SetRef(BaseOpnd);
-			this->Uses.SetRef(BaseOpnd);
+			this->Defs.SetRef(BaseOpnd, POINTER);
+			this->Uses.SetRef(BaseOpnd, POINTER);
 		}
 		BaseOpnd.reg = R_di;
-		this->Defs.SetRef(BaseOpnd);
-		this->Uses.SetRef(BaseOpnd);
+		this->Defs.SetRef(BaseOpnd, POINTER);
+		this->Uses.SetRef(BaseOpnd, POINTER);
 	}
 
 	// Now, handle special instruction categories that have implicit operands.
@@ -1017,7 +1041,7 @@ void SMPInstr::MDFixupDefUseLists(void) {
 		this->MDAddRegUse(R_bp, false);
 	}
 	else if (this->SMPcmd.itype == NN_maskmovq) {
-		this->MDAddRegUse(R_di, false);
+		this->MDAddRegUse(R_di, false, POINTER);
 	}
 	else if (8 == this->GetOptType()) {
 		// This category implicitly writes to EDX:EAX.
@@ -2753,9 +2777,18 @@ bool SMPInstr::BuildBinaryRTL(SMPoperator BinaryOp) {
 					TempRT = new SMPRegTransfer;
 					TempRT->SetLeftOperand(TempOp);
 					TempRT->SetOperator(SMP_ASSIGN);
-					RightRT->SetLeftOperand(TempOp);
-					RightRT->SetOperator(BinaryOp);
-					TempRT->SetRightTree(RightRT);
+					if (this->RegClearIdiom) {
+						op_t ImmOp;
+						ImmOp.type = o_imm;
+						ImmOp.value = 0;
+						TempRT->SetRightOperand(ImmOp);
+						SourceFound = true; // cause loop exit
+					}
+					else {
+						RightRT->SetLeftOperand(TempOp);
+						RightRT->SetOperator(BinaryOp);
+						TempRT->SetRightTree(RightRT);
+					}
 				}
 				else {
 					;
diff --git a/SMPInstr.h b/SMPInstr.h
index ab661a2f..63e213ba 100644
--- a/SMPInstr.h
+++ b/SMPInstr.h
@@ -250,6 +250,7 @@ private:
 	bool TailCall;  // This instruction is a tail call (jump to far chunk with stack restored).
 	bool CondTailCall;  // Tail call is conditional branch.
 	bool Interrupt;  // Instruction is a software interrupt call.
+	bool RegClearIdiom; // ASM idiom for move zero into register?
 	char DeadRegsString[MAXSTR]; // Registers that are dead at this instruction
 	bool DefsFlags;  // Instr DEFs the flags
 	bool UsesFlags;  // Instr USEs the flags
@@ -264,8 +265,10 @@ private:
 	bool AllDefsNumeric(void);  // true if all DEFs are NUMERIC or CODEPTR
 	void BuildSMPDefUseLists(void); // Build DEF and USE lists for instruction
 	void MDFixupDefUseLists(void); // Machine-dependent ad hoc fixes
-	void MDAddRegDef(ushort, bool); // Add DEF of register if not already a DEF
-	void MDAddRegUse(ushort, bool); // Add USE of register if not already a USE
+	void MDAddRegDef(ushort DefReg, bool Shown, SMPOperandType Type = UNINIT);
+		// Add DEF of register if not already a DEF
+	void MDAddRegUse(ushort UseReg, bool Shown, SMPOperandType Type = UNINIT);
+		// Add USE of register if not already a USE
 	void MDAnnotateSIBStackConstants(FILE *, op_t, ea_t, bool); // Handle x86 opcode SIB byte
 	bool MDFindPointerUse(op_t MemOp, bool UseFP); // Set base reg to POINTER
 	op_t MDGetMemUseOp(void);
-- 
GitLab