From 42f9625d0d807c04e4a3f3305a51ce6f23de9c8c Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Mon, 24 Jun 2013 22:54:07 +0000
Subject: [PATCH] Extend several idioms based on operand source to include
 stack locations in search chain.

---
 SMPBasicBlock.cpp |  16 +--
 SMPFunction.cpp   |  42 +++++++-
 SMPFunction.h     |  12 ++-
 SMPInstr.cpp      | 262 ++++++++++++++++++++++++++++++++--------------
 4 files changed, 244 insertions(+), 88 deletions(-)

diff --git a/SMPBasicBlock.cpp b/SMPBasicBlock.cpp
index ad7c8017..fd1152ef 100644
--- a/SMPBasicBlock.cpp
+++ b/SMPBasicBlock.cpp
@@ -834,7 +834,9 @@ bool SMPBasicBlock::IsOpDestTruncatedWrite(op_t DefOp, int DefSSANum, ea_t DefAd
 						LastUseIsTruncatedWrite = true;
 					}
 					else if (LastUseInst->MDIsReducedWidthMove()) {
-						LastUseIsTruncatedWrite = true;
+						// If DefOp is used as an address reg, not a truncated write of DefOp;
+						//  otherwise, it is.
+						LastUseIsTruncatedWrite = LastUseInst->IsNonAddressReg(DefOp);
 					}
 				}
 				break;
@@ -3701,6 +3703,8 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd
 	bool RegDef = (o_reg == DefOp.type);
 	struct FineGrainedInfo DefFGInfo;
 	bool LocalDefName = this->IsLocalName(DefOp);
+	bool UseFP = this->GetFunc()->UsesFramePointer();
+
 	if (RegDef) {
 		unsigned int DefHashValue = HashGlobalNameAndSSA(DefOp, DefSSANum);
 		if (LocalDefName) {
@@ -3711,7 +3715,7 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd
 			DefFGInfo = this->GetFunc()->GetDefFGInfo(DefHashValue);
 		}
 	}
