From 3bebaac353869682cdeed278a307d7185d1d81ab Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Wed, 14 May 2008 01:18:27 +0000
Subject: [PATCH] Infer local POINTER DEF from any POINTER USE; fix
 add/sub/interrupt problems.

---
 SMPBasicBlock.cpp |  57 +++++++++++++++++----
 SMPInstr.cpp      | 125 ++++++++++++++++++++++++++++++++++++++++++----
 SMPInstr.h        |   2 +
 3 files changed, 162 insertions(+), 22 deletions(-)

diff --git a/SMPBasicBlock.cpp b/SMPBasicBlock.cpp
index d7ba6bbc..6673d378 100644
--- a/SMPBasicBlock.cpp
+++ b/SMPBasicBlock.cpp
@@ -980,7 +980,7 @@ bool SMPBasicBlock::InferLocalDefType(op_t DefOp, unsigned int LocIndex, ea_t De
 	bool changed = false;
 	bool DebugFlag = false;
 #if SMP_DEBUG_OPTIMIZATIONS
-	DebugFlag |= (0 == strcmp("memset", this->MyFunc->GetFuncName()));
+	DebugFlag |= (0 == strcmp("weightadj", this->MyFunc->GetFuncName()));
 #endif
 
 	if (DebugFlag) {
@@ -1030,6 +1030,11 @@ bool SMPBasicBlock::InferLocalDefType(op_t DefOp, unsigned int LocIndex, ea_t De
 	//  a single type (other than UNINIT), change the DEF type to match the USE type
 	//  and set changed to true.
 	bool FirstUseSeen = false;
+	bool FoundUninit = false;
+	bool FoundNumeric = false;
+	bool FoundPointer = false;
+	bool FoundUnknown = false;
+	SMPOperandType PtrType = UNINIT;
 	SMPOperandType UseType = UNINIT;
 	for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
 		ea_t CurrAddr = (*InstIter)->GetAddr();
@@ -1038,26 +1043,56 @@ bool SMPBasicBlock::InferLocalDefType(op_t DefOp, unsigned int LocIndex, ea_t De
 		if (CurrAddr > StartAddr) {
 			CurrUse = (*InstIter)->FindUse(DefOp);
 			if (CurrUse != (*InstIter)->GetLastUse()) { // found a USE in the chain
-				if (!FirstUseSeen) {
+				if (!FirstUseSeen)
 					FirstUseSeen = true;
-					UseType = CurrUse->GetType();
-					if (UNINIT == UseType)
-						return false;
-				}
-				else {
-					if (IsNotEqType(CurrUse->GetType(), UseType))
-						return false;  // no consistent type
+				UseType = CurrUse->GetType();
+				if (UNINIT == UseType)
+					FoundUninit = true;
+				else if (IsNumeric(UseType))
+					FoundNumeric = true;
+				else if (IsUnknown(UseType))
+					FoundUnknown = true;
+				else if (IsDataPtr(UseType)) {
+					if (FoundPointer) {
+						if (IsNotEqType(PtrType, UseType)) {
+							msg("WARNING: Differing ptr types in local chain:");
+							msg(" Prev: %d Current: %d %s\n", PtrType, UseType,
+								(*InstIter)->GetDisasm());
+						}
+						PtrType = POINTER;
+					}
+					else {
+						FoundPointer = true;
+						PtrType = UseType;
+					}
 				}
 			}
 		}
 	} // end for all instructions
 
 	if (FirstUseSeen) {
-		// We have a consistent type, else we would have returned false above.
-		assert(UNINIT != UseType);
+		// See if we have a consistent type.
+		// If we see any definite POINTER uses, we must set the DEF
+		//  to type POINTER or a refinement of it.
+#if 1
+		if (!FoundNumeric || FoundUninit || FoundPointer || FoundUnknown)
+			return false;
+#endif
+		if (FoundPointer)
+			UseType = PtrType;
+		else if (FoundNumeric && !FoundUninit && !FoundUnknown)
+			UseType = NUMERIC;
+		else
+			return false; // no POINTER, but no consistent type
+
 		if (DebugFlag) msg("Inferring local DEF of type %d\n", UseType);
 		CurrDef = (*DefInstIter)->SetDefType(DefOp, UseType);
 		changed = true;
+		if (FoundPointer && FoundUninit) {
+			// We will propagate PtrType to the UNINIT elements of
+			//  the DEF-USE chain.
+			changed |= this->PropagateLocalDefType(DefOp, PtrType, DefAddr);
+		}
 	}
 
 	return changed;
diff --git a/SMPInstr.cpp b/SMPInstr.cpp
index 04a6d9d3..faedc54d 100644
--- a/SMPInstr.cpp
+++ b/SMPInstr.cpp
@@ -245,6 +245,38 @@ bool SMPInstr::HasSourceMemoryOperand(void) {
 	return MemSrc;
 } // end of SMPInstr::HasSourceMemoryOperand()
 
+// Get the first memory operand in the DEF list.
+op_t SMPInstr::MDGetMemDefOp(void) {
+	set<DefOrUse, LessDefUse>::iterator DefIter;
+	op_t MemOp;
+	MemOp.type = o_void;
+
+	for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
+		optype_t DefType = DefIter->GetOp().type;
+		if ((DefType >= o_mem) && (DefType <= o_displ)) {
+			MemOp = DefIter->GetOp();
+			break;
+		}
+	}
+	return MemOp;
+} // end of SMPInstr::MDGetMemDefOp()
+
+// Get the first memory operand in the USE list.
+op_t SMPInstr::MDGetMemUseOp(void) {
+	set<DefOrUse, LessDefUse>::iterator UseIter;
+	op_t MemOp;
+	MemOp.type = o_void;
+
+	for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
+		optype_t UseType = UseIter->GetOp().type;
+		if ((UseType >= o_mem) && (UseType <= o_displ)) {
+			MemOp = UseIter->GetOp();
+			break;
+		}
+	}
+	return MemOp;
+} // end of SMPInstr::MDGetMemUseOp()
+
 // Does the instruction whose flags are in F have a numeric type
 //   as the second source operand?
 // NOTE: We can only analyze immediate values now. When data flow analyses are implemented,
@@ -267,18 +299,33 @@ bool SMPInstr::IsSecondSrcOperandNumeric(flags_t F) const {
 //  annotation will result.
 void SMPInstr::SetAddSubSourceType(void) {
 	set<DefOrUse, LessDefUse>::iterator UseIter, DefIter;
+	bool MemSrc = this->HasSourceMemoryOperand();
 
+#if 0
 	// First, ensure that we are dealing with a register source.
-	if (this->HasSourceMemoryOperand()) {
+	if (MemSrc) {
 		this->AddSubSourceType = UNINIT;
 		return;
 	}
+#endif
 
 	// The USE and DEF lists will have the flags and the destination
-	//  operand in common for adds and subtracts. The USE-only operand
-	//  is the one we are concerned with.
+	//  operand in common for register adds and subtracts. The USE-only
+	//  operand is the one we are concerned with.
 	for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
-		if (this->GetLastDef() == this->FindDef(UseIter->GetOp())) {
+		op_t UseOp = UseIter->GetOp();
+		if (MemSrc) {
+			if ((UseOp.type >= o_mem) && (UseOp.type <= o_displ)) {
+				// Found the memory USE.
+				this->AddSubSourceType = UseIter->GetType();
+#if SMP_VERBOSE_DEBUG_INFER_TYPES
+				msg("Set AddSubSourceType to %d at %x: %s\n", UseIter->GetType(),
+					this->address, this->GetDisasm());
+#endif
+				break;
+			}
+		}
+		else if (this->GetLastDef() == this->FindDef(UseOp)) {
 			// Found the USE that is not a DEF
 			this->AddSubSourceType = UseIter->GetType();
 #if SMP_VERBOSE_DEBUG_INFER_TYPES
@@ -1090,27 +1137,69 @@ bool SMPInstr::MDFindPointerUse(op_t MemOp, bool UseFP) {
 	// At this point, we must have a base address in a register.
 	if ((0 < ScaleFactor) || (R_none == IndexReg)) {
 		// IndexReg is scaled, meaning it is NUMERIC, so BaseReg must
-		//  be a POINTER, or IndexReg is not present, so BaseReg is the
+		//  be a POINTER; or IndexReg is not present, so BaseReg is the
 		//  only possible holder of an address.
 		if (R_none != BaseReg) {
-			changed = true;
 			op_t BaseOp;
 			BaseOp.type = o_reg;
 			BaseOp.reg = MDCanonicalizeSubReg(BaseReg);
-			UseIter = this->SetUseType(BaseOp, POINTER);
+			UseIter = this->FindUse(BaseOp);
 			assert(UseIter != this->GetLastUse());
+			if (UNINIT == UseIter->GetType()) {
+				changed = true;
+				UseIter = this->SetUseType(BaseOp, POINTER);
+				assert(UseIter != this->GetLastUse());
+			}
 		}
 	}
 	else if (R_none == BaseReg) {
 		// We have an unscaled IndexReg and no BaseReg and offset was
 		//  not a global offset, so IndexReg must be a POINTER.
 		if (R_none != IndexReg) {
-			changed = true;
 			op_t IndexOp;
 			IndexOp.type = o_reg;
 			IndexOp.reg = MDCanonicalizeSubReg(IndexReg);
-			UseIter = this->SetUseType(IndexOp, POINTER);
+			UseIter = this->FindUse(IndexOp);
+			assert(UseIter != this->GetLastUse());
+			if (UNINIT == UseIter->GetType()) {
+				changed = true;
+				UseIter = this->SetUseType(IndexOp, POINTER);
+				assert(UseIter != this->GetLastUse());
+			}
+		}
+	}
+	else { // We have BaseReg and an unscaled IndexReg.
+		// The only hope for typing something like [ebx+edx] is for
+		//  one register to already be typed NUMERIC, in which case
+		//  the other one must be a POINTER.
+		op_t IndexOp;
+		IndexOp.type = o_reg;
+		IndexOp.reg = MDCanonicalizeSubReg(IndexReg);
+		op_t BaseOp;
+		BaseOp.type = o_reg;
+		BaseOp.reg = MDCanonicalizeSubReg(BaseReg);
+		UseIter = this->FindUse(BaseOp);
+		assert(UseIter != this->GetLastUse());
+		if (IsNumeric(UseIter->GetType())) {
+			UseIter = this->FindUse(IndexOp);
 			assert(UseIter != this->GetLastUse());
+			if (UNINIT == UseIter->GetType()) {
+				// Set to POINTER or PROF_POINTER
+				changed = true;
+				UseIter = this->SetUseType(IndexOp, POINTER);
+				assert(UseIter != this->GetLastUse());
+			}
+		}
+		else { // BaseReg was not NUMERIC
+			if (UNINIT == UseIter->GetType()) { // BaseReg is UNINIT
+				UseIter = this->FindUse(IndexOp);
+				assert(UseIter != this->GetLastUse());
+				if (IsNumeric(UseIter->GetType())) {
+					changed = true;
+					UseIter = this->SetUseType(BaseOp, POINTER);
+					assert(UseIter != this->GetLastUse());
+				}
+			}
 		}
 	}
 
@@ -1240,6 +1329,7 @@ bool SMPInstr::InferTypes(void) {
 	set<DefOrUse, LessDefUse>::iterator CurrUse;
 	op_t DefOp, UseOp;
 	bool DebugFlag = false;
+	bool UseFP = this->BasicBlock->GetFunc()->UsesFramePointer();
 #if SMP_VERBOSE_DEBUG_INFER_TYPES
 	DebugFlag |= (0 == strcmp("__libc_csu_fini", this->BasicBlock->GetFunc()->GetFuncName()));
 #endif
@@ -1252,6 +1342,13 @@ bool SMPInstr::InferTypes(void) {
 	if (this->TypeInferenceComplete)
 		return false;
 
+	if (this->HasDestMemoryOperand()) {
+		changed |= this->MDFindPointerUse(this->MDGetMemDefOp(), UseFP);
+	}
+	if (this->HasSourceMemoryOperand()) {
+		changed |= this->MDFindPointerUse(this->MDGetMemUseOp(), UseFP);
+	}
+
 	// The control flow instructions can be handled simply based on their type
 	//  and do not need an RTL walk.
 	SMPitype DFAType = this->GetDataFlowType();
@@ -1260,13 +1357,17 @@ bool SMPInstr::InferTypes(void) {
 	}
 	if ((DFAType >= JUMP) && (DFAType <= INDIR_CALL)) {
 		// All USEs are either the flags (NUMERIC) or the target address (CODEPTR).
+		//  The exception is the USE list for interrupt calls, which includes
+		//  the caller-saved regs.
 		CurrUse = this->GetFirstUse();
 		while (CurrUse != this->GetLastUse()) {
 			UseOp = CurrUse->GetOp();
 			if (UseOp.is_reg(X86_FLAGS_REG))
 				CurrUse = this->SetUseType(UseOp, NUMERIC);
-			else if (CurrUse->GetType() != CODEPTR)
+			else if ((CurrUse->GetType() != CODEPTR)
+				&& (!(this->MDIsInterruptCall() && (o_reg == UseOp.type)))) {
 				CurrUse = this->SetUseType(UseOp, CODEPTR);
+			}
 			++CurrUse;
 		}
 		this->TypeInferenceComplete = true;
@@ -2303,7 +2404,9 @@ void SMPInstr::EmitTypeAnnotations(bool UseFP, bool AllocSeen, FILE *AnnotFile)
 				++AnnotationCount[OptType];
 			}
 			else if (IsEqType(NUMERIC, this->AddSubSourceType)
-				&& !this->MDIsFrameAllocInstr()) {
+				&& !this->MDIsFrameAllocInstr()
+				&& (this->SMPcmd.itype != NN_adc)
+				&& (this->SMPcmd.itype != NN_sbb)) {
 				qfprintf(AnnotFile, "%10x %6d INSTR LOCAL 2ndSrcNumeric %s \n",
 						addr, -1, disasm);
 				++AnnotationCount[OptType];
diff --git a/SMPInstr.h b/SMPInstr.h
index 7c9b4471..a4ca2bd9 100644
--- a/SMPInstr.h
+++ b/SMPInstr.h
@@ -263,6 +263,8 @@ private:
 	void MDAddRegUse(ushort, bool); // 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);
+	op_t MDGetMemDefOp(void);
 	bool BuildUnaryRTL(SMPoperator UnaryOp); // helper for BuildRTL()
 	bool BuildUnary2OpndRTL(SMPoperator UnaryOp); // helper for BuildRTL()
 	bool BuildBinaryRTL(SMPoperator BinaryOp); // helper for BuildRTL()
-- 
GitLab