-	else if (MDIsStackAccessOpnd(DefOp, this->GetFunc()->UsesFramePointer())) {
+	else if (MDIsStackAccessOpnd(DefOp, UseFP)) {
 		bool success = this->GetFunc()->MDGetFGStackLocInfo(DefAddr, DefOp, DefFGInfo);
 		assert(success);
 	}
@@ -3779,7 +3783,7 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd
 	if (!benign) {
 		SMPInstr *DefInst = this->GetFunc()->GetInstFromAddr(DefAddr);
 		int UseSSANum;
-		if (UnderflowOpcode && RegDef) {
+		if (UnderflowOpcode && MDIsDataFlowOpnd(DefOp, UseFP)) {
 			UseIter = DefInst->FindUse(DefOp); // DEF is also USE in subtraction
 			UseSSANum = UseIter->GetSSANum();
 			// Prepare for possible recursive traversals through the function blocks.
@@ -3791,7 +3795,7 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd
 				}
 				else { // For subtraction, need to see if BOTH operands came from condition codes (flags).
 					UseOp = DefInst->GetUseOnlyAddSubOp();
-					if (UseOp.type == o_reg) {
+					if (MDIsDataFlowOpnd(UseOp, UseFP)) {
 						CanonicalizeOpnd(UseOp);
 						UseIter = DefInst->FindUse(UseOp);
 						int SubtrahendSSANum = UseIter->GetSSANum();
@@ -3815,7 +3819,7 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd
 				}
 				else { // For subtraction, need to see if BOTH operands came from zero-extended moves.
 					UseOp = DefInst->GetUseOnlyAddSubOp();
-					if (UseOp.type == o_reg) {
+					if (MDIsDataFlowOpnd(UseOp, UseFP)) {
 						CanonicalizeOpnd(UseOp);
 						UseIter = DefInst->FindUse(UseOp);
 						UseSSANum = UseIter->GetSSANum();
@@ -3878,7 +3882,7 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd
 					}
 				}
 			}
-		} // end if (UnderflowOpcode && RegDef)
+		} // end if (UnderflowOpcode && MDIsDataFlowOpnd())
 		// Fourth case: lea reg, [basereg+indexreg*scalefactor+offset], where
 		//  basereg and indexreg both got their values from condition codes, so the
 		//  computational values are too small for non-benign overflow or underflow.
diff --git a/SMPFunction.cpp b/SMPFunction.cpp
index 7e180f86..02318e18 100644
--- a/SMPFunction.cpp
+++ b/SMPFunction.cpp
@@ -331,6 +331,15 @@ unsigned short SMPFunction::GetDefSignMiscInfo(int DefHashValue) {
 		return 0;
 } // end of SMPFunction::GetDefSignMiscInfo()
 
+unsigned short SMPFunction::GetStackDefSignMiscInfo(ea_t InstAddr) {
+	map<ea_t, struct FineGrainedInfo>::iterator MapIter;
+
+	MapIter = this->StackDefFGInfo.find(InstAddr);
+	assert(MapIter != this->StackDefFGInfo.end());
+
+	return MapIter->second.SignMiscInfo;
+}
+
 unsigned short SMPFunction::GetUseSignMiscInfo(int UseHashValue) {
 	map<int, struct FineGrainedInfo>::iterator MapIter;
 	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;
@@ -342,6 +351,15 @@ unsigned short SMPFunction::GetUseSignMiscInfo(int UseHashValue) {
 		return 0;
 } // end of SMPFunction::GetUseSignMiscInfo()
 
+unsigned short SMPFunction::GetStackUseSignMiscInfo(ea_t InstAddr) {
+	map<ea_t, struct FineGrainedInfo>::iterator MapIter;
+
+	MapIter = this->StackUseFGInfo.find(InstAddr);
+	assert(MapIter != this->StackUseFGInfo.end());
+
+	return MapIter->second.SignMiscInfo;
+}
+
 unsigned short SMPFunction::GetDefWidthTypeInfo(int DefHashValue) {
 	map<int, struct FineGrainedInfo>::iterator MapIter;
 	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;
@@ -524,7 +542,7 @@ op_t SMPFunction::GetNormalizedOperand(ea_t InstAddr, op_t RTLop) {
 } // end of SMPFunction::GetNormalizedOperand()
 
 
-// Six methods to set values into the maps of global reg/SSA to FG info.
+// Eight methods to set values into the maps of global reg/stack/SSA to FG info.
 //  For local names, see corresponding methods in SMPBasicBlock.
 void SMPFunction::UpdateDefSignMiscInfo(int DefHashValue, unsigned short NewInfo) {
 	map<int, struct FineGrainedInfo>::iterator MapIter;
@@ -547,6 +565,17 @@ void SMPFunction::UpdateDefSignMiscInfo(int DefHashValue, unsigned short NewInfo
 	return;
 } // end of SMPFunction::UpdateDefSignMiscInfo()
 
+void SMPFunction::UpdateStackDefSignMiscInfo(ea_t InstAddr, unsigned short NewInfo) {
+	map<ea_t, struct FineGrainedInfo>::iterator MapIter;
+
+	MapIter = this->StackDefFGInfo.find(InstAddr);
+	assert(MapIter != this->StackDefFGInfo.end());
+	// found; just OR in the new bits.
+	MapIter->second.SignMiscInfo |= NewInfo;
+
+	return;
+} // end of SMPFunction::UpdateStackDefSignMiscInfo()
+
 void SMPFunction::UpdateUseSignMiscInfo(int UseHashValue, unsigned short NewInfo) {
 	map<int, struct FineGrainedInfo>::iterator MapIter;
 	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;
@@ -568,6 +597,17 @@ void SMPFunction::UpdateUseSignMiscInfo(int UseHashValue, unsigned short NewInfo
 	return;
 } // end of SMPFunction::UpdateUseSignMiscInfo()
 
+void SMPFunction::UpdateStackUseSignMiscInfo(ea_t InstAddr, unsigned short NewInfo) {
+	map<ea_t, struct FineGrainedInfo>::iterator MapIter;
+
+	MapIter = this->StackUseFGInfo.find(InstAddr);
+	assert(MapIter != this->StackUseFGInfo.end());
+	// found; just OR in the new bits.
+	MapIter->second.SignMiscInfo |= NewInfo;
+
+	return;
+} // end of SMPFunction::UpdateStackUseSignMiscInfo()
+
 void SMPFunction::UpdateDefWidthTypeInfo(int DefHashValue, unsigned short NewInfo) {
 	map<int, struct FineGrainedInfo>::iterator MapIter;
 	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;
diff --git a/SMPFunction.h b/SMPFunction.h
index fa3fab34..9af89db5 100644
--- a/SMPFunction.h
+++ b/SMPFunction.h
@@ -163,10 +163,12 @@ public:
 	set<SMPPhiFunction, LessPhi>::iterator GetPhiIterForPhiDef(size_t BlockNumber, op_t DefOp, int SSANum);
 		// Given block # and PhiDef op_t and SSANum, return the Phi iterator or assert.
 	
-	// Six methods to get values from the maps of global reg/SSA to FG info.
+	// Eight methods to get values from the maps of global reg/SSA to FG info.
 	//  For local names, see corresponding methods in SMPBasicBlock.
 	unsigned short GetDefSignMiscInfo(int DefHashValue);
+	unsigned short GetStackDefSignMiscInfo(ea_t InstAddr);
 	unsigned short GetUseSignMiscInfo(int UseHashValue);
+	unsigned short GetStackUseSignMiscInfo(ea_t InstAddr);
 	unsigned short GetDefWidthTypeInfo(int DefHashValue);
 	unsigned short GetUseWidthTypeInfo(int UseHashValue);
 	struct FineGrainedInfo GetDefFGInfo(int DefHashValue);
@@ -190,10 +192,12 @@ public:
 	void AddLeaOperand(ea_t addr, op_t LeaOperand); // add map entry to LeaInstOpMap
 	void AddNormalizedStackOperand(op_t OldOp, ea_t InstAddr, op_t NormalizedOp); // add to map for RTL lookup later
 
-	// Six methods to set values into the maps of global reg/SSA to FG info.
+	// Eight methods to set values into the maps of global reg/stack/SSA to FG info.
 	//  For local names, see corresponding methods in SMPBasicBlock.
 	void UpdateDefSignMiscInfo(int DefHashValue, unsigned short NewInfo);
+	void UpdateStackDefSignMiscInfo(ea_t InstAddr, unsigned short NewInfo);
 	void UpdateUseSignMiscInfo(int UseHashValue, unsigned short NewInfo);
+	void UpdateStackUseSignMiscInfo(ea_t InstAddr, unsigned short NewInfo);
 	void UpdateDefWidthTypeInfo(int DefHashValue, unsigned short NewInfo);
 	void UpdateUseWidthTypeInfo(int UseHashValue, unsigned short NewInfo);
 	void UpdateDefFGInfo(int DefHashValue, struct FineGrainedInfo NewFG);
@@ -386,8 +390,8 @@ private:
 	map<int, struct FineGrainedInfo> GlobalUseFGInfoBySSA; // map hash of global name & SSANum to USE FG info.
 		// NOTE: We are currently limiting this map to registers, not all global names.
 
-	map<ea_t, struct FineGrainedInfo> StackDefFGInfo; // map stack FG info to instruction address of stack def
-	map<ea_t, struct FineGrainedInfo> StackUseFGInfo; // map stack FG info to instruction address of stack use
+	map<ea_t, struct FineGrainedInfo> StackDefFGInfo; // map stack FG info to instruction address of stack def; UNUSED
+	map<ea_t, struct FineGrainedInfo> StackUseFGInfo; // map stack FG info to instruction address of stack use; UNUSED
 	map<ea_t, op_t> LeaInstOpMap; // map original Lea instruction pseudo-memory operand to instruction address.
 	map<int, struct STARS_SCCP_Const_Struct> ConstantDefs; // map hash of global name & SSANum to constant value from SCCP.
 		// NOTE: We are currently limiting this map to registers, not all global names. 
diff --git a/SMPInstr.cpp b/SMPInstr.cpp
index f3fe49ca..8954a2e0 100644
--- a/SMPInstr.cpp
+++ b/SMPInstr.cpp
@@ -3525,18 +3525,61 @@ bool SMPInstr::IsSubRegUsedAsShiftCount(op_t UseOp) {
 
 // Does UseOp ultimately come from a small positive constant?
 bool SMPInstr::IsOpSourceSmallPositiveConstant(op_t UseOp, int UseSSANum) {
-	bool FoundSmallConst = false;
+	if (UseSSANum == -1) {
+		return false;
+	}
 
+	bool FoundSmallConst = false;
+	bool RegDef = (o_reg == UseOp.type);
+	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
 	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
+	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
+	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
 	ea_t UseAddr = this->GetAddr();
-	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
 	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
+	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
+	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));
 
-	if ((o_reg != UseOp.type) || (UseDefAddr < FirstFuncAddr)) {
-		// Cannot search for non-reg defs by SSANum reliably.
-		//  Need inst DEF, not Phi DEF, to have a const.
+	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
+		// Try to find in the function level.
+		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
+	}
+
+	if ((!MDIsDataFlowOpnd(UseOp, UseFP)) || (UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
+		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
+		// Cannot search for general memory DEFs; must be stack or register.
+		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
+		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
+		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
+		//   and LocalName means we will not find a DEF anywhere besides this block.
+		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
 		FoundSmallConst = false; 
 	}
+	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
+		// A block number was returned. That means the DEF is in a Phi Function.
+		//  We could trace all Phi USEs and see if all of them come from small constants
+		//  but we only need one of the Phi USEs to come from
+		//  a small constant to potentially lead to a false positive numeric error. We
+		//  will recurse on all Phi USEs, declaring success if we find a single one of them
+		//  to come from a small constant.
+		size_t BlockNum = (size_t) UseDefAddr;
+		assert(!LocalName);
+		SMPBasicBlock *PhiDefBlock = this->GetBlock()->GetFunc()->GetBlockByNum(BlockNum);
+		assert(NULL != PhiDefBlock);
+		if (!PhiDefBlock->IsProcessed()) { // Prevent infinite recursion
+			set<SMPPhiFunction, LessPhi>::iterator DefPhiIter = PhiDefBlock->FindPhi(UseOp);
+			assert(DefPhiIter != PhiDefBlock->GetLastPhi());
+			size_t PhiListSize = DefPhiIter->GetPhiListSize();
+			PhiDefBlock->SetProcessed(true); // Prevent infinite recursion
+			for (size_t UseIndex = 0; UseIndex < PhiListSize; ++UseIndex) {
+				int PhiUseSSANum = DefPhiIter->GetUseSSANum(UseIndex);
+				if (this->IsOpSourceSmallPositiveConstant(UseOp, PhiUseSSANum)) {
+					FoundSmallConst = true; // only one success on all Phi USEs is needed
+					break;
+				}
+			}
+		}
+	}
 	else {
 		bool ValueFound;
 		uval_t ConstValue;
@@ -3559,12 +3602,12 @@ bool SMPInstr::IsOpSourceBitwiseNot(op_t UseOp, int UseSSANum) {
 	bool RegDef = (o_reg == UseOp.type);
 	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
 	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
-	bool AboveStackFrame = (!RegDef && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
+	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
+	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
 	ea_t UseAddr = this->GetAddr();
 	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
 	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
 	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));
-	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
 
 	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
 		// Try to find in the function level.
@@ -3583,11 +3626,11 @@ bool SMPInstr::IsOpSourceBitwiseNot(op_t UseOp, int UseSSANum) {
 	}
 	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
 		// A block number was returned. That means the DEF is in a Phi Function.
-		//  We could trace all Phi USEs and see if all of them come from condition codes
+		//  We could trace all Phi USEs and see if all of them come from bitwise nots
 		//  but we only need one of the Phi USEs to come from
-		//  a condition code to potentially lead to a false positive numeric error. We
+		//  a bitwise not to potentially lead to a false positive numeric error. We
 		//  will recurse on all Phi USEs, declaring success if we find a single one of them
-		//  to come from a condition code.
+		//  to come from a bitwise not.
 		size_t BlockNum = (size_t) UseDefAddr;
 		assert(!LocalName);
 		SMPBasicBlock *PhiDefBlock = this->GetBlock()->GetFunc()->GetBlockByNum(BlockNum);
@@ -3632,16 +3675,34 @@ bool SMPInstr::IsOpSourceBitwiseNot(op_t UseOp, int UseSSANum) {
 
 // Does UseOp ultimately come from a set-condition-code instruction?
 bool SMPInstr::IsOpSourceConditionCode(op_t UseOp, int UseSSANum) {
+	if (UseSSANum == -1) {
+		return false;
+	}
+
 	bool FoundConditionalSetInst = false;
+	bool RegDef = (o_reg == UseOp.type);
+	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
 	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
+	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
+	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
 	ea_t UseAddr = this->GetAddr();
-	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
 	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
+	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
+	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));
 
-	if ((o_reg != UseOp.type) || (UseDefAddr == (FirstFuncAddr - 1))) {
-		// Cannot search for non-reg defs by SSANum reliably.
+	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
+		// Try to find in the function level.
+		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
+	}
+
+	if ((!MDIsDataFlowOpnd(UseOp, UseFP)) || (UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
+		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
+		// Cannot search for general memory DEFs; must be stack or register.
 		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
-		//  that are LiveIn to the function; pseudo-inst is not a condition code set.
+		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
+		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
+		//   and LocalName means we will not find a DEF anywhere besides this block.
+		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
 		FoundConditionalSetInst = false; 
 	}
 	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
@@ -3676,7 +3737,7 @@ bool SMPInstr::IsOpSourceConditionCode(op_t UseOp, int UseSSANum) {
 		}
 		else if (DefInst->MDIsMoveInstr()) {
 			op_t MoveUseOp = DefInst->GetMoveSource();
-			if (o_reg == MoveUseOp.type) { // pattern is simple; don't try to follow through memory
+			if (MDIsDataFlowOpnd(MoveUseOp, UseFP)) { // pattern is simple; don't try to follow through non-stack memory
 				CanonicalizeOpnd(MoveUseOp);
 				set<DefOrUse, LessDefUse>::iterator MoveUseIter = DefInst->FindUse(MoveUseOp);
 				assert(MoveUseIter != DefInst->GetLastUse());
@@ -3695,16 +3756,34 @@ bool SMPInstr::IsOpSourceConditionCode(op_t UseOp, int UseSSANum) {
 
 // Does UseOp ultimately come from a move-with-zero-extension instruction?
 bool SMPInstr::IsOpSourceZeroExtendedMove(op_t UseOp, int UseSSANum, bool TruncationCheck) {
+	if (UseSSANum == -1) {
+		return false;
+	}
+
 	bool FoundMoveZX = false;
+	bool RegDef = (o_reg == UseOp.type);
+	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
 	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
+	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
+	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
 	ea_t UseAddr = this->GetAddr();
-	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
 	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
+	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
+	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));
 
-	if ((o_reg != UseOp.type) || (UseDefAddr == (FirstFuncAddr - 1))) {
-		// Cannot search for non-reg defs by SSANum reliably.
+	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
+		// Try to find in the function level.
+		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
+	}
+
+	if ((!MDIsDataFlowOpnd(UseOp, UseFP)) || (UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
+		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
+		// Cannot search for general memory DEFs; must be stack or register.
 		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
-		//  that are LiveIn to the function; pseudo-inst is not a zero-extended load.
+		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
+		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
+		//   and LocalName means we will not find a DEF anywhere besides this block.
+		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
 		FoundMoveZX = false; 
 	}
 	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
@@ -3740,7 +3819,7 @@ bool SMPInstr::IsOpSourceZeroExtendedMove(op_t UseOp, int UseSSANum, bool Trunca
 		}
 		else if (DefInst->MDIsMoveInstr()) {
 			op_t MoveUseOp = DefInst->GetMoveSource();
-			if (o_reg == MoveUseOp.type) { // pattern is simple; don't try to follow through memory
+			if (MDIsDataFlowOpnd(MoveUseOp, UseFP)) { // pattern is simple; don't try to follow through non-stack memory
 				CanonicalizeOpnd(MoveUseOp);
 				set<DefOrUse, LessDefUse>::iterator MoveUseIter = DefInst->FindUse(MoveUseOp);
 				assert(MoveUseIter != DefInst->GetLastUse());
@@ -3775,16 +3854,34 @@ bool SMPInstr::IsOpSourceZeroExtendedMove(op_t UseOp, int UseSSANum, bool Trunca
 
 // Does UseOp ultimately come from a move-with-zero-extension instruction OR from a condition code OR from a right shift?
 bool SMPInstr::IsOpSourceZeroExtendedMoveShiftRightOrConditionCode(op_t UseOp, int UseSSANum, bool TruncationCheck) {
+	if (UseSSANum == -1) {
+		return false;
+	}
+
 	bool FoundMoveZXCC = false;
+	bool RegDef = (o_reg == UseOp.type);
+	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
 	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
+	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
+	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
 	ea_t UseAddr = this->GetAddr();
-	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
 	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
+	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
+	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));
 
-	if ((o_reg != UseOp.type) || (UseDefAddr == (FirstFuncAddr - 1))) {
-		// Cannot search for non-reg defs by SSANum reliably.
+	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
+		// Try to find in the function level.
+		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
+	}
+
+	if ((!MDIsDataFlowOpnd(UseOp, UseFP)) || (UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
+		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
+		// Cannot search for general memory DEFs; must be stack or register.
 		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
-		//  that are LiveIn to the function; pseudo-inst is not a zero-extended load.
+		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
+		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
+		//   and LocalName means we will not find a DEF anywhere besides this block.
+		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
 		FoundMoveZXCC = false; 
 	}
 	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
@@ -6169,6 +6266,7 @@ void SMPInstr::MDFixupSignedness(void) {
 	int DefSSANum;
 	int IdiomCode;
 	bool UnderflowOpcode = this->MDIsUnderflowingOpcode();
+	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
 
 	if (DefIter != this->GetLastDef()) {
 		DefOp = DefIter->GetOp();
@@ -6238,7 +6336,7 @@ void SMPInstr::MDFixupSignedness(void) {
 	//   will be small and no overflow check is needed.
 	int UseSSANum;
 	bool BenignUnderflow = false;
-	if (UnderflowOpcode && (DefOp.type == o_reg)) {
+	if (UnderflowOpcode && MDIsDataFlowOpnd(DefOp, UseFP)) {
 		UseIter = this->FindUse(DefOp); // DEF is also USE in subtraction
 		assert(UseIter != this->GetLastUse());
 		UseSSANum = UseIter->GetSSANum();
@@ -6249,7 +6347,7 @@ void SMPInstr::MDFixupSignedness(void) {
 			}
 			else { // For subtraction, need to see if BOTH operands came from condition codes (flags).
 				op_t UseOp = this->GetUseOnlyAddSubOp();
-				if (UseOp.type == o_reg) {
+				if (MDIsDataFlowOpnd(UseOp, UseFP)) {
 					CanonicalizeOpnd(UseOp);
 					UseIter = this->FindUse(UseOp);
 					assert(UseIter != this->GetLastUse());
@@ -6470,35 +6568,40 @@ bool SMPInstr::UpdateDefOpFGInfo(op_t DefOp, struct FineGrainedInfo NewFG) {
 	bool LocalName;
 	struct FineGrainedInfo OldFG, UnionFG;
 
-	// If operator is inherently signed, then we will have 
-	//  a sign bit set in NewFG from InitFGInfoFromOperator().
-	DefHashValue = this->GetDefOpHashAndSSA(DefOp, SSANum);
-	LocalName = this->BasicBlock->IsLocalName(DefOp);
-	if (LocalName) {
-		// Get old FG info from block level.
-		OldFG = this->BasicBlock->GetDefFGInfo(DefHashValue);
-	}
-	else { // global name
-		// Get old FG info from function level.
-		OldFG = this->BasicBlock->GetFunc()->GetDefFGInfo(DefHashValue);
-	}
-
-	// Get rid of stack access bits being passed around in InferOperatorFGInfo()
-	//  for register operands in RTLs.
 	if (o_reg == DefOp.type) {
+		// If operator is inherently signed, then we will have 
+		//  a sign bit set in NewFG from InitFGInfoFromOperator().
+		DefHashValue = this->GetDefOpHashAndSSA(DefOp, SSANum);
+		LocalName = this->BasicBlock->IsLocalName(DefOp);
+		if (LocalName) {
+			// Get old FG info from block level.
+			OldFG = this->BasicBlock->GetDefFGInfo(DefHashValue);
+		}
+		else { // global name
+			// Get old FG info from function level.
+			OldFG = this->BasicBlock->GetFunc()->GetDefFGInfo(DefHashValue);
+		}
+
+		// Get rid of stack access bits being passed around in InferOperatorFGInfo()
+		//  for register operands in RTLs.
 		NewFG.SignMiscInfo &= FG_MASK_SIGNEDNESS_BITS;
-	}
 
-	UnionFG.SignMiscInfo = OldFG.SignMiscInfo | NewFG.SignMiscInfo;
-	UnionFG.SizeInfo = OldFG.SizeInfo | NewFG.SizeInfo;
-	if ((OldFG.SignMiscInfo != UnionFG.SignMiscInfo) || (OldFG.SizeInfo != UnionFG.SizeInfo)) {
-		// The signs they are a-changin'.
-		MapsChanged = true;
-		if (LocalName)
-			this->BasicBlock->UpdateDefFGInfo(DefHashValue, UnionFG);
-		else
-			this->BasicBlock->GetFunc()->UpdateDefFGInfo(DefHashValue, UnionFG);
+		UnionFG.SignMiscInfo = OldFG.SignMiscInfo | NewFG.SignMiscInfo;
+		UnionFG.SizeInfo = OldFG.SizeInfo | NewFG.SizeInfo;
+		if ((OldFG.SignMiscInfo != UnionFG.SignMiscInfo) || (OldFG.SizeInfo != UnionFG.SizeInfo)) {
+			// The signs they are a-changin' (or the sizes).
+			MapsChanged = true;
+			if (LocalName)
+				this->BasicBlock->UpdateDefFGInfo(DefHashValue, UnionFG);
+			else
+				this->BasicBlock->GetFunc()->UpdateDefFGInfo(DefHashValue, UnionFG);
+		}
 	}
+	else if (MDIsStackAccessOpnd(DefOp, this->GetBlock()->GetFunc()->UsesFramePointer())) {
+		ea_t InstAddr = this->GetAddr();
+		MapsChanged = this->GetBlock()->GetFunc()->MDUpdateFGStackLocInfo(InstAddr, DefOp, NewFG);
+	}
+
 	return MapsChanged;
 } // end of SMPInstr::UpdateDefOpFGInfo()
 
@@ -6510,35 +6613,40 @@ bool SMPInstr::UpdateUseOpFGInfo(op_t UseOp, struct FineGrainedInfo NewFG) {
 	bool LocalName;
 	struct FineGrainedInfo OldFG, UnionFG;
 
-	// If operator is inherently signed, then we will have 
-	//  a sign bit set in NewFG from InitFGInfoFromOperator().
-	UseHashValue = this->GetUseOpHashAndSSA(UseOp, SSANum);
-	LocalName = this->BasicBlock->IsLocalName(UseOp);
-	if (LocalName) {
-		// Get old FG info from block level.
-		OldFG = this->BasicBlock->GetUseFGInfo(UseHashValue);
-	}
-	else { // global name
-		// Get old FG info from function level.
-		OldFG = this->BasicBlock->GetFunc()->GetUseFGInfo(UseHashValue);
-	}
-
-	// Get rid of stack access bits being passed around in InferOperatorFGInfo()
-	//  for register operands in RTLs.
 	if (o_reg == UseOp.type) {
+		// If operator is inherently signed, then we will have 
+		//  a sign bit set in NewFG from InitFGInfoFromOperator().
+		UseHashValue = this->GetUseOpHashAndSSA(UseOp, SSANum);
+		LocalName = this->BasicBlock->IsLocalName(UseOp);
+		if (LocalName) {
+			// Get old FG info from block level.
+			OldFG = this->BasicBlock->GetUseFGInfo(UseHashValue);
+		}
+		else { // global name
+			// Get old FG info from function level.
+			OldFG = this->BasicBlock->GetFunc()->GetUseFGInfo(UseHashValue);
+		}
+
+		// Get rid of stack access bits being passed around in InferOperatorFGInfo()
+		//  for register operands in RTLs.
 		NewFG.SignMiscInfo &= FG_MASK_SIGNEDNESS_BITS;
-	}
 
-	UnionFG.SignMiscInfo = OldFG.SignMiscInfo | NewFG.SignMiscInfo;
-	UnionFG.SizeInfo = OldFG.SizeInfo | NewFG.SizeInfo;
-	if ((OldFG.SignMiscInfo != UnionFG.SignMiscInfo) || (OldFG.SizeInfo != UnionFG.SizeInfo)) {
-		// The signs they are a-changin'.
-		MapsChanged = true;
-		if (LocalName)
-			this->BasicBlock->UpdateUseFGInfo(UseHashValue, UnionFG);
-		else
-			this->BasicBlock->GetFunc()->UpdateUseFGInfo(UseHashValue, UnionFG);
+		UnionFG.SignMiscInfo = OldFG.SignMiscInfo | NewFG.SignMiscInfo;
+		UnionFG.SizeInfo = OldFG.SizeInfo | NewFG.SizeInfo;
+		if ((OldFG.SignMiscInfo != UnionFG.SignMiscInfo) || (OldFG.SizeInfo != UnionFG.SizeInfo)) {
+			// The signs they are a-changin'.
+			MapsChanged = true;
+			if (LocalName)
+				this->BasicBlock->UpdateUseFGInfo(UseHashValue, UnionFG);
+			else
+				this->BasicBlock->GetFunc()->UpdateUseFGInfo(UseHashValue, UnionFG);
+		}
 	}
+	else if (MDIsStackAccessOpnd(UseOp, this->GetBlock()->GetFunc()->UsesFramePointer())) {
+		ea_t InstAddr = this->GetAddr();
+		MapsChanged = this->GetBlock()->GetFunc()->MDUpdateFGStackLocInfo(InstAddr, UseOp, NewFG);
+	}
+
 	return MapsChanged;
 } // end of SMPInstr::UpdateUseOpFGInfo()
 
@@ -7816,7 +7924,7 @@ void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile, list<size_t> &Lo
 					if (UseIter != this->GetLastUse()) {
 						UseOp = UseIter->GetOp();
 						UseSSANum = UseIter->GetSSANum();
-						if (o_reg == UseOp.type){
+						if ((o_reg == UseOp.type) || MDIsStackAccessOpnd(UseOp, UseFP)) {
 							if (this->IsOpSourceZeroExtendedMove(UseOp, UseSSANum, false)) {
 								if (this->GetBlock()->IsOpDestTruncatedWrite(DefOp, SSANum, this->GetAddr())) {
 									// Operand source was reduced-width, zero-extended; ultimate use is to store
-- 
GitLab