/*
 * SMPBasicBlock.cpp - Class file for basic block analysis.
 *
 * Copyright (c) 2000, 2001, 2010 - University of Virginia 
 *
 * This file is part of the Memory Error Detection System (MEDS) infrastructure.
 * This file may be used and modified for non-commercial purposes as long as 
 * all copyright, permission, and nonwarranty notices are preserved.  
 * Redistribution is prohibited without prior written consent from the University 
 * of Virginia.
 *
 * Please contact the authors for restrictions applying to commercial use.
 *
 * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Author: University of Virginia
 * e-mail: jwd@virginia.com
 * URL   : http://www.cs.virginia.edu/
 *
 * Additional copyrights 2010, 2011 by Zephyr Software LLC
 * e-mail: {clc,jwd}@zephyr-software.com
 * URL   : http://www.zephyr-software.com/
 *
 */

//
// SMPBasicBlock.cpp
//
// This module performs the fundamental basic block level analyses needed for the
//   SMP project (Software Memory Protection).
//

#include <list>
#include <set>
#include <vector>
#include <algorithm>

#include <cstring>

#include <pro.h>
#include <assert.h>
#include <ida.hpp>
#include <idp.hpp>
#include <auto.hpp>
#include <bytes.hpp>
#include <funcs.hpp>
#include <name.hpp>
#include <intel.hpp>

#include "SMPDBInterface.h"
#include "SMPStaticAnalyzer.h"
#include "SMPDataFlowAnalysis.h"
#include "SMPBasicBlock.h"
#include "SMPInstr.h"
#include "SMPFunction.h"

#define SMP_DEBUG_DATAFLOW 0   // verbose output for setting up SSA/LVA data structures
#define SMP_DEBUG_OPTIMIZATIONS 0    // verbose output for type propagation
#define SMP_VERBOSE_POINTER_REFINEMENT 0 // refining POINTER to HEAPPTR, STACKPTR, etc.
#define SMP_VERBOSE_ALIAS_DETECTION 0  // log message every time alias in DU chain is seen
#define STARS_DETECT_OPTIMIZED_RANGE_CHECK 1 // Detect misleading signedness case
#define STARS_MINIMIZE_UNSIGNED_BRANCH_PROPAGATION 1 // stop propagation at possible mixed-mode arithmetic
#define STARS_AGGRESSIVE_BENIGN_POINTER_ARITHMETIC 1 // subtract then add to POINTER can underflow then overflow benignly

// Basic block number 0 is the top of the CFG lattice.
#define SMP_TOP_BLOCK 0 

// *****************************************************************
// Class SMPBasicBlock
// *****************************************************************

// Constructor
SMPBasicBlock::SMPBasicBlock(SMPFunction *Func, list<SMPInstr *>::iterator First, list<SMPInstr *>::iterator Last) {
	this->FirstAddr = (*First)->GetAddr();
	this->BlockNum = SMP_BLOCKNUM_UNINIT;
	this->LoopHeaderNumber = SMP_BLOCKNUM_UNINIT;
	this->MyFunc = Func;
	this->SetOutgoingStackDelta(0);
#if 0
	this->IncomingStackPtrDelta = 0;
#endif
#if 1
	this->SetProcessed(false);
	this->SetIndirectJump(false);
	this->SetReturns(false);
	this->ResetShared();
	this->SetLiveInStale(true);
	this->SetUnreachableBlock(false);
	this->SetFlagsDeadBeforeFirstKill(false);
	this->SetMaybeAliased(false);
#else
	this->booleans1 = 0;
	this->SetLiveInStale(true);
#endif
	this->booleans2 = 0;

	this->InstVec.clear();
	this->AddrInstMap.clear();
	this->Predecessors.clear();
	this->Successors.clear();
	this->KillSet.clear();
	this->UpExposedSet.clear();
	this->LiveOutSet.clear();
	this->LiveInSet.clear();
	this->DomFrontier.clear();
	this->PhiFunctions.clear();
	this->LocalNames.clear();

	ea_t InstAddr;

	list<SMPInstr *>::iterator InstIter = First;
	SMPInstr *CurrInst;
	size_t VecIndex = this->InstVec.size() - 1;
	while (InstIter != Last) {
		CurrInst = (*InstIter);
		this->InstVec.push_back(CurrInst);
		VecIndex = this->InstVec.size() - 1;
		InstAddr = CurrInst->GetAddr();
		pair<ea_t, size_t> MapItem(InstAddr, VecIndex);
		this->AddrInstMap.insert(MapItem);
		++InstIter;
	}

	// Now process the last instruction.
	CurrInst = (*Last);
	this->InstVec.push_back(CurrInst); // Add last instruction
	InstAddr = CurrInst->GetAddr();
	VecIndex = this->InstVec.size() - 1;
	pair<ea_t, size_t> MapItem2(InstAddr, VecIndex);
	this->AddrInstMap.insert(MapItem2);
	CurrInst->SetTerminatesBlock();

	// Mark first true (non-marker) instruction. Marker is a floating point
	//  no-op at an odd address, 1 byte before actual first address of block.
	InstIter = First;
	CurrInst = (*InstIter);
	if ((CurrInst->IsFloatNop()) && (0 != (0x1 & CurrInst->GetAddr()))) {
		// Floating point no-op at odd address; this is SSA marker instruction.
		++InstIter; // skip to first real instruction
		CurrInst = (*InstIter);
	}
	CurrInst->SetFirstInBlock();
}

// Get address of first instruction in the block.
ea_t SMPBasicBlock::GetFirstAddr(void) const {
	return this->FirstAddr;
}

// Six methods to get values from the maps of global reg/SSA to FG info.
//  For global names, see corresponding methods in SMPFunction.
unsigned short SMPBasicBlock::GetDefSignMiscInfo(int DefHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter != this->LocalDefFGInfoBySSA.end())
		return MapIter->second.SignMiscInfo;
	else
		return 0;
} // end of SMPBasicBlock::GetDefSignMiscInfo()

unsigned short SMPBasicBlock::GetUseSignMiscInfo(int UseHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter != this->LocalUseFGInfoBySSA.end())
		return MapIter->second.SignMiscInfo;
	else
		return 0;
} // end of SMPBasicBlock::GetUseSignMiscInfo()

unsigned short SMPBasicBlock::GetDefWidthTypeInfo(int DefHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter != this->LocalDefFGInfoBySSA.end())
		return MapIter->second.SizeInfo;
	else
		return 0;
} // end of SMPBasicBlock::GetDefWidthTypeInfo()

unsigned short SMPBasicBlock::GetUseWidthTypeInfo(int UseHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter != this->LocalUseFGInfoBySSA.end())
		return MapIter->second.SizeInfo;
	else
		return 0;
} // end of SMPBasicBlock::GetUseWidthTypeInfo()

struct FineGrainedInfo SMPBasicBlock::GetDefFGInfo(int DefHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter != this->LocalDefFGInfoBySSA.end())
		return MapIter->second;
	else {
		struct FineGrainedInfo EmptyFG;
		EmptyFG.SignMiscInfo = 0;
		EmptyFG.SizeInfo = 0;
		return EmptyFG;
	}
} // end of SMPBasicBlock::GetDefFGInfo()

struct FineGrainedInfo SMPBasicBlock::GetUseFGInfo(int UseHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter != this->LocalUseFGInfoBySSA.end())
		return MapIter->second;
	else {
		struct FineGrainedInfo EmptyFG;
		EmptyFG.SignMiscInfo = 0;
		EmptyFG.SizeInfo = 0;
		return EmptyFG;
	}
} // end of SMPBasicBlock::GetUseFGInfo()

bool SMPBasicBlock::IsLocalName(op_t CurrOp) const {
	return (!this->LocalNames.empty()
		&& (this->LocalNames.end() != this->LocalNames.find(CurrOp)));
}

set<op_t, LessOp>::iterator SMPBasicBlock::FindLocalName(op_t FindOp) {
	return this->LocalNames.find(FindOp);
}

// Equality operator for SMPBasicBlock. Key field is address of first instruction.
int SMPBasicBlock::operator==(const SMPBasicBlock &rhs) const {
	if (rhs.GetFirstAddr() != this->FirstAddr)
		return 0;
	else
		return 1;
}

// Link to predecessor block.
void SMPBasicBlock::LinkToPred(SMPBasicBlock *Predecessor) {
	this->Predecessors.push_back(Predecessor);
	return;
}

// Link to successor block.
void SMPBasicBlock::LinkToSucc(SMPBasicBlock *Successor) {
	this->Successors.push_back(Successor);
	return;
}

// See if all predecessors have set their ordering number.
bool SMPBasicBlock::AllPredecessorsNumbered(void) {
	list<SMPBasicBlock *>::iterator CurrPred;
	for (CurrPred = this->Predecessors.begin(); CurrPred != this->Predecessors.end(); ++CurrPred) {
		// Don't count current block, in case we have a one-block loop with this block
		//  as its own predecessor.
		if (**CurrPred == *this)
			continue;
		if ((*CurrPred)->GetNumber() == SMP_BLOCKNUM_UNINIT)
			return false;
	}
	return true;
} // end of SMPBasicBlock::AllPredecessorsNumbered()

// Mark as processed, recurse into successors depth-first.
void SMPBasicBlock::DepthFirstMark(void) {
	if (this->IsProcessed()) {
		return;
	}
	this->SetProcessed(true);
	list<SMPBasicBlock *>::iterator CurrSucc;
	for (CurrSucc = this->Successors.begin(); CurrSucc != this->Successors.end(); ++CurrSucc) {
		(*CurrSucc)->DepthFirstMark();
	}
	return;
} // end of SMPBasicBlock::DepthFirstMark()

// Are all instructions in the block no-ops?
bool SMPBasicBlock::AllNops(void) {
	size_t NopCount = 0;
	size_t GoodCount = 0;  // non-nop instructions
	vector<SMPInstr *>::iterator InstIter;
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		if (CurrInst->IsNop()) {
			++NopCount;
		}
		else {
			++GoodCount;
			break;
		}
	}
	return ((0 == GoodCount) && (0 < NopCount));
} // end of SMPBasicBlock::AllNops()

// Analyze basic block and fill data members.
void SMPBasicBlock::Analyze() {
	vector<SMPInstr *>::reverse_iterator RevInstIter = this->GetRevInstBegin();
	SMPInstr *BackInst = (*RevInstIter);
	if (BackInst->GetDataFlowType() == INDIR_JUMP) {
		this->SetIndirectJump(true);
	}
	else if (BackInst->GetDataFlowType() == RETURN) {
		this->SetReturns(true);
	}
} // end of SMPBasicBlock::Analyze()

// DEBUG dump of block
void SMPBasicBlock::Dump(void) {
	SMP_msg("Dump of basic block %d\n", this->BlockNum);
	// Dump dataflow analysis sets and links before dumping instructions.
	list<SMPBasicBlock *>::iterator CurrLink;
	SMP_msg("Predecessors: ");
	if (!this->Predecessors.empty()) {
		for (CurrLink = this->Predecessors.begin(); CurrLink != this->Predecessors.end(); ++CurrLink) {
			SMP_msg("%d ", (*CurrLink)->GetNumber());
		}
	}
	SMP_msg("\n");
	SMP_msg("Successors: ");
	if (!this->Successors.empty()) {
		for (CurrLink = this->Successors.begin(); CurrLink != this->Successors.end(); ++CurrLink) {
			SMP_msg("%d ", (*CurrLink)->GetNumber());
		}
	}
	SMP_msg("\n");
	set<op_t, LessOp>::iterator SetItem;
	SMP_msg("VarKill set: ");
	if (!this->KillSet.empty()) {
		SMP_msg("size: %zu ", this->KillSet.size());
		for (SetItem = this->KillSet.begin(); SetItem != this->KillSet.end(); ++SetItem) {
			PrintListOperand(*SetItem);
		}
	}
	SMP_msg("\n\n");
	SMP_msg("UpExposed set: ");
	if (!this->UpExposedSet.empty()) {
		for (SetItem = this->GetFirstUpExposed(); SetItem != this->GetLastUpExposed(); ++SetItem) {
			PrintListOperand(*SetItem);
		}
	}
	SMP_msg("\n\n");
	SMP_msg("LiveIn set: ");
	if (!this->LiveInSet.empty()) {
		for (SetItem = this->LiveInSet.begin(); SetItem != this->LiveInSet.end(); ++SetItem) {
			PrintListOperand(*SetItem);
		}
	}
	SMP_msg("\n\n");
	SMP_msg("LiveOut set: ");
	if (!this->LiveOutSet.empty()) {
		for (SetItem = this->LiveOutSet.begin(); SetItem != this->LiveOutSet.end(); ++SetItem) {
			PrintListOperand(*SetItem);
		}
	}
	SMP_msg("\n\n");
	SMP_msg("Dominance frontier: ");
	set<int>::iterator DomIter;
	if (!this->DomFrontier.empty()) {
		for (DomIter = this->DomFrontier.begin(); DomIter != this->DomFrontier.end(); ++DomIter) {
			SMP_msg("%d ", *DomIter);
		}
	}
	SMP_msg("\n\n");
	set<SMPPhiFunction, LessPhi>::iterator PhiIter;
	if (!this->PhiFunctions.empty()) {
		for (PhiIter = this->PhiFunctions.begin(); PhiIter != this->PhiFunctions.end(); ++PhiIter) {
			SMP_msg("Phi function for %d : ", PhiIter->GetIndex());
			// Dump out all phi operands
			PhiIter->Dump();
		}
	}
	SMP_msg("\n");

#if STARS_BUILD_DEF_USE_CHAINS
	SMP_msg("DEF-USE chains for block-local names: \n");
	this->LocalDUChains.Dump();

	SMP_msg("\n");
	SMP_msg("DEF-USE chains for block-local use of global names: \n");
	this->GlobalDUChains.Dump();
#endif

	SMP_msg("\n");
	if (this->HasIndirectJump())
		SMP_msg("Has indirect jump. ");
	if (this->HasReturn())
		SMP_msg("Has return. ");
	if (this->IsShared())
		SMP_msg("Is shared tail chunk block. ");
	SMP_msg("\n");

	// Now, dump all the instructions.
	vector<SMPInstr *>::iterator CurrInst;
	for (CurrInst = this->GetFirstInst(); CurrInst != this->GetLastInst(); ++CurrInst) {
		(*CurrInst)->Dump();
	}
	SMP_msg("\n");
	return;
} // end of SMPBasicBlock::Dump()

// Search successors for fall-through block, if any
list<SMPBasicBlock *>::iterator SMPBasicBlock::GetFallThroughSucc(void) {
	list<SMPBasicBlock *>::iterator FallThroughSuccIter = this->GetLastSucc();
	list<SMPBasicBlock *>::iterator SuccIter;
	vector<SMPInstr *>::reverse_iterator LastInstIter = this->GetRevInstBegin();
	SMPInstr *LastInst = (*LastInstIter);
	ea_t LastAddr = LastInst->GetAddr(), AddrDiff = 1000, FirstAddr;
	SMPitype LastDataFlow = LastInst->GetDataFlowType();

	if ((JUMP != LastDataFlow) && (RETURN != LastDataFlow) && (HALT != LastDataFlow)) {
		// Block has fall-through.
		for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) {
			FirstAddr = (*SuccIter)->GetFirstAddr();
			if (FirstAddr > LastAddr) { // block comes after this block; candidate for fall-through
				ea_t NewAddrDiff = FirstAddr - LastAddr;
				if (NewAddrDiff < AddrDiff) { // better candidate than previous successors
					AddrDiff = NewAddrDiff;
					FallThroughSuccIter = SuccIter;
				}
			}
		}
	}

	return FallThroughSuccIter;
} // end of SMPBasicBlock::GetFallThroughSucc()


// Return true if anything already in the KillSet would kill the operand value.
bool SMPBasicBlock::MDAlreadyKilled(op_t Opnd1) const {
	// We have assembly language operands that can be complex, such as
	//  [ebx + esi*4 + 04h]. If ebx or esi have been killed, then this memory
	//  phrase should be considered killed. We could be even more conservative
	//  with base addresses, declaring an entire array killed whenever its base
	//  address appears in a definition, for example. We will do that if it proves
	//  to be necessary.
	bool FoundInKillSet = (KillSet.end() != KillSet.find(Opnd1));
	bool DirectAccess = false;
	bool StackAccess = false;
	bool UseFP = this->MyFunc->UsesFramePointer();

	switch (Opnd1.type) {
		// Some types are simple to test for equality.
		case o_void:
		case o_reg:
		case o_mem:
		case o_imm:
		case o_far:
		case o_near:
		case o_trreg:
		case o_dbreg:
		case o_crreg:
		case o_fpreg:
		case o_mmxreg:
		case o_xmmreg:
			// Look in KillSet. These simple types should be found there with
			//  no complicated comparisons needed.
			return FoundInKillSet;

		case o_phrase:
		case o_displ:
			StackAccess = MDIsStackAccessOpnd(Opnd1, UseFP);
			if (StackAccess) {
				DirectAccess = !MDIsIndirectMemoryOpnd(Opnd1, UseFP);
			}
			// If found directly in KillSet, return true. Otherwise, see if any registers
			//  used in the memory addressing expression were killed.
			if (FoundInKillSet)
				return true;
			else if (!(DirectAccess && StackAccess)) {
				// Should we add Opnd1 to the KillSet every time we return true below? **!!**
				op_t TempOp = InitOp;
				TempOp.type = o_reg;
				int BaseReg;
				int IndexReg;
				ushort ScaleFactor;
				ea_t displacement;

				MDExtractAddressFields(Opnd1, BaseReg, IndexReg, ScaleFactor, displacement);
			
				if (R_none != BaseReg) {
					TempOp.reg = (ushort) BaseReg;
					if (this->KillSet.end() != this->KillSet.find(TempOp))
						return true;
				}
				if (R_none != IndexReg) { // Cannot have ESP index reg in SIB
					TempOp.reg = (ushort) IndexReg;
					if (this->KillSet.end() != this->KillSet.find(TempOp))
						return true;
				}
			} // end if (FoundInKillSet) ... else ...
			break;
		default:
			SMP_msg("Unknown operand type %d in MDAlreadyKilled, block %d\n", Opnd1.type, this->BlockNum);
	} // end of switch on Opnd1.type

	return false;
} // end of SMPBasicBlock::MDAlreadyKilled()

// Initialize the KilledSet and UpExposedSet for live variable analysis.
void SMPBasicBlock::InitKilledExposed(bool UseFP) {
	// Find all upwardly exposed operands and killed operands in this block.
	vector<SMPInstr *>::iterator CurrIter;
	set<DefOrUse, LessDefUse>::iterator CurrUse, CurrDef;
	for (CurrIter = this->GetFirstInst(); CurrIter != this->GetLastInst(); ++CurrIter) {
		SMPInstr *CurrInst = (*CurrIter);

		// Dataflow equation for upward exposed variables: If a variable has not been
		//  killed yet in this block, starting from the top of the block, and it is used
		//  in the current instruction, then it is upwardly exposed.
		for (CurrUse = CurrInst->GetFirstUse(); CurrUse != CurrInst->GetLastUse(); ++CurrUse) {
			op_t UseOp = CurrUse->GetOp();
			// Only add non-immediate operands that are not already killed in this block.
			//  o_near and o_far operands are code addresses in immediate form, e.g.
			//  call _printf might be call 0x8048040, with o_near = 0x8048040.
			if ((!(this->MDAlreadyKilled(UseOp))) && (MDIsDataFlowOpnd(UseOp, UseFP))) {
				this->AddUpExposed(UseOp);
			}
		}
		// Dataflow equation for killed variables: If a variable is defined in any
		//  instruction in the block, it is killed by this block (i.e. prior definitions
		//  of that variable will not make it through the block).
		for (CurrDef = CurrInst->GetFirstDef(); CurrDef != CurrInst->GetLastDef(); ++CurrDef) {
			op_t DefOp = CurrDef->GetOp();
			if (MDIsDataFlowOpnd(DefOp, UseFP)) {
				this->KillSet.insert(DefOp);
			}
		}
	} // end for all instrs in block
	this->SetLiveInStale(true);  // Would need to compute LiveInSet for first time
	return;
} // end of SMPBasicBlock::InitKilledExposed()

// returns size in bytes
size_t SMPBasicBlock::GetBlockSize(void) {
	vector<SMPInstr *>::reverse_iterator LastInstIter = this->GetRevInstBegin();
	SMPInstr *LastInst = (*LastInstIter);
	size_t BlockSize = LastInst->GetSize() + (size_t)(LastInst->GetAddr() - this->FirstAddr);
	return BlockSize;
} // end of SMPBasicBlock::GetBlockSize()


// Return an iterator for the beginning of the LiveInSet. If the set is stale,
//  recompute it first.
set<op_t, LessOp>::iterator SMPBasicBlock::GetFirstLiveIn(void) {
	if (this->IsLiveInStale()) {
		// Dataflow equation: A variable is live-in to this block if it
		//  is upwardly exposed from this block, or if it passes through
		//  the block unchanged (i.e. it is not killed and is live out).
		this->LiveInSet.clear();
		set<op_t, LessOp>::iterator OutIter;
		for (OutIter = this->GetFirstUpExposed(); OutIter != this->GetLastUpExposed(); ++OutIter) {
			this->LiveInSet.insert(*OutIter);
		}
		for (OutIter = this->LiveOutSet.begin(); OutIter != this->LiveOutSet.end(); ++OutIter) {
			if (KillSet.end() == this->KillSet.find(*OutIter)) // Found live out but not killed
				this->LiveInSet.insert(*OutIter);
		}
		this->SetLiveInStale(false);
	}
	return this->LiveInSet.begin();
} // end of SMPBasicBlock::GetFirstLiveIn()

// Get termination iterator marker for the LiveIn set, for use by predecessors.
set<op_t, LessOp>::iterator SMPBasicBlock::GetLastLiveIn(void) {
	// Does not matter if it is stale or not; end marker is the same
	return this->LiveInSet.end();
}

// Get iterator for the start of the LiveOut set.
set<op_t, LessOp>::iterator SMPBasicBlock::GetFirstLiveOut(void) {
	return this->LiveOutSet.begin();
}

// Get termination iterator marker for the LiveOut set.
set<op_t, LessOp>::iterator SMPBasicBlock::GetLastLiveOut(void) {
	return this->LiveOutSet.end();
}

// Get iterator for the start of the VarKill set.
set<op_t, LessOp>::iterator SMPBasicBlock::GetFirstVarKill(void) {
	return this->KillSet.begin();
}

// Get termination iterator marker for the VarKill set.
set<op_t, LessOp>::iterator SMPBasicBlock::GetLastVarKill(void) {
	return this->KillSet.end();
}

// Get iterator for the start of the UpExposed set.
set<op_t, LessOp>::iterator SMPBasicBlock::GetFirstUpExposed(void) {
	return this->UpExposedSet.begin();
}

// Get termination iterator marker for the UpExposed set.
set<op_t, LessOp>::iterator SMPBasicBlock::GetLastUpExposed(void) {
	return this->UpExposedSet.end();
}

// Get iterator for the start of the LocalNames set.
set<op_t, LessOp>::iterator SMPBasicBlock::GetFirstLocalName(void) {
	return this->LocalNames.begin();
}

// Get termination iterator marker for the LocalNames set.
set<op_t, LessOp>::iterator SMPBasicBlock::GetLastLocalName(void) {
	return this->LocalNames.end();
}

// Get iterator for the start of the DomFrontier set.
set<int>::iterator SMPBasicBlock::GetFirstDomFrontier(void) {
	return this->DomFrontier.begin();
}

// Get termination iterator marker for the DomFrontier set.
set<int>::iterator SMPBasicBlock::GetLastDomFrontier(void) {
	return this->DomFrontier.end();
}

// Get iterator for first Phi function.
set<SMPPhiFunction, LessPhi>::iterator SMPBasicBlock::GetFirstPhi(void) {
	return this->PhiFunctions.begin();
}

// Get termination iterator marker for Phi functions set.
set<SMPPhiFunction, LessPhi>::iterator SMPBasicBlock::GetLastPhi(void) {
	return this->PhiFunctions.end();
}

// Find the Phi function that matches the given op_t.
set<SMPPhiFunction, LessPhi>::iterator SMPBasicBlock::FindPhi(op_t FindOp) {
	set<SMPPhiFunction, LessPhi>::iterator PhiIter;
	set<op_t, LessOp>::value_compare OpComp = this->LiveOutSet.value_comp(); // LessOp()
	for (PhiIter = this->GetFirstPhi(); PhiIter != this->GetLastPhi(); ++PhiIter) {
		op_t PhiOp = PhiIter->GetPhiRef(0).GetOp();
		if (OpComp(FindOp, PhiOp) || OpComp(PhiOp, FindOp)) {
			// One is less than the other.
			; // do nothing
		}
		else {
			// They are equal.
			return PhiIter;
		}
	}
	// If we exit the loop, we did not find it.
	return this->PhiFunctions.end();
} // end of SMPBasicBlock::FindPhi()

// Get a pointer to the instruction at address InstAddr.
//  Will assert if it does not find the instruction.
SMPInstr *SMPBasicBlock::FindInstr(ea_t InstAddr) {
	SMPInstr *CurrInst;
	map<ea_t, size_t>::iterator MapEntry;

	MapEntry = this->AddrInstMap.find(InstAddr);
	if (MapEntry == this->AddrInstMap.end()) {
		SMP_msg("FATAL ERROR: Failure on AddrInstMap. Size: %zu Addr: %lx \n",
			this->AddrInstMap.size(), (unsigned long) InstAddr);
		SMP_msg("First addr in block: %lx \n", (unsigned long) this->FirstAddr);
	}
	assert(MapEntry != this->AddrInstMap.end());
	CurrInst = this->GetInstFromIndex(MapEntry->second);

	return CurrInst;
} // end of SMPBasicBlock::FindInstr()

// Get an iterator to the instruction at address InstAddr.
//  Will assert if it does not find the instruction.
vector<SMPInstr *>::iterator SMPBasicBlock::GetInstIterFromAddr(ea_t InstAddr) {
#if 1
	size_t VecIndex = this->GetIndexFromInstAddr(InstAddr);
	vector<SMPInstr *>::iterator InstIter(this->InstVec.begin() + VecIndex);
#else

	vector<SMPInstr *>::iterator InstIter;
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		if (InstAddr == (*InstIter)->GetAddr()) {
			break;
		}
	}
	if (InstIter == this->GetLastInst()) {
		SMP_msg("FATAL ERROR: Failure to find Instr. Addr: %x \n", InstAddr);
		SMP_msg("First addr in block: %x \n", this->FirstAddr);
	}
#endif
	assert(InstIter != this->GetLastInst());

	return InstIter;
} // end of SMPBasicBlock::GetInstIterFromAddr()

// Get the InstVec index for the instruction at InstAddr. Assert if not found.
size_t SMPBasicBlock::GetIndexFromInstAddr(ea_t InstAddr) const {
	SMPInstr *CurrInst;
	ea_t CurrAddr;
	size_t VecIndex;
	size_t UpperLimit = this->InstVec.size();
	if (UpperLimit > 10) { // big enough for binary search
		size_t LowerLimit = 0;
		do {
			VecIndex = (LowerLimit + UpperLimit) / 2;
			CurrInst = this->InstVec[VecIndex];
			CurrAddr = CurrInst->GetAddr();
			if (CurrAddr > InstAddr) { // search lower half
				UpperLimit = VecIndex - 1;
			}
			else if (CurrAddr < InstAddr) { // search upper half
				LowerLimit = VecIndex + 1;
			}
		} while ((CurrAddr != InstAddr) && (LowerLimit <= UpperLimit));
	}
	else { // small enough for linear search
		for (VecIndex = 0; VecIndex < UpperLimit; ++VecIndex) {
			CurrInst = this->InstVec[VecIndex];
			CurrAddr = CurrInst->GetAddr();
			if (CurrAddr == InstAddr) {
				break;
			}
		}
	}
	assert((CurrAddr == InstAddr) && (VecIndex < this->InstVec.size()));
	return VecIndex;
} // end of SMPBasicBlock::GetIndexFromInstAddr()

// The predecessor order is used in SSA phi functions. Get the ordinal number
//  of a given block number in the predecessor list.
int SMPBasicBlock::GetPredPosition(int BlockNum) {
	int counter = 0;
	list<SMPBasicBlock *>::iterator PredIter;
	for (PredIter = this->GetFirstPred(); PredIter != this->GetLastPred(); ++PredIter) {
		if (BlockNum == (*PredIter)->GetNumber()) {
			return counter;
		}
		++counter;
	}
	return -1;
}

// Set the DEF iterator from the DefAddr and DefOp. Assert if not found.
set<DefOrUse, LessDefUse>::iterator SMPBasicBlock::GetGlobalDefIterFromDefAddr(op_t DefOp, ea_t DefAddr) {
	map<ea_t, size_t>::iterator MapIter = this->AddrInstMap.find(DefAddr);
	assert(MapIter != this->AddrInstMap.end());
	SMPInstr *DefInst = this->GetInstFromIndex(MapIter->second);
	set<DefOrUse, LessDefUse>::iterator DefIter = DefInst->FindDef(DefOp);
	assert(DefIter != DefInst->GetLastDef());
	return DefIter;
} // end of SMPBasicBlock::GetGlobalDefIterFromDefAddr()

#if 0 // never used
// Given a USE operand and the address of its instr, return DEF using DU chains or Phi func.
set<DefOrUse, LessDefUse>::iterator SMPBasicBlock::GetDefFromOpAddr(op_t UseOp, ea_t InstAddr, int SSANum) {
	ea_t DefAddr;
	SMPInstr *DefInstr;
	set<DefOrUse, LessDefUse>::iterator DefIter;

	if (this->IsLocalName(UseOp)) {
		// Search in the local DU chains.
		unsigned int LocalDUIndex = this->GetLocalDUIndex(UseOp, SSANum);
		DefAddr = this->LocalDUChains.ChainsByName.at(LocalDUIndex).GetDef(SSANum);
		DefInstr = this->FindInstr(DefAddr);
		DefIter = DefInstr->FindDef(UseOp);
		assert(DefIter != DefInstr->GetLastDef());
	}
	else {
		// Global DEF for this SSANum must be in the Phi functions or within a block.
		DefAddr = this->MyFunc->GetGlobalDefAddr(UseOp, SSANum);
		if (DefAddr == BADADDR) { // Could not find it anywhere.
			SMP_msg("ERROR: Failure in GetDefFromOpAddr(): InstAddr %x SSANum %d\n",
					InstAddr, SSANum);
			assert(DefAddr != BADADDR); // kablooey!
		}
		else if (DefAddr < this->MyFunc->GetNumBlocks()) {
			// A block number was returned, not an instruction address.
			//  The DEF for this SSANum is only in a Phi function for that
			//  block number.
			size_t BlockNumber = (size_t) DefAddr;
			set<SMPPhiFunction, LessPhi>::iterator PhiIter = this->MyFunc->GetPhiIterForPhiDef(BlockNumber, UseOp, SSANum);
				// PhiIter is guaranteed to be good, else we assert in GetPhiIterForPhiDef().
			assert(SSANum == PhiIter->GetDefSSANum());
			DefOrUse DefCopy = PhiIter->GetDefCopy();
			DefOrUseSet DummySet;
			DefIter = DummySet.InsertRef(DefCopy);
		}
		else { // Must be a DEF within a block, not in a Phi function.
			// NOTE: We might be looking within the current block with this code; perfectly OK.
			SMPBasicBlock *DefBlock = this->MyFunc->GetBlockFromInstAddr(DefAddr);
			DefIter = DefBlock->GetGlobalDefIterFromDefAddr(UseOp, DefAddr);
		}
	}

	return DefIter;
} // end of SMPBasicBlock::GetDefFromOpAddr()
#endif

#if STARS_BUILD_DEF_USE_CHAINS
// Given a USE operand and the address of its instr, return DEF addr using DU chains or Phi func.
//  If DEF is in a Phi function, we return the block number, which never conflicts with instruction
//   addresses.
ea_t SMPBasicBlock::GetDefAddrFromUseAddr(op_t UseOp, ea_t InstAddr, int SSANum, bool LocalName) {
	ea_t DefAddr = BADADDR;
	set<DefOrUse, LessDefUse>::iterator DefIter;
	bool RegisterOp = (o_reg == UseOp.type);

	if (LocalName) {
		// Search in the local DU chains.
		unsigned int LocalDUIndex = this->GetLocalDUIndex(UseOp, SSANum);
		DefAddr = this->GetFirstDefAddr(LocalDUIndex, SSANum, false);
	}
	else if (RegisterOp) {
		// Global DEF for this SSANum must be in the Phi functions or within a block.
		DefAddr = this->MyFunc->GetGlobalDefAddr(UseOp, SSANum);
		if (DefAddr == BADADDR) { // Could not find it anywhere.
			this->GetFunc()->Dump();
			SMP_msg("ERROR: Failure in GetDefAddrFromUseAddr(): InstAddr %x SSANum %d\n",
					InstAddr, SSANum);
			SMP_msg(" LocalName: %d UseOp.reg: %d\n", LocalName, UseOp.reg);
			assert(DefAddr != BADADDR); // kablooey!
		}
	}
	else if (MDIsDirectStackAccessOpnd(UseOp, this->GetFunc()->UsesFramePointer())) {
		// Func->GetGlobalDefAddr() only works on registers. Get stack DefAddr from
		//  Phi functions or DU chains.
		set<SMPPhiFunction, LessPhi>::iterator PhiIter = this->FindPhi(UseOp);
		if (PhiIter != this->GetLastPhi()) {
			// Found a Phi function for UseOp; does it DEF our SSANum?
			int PhiDefSSANum = PhiIter->GetDefSSANum();
			if (PhiDefSSANum == SSANum) {
				return this->BlockNum;  // BlockNum is signal that the Def has no real addr, is in Phi
			}
		}
		unsigned int GlobalDUIndex = this->GetGlobalDUIndex(UseOp, BADADDR);
		size_t chain;
		size_t NumChains = this->GetNumLocalChains(GlobalDUIndex, true);
		ea_t LastAddr;
		for (chain = 0; chain < NumChains; ++chain) {
			LastAddr = this->GetLastUseAddr(GlobalDUIndex, chain, true);
			if (LastAddr >= InstAddr) {
				// Found the chain with InstAddr within it.
				DefAddr = this->GetFirstDefAddr(GlobalDUIndex, chain, true);
				break;
			}
		}
	}

	return DefAddr;
} // end of SMPBasicBlock::GetDefAddrFromUseAddr()

#else

// Given a USE operand and the address of its instr, return DEF addr using SSA chains or Phi func.
//  If DEF is in a Phi function, we return the block number, which (hopefully) never conflicts with instruction
//   addresses.
ea_t SMPBasicBlock::GetDefAddrFromUseAddr(op_t UseOp, ea_t InstAddr, int SSANum, bool LocalName) {
	ea_t DefAddr = BADADDR;
	set<DefOrUse, LessDefUse>::iterator DefIter;
	bool RegisterOp = (o_reg == UseOp.type);
	bool PhiUse = (InstAddr < this->GetFunc()->GetNumBlocks());

	if (RegisterOp && (!LocalName)) {
		// Global DEF for this SSANum must be in the Phi functions or within a block.
		DefAddr = this->MyFunc->GetGlobalDefAddr(UseOp, SSANum); // only works on registers
		if (DefAddr == BADADDR) { // Could not find it anywhere.
			this->GetFunc()->Dump();
			SMP_msg("ERROR: Failure in GetDefAddrFromUseAddr(): InstAddr %lx SSANum %d\n",
					(unsigned long) InstAddr, SSANum);
			SMP_msg(" LocalName: %d UseOp.reg: %d\n", LocalName, UseOp.reg);
			assert(DefAddr != BADADDR); // kablooey!
		}
	}
	else if (LocalName || MDIsDirectStackAccessOpnd(UseOp, this->GetFunc()->UsesFramePointer())) {
		if (PhiUse) {
			// Need to find DEF for a PhiUse. Temporarily, we will use the slow linear search method.
			DefAddr = this->GetFunc()->GetGlobalDefAddr(UseOp, SSANum);
			if (BADADDR == DefAddr) { // Need to search Phi functions.
				// Rare case in which a Phi USE was traced only to a Phi DEF in an earlier block.
				DefAddr = (ea_t) this->GetFunc()->GetBlockNumForPhiDef(UseOp, SSANum);
				assert(BADADDR != DefAddr);
			}
		}
		else {
			vector<SMPInstr *>::iterator InstIter = this->GetInstIterFromAddr(InstAddr);
			if (this->IsVarKill(UseOp)) { // Cannot find a DEF in block if not in VarKill set for this block
				vector<SMPInstr *>::reverse_iterator RevInstIter(InstIter);
				while (RevInstIter != this->GetRevInstEnd()) {
					SMPInstr *CurrInst = (*RevInstIter);
					set<DefOrUse, LessDefUse>::iterator DefIter = CurrInst->FindDef(UseOp);
					if (DefIter != CurrInst->GetLastDef()) {
						DefAddr = CurrInst->GetAddr();
						assert(SSANum == DefIter->GetSSANum());
						break;
					}
					++RevInstIter;
				}
			}
			if (DefAddr == BADADDR) { // not found yet
				// Must be a global name defined in the Phi functions or LiveIn and UpExposed to the block, or a non-stack mem access.
				bool UseFP = this->GetFunc()->UsesFramePointer();
				assert(!LocalName || (!MDIsDataFlowOpnd(UseOp, UseFP)));
				set<SMPPhiFunction, LessPhi>::iterator PhiIter = this->FindPhi(UseOp);
				if (PhiIter != this->GetLastPhi()) {
					// Found a Phi function for UseOp; does it DEF our SSANum?
					int PhiDefSSANum = PhiIter->GetDefSSANum();
					if (PhiDefSSANum == SSANum) {
						DefAddr = this->BlockNum;  // BlockNum is signal that the Def has no real addr, is in Phi
					}
				}
				else {
					DefAddr = this->GetFirstAddr() - 1; // pseudo-def-addr for LiveIn, not in Phi, UpExposed
				}
			}
		}
	}

	return DefAddr;
} // end of SMPBasicBlock::GetDefAddrFromUseAddr()

#endif

ea_t SMPBasicBlock::GetUltimateDefAddr(op_t UseOp, ea_t InstAddr, int SSANum, bool LocalName) {
	ea_t DefAddr = BADADDR;
	DefAddr = this->GetDefAddrFromUseAddr(UseOp, InstAddr, SSANum, LocalName);
	bool LiveInAddr = (DefAddr == (this->GetFirstAddr() - 1));
	if (LiveInAddr && this->IsLiveIn(UseOp)) { // UpExposed or pass-through case
		// We need to find the predecessor block that DEFed the UseOp/SSANum.
		assert(!LocalName); // also cannot be a register; it is a global name stack var

#if 1
		size_t NumBlocks = this->GetFunc()->GetNumBlocks();
		bool FoundDEF = false;
		set<DefOrUse, LessDefUse>::iterator DefIter;
		// Check special case of DEF in marker instruction at beginning of function.
		if (SSANum == 0) {
			SMPInstr *FirstInst = this->GetFunc()->GetInstFromAddr(this->GetFunc()->GetFirstFuncAddr() - 1);
			if (FirstInst->IsFloatNop()) {
				DefIter = FirstInst->FindDef(UseOp);
				if (DefIter != FirstInst->GetLastDef()) {
					assert(0 == DefIter->GetSSANum());
					DefAddr = FirstInst->GetAddr();
					FoundDEF = true;
				}
			}
		}

		for (size_t BlockIndex = 0; (BlockIndex < NumBlocks) && (!FoundDEF); ++BlockIndex) {
			SMPBasicBlock *CurrBlock = this->GetFunc()->GetBlockByNum(BlockIndex);
			// Don't bother to look inside block insts unless UseOp is killed and LiveOut
			if (CurrBlock->IsLiveOut(UseOp)) {
				// Can we match the SSANum in an inst DEF or a Phi DEF?
				set<SMPPhiFunction, LessPhi>::iterator PhiIter = CurrBlock->FindPhi(UseOp);
				if (PhiIter != CurrBlock->GetLastPhi()) {
					if (SSANum == PhiIter->GetDefSSANum()) {
						DefAddr = (ea_t) BlockIndex;
						FoundDEF = true;
						break;
					}
				}
				if (CurrBlock->IsVarKill(UseOp)) {
					vector<SMPInstr *>::reverse_iterator RevInstIter;
					for (RevInstIter = CurrBlock->GetRevInstBegin(); RevInstIter != CurrBlock->GetRevInstEnd(); ++RevInstIter) {
						SMPInstr *CurrInst = (*RevInstIter);
						ea_t CurrAddr = CurrInst->GetAddr();
						if (CurrInst->HasDestMemoryOperand() || CurrInst->MDIsPushInstr()) {
							DefIter = CurrInst->FindDef(UseOp);
							if (DefIter != CurrInst->GetLastDef()) {
								// Because we are using a reverse iterator, the first DEF we encounter either
								//  matches the SSANum or else this block is irrelevant.
								if (SSANum == DefIter->GetSSANum()) {
									DefAddr = CurrAddr;
									FoundDEF = true;
								}
								break; // found it or did not; break regardless
							}
						}
					}
				}
			}
		}
#else
		list<SMPBasicBlock *>::iterator PredIter;
		bool FoundDefiningBlock = false;
		for (PredIter = this->GetFirstPred(); PredIter != this->GetLastPred(); ++PredIter) {
			SMPBasicBlock *PredBlock = (*PredIter);
			if (!PredBlock->IsProcessed() && PredBlock->IsLiveOut(UseOp)) {
				// Found possible defining block. At least one predecessor should have UseOp LiveOut.
				// We can recurse, but we need a pseudo UseAddr. We
				//  will use the last instruction in PredBlock as the pseudo UseAddr, but first
				//  we need to check to see if it is the DefAddr.
				vector<SMPInstr *>::reverse_iterator RevInstIter = PredBlock->GetRevInstBegin();
				SMPInstr *LastPredInst = (*RevInstIter);
				ea_t LastPredAddr = LastPredInst->GetAddr();
				if (LastPredInst->FindDef(UseOp) != LastPredInst->GetLastDef()) {
					DefAddr = LastPredAddr;
					PredBlock->SetProcessed(true);
					FoundDefiningBlock = true;
				}
				else { // We can use LastPredInst addr as pseudo-UseAddr.
					DefAddr = PredBlock->GetUltimateDefAddr(UseOp, LastPredAddr, SSANum, LocalName);
				}
				if (BADADDR != DefAddr) {
					break;
				}
			}
		}
#endif
	} // end if LiveIn
#if 0
	if (LiveInAddr) {
		DefAddr = BADADDR;
	}
#endif
	assert(BADADDR != DefAddr);
	return DefAddr;
} // end of SMPBasicBlock::GetUltimateDefAddr()

// STUB: Trace UseOp through move and Phi defs to some defining operation.
ea_t SMPBasicBlock::GetUltimateOperandSource(ea_t UseAddr, op_t UseOp, int UseSSANum) {
	bool LocalName = this->IsLocalName(UseOp);
	ea_t DefiningAddr = this->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
	SMPBasicBlock *CurrBlock;

	// We have four possibilities for DefiningAddr:
	//  1: BADADDR means we cannot trace the operand.
	//  2: An instruction address, in which case we recurse if inst is a move.
	//  3: Our block number, which means a Phi DEF, so we need to recurse into our predecessors.
	//  4: OUr block's first addr minus one, indicating upexposed in this block, need to recurse into predecessors.s


	return DefiningAddr;
} // end of SMPBasicBlock::GetUltimateOperandSource()

// Does DefOp get written out in truncated form (lower bits only)?
bool SMPBasicBlock::IsOpDestTruncatedWrite(op_t DefOp, int DefSSANum, ea_t DefAddr) { 
	vector<SMPInstr *>::iterator InstIter;
	SMPInstr *LastUseInst = NULL;
	set<DefOrUse, LessDefUse>::iterator DefIter;
	bool RegisterOp = (o_reg == DefOp.type);
	bool LocalName = this->IsLocalName(DefOp);
	bool LastUseIsTruncatedWrite = false;
	size_t chain;
	size_t NumChains;
	ea_t LastAddr = BADADDR;
	
	if (!RegisterOp || (DefSSANum == SMP_SSA_UNINIT))
		return false;

#if STARS_BUILD_DEF_USE_CHAINS
	if (LocalName) {
		// Search in the local DU chains.
		unsigned int LocalDUIndex = this->GetLocalDUIndex(DefOp, DefSSANum);
		NumChains = this->GetNumLocalChains(LocalDUIndex, false);
		for (chain = 0; chain < NumChains; ++chain) {
			if (this->GetFirstDefAddr(LocalDUIndex, chain, false) == DefAddr) {
				// Found the chain with DefAddr within it.
				LastAddr = this->GetLastUseAddr(LocalDUIndex, chain, false);
				break;
			}
		}
	}
	else {
		unsigned int GlobalDUIndex = this->GetGlobalDUIndex(DefOp, DefAddr);
		NumChains = this->GetNumLocalChains(GlobalDUIndex, true);
		for (chain = 0; chain < NumChains; ++chain) {
			if (this->GetFirstDefAddr(GlobalDUIndex, chain, true) == DefAddr) {
				// Found the chain with DefAddr within it.
				LastAddr = this->GetLastUseAddr(GlobalDUIndex, chain, true);
				break;
			}
		}
	}
#endif

	InstIter = this->GetInstIterFromAddr(DefAddr);
	++InstIter;
	while (InstIter != this->GetLastInst()) {
		LastUseInst = (*InstIter);
		if (LastUseInst->FindUse(DefOp) != LastUseInst->GetLastUse()) {
			LastAddr = LastUseInst->GetAddr();
		}
		if (LastUseInst->FindDef(DefOp) != LastUseInst->GetLastDef()) {
			// re-DEF
			break;
		}
		++InstIter;
	}

	if (BADADDR != LastAddr) {
		InstIter = this->GetInstIterFromAddr(LastAddr);
		LastUseInst = (*InstIter);
		if (LastUseInst->MDDoublesWidth()) {
			LastUseIsTruncatedWrite = true;
		}
		else if (LastUseInst->MDIsReducedWidthMove()) {
			// If DefOp is used as an address reg, it is not a truncated write of DefOp;
			//  otherwise, it is.
			LastUseIsTruncatedWrite = LastUseInst->IsNonAddressReg(DefOp);
		}
		if (!LastUseIsTruncatedWrite && (NULL != LastUseInst)) {
			// See if we can recurse through a regular move.
			if (LastUseInst->MDIsMoveInstr()) {
				DefIter = LastUseInst->GetFirstNonFlagsDef();
				assert(DefIter != LastUseInst->GetLastDef());
				op_t CopyDefOp = DefIter->GetOp();
				bool UseFP = this->GetFunc()->UsesFramePointer();
				if (MDIsDataFlowOpnd(CopyDefOp, UseFP)) {
					int CopyDefSSANum = DefIter->GetSSANum();
					LastUseIsTruncatedWrite = this->IsOpDestTruncatedWrite(CopyDefOp, CopyDefSSANum, LastAddr);
				}
			}
		}
	}

	return LastUseIsTruncatedWrite;
} // end of SMPBasicBlock::IsOpDestTruncatedWrite()

// Update the LiveOut set for the block.
// Return true if it changed, false otherwise.
bool SMPBasicBlock::UpdateLiveOut(void) {
	bool changed = false;
	set<op_t, LessOp> OldLiveOut(this->LiveOutSet); // save copy of old LiveOutSet
	this->LiveOutSet.clear();  // Clear it and rebuild it
	// Dataflow equation for LiveOutSet: If a variable is live-in for any successor
	//  block, it is live out for this block.
	list<SMPBasicBlock *>::iterator SuccIter;
	set<op_t, LessOp>::iterator InSuccIter;
	for (SuccIter = this->Successors.begin(); SuccIter != this->Successors.end(); ++SuccIter) {
		for (InSuccIter = (*SuccIter)->GetFirstLiveIn(); InSuccIter != (*SuccIter)->GetLastLiveIn(); ++InSuccIter) {
			this->LiveOutSet.insert(*InSuccIter);
		}
	}

	// Only remaining question: Did the LiveOutSet change?
	// Short cut: If the set cardinality changed, then the set changed.
	if (this->LiveOutSet.size() != OldLiveOut.size()) {
		changed = true;
	}
	else { // Same # of elements; move through in lockstep and compare.
		set<op_t, LessOp>::iterator NewIter = this->LiveOutSet.begin();
		set<op_t, LessOp>::iterator OldIter = OldLiveOut.begin();
		set<op_t, LessOp>::value_compare OpComp = OldLiveOut.value_comp(); // LessOp()
		while (OldIter != OldLiveOut.end()) { // both iters terminate simultaneously
			if (OpComp(*OldIter, *NewIter) || OpComp(*NewIter, *OldIter)) {
				changed = true;
				break;
			}
			++OldIter;
			++NewIter;
		}
	}

	if (changed)
		this->SetLiveInStale(true);

	OldLiveOut.clear();
	return changed;
} // end of SMPBasicBlock::UpdateLiveOut()

#if 0
// Set the SSA numbers for the DEFs in the LiveOut set.
void SMPBasicBlock::SetLiveOutSSANums(void) {
	size_t LiveOutCount = this->LiveOutSet.size();
	size_t LiveOutDefsMarked = 0;
	vector<SMPInstr *>::reverse_iterator RevInstIter;

	for (RevInstIter = this->GetRevInstBegin(); (RevInstIter != this->GetRevInstEnd()) &&  (LiveOutDefsMarked < LiveOutCount); ++RevInstIter) {
		set<DefOrUse, LessDefUse>::iterator DefIter;
		SMPInstr *CurrInst = (*RevInstIter);
		for (DefIter = CurrInst->GetFirstDef(); DefIter != CurrInst->GetLastDef(); ++DefIter) {
			op_t DefOp = DefIter->GetOp();
			set<DefOp, LessOp>::iterator LiveOutIter = this->LiveOutSet.find(DefOp);
			if (LiveOutIter != this->GetLastLiveOut()) { // found DefOp in LiveOut set
				;
			}
		}
	}
	return;
} // end of SMPBasicBlock::SetLiveOutSSANums()
#endif

// Compute the ReachesIn set as the union of the ReachesOut sets of all predecessor blocks.
// Return TRUE if the ReachesIn set was updated, false if it gained no new elements.
bool SMPBasicBlock::ComputeReachesInSet(void) {
	size_t OldSize = this->ReachesInSet.size();
	size_t NewSize; // If NewSize becomes different from OldSize, then ReachesInSet changed.
	list<SMPBasicBlock *>::iterator PredIter;

	for (PredIter = this->GetFirstPred(); PredIter != this->GetLastPred(); ++PredIter) {
		SMPBasicBlock *CurrPred = *PredIter;
		this->ReachesInSet.insert(CurrPred->GetFirstReachesOut(), CurrPred->GetLastReachesOut());
	}

	NewSize = this->ReachesInSet.size();
	return (NewSize != OldSize);
} // end of SMPBasicBlock::ComputeReachesInSet()

// Compute the ReachesOut set according to its dataflow formula: ReachesOut = ((ReachesIn minus VarKill) union DownExposedDefs).
bool SMPBasicBlock::ComputeReachesOutSet(void) {
	size_t OldSize = this->ReachesOutSet.size();
	size_t NewSize; // If NewSize becomes different from OldSize, then ReachesOutSet changed.

	// First step: Add all ReachesIn defns that are not killed.
	set<pair<op_t, ea_t>, LessDefinition>::iterator ReachesInIter;
	for (ReachesInIter = this->GetFirstReachesIn(); ReachesInIter != this->GetLastReachesIn(); ++ReachesInIter) {
		op_t InOp = ReachesInIter->first;
		if (!(this->IsVarKill(InOp))) {
			this->AddReachesOut(*ReachesInIter);
		}
	}

	// Second step: Add DEDefns.
	set<pair<op_t, ea_t>, LessDefinition>::iterator DEDefnIter;
	for (DEDefnIter = this->GetFirstDownExposedDefn(); DEDefnIter != this->GetLastDownExposedDefn(); ++DEDefnIter) {
		this->AddReachesOut(*DEDefnIter);
	}

	NewSize = this->ReachesOutSet.size();
	this->ResetReachesOutStale();
	return (NewSize != OldSize);
} // end of SMPBasicBlock::ComputeReachesOutSet()

// Add DefOp, remove previous defs of DefOp that now do not reach the end of the block.
void SMPBasicBlock::UpdateDownExposedDefs(op_t DefOp, ea_t InstAddr) {
	// First, remove any definition of DefOp that precedes the current definition.
	set<pair<op_t, ea_t>, LessDefinition>::iterator DEDefnIter = this->GetFirstDownExposedDefn();
	while (DEDefnIter != this->GetLastDownExposedDefn()) {
		op_t OldOp = DEDefnIter->first;
		if (IsEqOpIgnoreBitwidth(OldOp, DefOp)) {
			(void) this->DownExposedDefnSet.erase(DEDefnIter);
			break; // save time; should never be more than one defn per DefOp in this set, unlike ReachesIn & ReachesOut
		}
		else {
			++DEDefnIter;
		}
	}
	// Next, insert the new definition.
	pair<op_t, ea_t> NewDefn(DefOp, InstAddr);
	pair<set<pair<op_t, ea_t>, LessDefinition>::iterator, bool> InsertResult;
	InsertResult = this->DownExposedDefnSet.insert(NewDefn);
	assert(InsertResult.second);
	this->SetReachesOutStale();
	return;
} // end of SMPBasicBlock::UpdateDownExposedDefs()

// Evaluate constants for all instructions as part of SCCP algorithm at SMPFunction level.
void SMPBasicBlock::SCCPEvaluateConstants(enum STARSBranchConst &BranchEval, list<pair<int, int> > &CFGWorkList, list<pair<int, int> > &SSAWorkList) {
	// for (each instruction i in block) do
	//    if (i is an assignment) then
	//       EvaluateAssign(i)
	//    else if (i is a conditional branch) then
	//       EvaluateConditional(i)
	//    endif
	// endfor

	BranchEval = STARS_BRANCH_UNKNOWN;

	// for (each instruction i in block) do
	vector<SMPInstr *>::iterator InstIter;
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
	//    if (i is an assignment) then
	//       EvaluateAssign(i)
		SMPitype DataFlowType = CurrInst->GetDataFlowType();
		if (DEFAULT == DataFlowType) {
			CurrInst->SCCPEvaluateAssignment(SSAWorkList);
		}
	//    else if (i is a conditional branch) then
	//       EvaluateConditional(i)
		else if (COND_BRANCH == DataFlowType) {
			CurrInst->SCCPEvaluateCondBranch(BranchEval);
		}
	//    endif
	// endfor
	}
	this->SetSCCPVisited(true);

	// Handle successors, based on BranchEval.
	this->SCCPHandleSuccessors(BranchEval, CFGWorkList);

	return;
} // end of SMPBasicBlock::SCCPEvaluateConstants()

// Propagate GlobalOp/DefSSANum const value
void SMPBasicBlock::SCCPGlobalPropagationHelper(op_t GlobalOp, int DefSSANum, vector<STARSBitSet> ExecutedEdgeBitSet, list<pair<int, int> > &CFGWorkList, list<pair<int, int> > &SSAWorkList) {
	// Three cases: 
	// (1) GlobalOp/DefSSANum is a Phi USE, in which case we re-eval the Phi Function and return.
	// (2) GlobalOp/DefSSANum is upward exposed, in which case we find the UpExposed USEs and re-eval those statements and recurse if LiveOut.
	// (3) GlobalOp/DefSSANum is the pass-through case, so it must be LiveOut and we recurse.
	bool FoundReDEF = true;
	enum STARSBranchConst BranchEval;
	BranchEval = STARS_BRANCH_UNKNOWN;
	this->SetProcessed(true); // prevent infinite recursion
	set<SMPPhiFunction, LessPhi>::iterator PhiIter = this->FindPhi(GlobalOp);
	if (PhiIter != this->GetLastPhi()) { // Case 1.
		int PhiDefSSANum = PhiIter->GetDefSSANum();
		if (PhiDefSSANum != DefSSANum) { // DefSSANum should be found among the Phi USEs
			this->GetFunc()->EvaluateAllPhiConstants(this->GetNumber(), ExecutedEdgeBitSet, SSAWorkList);
		}
	}
	else if (this->IsUpExposed(GlobalOp)) { // case 2
		FoundReDEF = false;
		vector<SMPInstr *>::iterator InstIter;
		for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
			SMPInstr *CurrInst = (*InstIter);
			set<DefOrUse, LessDefUse>::iterator UseIter = CurrInst->FindUse(GlobalOp);
			if (UseIter != CurrInst->GetLastUse()) { // operand is USEd; check SSANum
				int UseSSANum = UseIter->GetSSANum();
				if (UseSSANum == DefSSANum) {
					SMPitype DataFlowType = CurrInst->GetDataFlowType();
					if (DEFAULT == DataFlowType) {
						CurrInst->SCCPEvaluateAssignment(SSAWorkList);
					}
					else if (COND_BRANCH == DataFlowType) {
						CurrInst->SCCPEvaluateCondBranch(BranchEval);
						this->SCCPHandleSuccessors(BranchEval, CFGWorkList);
					}
				}
			}
			set<DefOrUse, LessDefUse>::iterator DefIter = CurrInst->FindDef(GlobalOp);
			if (DefIter != CurrInst->GetLastDef()) { // check for re-DEF
				int NewDefSSANum = DefIter->GetSSANum();
				if (NewDefSSANum > DefSSANum) { // re-DEF; we can stop searching for USEs of DefOp/DefSSANum in this block
					FoundReDEF = true;
					break;
				}
			}
		} // end for all insts in block
	}
	else if (this->IsLiveOut(GlobalOp)) { // case 3
		// Not UpExposed, but LiveOut; not re-DEF in block
		FoundReDEF = false;
	}
	if (!FoundReDEF) { // common recursion for case 2 and case 3
		list<SMPBasicBlock *>::iterator SuccIter;
		for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) {
			SMPBasicBlock *SuccBlock = (*SuccIter);
			if ((!SuccBlock->IsProcessed()) && SuccBlock->IsSCCPVisited() && SuccBlock->IsLiveIn(GlobalOp)) {
				SuccBlock->SCCPGlobalPropagationHelper(GlobalOp, DefSSANum, ExecutedEdgeBitSet, CFGWorkList, SSAWorkList);
			}
		}
	}

	return;
} // end of SMPBasicBlock::SCCPGlobalPropagationHelper()

// Based on BranchEval, push successors onto CFGWorkList
void SMPBasicBlock::SCCPHandleSuccessors(enum STARSBranchConst &BranchEval, list<pair<int, int> > &CFGWorkList) {
	//  Put block successors on CFGWorkList, based on conditional branch evaluation if any
	bool TakeDistantSucc = (BranchEval != STARS_BRANCH_NEVER_TAKEN);
	bool TakeFallThroughSucc = (BranchEval != STARS_BRANCH_ALWAYS_TAKEN);
	list<SMPBasicBlock *>::iterator SuccBlockIter = this->GetFirstSucc();
	list<SMPBasicBlock *>::iterator FallThroughSuccIter = this->GetFallThroughSucc();
	while (SuccBlockIter != this->GetLastSucc()) { // not the return block; has a successor
		if (((SuccBlockIter == FallThroughSuccIter) && (TakeFallThroughSucc)) 
			|| ((SuccBlockIter != FallThroughSuccIter) && (TakeDistantSucc))) {
			int NextBlockNum = (*SuccBlockIter)->GetNumber();
			pair<int, int> TempEdge(this->GetNumber(), NextBlockNum);
			CFGWorkList.push_back(TempEdge);
		}
		++SuccBlockIter;
	}
	return;
} // end of SMPBasicBlock::SCCPHandleSuccessors()

// Patch binary to make this block into nops.
void SMPBasicBlock::SCCPNullifyUnreachableBlock(void) {
	SMP_msg("INFO: SCCP: Removing unreachable block at %lx, patching in NOPs\n", 
		(unsigned long) this->GetFirstAddr());

	// Remove this block from the predecessors list of its successors.
	list<SMPBasicBlock *>::iterator SuccIter;
	ea_t TempAddr = this->GetFirstAddr();
	for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) {
		(*SuccIter)->ErasePred(TempAddr);
	}

#if 1
	// Remove this block from the successors list of its predecessors.
	list<SMPBasicBlock *>::iterator PredIter;
	for (PredIter = this->GetFirstPred(); PredIter != this->GetLastPred(); ++PredIter) {
		(*PredIter)->EraseSucc(TempAddr);
	}
#endif

	// Patch all bytes in the database for this block into nops.
	size_t NumBytes = this->GetBlockSize();
	ea_t CurrAddr = this->GetFirstAddr();
	for (size_t ByteIndex = 0; ByteIndex < NumBytes; ++ByteIndex) {
		bool success = patch_byte(CurrAddr, MD_BINARY_NOP_INSTRUCTION);
		// If success == false, that just means the byte already had that value in the 
		//  database, so nothing was changed. Cannot assert that success should be true.
		//  assert(success);
		++CurrAddr;
	}

	return;
} // end of SMPBasicBlock::SCCPNullifyUnreachableBlock()

// Gather statistics on SCCP effectiveness
void SMPBasicBlock::SCCPGatherStatistics(void) {
#if STARS_SCCP_GATHER_STATISTICS
	vector<SMPInstr *>::iterator InstIter;
	bool ConstArgFound = false;
	bool ArgWriteFound = false;
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		SMPitype DataFlowType = CurrInst->GetDataFlowType();
		if (CurrInst->HasDestMemoryOperand()) { // NOTE: Use MDIsArgumentPass() instead?
			op_t MoveSourceOp = CurrInst->GetMoveSource();
			op_t DEFMemOp = CurrInst->GetMemDef();
			if ((o_void != MoveSourceOp.type) && this->GetFunc()->IsInOutgoingArgsRegion(DEFMemOp)) {
				++SCCPOutgoingArgWriteCount;
				ArgWriteFound = true;
				if (o_imm == MoveSourceOp.type) {
					++SCCPConstantOutgoingArgWriteCount;
					ConstArgFound = true;
				}
				else if (o_reg == MoveSourceOp.type) {
					CanonicalizeOpnd(MoveSourceOp);
					set<DefOrUse, LessDefUse>::iterator UseIter = CurrInst->FindUse(MoveSourceOp);
					assert(UseIter != CurrInst->GetLastUse());
					int UseSSANum = UseIter->GetSSANum();
					int UseHashIndex = HashGlobalNameAndSSA(MoveSourceOp, UseSSANum);
					map<int, struct STARS_SCCP_Const_Struct>::iterator ConstIter = this->GetFunc()->FindConstValue(UseHashIndex);
					if (ConstIter != this->GetFunc()->GetLastConstValueIter()) { // found an SCCP const entry
						++SCCPConstantOutgoingArgWriteCount;
						ConstArgFound = true;
					}
				}
			}
		}
		else if ((DataFlowType == CALL) || (DataFlowType == INDIR_CALL)) {
			// Need to start gathering data for the next call; reset counters.
			//  Can have multiple calls in one basic block.
			if (ArgWriteFound) {
				++SCCPFuncsWithArgWriteCount;
				if (ConstArgFound) {
					++SCCPFuncsWithConstantArgWriteCount;
				}
			}
			ArgWriteFound = false;
			ConstArgFound = false;
		}
	} // end for all instructions
	if (ArgWriteFound) {
		++SCCPFuncsWithArgWriteCount;
		if (ConstArgFound) {
			++SCCPFuncsWithConstantArgWriteCount;
		}
	}
#endif
	return;
} // end of SMPBasicBlock::SCCPGatherStatistics()

// Insert RPO number block into the dominance frontier set.
void SMPBasicBlock::AddToDomFrontier(int block) {
	this->DomFrontier.insert(block);
	return;
} // end of SMPBasicBlock::AddToDomFrontier()

// Fill the set of non-global names used in this block. Set local indices that can be
//  used later to index into a vector of def-use chains.
void SMPBasicBlock::SetLocalNames(void) {
	vector<SMPInstr *>::iterator InstIter;
	size_t LocalIndex = 0;
#if SMP_DEBUG_DATAFLOW
	SMP_msg("Entered SetLocalNames.\n");
#endif
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		for (CurrDef = CurrInst->GetFirstDef(); CurrDef != CurrInst->GetLastDef(); ++CurrDef) {
			op_t DefOp = CurrDef->GetOp();
			if (!(this->MyFunc->IsGlobalName(DefOp))) {
				// Not in global names set
				if (this->LocalNames.end() == this->LocalNames.find(DefOp)) {
					// Not yet in LocalNames, so add it.
					SetGlobalIndex(&DefOp, LocalIndex);
					this->LocalNames.insert(DefOp);
					++LocalIndex;
				}
			}
		}
	}
	return;
} // end of SMPBasicBlock::SetLocalNames()

#if STARS_BUILD_DEF_USE_CHAINS
// Create local def-use chains for all global names
// Important to remember that a chain can start without a def because the variable is Live-In;
//   in this case we give the chain a pseudo-def at address (first addr in block - 1) **!!**
// Variant on SSALocalRenumber
void SMPBasicBlock::CreateGlobalChains() {
	bool DebugFlag = false;
#if 0
	DebugFlag |= (0 == strcmp(".init_proc", this->MyFunc->GetFuncName()));
#endif
	size_t NumGlobals = this->MyFunc->NumGlobalNames();
	size_t LocalIndex;
	vector<int> LocalUseIndex;
	// Initialize LocalUseIndex and DUChain values for each local name.
	set<op_t, LessOp>::iterator NameIter;
	if (NumGlobals < 1)
		return;
	this->GlobalDUChains.ChainsByName.clear();
	this->GlobalDUChains.ChainsByName.reserve(NumGlobals);
	op_t TempOp = InitOp;
	SMPDUChainArray Temp(TempOp, this->GetFirstAddr() - 1);
	if (DebugFlag)
		SMP_msg("Initializing GlobalChainsByName.\n");
	this->GlobalDUChains.ChainsByName.assign(NumGlobals, Temp);
	for (NameIter = this->MyFunc->GetFirstGlobalName(); NameIter != this->MyFunc->GetLastGlobalName(); ++NameIter) {
		LocalIndex = (size_t) ExtractGlobalIndex(*NameIter);
		LocalUseIndex.push_back(-1); // init LocalUse indices to -1; first DEF will make it 0
		// Set the local name for each DU chain array.
		if (LocalIndex > this->GlobalDUChains.ChainsByName.size())
			SMP_msg("FATAL ERROR: LocalIndex %zu out of bounds in CreateGlobalChains.\n", LocalIndex);
		if (DebugFlag)
			SMP_msg("Setting name for LocalIndex = %zu\n", LocalIndex);
		this->GlobalDUChains.ChainsByName.at(LocalIndex).SetName(*NameIter, this->GetFirstAddr() - 1);
	}

	// Iterate through all instructions in the block. For each DEF of a global name,
	//  set a new LocalUse index and start a new DU chain. For each USE of a global name,
	//  set the current LocalUse index for that name and add the instruction to the DU
	//  chain.
	vector<SMPInstr *>::iterator InstIter;
	set<DefOrUse, LessDefUse>::iterator CurrUse, CurrDef;
	set<op_t, LessOp>::iterator UseNameIter, DefNameIter;
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		size_t NameIndex;
		ea_t InstAddr = CurrInst->GetAddr();
		// USEs get referenced logically before DEFs, so start with them.
		CurrUse = CurrInst->GetFirstUse();
		while (CurrUse != CurrInst->GetLastUse()) {
			op_t UseOp = CurrUse->GetOp();
			UseNameIter = this->MyFunc->FindGlobalName(UseOp);
			if (UseNameIter != this->MyFunc->GetLastGlobalName()) {
				// Found USE of a global name
				NameIndex = ExtractGlobalIndex(*UseNameIter);
				if (NameIndex > LocalUseIndex.size())
					SMP_msg("NameIndex %zu out of range in CreateGlobalChains.\n", NameIndex);
				int LocalUseNum = LocalUseIndex.at(NameIndex);
				if (LocalUseNum == -1) { // LiveIn, use before def
					LocalUseIndex.at(NameIndex)++;
					LocalUseNum++;
					// Make the DEF be just before the start of the block
					SMPDefUseChain TempDefChain(UseOp, 0);
					this->GlobalDUChains.ChainsByName.at(NameIndex).PushChain(TempDefChain);
#if SMP_COUNT_MEMORY_ALLOCATIONS
					SMPDefUseChainBytes += sizeof(TempDefChain);
#endif
				}
				// Push address of USE instruction onto the DEF-USE chain for this LocalUseNum.
				this->GlobalDUChains.ChainsByName.at(NameIndex).PushUse(LocalUseNum, CurrInst->GetAddr());
#if SMP_COUNT_MEMORY_ALLOCATIONS
				SMPDefUseChainBytes += SMP_DU_ADDR_SIZE;
#endif
			}
			++CurrUse;
		} // end for all USEs in the instruction.
		// Now do the DEFs.
		CurrDef = CurrInst->GetFirstDef();
		while (CurrDef != CurrInst->GetLastDef()) {
			op_t DefOp = CurrDef->GetOp();
			DefNameIter = this->MyFunc->FindGlobalName(DefOp);
			if (DefNameIter != this->MyFunc->GetLastGlobalName()) {
				// Found DEF of a global name.
				size_t NameIndex = ExtractGlobalIndex(*DefNameIter);
				if (NameIndex > LocalUseIndex.size())
					SMP_msg("DEF NameIndex %zu out of range in CreateGlobalChains.\n", NameIndex);
				++LocalUseIndex[NameIndex]; // move up to next LocalUse subscript number
#if 0
				// Before the push_back() call, we should have # chains equal to new LocalUseNum
				int LocalUseNum = LocalUseIndex.at(NameIndex);
				assert(LocalUseNum == this->GlobalDUChains.ChainsByName.at(NameIndex).GetSize());
#endif
				// Set up a new DU chain and push it onto the vector of DU chains for this
				//  local name. Push the DEF onto the list (it will be the first reference
				//  on the list, because the list was newly created).
				SMPDefUseChain TempDefChain(DefOp, CurrInst->GetAddr() - this->GetFirstAddr() + 1);
				this->GlobalDUChains.ChainsByName.at(NameIndex).PushChain(TempDefChain);
#if SMP_COUNT_MEMORY_ALLOCATIONS
				SMPDefUseChainBytes += sizeof(TempDefChain);
#endif
			}
			++CurrDef;
		} // end for all DEFs in the instruction
	} // end for all instructions in the block

#if SMP_COUNT_MEMORY_ALLOCATIONS
	for (size_t ArrayIndex = 0; ArrayIndex < this->GlobalDUChains.ChainsByName.size(); ++ArrayIndex) {
		SMPDefUseChainCount += this->GlobalDUChains.ChainsByName.at(ArrayIndex).GetSize();
	}
#endif

	if (DebugFlag)
		SMP_msg("Exiting CreateGlobalChains()\n");
	return;
} // end of SMPBasicBlock::CreateGlobalChains()
#endif

// Create local DEF-USE chains and renumber all references to all names in LocalNames.
void SMPBasicBlock::SSALocalRenumber(void) {
	bool DebugFlag = false;
#if 0
	DebugFlag |= (0 == strcmp(".init_proc", this->MyFunc->GetFuncName()));
#endif
	size_t NumLocals = this->LocalNames.size();
	size_t LocalIndex;
	vector<int> SSAIndex;
	// Initialize SSAIndex and DUChain values for each local name.
	set<op_t, LessOp>::iterator NameIter;
	if (DebugFlag)
		SMP_msg("LocalNames size: %zu\n", NumLocals);
#if STARS_BUILD_DEF_USE_CHAINS
	this->LocalDUChains.ChainsByName.clear();
	this->LocalDUChains.ChainsByName.reserve(NumLocals);
#endif
	op_t TempOp = InitOp;
#if STARS_BUILD_DEF_USE_CHAINS
	SMPDUChainArray Temp(TempOp, this->GetFirstAddr() - 1);
	if (DebugFlag)
		SMP_msg("Initializing ChainsByName.\n");
	this->LocalDUChains.ChainsByName.assign(NumLocals, Temp);
	for (NameIter = this->LocalNames.begin(); NameIter != this->LocalNames.end(); ++NameIter) {
		LocalIndex = (size_t) ExtractGlobalIndex(*NameIter);
		SSAIndex.push_back(-1); // init SSA indices to -1; first DEF will make it 0
		// Set the local name for each DU chain array.
		if (LocalIndex > this->LocalDUChains.ChainsByName.size())
			SMP_msg("FATAL ERROR: LocalIndex %zu out of bounds in SSALocalRenumber.\n", LocalIndex);
		if (DebugFlag)
			SMP_msg("Setting name for LocalIndex = %zu\n", LocalIndex);
		this->LocalDUChains.ChainsByName.at(LocalIndex).SetName(*NameIter, this->GetFirstAddr() - 1);
	}
#else
	for (NameIter = this->LocalNames.begin(); NameIter != this->LocalNames.end(); ++NameIter) {
		LocalIndex = (size_t) ExtractGlobalIndex(*NameIter);
		SSAIndex.push_back(-1); // init SSA indices to -1; first DEF will make it 0
	}

#endif

	// Iterate through all instructions in the block. For each DEF of a local name,
	//  set a new SSA index and start a new DU chain. For each USE of a local name,
	//  set the current SSA index for that name and add the instruction to the DU
	//  chain.
	vector<SMPInstr *>::iterator InstIter;
	set<DefOrUse, LessDefUse>::iterator CurrUse, CurrDef;
	set<op_t, LessOp>::iterator UseNameIter, DefNameIter;
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		size_t NameIndex;
		// USEs get referenced logically before DEFs, so start with them.
		CurrUse = CurrInst->GetFirstUse();
		while (CurrUse != CurrInst->GetLastUse()) {
			op_t UseOp = CurrUse->GetOp();
			UseNameIter = this->LocalNames.find(UseOp);
			if (UseNameIter != this->LocalNames.end()) {
				// Found USE of a local name.
				NameIndex = ExtractGlobalIndex(*UseNameIter);
				if (NameIndex > SSAIndex.size())
					SMP_msg("FATAL ERROR: NameIndex %zu out of range in SSALocalRenumber.\n", NameIndex);
				int SSANum = SSAIndex.at(NameIndex);
				// Update the SSA subscript in the DEF-USE list for the instruction.
#if SMP_DEBUG_DATAFLOW
				if (DebugFlag) {
					SMP_msg("Setting SSANum to %d for local NameIndex %d\n", SSANum, NameIndex);
					SMP_msg("Addr %x USE operand: ", CurrInst->GetAddr()); 
					PrintOneOperand(UseOp, 0, -1);
					SMP_msg("\n");
				}
#endif
				CurrUse = CurrInst->SetUseSSA(UseOp, SSANum);
#if STARS_BUILD_DEF_USE_CHAINS
				if (SSANum >= 0) { // skip USE before DEF names
					if ((size_t) SSANum > this->LocalDUChains.ChainsByName.at(NameIndex).GetSize())
						SMP_msg("FATAL ERROR: SSANum %d out of range in SSALocalRenumber.\n", SSANum);
					// Push address of USE instruction onto the DEF-USE chain for this SSANum.
					this->LocalDUChains.ChainsByName.at(NameIndex).PushUse(SSANum, CurrInst->GetAddr());
				}
#endif
			}
			++CurrUse;
		} // end for all USEs in the instruction.
		// Now do the DEFs.
		CurrDef = CurrInst->GetFirstDef();
		while (CurrDef != CurrInst->GetLastDef()) {
			op_t DefOp = CurrDef->GetOp();
			DefNameIter = this->LocalNames.find(DefOp);
			if (DefNameIter != this->LocalNames.end()) {
				// Found DEF of a local name.
				NameIndex = ExtractGlobalIndex(*DefNameIter);
				if (NameIndex > SSAIndex.size())
					SMP_msg("ERROR: DEF NameIndex %zu out of range in SSALocalRenumber.\n", NameIndex);
				++SSAIndex[NameIndex]; // move up to next SSA subscript number
				int SSANum = SSAIndex.at(NameIndex);
				// Put new SSA number into DEF list entry in the instruction.
				CurrDef = CurrInst->SetDefSSA(DefOp, SSANum);
#if STARS_BUILD_DEF_USE_CHAINS
				// Before the push_back() call, we should have # chains equal to new SSANum
				assert(SSANum == (int) this->LocalDUChains.ChainsByName.at(NameIndex).GetSize());
#endif
				SetGlobalIndex(&DefOp, NameIndex);
#if STARS_BUILD_DEF_USE_CHAINS
				// Set up a new DU chain and push it onto the vector of DU chains for this
				//  local name. Push the DEF onto the list (it will be the first reference
				//  on the list, because the list was newly created).
				SMPDefUseChain TempDefChain(DefOp, CurrInst->GetAddr() - this->GetFirstAddr() + 1);
				this->LocalDUChains.ChainsByName.at(NameIndex).PushChain(TempDefChain);
#endif
			}
			++CurrDef;
		} // end for all DEFs in the instruction
	} // end for all instructions in the block

#if STARS_BUILD_DEF_USE_CHAINS
#if SMP_COUNT_MEMORY_ALLOCATIONS
	for (size_t ArrayIndex = 0; ArrayIndex < this->LocalDUChains.ChainsByName.size(); ++ArrayIndex) {
		SMPDefUseChainCount += this->LocalDUChains.ChainsByName.at(ArrayIndex).GetSize();
	}
#endif
#endif

	if (DebugFlag)
		SMP_msg("Exiting SSALocalRenumber()\n");
	return;
} // end of SMPBasicBlock::SSALocalRenumber()

// Determine if block is loop tail, also set loop header flag for dominating back-edge successor.
bool SMPBasicBlock::FindLoopHeadsAndTails(void) {
	bool LoopTail = false;
	list<SMPBasicBlock *>::iterator SuccIter;
	for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) {
		int SuccBlockNum = (*SuccIter)->GetNumber();
		if (this->GetFunc()->DoesBlockDominateBlock(SuccBlockNum, this->GetNumber())) {
			LoopTail = true;
			this->SetLoopTailBlock();
			(*SuccIter)->SetLoopHeaderBlock();
			this->LoopHeaderNumber = (*SuccIter)->GetNumber();
			break; // should only be able to have one back edge to a loop header
		}
	}
	return LoopTail;
} // end of SMPBasicBlock::FindLoopHeadsAndTails()

// Free memory for reaching defs sets after they are no longer needed.
void SMPBasicBlock::FreeReachingDefsMemory(void) {
	this->ReachesInSet.clear();
	this->ReachesOutSet.clear();
	this->DownExposedDefnSet.clear();
	return;
} // end of SMPBasicBlock::FreeReachingDefsMemory()

// Free SSA data structures that are no longer needed when all SSA numbers have
//  been recorded in DEFs and USEs.
void SMPBasicBlock::FreeSSAMemory(void) {
	this->DomFrontier.clear();
#if SMP_SHRINK_TO_FIT
	std::set<int>(this->DomFrontier).swap(this->DomFrontier);
#endif
	return;
} // end of SMPBasicBlock::FreeSSAMemory()

// After type inference, before annotation emission, free memory that is no
//  longer needed (i.e. after loop 4 in SMPProgram::Analyze()).
void SMPBasicBlock::FreeUnusedMemory4(void) {
	this->LiveInSet.clear();
#if 0  // PhiFunctions, LiveOutSet, Successors and AddrInstMap are used in SMPInstr::EmitIntegerErrorAnnotations()
	this->KillSet.clear();
	this->LiveOutSet.clear();
	this->Predecessors.clear();
	this->Successors.clear();
	this->PhiFunctions.clear();
	this->AddrInstMap.clear();
#endif
	this->UpExposedSet.clear();
#if SMP_SHRINK_TO_FIT
	std::set<op_t, LessOp>(this->LiveInSet).swap(this->LiveInSet);
	std::set<op_t, LessOp>(this->UpExposedSet).swap(this->UpExposedSet);
#if 0
	std::set<op_t, LessOp>(this->KillSet).swap(this->KillSet);
	std::set<op_t, LessOp>(this->LiveInSet).swap(this->LiveOutSet);
	std::set<SMPPhiFunction, LessPhi>(this->PhiFunctions).swap(this->PhiFunctions);
	std::map<ea_t, size_t>(this->AddrInstMap).swap(this->AddrInstMap);
	std::list<SMPBasicBlock *>(this->Predecessors).swap(this->Predecessors);
	std::list<SMPBasicBlock *>(this->Successors).swap(this->Successors);
#endif
#endif
	return;
} // end of SMPBasicBlock::FreeUnusedMemory4()

// Find the local Def-Use chain index for the given DefOp with given SSA index.
unsigned int SMPBasicBlock::GetLocalDUIndex(op_t DefOp, int SSANum) {
	unsigned int RegIndex = 0;
	set<op_t, LessOp>::iterator NameIter;

	NameIter = this->LocalNames.find(DefOp);
	if (NameIter == this->LocalNames.end()) {
		SMP_msg("ERROR: local DEF name not in LocalNames: ");
		PrintOperand(DefOp);
		SMP_msg("\n");
		assert(NameIter != this->LocalNames.end()); // abort
	}
	else {
		// DefOp is in the LocalNames, as expected
		RegIndex = ExtractGlobalIndex(*NameIter);
		assert(0 <= SSANum);
#if STARS_BUILD_DEF_USE_CHAINS
		assert(SSANum < (int) this->GetNumLocalChains(RegIndex, false));
#endif
	}
	return RegIndex;
} // end of SMPBasicBlock::GetLocalDUIndex()

// Find the global Def-Use chain index for the given DefOp with given address.
unsigned int SMPBasicBlock::GetGlobalDUIndex(op_t DefOp, ea_t DefAddr) {
	unsigned int RegIndex = 0;
	set<op_t, LessOp>::iterator NameIter;

	NameIter = this->MyFunc->FindGlobalName(DefOp);
	if (NameIter == this->MyFunc->GetLastGlobalName()) {
		SMP_msg("ERROR: global DEF name at %lx not in GlobalNames: ", (unsigned long) DefAddr);
		PrintOperand(DefOp);
		SMP_msg("\n");
		assert(NameIter != this->MyFunc->GetLastGlobalName()); // abort
	}
	else {
		// DefOp is in the GlobalNames, as expected
		RegIndex = ExtractGlobalIndex(*NameIter);
	}
	return RegIndex;
} // end of SMPBasicBlock::GetGlobalDUIndex()

#if STARS_BUILD_DEF_USE_CHAINS
// Any global DU chains for DefOp?
bool SMPBasicBlock::HasGlobalDUChain(op_t DefOp, ea_t DefAddr) {
	unsigned int DUIndex = this->GetGlobalDUIndex(DefOp, DefAddr);
	size_t NumChains = this->GetNumLocalChains(DUIndex, true);
	return (0 < NumChains);
}

// Any global DU chains for DUIndex?
bool SMPBasicBlock::IsGlobalReferenced(unsigned int DUIndex) {
	size_t NumChains = this->GetNumLocalChains(DUIndex, true);
	return (0 < NumChains);
}
#endif

#if STARS_BUILD_DEF_USE_CHAINS
// For the local Def-Use chain for DefOp/SSANum, return the IndWrite flag.
bool SMPBasicBlock::GetLocalDUChainIndWrite(op_t DefOp, int SSANum) {
	unsigned int DUIndex = this->GetLocalDUIndex(DefOp, SSANum);
	return this->LocalDUChains.ChainsByName.at(DUIndex).HasIndirectWrite(SSANum);
}

// For the global Def-Use chain for DefOp at DefAddr, return the IndWrite flag.
bool SMPBasicBlock::GetGlobalDUChainIndWrite(op_t DefOp, ea_t DefAddr) {
	unsigned int DUIndex = this->GetGlobalDUIndex(DefOp, DefAddr);
	size_t chain;
	size_t NumChains = this->GetNumLocalChains(DUIndex, true);
	for (chain = 0; chain < NumChains; ++chain) {
		if (DefAddr == this->GetFirstDefAddr(DUIndex, chain, true)) {
			// Found the chain with matching DefAddr.
			return this->GlobalDUChains.ChainsByName.at(DUIndex).HasIndirectWrite(chain);
		}
	}
	return false; // not found; pass-through case, global not def or use in block
} // end of SMPBasicBlock::GetGlobalDUChainIndWrite()

// Is DU-chain at DefAddr the last one for global DefOp?
bool SMPBasicBlock::IsLastGlobalChain(op_t DefOp, ea_t DefAddr) {
	unsigned int DUIndex = this->GetGlobalDUIndex(DefOp, DefAddr);
	size_t LastIndex = this->GetNumLocalChains(DUIndex, true) - 1;
	ea_t LastDefAddr = this->GetFirstDefAddr(DUIndex, LastIndex, true);
	return (DefAddr == LastDefAddr);
} // end of SMPBasicBlock::IsLastGlobalChain()
#endif

// MemDefOp starting at InstIter has DU chain overlapping an indirect mem write
bool SMPBasicBlock::HasUseAfterIndWrite(op_t MemDefOp, vector<SMPInstr *>::iterator InstIter, bool &IndWriteSeen, bool &ReDef) {
	IndWriteSeen = false;
	ReDef = false;

	bool FoundIndirectWrite = false;
	set<DefOrUse, LessDefUse>::iterator UseIter;
	while (InstIter != this->GetLastInst()) {
		SMPInstr *TempInst = (*InstIter);
		if (TempInst->FindDef(MemDefOp) != TempInst->GetLastDef()) {
			// Re-DEF before indirect write.
			ReDef = true;
			return false;
		}
		else if (FoundIndirectWrite) {
			UseIter = TempInst->FindUse(MemDefOp);
			if (UseIter != TempInst->GetLastUse()) {
				// USEd after indirect write.
				return true;
			}
		}
		else if (TempInst->HasIndirectMemoryWrite()) {
			// Indirect write before re-DEF.
			FoundIndirectWrite = true;
			IndWriteSeen = true;
		}
		++InstIter;
	}
	// No re-DEF, no use after indirect write.
	return false;
} // end of SMPBasicBlock::HasUseAfterIndWrite()

// If branch at block end is signed/unsigned, propagate to operands that set flags before it.
void SMPBasicBlock::MarkBranchSignedness(void) {
	unsigned short SignMask;
	set<DefOrUse, LessDefUse>::iterator UseIter;
	op_t UseOp = InitOp;
	ea_t DefAddr;  // for flags USE in branch
	int SSANum;    // for flags USE in branch
	bool LocalFlags;  // is flags register a local name?
	vector<SMPInstr *>::reverse_iterator InstRevIter;

	InstRevIter = this->GetRevInstBegin(); // Any conditional branch would be last instruction
	SMPInstr *LastInst = (*InstRevIter);
	if (LastInst->MDIsUnsignedBranch()) {
		if (this->IsBranchSignednessUnreliable()) {
			return;
		}
		SignMask = FG_MASK_UNSIGNED;
	}
	else if (LastInst->MDIsSignedBranch()) {
		SignMask = FG_MASK_SIGNED;
	}
	else
		return; // Last instruction is not a signed or unsigned branch.

	// Find the flags USE.
	UseOp.type = o_reg; // set up a dummy op for searching
	UseOp.reg = X86_FLAGS_REG;
	UseIter = LastInst->FindUse(UseOp);
	assert(UseIter != LastInst->GetLastUse());
	UseOp = UseIter->GetOp(); // get full info in all fields
	SSANum = UseIter->GetSSANum();
	LocalFlags = this->IsLocalName(UseOp);

	DefAddr = this->GetDefAddrFromUseAddr(UseOp, LastInst->GetAddr(), SSANum, LocalFlags);
	// Pass DefAddr to recursive helper function.
	this->PropagateBranchSignedness(DefAddr, UseOp, SignMask);

	return;
} // end of SMPBasicBlock::MarkBranchSignedness()

// For the DefAddr of the SearchOp, propagate SignMask to all DEFs and USEs in the
//  instruction or Phi function indicated by DefAddr.
// Currently, the DefAddr initially will be an instruction that defined the flags that were used in a signed or
//  unsigned branch instruction, and the SearchOp will be the flags register. Upon recursion, the DefAddr
//  and SearchOp will change as we backtrack up the signedness propagation chain.
// We recurse on all USEs until we encounter memory operands, also terminating the recursion as
//  soon as we see an instruction other than a move, compare, or test.
void SMPBasicBlock::PropagateBranchSignedness(ea_t DefAddr, op_t SearchOp, unsigned short SignMask) {
	SMPInstr *DefInst;
	SMPBasicBlock *DefBlock;
	set<DefOrUse, LessDefUse>::iterator UseIter;
	set<DefOrUse, LessDefUse>::iterator DefIter;
	int DefHashValue, UseHashValue;
	ea_t PhiUseDefAddr; // for a Phi USE, where was it DEFed?
	ea_t UseDefAddr; // for an instruction USE, where was it DEFed?
	bool LocalDef = this->IsLocalName(SearchOp);

	if (SearchOp.type == o_reg)
		CanonicalizeOpnd(SearchOp);
	else
		return;  // Limit to registers for now

	if (DefAddr < this->MyFunc->GetNumBlocks()) { // found in Phi DEF; DefAddr is block #
		// We need to propagate the SignMask to the Phi DEF, and then to the Phi USEs, and
		//  then we need to propagate the SignMask to the DEF of each Phi USE. It is possible
		//  that a Phi USE has its DEF in another block's Phi function, so this might recurse.
		size_t BlockNum = (size_t) DefAddr;
		if (IsMemOperand(SearchOp))
			return;  // end recursion
		DefBlock = this->MyFunc->GetBlockByNum(BlockNum);
		set<SMPPhiFunction, LessPhi>::iterator PhiIter = DefBlock->FindPhi(SearchOp);
		assert(PhiIter != DefBlock->GetLastPhi());
		int SSANum = PhiIter->GetDefSSANum();
		DefHashValue = HashGlobalNameAndSSA(SearchOp, SSANum);
		this->MyFunc->UpdateDefSignMiscInfo(DefHashValue, SignMask);

		size_t UseIndex, UseLimit;
		UseLimit = PhiIter->GetPhiListSize();
		for (UseIndex = 0; UseIndex < UseLimit; ++UseIndex) {
			int UseSSANum = PhiIter->GetUseSSANum(UseIndex);
			UseHashValue = HashGlobalNameAndSSA(SearchOp, UseSSANum);
			// Avoid propagation and recursion if no change will be made.
			unsigned short OldSignInfo = this->MyFunc->GetUseSignMiscInfo(UseHashValue);
			if (OldSignInfo != (OldSignInfo | SignMask)) { // sign info will change
				this->MyFunc->UpdateUseSignMiscInfo(UseHashValue, SignMask);
				PhiUseDefAddr = this->MyFunc->GetGlobalDefAddr(SearchOp, UseSSANum);
				assert(BADADDR != PhiUseDefAddr);
				if (PhiUseDefAddr < this->MyFunc->GetNumBlocks()) {
					// DEF of current Phi USE is in another Phi function.
					DefBlock = this->MyFunc->GetBlockByNum((size_t) PhiUseDefAddr);
				}
				else { // DEF is in an instruction.
					DefBlock = this->MyFunc->GetBlockFromInstAddr(PhiUseDefAddr);
				}
				if (PhiUseDefAddr != DefAddr) { // Don't recurse infinitely
					DefBlock->PropagateBranchSignedness(PhiUseDefAddr, SearchOp, SignMask); // recurse
				}
			}
		}
	}
	else { // DEF must be in an instruction
		if (LocalDef) { // DEF must be in a local instruction
			DefInst = this->FindInstr(DefAddr);
		}
		else { // DEF might be in any block in the function
			DefBlock = this->MyFunc->GetBlockFromInstAddr(DefAddr);
			// DefBlock must be good, else GetBlockFromInstAddr() would assert.
			DefInst = DefBlock->FindInstr(DefAddr);
		}

		// We sometimes have a compiler idiom in which a comparison is made between a signed char and
		//  an ASCII value, and then an unsigned branch is taken. We don't want to propagate UNSIGNED
		//  in this case, and we are unsure what signedness is truly present, so we just return.
		if ((FG_MASK_UNSIGNED == SignMask) && (DefInst->MDComparesImmedASCII())) {
			return;
		}

		// If the DEF is from a call instruction, we only want to propagate the sign to the DEF
		//  itself and stop the recursion. The other register USEs and DEFs of the call are unrelated
		//  to the SearchOp DEF, unlike arithmetic instructions.
		if (DefInst->GetDataFlowType() >= JUMP) {
			DefIter = DefInst->FindDef(SearchOp);
			assert(DefIter != DefInst->GetLastDef());
			DefHashValue = HashGlobalNameAndSSA(SearchOp, DefIter->GetSSANum());
			if (LocalDef) {
				this->UpdateDefSignMiscInfo(DefHashValue, SignMask);
			}
			else {
				this->MyFunc->UpdateDefSignMiscInfo(DefHashValue, SignMask);
			}
			return;
		}

		// Now we should have a good DefInst for the Inst that DEFs SearchOp.
		//  Loop through the DEFs and USEs in this Inst and OR in the SignMask for register operands.
		for (DefIter = DefInst->GetFirstDef(); DefIter != DefInst->GetLastDef(); ++DefIter) {
			op_t DefOp = DefIter->GetOp();
			if (DefOp.type == o_reg) {
				CanonicalizeOpnd(DefOp);
				DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
				if ((LocalDef && this->IsLocalName(DefOp))
					|| (!LocalDef && DefBlock->IsLocalName(DefOp))) {
					// DefOp is local to a block, must use block-local maps.
					if (LocalDef) { // still within current block
						this->UpdateDefSignMiscInfo(DefHashValue, SignMask);
					}
					else { // DEF in another block; use DefBlock
						DefBlock->UpdateDefSignMiscInfo(DefHashValue, SignMask);
					}
				}
				else { // DefOp is global, use SMPFunction global maps.
					this->MyFunc->UpdateDefSignMiscInfo(DefHashValue, SignMask);
				}
			}
		} // end for all DEFs

		// We don't want to propagate to USEs of instructions that load from non-stack memory. All of the
		//  uses are either memory locations or just addressing registers.
		bool ReadsMemory = DefInst->HasSourceMemoryOperand();
		if (ReadsMemory) {
			if (DefInst->HasIndirectMemoryRead()
				|| (!(DefInst->IsLoadFromStack()) && (DefInst->GetOptType() == 3))) {
				// Either a load that is not from the stack, or an indirect access to memory.
				return; // No USEs we can propagate through
			}
		}

#if STARS_MINIMIZE_UNSIGNED_BRANCH_PROPAGATION
		// Now we propagate to the USEs of the instruction. However, we need to beware of
		//  propagating too much UNSIGNEDNESS, as we sometimes have mixed-mode arithmetic
		//  and lea instructions can add SIGNED and UNSIGNED to produce UNSIGNED, e.g.:
		//   lea edi,[eax+ebx]
		//  Just because EDI is UNSIGNED does not mean that both EAX and EBX are UNSIGNED.
		//   Perhaps EAX is UNSIGNED and EBX is SIGNED, or vice versa.
		if (DefInst->MDIsLoadEffectiveAddressInstr()) {
			// Se if we have more than one non-flags register USE.
			size_t RegUseCount = 0;
			for (UseIter = DefInst->GetFirstUse(); UseIter != DefInst->GetLastUse(); ++UseIter) {
				op_t UseOp = UseIter->GetOp();
				if ((UseOp.type == o_reg) && ((!ReadsMemory) || (DefInst->IsNonAddressReg(UseOp)))) { // don't want addressing registers
					if (!(UseOp.is_reg(X86_FLAGS_REG))) {
						++RegUseCount;
					}
				}
			}
			if (RegUseCount > 1) {
				return;
			}
		}
#endif

		// A USE in the instruction that DEFed the flags used in our original condition branch
		//  could be local to the block containing the instruction, else it is a global name.
		//  We always want to update the sign info of the USE. Propagation to the DEF of that USE
		//  will happen only if the instruction is a simple move, compare, or test (for now).
		//  NOTE: We might try to propagate to DEFs of registers by arithmetic instructions later.
#if 1
		bool PropagateThroughUses = DefInst->MDPropagateUseUpFromBranch();
#else
		bool PropagateThroughUses = false;
#endif
		ea_t UseDefAddr = BADADDR;
		for (UseIter = DefInst->GetFirstUse(); UseIter != DefInst->GetLastUse(); ++UseIter) {
			op_t UseOp = UseIter->GetOp();
			if ((UseOp.type == o_reg) && ((!ReadsMemory) || (DefInst->IsNonAddressReg(UseOp)))) { // don't want addressing registers
#if 0  // USEs should already be canonicalized
				CanonicalizeOpnd(UseOp);
#endif
				if (UseOp.is_reg(X86_FLAGS_REG)) { 
					// don't need to propagate to flags after initial call to this method
					continue; // save time
				}
				int UseSSANum = UseIter->GetSSANum();
				bool LocalUseOp;
				if (LocalDef) {
					LocalUseOp = this->IsLocalName(UseOp);
				}
				else {
					LocalUseOp = DefBlock->IsLocalName(UseOp);
				}
				UseHashValue = HashGlobalNameAndSSA(UseOp, UseSSANum);
				if (LocalDef) {
					if (LocalUseOp) {// USE must be in a local instruction
						this->UpdateUseSignMiscInfo(UseHashValue, SignMask);
					}
					else { // USE is global name
						this->MyFunc->UpdateUseSignMiscInfo(UseHashValue, SignMask);
					}
				}
				else if (LocalUseOp) { // USE is local to DEF block
					DefBlock->UpdateUseSignMiscInfo(UseHashValue, SignMask);
				}
				else { // USE is global name
					this->MyFunc->UpdateUseSignMiscInfo(UseHashValue, SignMask);
				}
				if (PropagateThroughUses) {
					// For this opcode, we propagate through register USEs to their DEFs.
					if (LocalDef) {
						UseDefAddr = this->GetDefAddrFromUseAddr(UseOp, DefInst->GetAddr(), UseSSANum, LocalUseOp);
						this->PropagateBranchSignedness(UseDefAddr, UseOp, SignMask); // recurse
					}
					else { // recurse through the DEF block
						UseDefAddr = DefBlock->GetDefAddrFromUseAddr(UseOp, DefInst->GetAddr(), UseSSANum, LocalUseOp);
						DefBlock->PropagateBranchSignedness(UseDefAddr, UseOp, SignMask); // recurse
					}
				}
			}
			else if (MDIsDirectStackAccessOpnd(UseOp, this->MyFunc->UsesFramePointer())) {
				// Arithmetic or load using the stack as a source operand. We need to update
				//  our stack frame FG info sign inferences, in case we have some
				//  code that never does signed/unsigned loads from this stack location but uses it
				//  as a source operand for arithmetic or regular loads.
				if (PropagateThroughUses && this->GetFunc()->HasGoodFGStackTable() 
					&& (!this->GetFunc()->IsInOutgoingArgsRegion(UseOp))) {
					struct FineGrainedInfo StackFG;
					bool success = this->GetFunc()->MDGetFGStackLocInfo(DefInst->GetAddr(), UseOp, StackFG);
					assert(success);
					if (0 == (StackFG.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS)) {
						// Stack operand has no signedness info. Time to give it some.
						StackFG.SignMiscInfo |= SignMask;
						success = this->GetFunc()->MDUpdateFGStackLocInfo(DefInst->GetAddr(), UseOp, StackFG);
						assert(success);
						// success => an update occurred
					}
				}
			}
		} // end for all USEs
	} // end if (Phi DEF) else ...
	return;
} // end of SMPBasicBlock::PropagateBranchSignedness()

// propagate DEF signedness to USE if USE has no signedness info.
bool SMPBasicBlock::PropagateDEFSignedness(void) {
	bool changed = false;
	map<int, struct FineGrainedInfo>::iterator UseFGIter, DefFGIter;
	for (UseFGIter = this->LocalUseFGInfoBySSA.begin(); UseFGIter != this->LocalUseFGInfoBySSA.end(); ++UseFGIter) {
		struct FineGrainedInfo UseFG = UseFGIter->second;
		if (0 == (UseFG.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS)) {
			// No signedness info. Propagate any signedness info from DEF.
			int UseHashValue = UseFGIter->first;
			unsigned short DefSignMask = this->GetDefSignMiscInfo(UseHashValue);
			DefSignMask &= FG_MASK_SIGNEDNESS_BITS;
			if (0 != DefSignMask) {
				// DEF has signedness info.
				UseFGIter->second.SignMiscInfo |= DefSignMask;
				changed = true;
			}
		}
	}
	// See if we have DEF signedness info for DEFs with no corresponding USE map entries.
	for (DefFGIter = this->LocalDefFGInfoBySSA.begin(); DefFGIter != this->LocalDefFGInfoBySSA.end(); ++DefFGIter) {
		struct FineGrainedInfo DefFG = DefFGIter->second;
		unsigned short DefSignMask = (DefFG.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
		if (0 != DefSignMask) {
			// Has signedness info. See if USE has no entry.
			int DefHashValue = DefFGIter->first;
			UseFGIter = this->LocalUseFGInfoBySSA.find(DefHashValue);
			if (UseFGIter == this->LocalUseFGInfoBySSA.end()) {
				this->UpdateUseSignMiscInfo(DefHashValue, DefSignMask);
				changed = true;
			}
		}
	}
	return changed;
} // end of SMPBasicBlock::PropagateDEFSignedness()

// backtrack from CallAddr and mark unsigned args based on bitset
void SMPBasicBlock::MarkUnsignedArgs(ea_t CallAddr, unsigned int ArgPosBits) {
	vector<SMPInstr *>::reverse_iterator RevInstIter;
	unsigned int UnsignedArgCount = CountBitsSet(ArgPosBits);
	unsigned int UnsignedArgsFound = 0;

	for (RevInstIter = this->GetRevInstBegin(); RevInstIter != this->GetRevInstEnd(); ++RevInstIter) {
		SMPInstr *CurrInst = (*RevInstIter);
		ea_t InstAddr = CurrInst->GetAddr();
		if (InstAddr < CallAddr) {
			SMPitype FlowType = CurrInst->GetDataFlowType();
			if ((FlowType == CALL) || (FlowType == INDIR_CALL)) {
				// We have reached a call before the one we care about. Done.
				break;
			}
			size_t ArgumentNumber;
			if (CurrInst->MDIsArgumentPass(ArgumentNumber)) {
				if (0 != (ArgPosBits & (1 << ArgumentNumber))) {
					// ArgumentNumber matches a bit set in ArgPosBits.
					CurrInst->SetUnsignedArg();
					++UnsignedArgsFound;
					if (UnsignedArgsFound >= UnsignedArgCount) {
						break; // found them all
					}
				}
			}
		}
	}

	return;
} // end of SMPBasicBlock::MarkUnsignedArgs()

// Find the stack target of a call to memset() and the size in bytes of the memset() region.
//  If the memset() target is not on the stack, return false. If the 
//  size of the memset() region is not a constant, we also return false.
bool SMPBasicBlock::AnalyzeMemSet(ea_t MemSetAddr, op_t &MemSetTarget, size_t &MemSetSize, int &StackOffset, bool &FPRelativeTarget) {
	set<DefOrUse, LessDefUse>::iterator UseIter;
	op_t DefOp, UseOp, UltimateSourceOp;
	ea_t InstAddr;
	int UseSSANum;
	bool FoundTarget = false, FoundSize = false;
	bool UseFP = this->GetFunc()->UsesFramePointer();
	bool DummyFPRelative = false; // don't care about this for the size argument to memset(), which is o_imm anyway
	vector<SMPInstr *>::reverse_iterator InstRevIter;
	sval_t CurrentDelta;

	assert(MemSetAddr >= this->FirstAddr);
	MemSetTarget = InitOp;
	MemSetSize = 0;

	// The MemSetTarget will be moved into [ESP+0] and the size will be moved
	//  into [ESP+8]. The value being copied into each byte will be moved into
	//  [ESP+4], which we do not care about. We will move backwards through the block until
	//  we find the MemSetAddr, then we will trace the def-use SSA chain back to its 
	//  source for each argument to memset() that we care about.
	// NOTE: [ESP+0], [ESP+4], etc., do not look like that any more, because stack ops have
	//  been normalized.
	InstRevIter = this->GetRevInstBegin(); 
	SMPInstr *CurrInst = (*InstRevIter);
	InstAddr = CurrInst->GetAddr();
	while ((InstAddr > MemSetAddr) && (InstRevIter != this->GetRevInstEnd())) {
		++InstRevIter; // move backwards through block by incrementing the reverse iterator.
		CurrInst = (*InstRevIter);
		InstAddr = CurrInst->GetAddr();
	}
	if (InstAddr != MemSetAddr) {
		SMP_msg("ERROR: Memset not found at MemSetAddr %lx\n", (unsigned long) MemSetAddr);
		return false;
	}

	// Keep iterating backwards from MemSetAddr, searching for DEFs of [ESP] and [ESP+8].
	++InstRevIter; // move backwards through block by incrementing the reverse iterator.
	while (InstRevIter != this->GetRevInstEnd()) {
		CurrInst = (*InstRevIter);
		InstAddr =  CurrInst->GetAddr();
		if (CurrInst->HasDestMemoryOperand()) {
			DefOp = CurrInst->MDGetMemDefOp();
			// We want to know if DefOp is ESP-relative, so we do not want to find
			//  an EBP-relative DefOp, as arguments are not passed EBP-relative. So,
			//  regardless of whether we actually use EBP as a frame pointer in this
			//  function, we will pass FALSE as the second argument of this next query.
			// NOTE: There are no more EBP-relative DEFs after normalization, anyway.
			if (MDIsDirectStackAccessOpnd(DefOp, false)) {
				// Found write to stack, ESP-relative. Determine if it is [ESP+0] or [ESP+8].
				int BaseReg, IndexReg;
				ushort ScaleFactor;
				ea_t offset;
				MDExtractAddressFields(DefOp, BaseReg, IndexReg, ScaleFactor, offset);
				// We don't want scaled or indexed accesses to the stack; cannot analyze easily.
				if ((R_none == IndexReg) && (0 == ScaleFactor)) {
					assert(BaseReg == MD_STACK_POINTER_REG);
					int SignedOffset = (int) offset; // IDA Pro has signedness problem to fix here.
					CurrentDelta = CurrInst->GetStackPtrOffset();
					SignedOffset -= (int) CurrentDelta; // undo normalization of stack offset
					if (0 == SignedOffset) {
						UseOp = CurrInst->GetMoveSource();
						if (o_reg == UseOp.type) {
							CanonicalizeOpnd(UseOp);
						}
						if (o_void == UseOp.type) {
							SMP_msg("ERROR: No move source at %lx within AnalyzeMemSet().\n", (unsigned long) InstAddr);
							break;
						}
						else {
							UseIter = CurrInst->FindUse(UseOp);
							assert(UseIter != CurrInst->GetLastUse());
							UseSSANum = UseIter->GetSSANum();
							if (CurrInst->TraceUltimateMoveSource(UseOp, UseSSANum, UltimateSourceOp, FPRelativeTarget)) {
								if (MDIsDirectStackAccessOpnd(UltimateSourceOp, UseFP)) {
									// memset() has a stack location as its target. Extract info from
									//  UltimateSourceOp.
									MDExtractAddressFields(UltimateSourceOp, BaseReg, IndexReg, ScaleFactor, offset);
									if ((R_none != IndexReg) || (0 != ScaleFactor)) {
										break; // cannot make use of complex stack loc expression
									}
									else {
										MemSetTarget = UltimateSourceOp;
										StackOffset = (int) offset; // NOTE: this is a normalized offset
										FoundTarget =  true; // success on argument #1
										if (FoundSize) break;  // nothing left to find
									}
								}
								else {
									// Found ultimate source of argument #1, but not a stack operand.
									break; // return false
								}
							}
							else { // could not find ultimate source of argument #1
								break;  // time to return false
							}
						}
					}
					else if (8 == SignedOffset) {
						UseOp = CurrInst->GetMoveSource();
						if (o_reg == UseOp.type) {
							CanonicalizeOpnd(UseOp);
						}
						if (o_void == UseOp.type) {
							SMP_msg("ERROR: No move source at %lx within AnalyzeMemSet().\n",
								(unsigned long) InstAddr);
							break;
						}
						else {
							UseIter = CurrInst->FindUse(UseOp);
							assert(UseIter != CurrInst->GetLastUse());
							UseSSANum = UseIter->GetSSANum();
							if (CurrInst->TraceUltimateMoveSource(UseOp, UseSSANum, UltimateSourceOp, DummyFPRelative)) {
								if (o_imm != UltimateSourceOp.type) {
									break; // return false if cannot find an immediate value for argument #3
								}
								else {
									uval_t ImmVal;
									ImmVal = UseOp.value;
									MemSetSize = (size_t) ImmVal;
									FoundSize = true;
									if (FoundTarget) break;  // nothing left to find
								}
							}
						}
					} // end if ((0 == SignedOffset) || (8 == SignedOffset))
				}
			} // end if MDIsStackAccessOpnd(DefOp, false)
		} // end if CurrInst->HasDestMemoryOperand()

		++InstRevIter; // move backwards through block by incrementing the reverse iterator.
	} // end while we have not reached the block Instrs.rend()

	return (FoundTarget && FoundSize);
} // end of SMPBasicBlock::AnalyzeMemset()

#if STARS_BUILD_DEF_USE_CHAINS
// For the newly defined type DefType for DefOp at instruction DefAddr, propagate the
//  type to all USEs in the local SSA chain for the DEF. If any USE types change,
// return true.
bool SMPBasicBlock::PropagateLocalDefType(op_t DefOp, SMPOperandType DefType, ea_t DefAddr, int SSANum, bool IsMemOp) {
	bool changed = false;
	bool SafeFunc = (this->MyFunc) && this->MyFunc->IsSafe();
	bool DebugFlag = false;
#if SMP_DEBUG_OPTIMIZATIONS
	DebugFlag |= (0 == strcmp("memset", this->MyFunc->GetFuncName()));
#endif
	set<op_t, LessOp>::iterator NameIter;

	if (DebugFlag) {
		SMP_msg("PropagateLocalDefType for DefType %d at %x ", DefType, DefAddr);
		PrintOperand(DefOp);
		SMP_msg("\n");
	}

	unsigned int RegIndex = this->GetLocalDUIndex(DefOp, SSANum);

	ea_t StartAddr = this->GetFirstDefAddr(RegIndex, SSANum, false);
	assert(DefAddr == StartAddr);
	ea_t LastAddr = this->GetLastUseAddr(RegIndex, SSANum, false);
	if (BADADDR == LastAddr)
		return false;  // DEF had no USEs, so no propagation
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	vector<SMPInstr *>::iterator InstIter;
	// Go through the instructions in the block and find the instructions between StartAddr
	//  and LastAddr that have USEs of DefOp. These will all have SSANum, based on the
	//  local du-chain, so it does not have to be checked. If any USE in the chain has
	//  a type other than DefType, change it to DefType and set changed to true.
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		ea_t CurrAddr = CurrInst->GetAddr();
		if (CurrAddr > LastAddr)
			break;
		if (CurrAddr > StartAddr) {
#if SMP_VERBOSE_ALIAS_DETECTION
			if (IsMemOp && (CurrInst->HasIndirectMemoryWrite())) {
				SMP_msg("CAUTION: Indirect memory write in MemOp chain.\n");
				SMP_msg("CAUTION: at %x ChainStart: %x ChainEnd: %x \n",
					CurrAddr, StartAddr, LastAddr);
#if 0
				if (!SafeFunc) {
					SMP_msg("Local type propagation terminated in unsafe func %s\n",
						this->MyFunc->GetFuncName());
					break;
				}
#endif
			}
#endif
			CurrUse = CurrInst->FindUse(DefOp);
			if (CurrUse != CurrInst->GetLastUse()) { // found a USE in the chain
				ushort InstOpcode = CurrInst->GetCmd().itype;
				SMPOperandType UseType = CurrUse->GetType();
				if (UseType == UNINIT) {
					assert(SSANum == CurrUse->GetSSANum());
					CurrUse = CurrInst->SetUseType(DefOp, DefType);
					assert(CurrUse != CurrInst->GetLastUse()); // found USE
					changed = true;
				}
				else if (DefType != UseType) {
					// See lengthy explanation in PropagateGlobalDefType().
					if (IsRefinedDataPtr(DefType) && (IsEqType(POINTER, UseType))) {
#if SMP_VERBOSE_POINTER_REFINEMENT
						SMP_msg("Refining POINTER to %d at %x %s for USE:", DefType,
							CurrInst->GetAddr(), CurrInst->GetDisasm());
						CurrUse->Dump();
						SMP_msg("\n");
#endif
						CurrUse = CurrInst->SetUseType(DefOp, DefType);
						assert(CurrUse != CurrInst->GetLastUse()); // found USE
						changed = true;
					}
					else if (IsDataPtr(DefType) && IsNumeric(UseType)
							&& ((InstOpcode == NN_adc) || (InstOpcode == NN_sbb))) {
						SMP_msg("ADC/SBB: Refining NUMERIC to %d at %x %s for USE:", DefType,
							CurrInst->GetAddr(), CurrInst->GetDisasm());
						CurrUse->Dump();
						SMP_msg("\n");
						CurrUse = CurrInst->SetUseType(DefOp, DefType);
						assert(CurrUse != CurrInst->GetLastUse()); // found USE
						changed = true;
					}
					else {
						;
#if SMP_DEBUG_OPTIMIZATIONS
						SMP_msg("WARNING: Not overriding type %d to %d at %x %s for USE:", UseType,
							DefType, CurrInst->GetAddr(), CurrInst->GetDisasm());
						CurrUse->Dump();
						SMP_msg("\n");
#endif
					}
				}
			}
		}
	} // end for all instructions

	return changed;
} // end of SMPBasicBlock::PropagateLocalDefType()

#else
// For the newly defined type DefType for DefOp at instruction DefAddr, propagate the
//  type to all USEs in the local SSA chain for the DEF. If any USE types change,
// return true.
bool SMPBasicBlock::PropagateLocalDefType(op_t DefOp, SMPOperandType DefType, ea_t DefAddr, int SSANum, bool IsMemOp) {
	bool changed = false;
	bool SafeFunc = (this->MyFunc) && this->MyFunc->IsSafe();
	bool DebugFlag = false;
#if SMP_DEBUG_OPTIMIZATIONS
	DebugFlag |= (0 == strcmp("memset", this->MyFunc->GetFuncName()));
#endif

	if (DebugFlag) {
		SMP_msg("PropagateLocalDefType for DefType %d at %lx ",
			DefType, (unsigned long) DefAddr);
		PrintOperand(DefOp);
		SMP_msg("\n");
	}

	set<DefOrUse, LessDefUse>::iterator CurrUse;
	vector<SMPInstr *>::iterator InstIter = this->GetInstIterFromAddr(DefAddr);

	// Go through the instructions in the block and find the instructions that have USEs of DefOp/SSANum.
	//  If any USE in the chain has a type other than DefType, change it to DefType and set changed to true.
	++InstIter;
	while (InstIter != this->GetLastInst()) {
		SMPInstr *CurrInst = (*InstIter);
		++InstIter;
		ea_t CurrAddr = CurrInst->GetAddr();
#if SMP_VERBOSE_ALIAS_DETECTION
		if (IsMemOp && (CurrInst->HasIndirectMemoryWrite())) {
			SMP_msg("CAUTION: Indirect memory write in MemOp chain.\n");
			SMP_msg("CAUTION: at %lx ChainStart: %lx ChainEnd: %lx \n",
				(unsigned long) CurrAddr, (unsigned long) StartAddr, (unsigned long) LastAddr);
#if 0
			if (!SafeFunc) {
				SMP_msg("Local type propagation terminated in unsafe func %s\n",
					this->MyFunc->GetFuncName());
				break;
			}
#endif
		}
#endif
		CurrUse = CurrInst->FindUse(DefOp);
		if (CurrUse != CurrInst->GetLastUse()) { // found a USE in the chain
			ushort InstOpcode = CurrInst->GetCmd().itype;
			SMPOperandType UseType = CurrUse->GetType();
			if (UseType == UNINIT) {
				assert(SSANum == CurrUse->GetSSANum());
				CurrUse = CurrInst->SetUseType(DefOp, DefType);
				assert(CurrUse != CurrInst->GetLastUse()); // found USE
				changed = true;
			}
			else if (DefType != UseType) {
				// See lengthy explanation of propagation rules in PropagateGlobalDefType().
				if (IsRefinedDataPtr(DefType) && (IsEqType(POINTER, UseType))) {
#if SMP_VERBOSE_POINTER_REFINEMENT
					SMP_msg("Refining POINTER to %d at %lx %s for USE:", DefType,
						(unsigned long) CurrInst->GetAddr(), CurrInst->GetDisasm());
					CurrUse->Dump();
					SMP_msg("\n");
#endif
					CurrUse = CurrInst->SetUseType(DefOp, DefType);
					assert(CurrUse != CurrInst->GetLastUse()); // found USE
					changed = true;
				}
				else if (IsDataPtr(DefType) && IsNumeric(UseType)
						&& ((InstOpcode == NN_adc) || (InstOpcode == NN_sbb))) {
					SMP_msg("ADC/SBB: Refining NUMERIC to %d at %lx %s for USE:", DefType,
						(unsigned long) CurrInst->GetAddr(), CurrInst->GetDisasm());
					CurrUse->Dump();
					SMP_msg("\n");
					CurrUse = CurrInst->SetUseType(DefOp, DefType);
					assert(CurrUse != CurrInst->GetLastUse()); // found USE
					changed = true;
				}
				else {
					;
#if SMP_DEBUG_OPTIMIZATIONS
					SMP_msg("WARNING: Not overriding type %d to %d at %lx %s for USE:", UseType,
						DefType, (unsigned long) CurrInst->GetAddr(), CurrInst->GetDisasm());
					CurrUse->Dump();
					SMP_msg("\n");
#endif
				}
			}
		}
		if (CurrInst->FindDef(DefOp) != CurrInst->GetLastDef()) {
			// Instruction redefines DefOp. Terminate.
			break;
		}
	} // end for all instructions

	return changed;
} // end of SMPBasicBlock::PropagateLocalDefType()
#endif

// Propagate the DefType of the DEF in DefOp with SSANum to all USEs. DefOp is a global
//  name, so the propagation will have to recurse into successor blocks, check their
//  phi functions for occurrences of DefOp, etc.
// Return true if any USEs have their types changed.
bool SMPBasicBlock::PropagateGlobalDefType(op_t DefOp, SMPOperandType DefType, int SSANum, bool IsMemOp) {
	bool changed = false;
	bool FoundPhiDef = false;
	bool SafeFunc = (this->MyFunc) && this->MyFunc->IsSafe();
	bool DebugFlag = false;
#if SMP_DEBUG_OPTIMIZATIONS
	DebugFlag |= (0 == strcmp("__strtod_internal", this->MyFunc->GetFuncName()));
#endif
	vector<SMPInstr *>::iterator InstIter;
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	SMPOperandType UseType;

	// Use the Processed flag to avoid infinite recursion.
	if (this->IsProcessed())
		return false;
	else
		this->SetProcessed(true);

	if (DebugFlag) {
		SMP_msg("PropagateGlobalDefType: DefType %d SSANum %d ", DefType, SSANum);
		PrintOperand(DefOp);
		SMP_msg("\n");
	}

	// When we can traverse all paths of the global DEF-USE chains for this
	//  DefOp, we can be sure there is no aliasing. Until then, we must
	//  be more conservative on global MemOp propagation than for locals.
	if (IsMemOp && (!SafeFunc))
		return false;

	// This might be a recursive invocation, so the DefOp might be in the Phi functions.
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi = this->FindPhi(DefOp);
	if (CurrPhi != this->GetLastPhi()) { // Found a corresponding phi function
		if (DebugFlag) SMP_msg("Found Phi for DefOp\n");
		// If SSANum matches the DEF in the Phi function, then we are being
		//  called by InferPhiDefType() and we should proceed to process
		//  the instructions in the block.
		if (SSANum != CurrPhi->GetDefSSANum()) { // not DEF, so find USE
			if (DebugFlag) SMP_msg("Phi was a USE\n");
			// Now, find the SSANum entry in the phi arguments (USEs)
			bool FoundUse = false;
			size_t PhiIndex;
			for (PhiIndex = 0; PhiIndex < CurrPhi->GetPhiListSize(); ++PhiIndex) {
				if (SSANum == CurrPhi->GetUseSSANum(PhiIndex))  {
					FoundUse = true;
					if (DebugFlag) SMP_msg("Found the phi USE at index %zu\n", PhiIndex);
					if (UNINIT == CurrPhi->GetUseType(PhiIndex)) {
						changed = this->SetPhiUseType(DefOp, PhiIndex, DefType);
						assert(changed);
						if (DebugFlag) SMP_msg("Changed the phi USE type\n");
					}
#if 1
					break; // **!!** COULD BE MULTIPLE USES HERE
#endif
				}
			}
			if (!FoundUse) {
				// Not actually a problem. E.g. if we find an inst:  add eax,4 that
				//  uses eax SSA #7 and DEFs eax SSA #8, we will call this function
				//  to propagate the type of SSA #8. There could be a phi function
				//  at the top of this block that DEFs eax SSA #7 from earlier USEs
				//  of eax. We will not find eax SSA #8 in that phi function, so we
				//  pass down to the code below to process all instructions.
				;
#if 0
				SMP_msg("ERROR: Failed to find Phi use of SSA %d in block %d for: ", SSANum,
					this->GetNumber());
				PrintOperand(DefOp);
				SMP_msg("\n");
#endif
			}
			else 
				return changed;  // end the recursion; phi function does not permit DefOp
								//   with SSANum to be referenced on this path again
		} // end if DefOp and SSANum are not the phi function DEF
		else {
			FoundPhiDef = true;
		}
	} // end if we found a phi function for DefOp

	// If not in the Phi functions, it could be in the instructions for the block.
	bool FoundUse = false;
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
#if 0
		if (IsMemOp && (CurrInst->HasIndirectMemoryWrite())) {
			if (!SafeFunc) {
				SMP_msg("Global type propagation terminated in unsafe func %s\n",
					this->MyFunc->GetFuncName());
				return changed;
			}
		}
#endif
		CurrUse = CurrInst->FindUse(DefOp);
		if ((CurrUse == CurrInst->GetLastUse()) || (SSANum != CurrUse->GetSSANum())) {
			if (FoundUse) {
				// If we have already gone past the DEF and at least one use,
				//  another DEF will indicate that the original DEF-USE chain is
				//  finished. In that case, we can save a lot of time by not processing
				//  any more instructions and recursing into successor blocks, because
				//  the original DEF is now dead.
				CurrDef = CurrInst->FindDef(DefOp);
				if ((CurrDef != CurrInst->GetLastDef()) && (SSANum != CurrDef->GetSSANum())) {
					return changed;
				}
				else {
					continue;
				}
			}
			else {
				continue;
			}
		}
		// If we reach this point, we have found a use with the same SSA number.
		FoundUse = true;
		UseType = CurrUse->GetType();
		ushort InstOpcode = CurrInst->GetCmd().itype;
		if (DebugFlag) {
			SMP_msg("Found USE with same SSANum at %lx : %s\n", 
				(unsigned long) CurrInst->GetAddr(), CurrInst->GetDisasm());
		}
		if (UNINIT == UseType) {
			CurrUse = CurrInst->SetUseType(DefOp, DefType);
			assert(CurrUse != CurrInst->GetLastUse()); // found USE
			changed = true;
		}
		else if (DefType != UseType) {
			// Weird. USE already has a type, but it is not the DEF type.
			//  If we are refining a POINTER to a particular pointer type, fine.
			//  We don't want to change NUMERIC to something else, however,
			//  because it is possible to perform inherently NUMERIC operations
			//  on pointer types, e.g. def a pointer, use it as pointer, then
			//  perform hash function computations on it. Those computations
			//  (shift, xor, etc.) should truly remain NUMERIC.
			//
			// EXCEPTION: We need to propagate pointer types to USEs within
			//  subtract-with-borrow and add-with-carry instructions. This is
			//  because of phase ordering issues. E.g. sbb ecx,3 could have
			//  the DEF type inferred to be NUMERIC based on its later uses,
			//  but we still need to know if the USE of ecx was POINTER. This
			//  is a special case in which the sbb or adc instruction changes
			//  the type of the register. We need to observe this type change
			//  when we emit annotations, so that we emit an annotation to
			//  force the DEF metadata to NUMERIC rather than an annotation
			//  that squashes the instruction and leaves ecx with type POINTER.
			//  SMPInstr::InferOperatorType() will propagate NUMERIC from
			//  the SMP_SUBTRACT_BORROW operator to register ecx if ecx still
			//  had type UNINIT. We need to reset the USE of ecx to POINTER
			//  if we later discover that ecx came into the instruction with
			//  type POINTER.
			if (IsRefinedDataPtr(DefType) && (IsEqType(POINTER, UseType))) {
#if SMP_VERBOSE_POINTER_REFINEMENT
				SMP_msg("Refining POINTER to %d at %lx %s for USE:", DefType,
					(unsigned long) CurrInst->GetAddr(), CurrInst->GetDisasm());
				CurrUse->Dump();
				SMP_msg("\n");
#endif
				CurrUse = CurrInst->SetUseType(DefOp, DefType);
				assert(CurrUse != CurrInst->GetLastUse()); // found USE
				changed = true;
			}
			else if (IsDataPtr(DefType) && IsNumeric(UseType)
					&& ((InstOpcode == NN_adc) || (InstOpcode == NN_sbb))) {
				SMP_msg("ADC/SBB: Refining NUMERIC to %d at %lx %s for USE:", DefType,
					(unsigned long) CurrInst->GetAddr(), CurrInst->GetDisasm());
				CurrUse->Dump();
				SMP_msg("\n");
				CurrUse = CurrInst->SetUseType(DefOp, DefType);
				assert(CurrUse != CurrInst->GetLastUse()); // found USE
				changed = true;
			}
			else {
				;
#if SMP_DEBUG_OPTIMIZATIONS
				SMP_msg("WARNING: Not overriding type %d to %d at %x %s for USE:", UseType,
					DefType, CurrInst->GetAddr(), CurrInst->GetDisasm());
				CurrUse->Dump();
				SMP_msg("\n");
#endif
			}
		}
	} // end for all instructions in the block

	// We recurse into all successor blocks looking for more USEs. We know that there
	//  cannot be more USEs if the global name DefOp is not LiveOut from this block, so
	//  we can just return in that case.
	if (this->LiveOutSet.end() == LiveOutSet.find(DefOp))  // not LiveOut
		return changed;

	// Only recurse into successors that have DefOp in their LiveIn set. The others
	//  will not have Phi functions for DefOp, because we constructed fully pruned SSA
	//  form, nor will they have USEs of this SSANum.
	list<SMPBasicBlock *>::iterator SuccIter;
	for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) {
		if ((*SuccIter)->IsLiveIn(DefOp)) {
			changed |= (*SuccIter)->PropagateGlobalDefType(DefOp, DefType, SSANum, IsMemOp);
		}
	}

	return changed;
} // end of SMPBasicBlock::PropagateGlobalDefType()

// Propagate the metadata Status for UseOp/SSANum to its local DEF.
// Return true if successful.
bool SMPBasicBlock::PropagateLocalMetadata(op_t UseOp, SMPMetadataType Status, int SSANum, ea_t UseAddr) {
	bool changed = false;
	set<op_t, LessOp>::iterator NameIter;
	NameIter = this->FindLocalName(UseOp);
	if (this->GetLastLocalName() == NameIter) {
		return false;
	}
    assert(0 <= SSANum);

	ea_t DefAddr = this->GetDefAddrFromUseAddr(UseOp, UseAddr, SSANum, true);
	if ((DefAddr == BADADDR) || (DefAddr < this->GetFirstAddr())) {
		return false;
	}

	// Find the instruction at DefAddr
	vector<SMPInstr *>::iterator InstIter = this->GetInstIterFromAddr(DefAddr);
	SMPInstr *CurrInst = (*InstIter);
	set<DefOrUse, LessDefUse>::iterator CurrDef, CurrUse, NextUse;

	CurrDef = CurrInst->FindDef(UseOp);
	assert(CurrDef != CurrInst->GetLastDef());
	assert(SSANum == CurrDef->GetSSANum());
	// Set the new metadata status.
	if (Status != CurrDef->GetMetadataStatus()) {
		CurrDef = CurrInst->SetDefMetadata(UseOp, Status);
		changed = (CurrDef != CurrInst->GetLastDef());

		// If source operand was memory, we have two cases.
		//  (1) The instruction could be a load, in which
		//  case we should simply terminate the
		//  propagation, because the prior DEF of a memory
		//  location is always considered live metadata
		//  already, and we do not want to propagate liveness
		//  to the address regs in the USE list.
		//  EXCEPTION: For safe funcs, we propagate liveness
		//   for stack locations.
		//  (2) We could have an arithmetic operation such
		//  as reg := reg arithop memsrc. In this case, we
		//  still do not want to propagate through the memsrc,
		//  but the register is both DEF and USE and we need
		//  to propagate through the register.
		if (CurrInst->HasSourceMemoryOperand()) {
			if (this->MyFunc->IsSafe()) {
				bool UseFP = this->MyFunc->UsesFramePointer();
				op_t MemSrcOp = CurrInst->MDGetMemUseOp();
				assert(o_void != MemSrcOp.type);
				if (MDIsStackAccessOpnd(MemSrcOp, UseFP)) {
					// We have a SafeFunc stack access. This is
					//  the EXCEPTION case where we want to
					//  propagate metadata liveness for a memory
					//  location.
					CurrUse = CurrInst->FindUse(MemSrcOp);
					assert(CurrUse != CurrInst->GetLastUse());
					if (this->MyFunc->IsGlobalName(MemSrcOp)) {
						changed |= this->MyFunc->PropagateGlobalMetadata(MemSrcOp,
							Status, CurrUse->GetSSANum(), DefAddr);
					}
					else {
						changed |= this->PropagateLocalMetadata(MemSrcOp,
							Status, CurrUse->GetSSANum(), DefAddr);
					}
				} // end if stack access operand
			} // end if SafeFunc
			if (3 == CurrInst->GetOptType()) { // move inst
				return changed; // address regs are not live metadata
			}
			else if ((5 == CurrInst->GetOptType())
				|| (NN_and == CurrInst->GetCmd().itype)
				|| (NN_or == CurrInst->GetCmd().itype)
				|| (NN_xor == CurrInst->GetCmd().itype)) {
				// add, subtract, and, or with memsrc
				// Find the DEF reg in the USE list.
				CurrUse = CurrInst->FindUse(UseOp);
				assert(CurrUse != CurrInst->GetLastUse());
				changed |= this->PropagateLocalMetadata(UseOp,
					Status, CurrUse->GetSSANum(), DefAddr);
				return changed;
			}
		} // end if memory source

		// Now, propagate the metadata status to all the
		//  non-memory, non-flags-reg, non-special-reg 
		//  (i.e. regular registers) USEs.
		CurrUse = CurrInst->GetFirstUse();
		while (CurrUse != CurrInst->GetLastUse()) {
			NextUse = CurrUse;
			++NextUse;
			op_t UseOp2 = CurrUse->GetOp();
			// NOTE: **!!** To be less conservative, we
			//  should propagate less for exchange category
			//  instructions.
			if ((UseOp2.type == o_reg) && (!MDIsStackOrFramePointerReg(UseOp2, this->MyFunc->UsesFramePointer()))
				&& (!UseOp2.is_reg(X86_FLAGS_REG))) {

				if (this->MyFunc->IsGlobalName(UseOp2)) {
					changed |= this->MyFunc->PropagateGlobalMetadata(UseOp2,
						Status, CurrUse->GetSSANum(), DefAddr);
				}
				else {
					changed |= this->PropagateLocalMetadata(UseOp2,
						Status, CurrUse->GetSSANum(), DefAddr);
				}
			}
			CurrUse = NextUse;
		} // end while all USEs
	} // end if Status != CurrDef status

	return changed;
} // end of SMPBasicBlock::PropagateLocalMetadata()

// For the UNINIT type DEF DefOp at instruction DefAddr, see if all its USEs have
//  a single type. If so, set the DEF to that type and return true, else return false.
bool SMPBasicBlock::InferLocalDefType(op_t DefOp, unsigned int LocIndex, ea_t DefAddr) {
	bool changed = false;
	bool DebugFlag = false;
#if SMP_DEBUG_OPTIMIZATIONS
	DebugFlag |= (0 == strcmp("weightadj", this->MyFunc->GetFuncName()));
#endif

	if (DebugFlag) {
		SMP_msg("InferLocalDefType at %lx ", (unsigned long) DefAddr);
		PrintOperand(DefOp);
		SMP_msg("\n");
	}

	vector<SMPInstr *>::iterator InstIter;
	vector<SMPInstr *>::iterator DefInstIter = this->GetInstIterFromAddr(DefAddr);
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	SMPInstr *DefInst = (*DefInstIter);
	CurrDef = DefInst->FindDef(DefOp);
	if (CurrDef == DefInst->GetLastDef()) {
		SMP_msg("ERROR: DEF at %lx not found in DEF list by InferLocalDefType for DefOp: ", (unsigned long) DefAddr);
		PrintOperand(DefOp);
		SMP_msg("\n");
		return false;
	}
	int SSANum = CurrDef->GetSSANum();
	assert(0 <= SSANum);
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	// Go through the instructions in the block and find the instructions between DefAddr
	//  and the last inst that have USEs of DefOp/SSANum. If all USEs in the chain have
	//  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 DefType = CurrDef->GetType();
	SMPOperandType PtrType = UNINIT;
	SMPOperandType UseType = UNINIT;
	InstIter = DefInstIter;
	++InstIter;
	for ( ; InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		ea_t CurrAddr = CurrInst->GetAddr();
		CurrUse = CurrInst->FindUse(DefOp);
		if (CurrUse != CurrInst->GetLastUse()) { // found a USE in the chain
			if (!FirstUseSeen)
				FirstUseSeen = true;
			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)) {
						;
#if SMP_DEBUG_OPTIMIZATIONS
						SMP_msg("WARNING: Differing ptr types in local chain:");
						SMP_msg(" Prev: %d Current: %d %s\n", PtrType, UseType,
							CurrInst->GetDisasm());
#endif
					}
					PtrType = POINTER;
				}
				else {
					FoundPointer = true;
					PtrType = UseType;
				}
			}
		}
		if (CurrInst->FindDef(DefOp) != CurrInst->GetLastDef()) {
			// Redefined. Chain is finished.
			break;
		}
	} // end for all instructions

	if (FirstUseSeen) {
		// 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 (FoundPointer)
			UseType = PtrType;
		else if (FoundNumeric && !FoundUninit && !FoundUnknown)
			UseType = NUMERIC;
		else
			return false; // no POINTER, but no consistent type

		if (!IsEqType(DefType, UseType)) {
			if (DebugFlag) SMP_msg("Inferring local DEF of type %d\n", UseType);
			CurrDef = DefInst->SetDefType(DefOp, UseType);
			changed = true;
			if (FoundPointer && FoundUninit) {
				// We will propagate PtrType to the UNINIT elements of
				//  the DEF-USE chain.
				bool IsMemOp = (o_reg != DefOp.type);
				changed |= this->PropagateLocalDefType(DefOp, PtrType, DefAddr,
					CurrDef->GetSSANum(), IsMemOp);
			}
		}
	}

	return changed;
} // end of SMPBasicBlock::InferLocalDefType()

void SMPBasicBlock::InferGlobalDefType(op_t DefOp, int SSANum, ea_t DefAddr, bool &FoundNumeric, bool &FoundPointer,
	bool &FoundUnknown, bool &FoundUninit, SMPOperandType &PtrType) {

	// Avoid infinite recursion
	if (this->IsProcessed())
		return;
	else
		this->SetProcessed(true);

	bool DefEscapes = true;
	vector<SMPInstr *>::iterator InstIter;

	assert(0 <= SSANum);
	set<DefOrUse, LessDefUse>::iterator CurrUse, CurrDef;
	// Go through all instructions in the block and find the instructions
	//  that have USEs of DefOp with SSANum. Record the results in the
	//  boolean in-out arguments.
	SMPOperandType UseType = UNINIT;
	SMPOperandType DefType = UNINIT;
	
	if (BADADDR == DefAddr) { // DEF is USEd (and thus re-DEFed) in a Phi function
		DefEscapes = false;
		set<SMPPhiFunction, LessPhi>::iterator UsePhi;
		UsePhi = this->FindPhi(DefOp);
		if (UsePhi != this->GetLastPhi()) {
			// Found phi function for DefOp. See if we can find a USE
			//  with USE SSANum corresponding to our DEF SSANum.
			DefType = UsePhi->GetDefType();
			for (size_t PhiIndex = 0; PhiIndex < UsePhi->GetPhiListSize(); ++PhiIndex) {
				if (UsePhi->GetUseSSANum(PhiIndex) == SSANum) {
					// We have a Phi USE that matches our DEF.
					UseType = UsePhi->GetUseType(PhiIndex);
					FoundNumeric |= (IsNumeric(UseType));
					FoundUnknown |= (IsUnknown(UseType));
					FoundUninit |= (IsEqType(UNINIT, UseType));
					if (IsDataPtr(UseType)) {
						if (FoundPointer) {
							if (IsNotEqType(PtrType, UseType)) {
								PtrType = POINTER;
							}
						}
						else {
							FoundPointer = true;
							PtrType = UseType;
						}
					}
				} // end if matched SSA #
			} // end for all Phi USEs
		} // end if found matching Phi function for DefOp
	}
	else { // DEF is in an instruction in a previous block  !!!!****!!!! Why not current block?
		for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
			SMPInstr *CurrInst = (*InstIter);
			CurrDef = CurrInst->FindDef(DefOp);
			if (CurrDef != CurrInst->GetLastDef()) {
				// Found re-DEF of DefOp.
				DefEscapes = false;
			}
			CurrUse = CurrInst->FindUse(DefOp);
			if (CurrUse != CurrInst->GetLastUse()) { // found a USE of DefOp
				if (CurrUse->GetSSANum() == SSANum) { // matched SSA number
					UseType = CurrUse->GetType();
					FoundNumeric |= (IsNumeric(UseType));
					FoundUnknown |= (IsUnknown(UseType));
					FoundUninit |= (IsEqType(UNINIT, UseType));
					if (IsDataPtr(UseType)) {
						if (FoundPointer) {
							if (IsNotEqType(PtrType, UseType)) {
								// Have seen two different pointer types/subtypes
								PtrType = POINTER;
							}
						}
						else {
							FoundPointer = true;
							PtrType = UseType;
						}
					}
				} // end if matched SSA #
			} // end if found a USE of DefOp
		} // end for all instructions
	}

	if (DefEscapes) { // did not find re-def
		DefEscapes = this->IsLiveOut(DefOp);
	}

	if (DefEscapes) { // Need to recurse into successor blocks
		list<SMPBasicBlock *>::iterator SuccIter;
		ea_t TempAddr;
		set<SMPPhiFunction, LessPhi>::iterator PhiIter;
		for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) {
			SMPBasicBlock *CurrBlock = (*SuccIter);
			PhiIter = CurrBlock->FindPhi(DefOp);
			TempAddr = DefAddr;
			if (PhiIter != CurrBlock->GetLastPhi()) {
				TempAddr = BADADDR;  // signals that DefOp will get re-DEFed in a Phi function.
			}
			else if (BADADDR == TempAddr) { // was BADADDR coming in to this function
				// We don't want to pass BADADDR down the recursion chain, because it will be interpreted
				//  by each successor block to mean that DefOp was a Phi USE that got re-DEFed in a Phi function
				//  within itself. Pass the dummy address that indicates LiveIn to the block.
				TempAddr = CurrBlock->GetFirstAddr() - 1;
			}
			// Should we screen the recursive call below using CurrBlock->IsLiveIn(DefOp) for speed?  !!!!****!!!!
			CurrBlock->InferGlobalDefType(DefOp, SSANum, TempAddr, FoundNumeric, FoundPointer, FoundUnknown, FoundUninit, PtrType);
		}
	}

	return;
} // end of SMPBasicBlock::InferGlobalDefType()


// Iterate over all phi functions, calling InferPhiDefType() for any Phi DEF whose
//  type is still UNINIT.
// Return TRUE if any changes are made.
bool SMPBasicBlock::InferAllPhiDefTypes(void) {
	bool changed = false;
	bool NewChange;
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi = this->GetFirstPhi();
	while (CurrPhi != this->GetLastPhi()) {
		if (UNINIT == CurrPhi->GetDefType()) {
			CurrPhi = this->InferPhiDefType(CurrPhi, NewChange);
			changed = (changed || NewChange);
			if (NewChange) {
				this->MyFunc->IncTypedPhiDefs();
			}
			else {
				this->MyFunc->IncUntypedPhiDefs();
			}
		}
		else {
			this->MyFunc->IncTypedPhiDefs();
		}
		++CurrPhi;
	}
	return changed;
}  // end of SMPBasicBlock::InferAllPhiDefTypes()

// If all USEs in a Phi function are set in agreement with each other, then infer
//   the Phi DEF type is the same as the USEs type, set it, propagate it,
//   and return true.
// Otherwise, if all USEs of the Phi DEF in the function have a common type,
//  infer the Phi DEF type from them and return true.
set<SMPPhiFunction, LessPhi>::iterator SMPBasicBlock::InferPhiDefType(set<SMPPhiFunction, LessPhi>::iterator DefPhi, bool &changed) {
	changed = false;
	bool SkipToBackInference = false;
	bool PropagateChange = false;
	set<SMPPhiFunction, LessPhi>::iterator UsePhi;
	set<SMPPhiFunction, LessPhi>::iterator ReturnPhi = DefPhi;
	SMPOperandType MeetType = UNINIT;
	op_t DefOp = DefPhi->GetAnyOp();
	int SSANum = DefPhi->GetDefSSANum();
	bool SafeFunc = this->MyFunc->IsSafe();
	bool IndirectOp = MDIsIndirectMemoryOpnd(DefOp, this->MyFunc->UsesFramePointer());
	bool UnsafeOp = (IndirectOp || ((o_reg != DefOp.type) && (!SafeFunc)));
      // Relax the UnsafeOp definition with alias analysis?

	assert(UNINIT == DefPhi->GetDefType());
	for (size_t index = 0; index < DefPhi->GetPhiListSize(); ++index) {
		if (IsEqType(UNINIT, DefPhi->GetUseType(index))) {
			SkipToBackInference = true;
			break;
		}
	}

	if (!SkipToBackInference) {
		// Must have seen all non-UNINIT types if we reach this point.
		MeetType = DefPhi->ConditionalMeetType();
		if (IsNotEqType(UNKNOWN, MeetType)) {
			// Don't infer UNKNOWN until conditional type propagation stage.
			ReturnPhi = this->SetPhiDefType(DefOp, MeetType);
			changed = true;
			PropagateChange = true;
		}
	}
	else if (!UnsafeOp) { // try back inference from USEs of Phi DEF
		SMPOperandType DefType;
		DefType = this->MyFunc->InferGlobalDefType(DefOp, SSANum, this, false, BADADDR);
		if (IsNotEqType(UNINIT, DefType)) {
			// Don't set changed, because there is no downward propagation
			//  to do. Instead, propagate only to UNINIT Phi USEs.
			size_t limit = DefPhi->GetPhiListSize();
			set<size_t> UseUpdates;
			UseUpdates.clear();
			for (size_t index = 0; index < limit; ++index) {
				if (UNINIT == DefPhi->GetUseType(index)) {
					UseUpdates.insert(index); // keep list needing update
				}
			}
			set<size_t>::iterator UpIter;
			for (UpIter = UseUpdates.begin(); UpIter != UseUpdates.end(); ++UpIter) {
				this->SetPhiUseType(DefOp, *UpIter, DefType);
				// NOTE: DefPhi iterator is stale after this update
			}
			ReturnPhi = this->SetPhiDefType(DefOp, DefType);
			// We don't set PropagateChange to true for the back inference case,
			//  because there is no propagating to do.
			changed = true;
		}
	}

	// Propagate down to USEs of this DEF.
	if (PropagateChange && !UnsafeOp) {
		bool IsMemOp = (o_reg != DefOp.type);
		this->MyFunc->ResetProcessedBlocks();
		changed |= this->PropagateGlobalDefType(DefOp, MeetType, SSANum, IsMemOp);
	}
	return ReturnPhi;
} // end of SMPBasicBlock::InferPhiDefType()

#if STARS_BUILD_DEF_USE_CHAINS
size_t SMPBasicBlock::GetNumDUChains(bool GlobalName) const {
	size_t NumChains;
	if (GlobalName)
		NumChains = this->GlobalDUChains.ChainsByName.size();
	else
		NumChains = this->LocalDUChains.ChainsByName.size();
	return NumChains;
}

size_t SMPBasicBlock::GetNumLocalChains(unsigned int RegIndex, bool GlobalName) const {
	size_t NumLocalChains;
	if (GlobalName)
		NumLocalChains = this->GlobalDUChains.ChainsByName.at(RegIndex).GetSize();
	else
		NumLocalChains = this->LocalDUChains.ChainsByName.at(RegIndex).GetSize();
	return NumLocalChains;
}

// number of uses for RegIndex in ChainIndex in this block
size_t SMPBasicBlock::GetNumLocalUses(unsigned int RegIndex, size_t ChainIndex, bool GlobalName) const {
	size_t NumLocalUses;
	if (GlobalName)
		NumLocalUses = this->GlobalDUChains.ChainsByName.at(RegIndex).GetNumUses(ChainIndex);
	else
		NumLocalUses = this->LocalDUChains.ChainsByName.at(RegIndex).GetNumUses(ChainIndex);
	return NumLocalUses;
}

ea_t SMPBasicBlock::GetFirstDefAddr(unsigned int RegIndex, size_t ChainIndex, bool GlobalName) const {
	size_t DefAddr;
	if (GlobalName)
		DefAddr = this->GlobalDUChains.ChainsByName.at(RegIndex).GetDef(ChainIndex);
	else
		DefAddr = this->LocalDUChains.ChainsByName.at(RegIndex).GetDef(ChainIndex);
	return DefAddr;
}

ea_t SMPBasicBlock::GetLastUseAddr(unsigned int RegIndex, size_t ChainIndex, bool GlobalName) const {
	size_t UseAddr;
	if (GlobalName)
		UseAddr = this->GlobalDUChains.ChainsByName.at(RegIndex).GetLastUse(ChainIndex);
	else
		UseAddr = this->LocalDUChains.ChainsByName.at(RegIndex).GetLastUse(ChainIndex);
	return UseAddr;
}

//fetch USE addr #UseIndex from DU chain.
ea_t SMPBasicBlock::GetDUChainUse(unsigned int NameIndex, int SSANum, size_t UseIndex, bool GlobalName) const {
	size_t UseAddr;
	if (GlobalName)
		UseAddr = this->GlobalDUChains.ChainsByName.at(NameIndex).GetUse(SSANum, UseIndex);
	else
		UseAddr = this->LocalDUChains.ChainsByName.at(NameIndex).GetUse(SSANum, UseIndex);
	return UseAddr;
}


op_t SMPBasicBlock::GetDUName(unsigned int NameIndex, bool GlobalName) {
	op_t ChainOp;
	if (GlobalName)
		ChainOp = this->GlobalDUChains.ChainsByName.at(NameIndex).GetName();
	else
		ChainOp = this->LocalDUChains.ChainsByName.at(NameIndex).GetName();
	return ChainOp;
}

void SMPBasicBlock::SetIndWrite(unsigned int NameIndex, size_t ChainIndex, bool GlobalName, bool FlagValue) {
	if (GlobalName)
		this->GlobalDUChains.ChainsByName.at(NameIndex).SetIndWrite(ChainIndex, FlagValue);
	else 
		this->LocalDUChains.ChainsByName.at(NameIndex).SetIndWrite(ChainIndex, FlagValue);
	return;
}
#endif

// Is GlobalOp used anywhere in this block as a LiveIn value, including as a Phi USE?
bool SMPBasicBlock::IsGlobalNameUsedLiveIn(op_t GlobalOp) {
	bool FoundInLiveInSet = (LiveInSet.end() != LiveInSet.find(GlobalOp));
	bool OpUsed = FoundInLiveInSet;
	if (FoundInLiveInSet) {
		// exclude the pass-through case, in which the operand is LiveIn, LiveOut, but never killed or used.
		bool FoundInUpExposedSet = (this->GetLastUpExposed() != this->UpExposedSet.find(GlobalOp));
		OpUsed = FoundInUpExposedSet;
		if (!OpUsed) {
			// See if it is used as a Phi USE and is otherwise just passed through the block.
			set<SMPPhiFunction, LessPhi>::iterator PhiIter = this->FindPhi(GlobalOp);
			OpUsed = (PhiIter != this->GetLastPhi());
		}
	}

	return OpUsed;
} // end of SMPBasicBlock::IsGlobalNameUsed()

// Extension of IsRegDead for Global names.  Check and see if it overlaps with a DEF-USE chain
bool SMPBasicBlock::IsGlobalRegDead(ea_t InstAddr, op_t Operand, unsigned int RegIndex) {
	bool FoundInLiveInSet = (LiveInSet.end() != LiveInSet.find(Operand));
	bool FoundInLiveOutSet = (LiveOutSet.end() != LiveOutSet.find(Operand));
#if STARS_BUILD_DEF_USE_CHAINS
	bool FoundInUpExposedSet = (this->GetLastUpExposed() != this->UpExposedSet.find(Operand));
	size_t LocalChainIndex;
	size_t LocalChainMax = this->GetNumLocalChains(RegIndex, true);
	--LocalChainMax;
	bool HasLocalChains = (0 < LocalChainMax);
#endif
	bool FoundInKillSet = (KillSet.end() != KillSet.find(Operand));
	bool DebugFlag = (0x804837b == InstAddr);

#if STARS_BUILD_DEF_USE_CHAINS
	if (DebugFlag) {
		SMP_msg("IsGlobalRegDead for %x : ", InstAddr);
		PrintOperand(Operand);
		SMP_msg("\nLiveIn: %d LiveOut: %d UpExposed: %d VarKilled: %d\n", FoundInLiveInSet,
			FoundInLiveOutSet, FoundInUpExposedSet, FoundInKillSet);
	}
	if (DebugFlag) SMP_msg("A");

	// If there are no local chains for this global name, then it is either the pass-through
	//  case (LiveIn, LiveOut, !UpExposed, !VarKilled) or it must be dead.
	if (!HasLocalChains)
		return (!FoundInLiveInSet);

#endif


	if (DebugFlag) SMP_msg("A1");

	// If it is Live-In and Live-Out and not in the kill set,
	// it is live the whole time (either pass-through case or use-only case).
	if (FoundInLiveInSet && FoundInLiveOutSet && !FoundInKillSet)
		return false;

	if (DebugFlag) SMP_msg("B");
	// If it is not Live-In and not in the Kill set it is dead the whole time
	if (!FoundInLiveInSet && !FoundInKillSet) {
		// Must not have USEs, else it would be LiveIn. So, no DEFs, no USEs, not LiveIn: Dead.
		assert(!FoundInLiveOutSet);
		return true;
	}


	vector<SMPInstr *>::iterator InstIter = this->GetInstIterFromAddr(InstAddr);
	while (InstIter != this->GetLastInst()) {
		SMPInstr *CurrInst = (*InstIter);
		// Case 1: Not dead if reg is USE before it is a DEF.
		if (CurrInst->FindUse(Operand) != CurrInst->GetLastUse()) {
			return false;
		}
		// Case 2: Dead if DEF before USE.
		if (CurrInst->FindDef(Operand) != CurrInst->GetLastDef()) {
			return true;
		}
		++InstIter;
	}
	// Case 3: Reached end of block with no DEFs or USEs >=InstAddr. This is a global name,
	//  so it is dead if and only if it is not LiveOut. Does not really matter
	//  if it was DEFed or USEd before InstAddr.
	return (!FoundInLiveOutSet);

#if STARS_BUILD_DEF_USE_CHAINS

	if (DebugFlag) SMP_msg("C");
	// If it is not in the UpExposed set and is in the Kill set, it is dead
	// before the first def
	if (!FoundInUpExposedSet && FoundInKillSet) {
		ea_t StartAddr = this->GetFirstDefAddr(RegIndex, 0, true);
		if ((BADADDR != StartAddr) && (InstAddr <= StartAddr))
			return true;
	}

	if (DebugFlag) SMP_msg("D");
	// If it is in the UpExposedSet, it is live until the last use of the first chain
	if (FoundInUpExposedSet) {
		ea_t LastAddr = this->GetLastUseAddr(RegIndex, 0, true);
		if ((BADADDR != LastAddr) && (InstAddr <= LastAddr))
			return false;
	}

	if (DebugFlag) SMP_msg("E");
	// If it is not Live-Out, then it is dead after the last use
	if (!FoundInLiveOutSet) {
		ea_t LastAddr = this->GetLastUseAddr(RegIndex, LocalChainMax, true);
		if ((BADADDR != LastAddr) && (InstAddr > LastAddr))
			return true;
	}

	if (DebugFlag) SMP_msg("F");
	//If it is LiveOut and it is in the Kill Set, it will be live after the last definition	
	if (FoundInLiveOutSet && FoundInKillSet) {
		ea_t DefAddr = this->GetFirstDefAddr(RegIndex, LocalChainMax, true);
		if ((BADADDR != DefAddr) && (DefAddr < InstAddr))  // **!!**  <= or < ?
			return false;
	}

	if (DebugFlag) SMP_msg("G");
	// See if any DEF-USE chains overlap InstAddr's USE.
	for (LocalChainIndex = 0; LocalChainIndex <= LocalChainMax; ++LocalChainIndex) {
		// Need to check here to not break if this block does not have a def for this (LiveIn)
		// Skip this check if it is UpExposed and this is the first chain
		if (!FoundInUpExposedSet || LocalChainIndex > 0) {
			ea_t StartAddr = this->GetFirstDefAddr(RegIndex, LocalChainIndex, true);
			if (StartAddr >= InstAddr)
				continue;  // cannot overlap USE if DEF is after InstAddr
		}
		ea_t LastAddr = this->GetLastUseAddr(RegIndex, LocalChainIndex, true);
		if (DebugFlag) SMP_msg(" LastAddr: %x\n", LastAddr);
		if ((BADADDR != LastAddr) && (LastAddr >= InstAddr)) {
			if (DebugFlag) SMP_msg("Ga");
			return false;
		}
	}

	if (DebugFlag) SMP_msg("H");
	return true; // no DEF-USE chains overlapped the instrumentation point
#endif

} // end of SMPBasicBlock::IsGlobalRegDead()

// If no DEF-USE chains overlap the instrumentation point for InstAddr (which logically
//  falls between the USEs of the instruction at InstAddr and its DEFs), for register RegIndex,
//  then it is safe for the instrumentation to use that register without saving and
//  restoring its value. Return true in this case, false if there is DEF-USE overlap.
bool SMPBasicBlock::IsRegDead(ea_t InstAddr, uint16 RegNo) {
	// See if any DEF-USE chains overlap InstAddr's USEs.
	vector<SMPInstr *>::iterator InstIter = this->GetInstIterFromAddr(InstAddr);
	op_t RegOp = InitOp;
	RegOp.type = o_reg;
	RegOp.reg = RegNo;
	RegOp.dtyp = (*InstIter)->GetOperandDtypField();
	while (InstIter != this->GetLastInst()) {
		SMPInstr *CurrInst = (*InstIter);
		// Case 1: Not dead if reg is USE before it is a DEF.
		if (CurrInst->FindUse(RegOp) != CurrInst->GetLastUse()) {
			return false;
		}
		// Case 2: Dead if DEF before USE.
		if (CurrInst->FindDef(RegOp) != CurrInst->GetLastDef()) {
			return true;
		}
		++InstIter;
	}
	// Case 3: Reached end of block with no DEFs or USEs. This is a local name,
	//  so it was dead at the original InstAddr.
	return true;
} // end of SMPBasicBlock::IsRegDead()

// Mark the registers that are dead for each instruction in the block.
void SMPBasicBlock::MarkDeadRegs(void) {
	bool DebugFlag = false;
#if 0
	DebugFlag |= (0 == strcmp("_int_malloc", this->MyFunc->GetFuncName()));
#endif
	set<op_t, LessOp>::iterator NameIter;
	set<op_t, LessOp>::iterator FlagNameIter;
	vector<SMPInstr *>::iterator InstIter;
	op_t FlagsOp = InitOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.specflag1 = 0;
	FlagsOp.specflag2 = 0;
	bool GlobalFlags = this->MyFunc->IsGlobalName(FlagsOp);
	if (GlobalFlags) {
#if 0
		this->SetFlagsDeadAfterLastUse((this->LiveOutSet.find(FlagsOp) == this->LiveOutSet.end()));
#endif
		this->SetFlagsDeadBeforeFirstKill(((this->UpExposedSet.find(FlagsOp) == this->GetLastUpExposed())
			&& (this->KillSet.find(FlagsOp) != this->KillSet.end())));
		FlagNameIter = this->MyFunc->FindGlobalName(FlagsOp);
	}
	else {
		FlagNameIter = this->LocalNames.find(FlagsOp);
	}
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		ea_t InstAddr = CurrInst->GetAddr();
		DebugFlag = (0x804dafc == InstAddr);
		if (DebugFlag) {
			CurrInst->PrintOperands();
			SMP_msg("\n");
		}
		// First, put EFLAGS at beginning of string if it is dead.
		if (!GlobalFlags) {
			if (FlagNameIter != this->LocalNames.end()) {
				// EFLAGS is in the LocalNames
				uint16 RegNo = FlagNameIter->reg;
				unsigned int RegIndex = ExtractGlobalIndex(*FlagNameIter);
				if (this->IsRegDead(InstAddr, RegNo)) {
					CurrInst->SetRegDead((size_t) MD_FLAGS_REG);
				}
			}
			else { // EFLAGS are not locally used, but not global either; they are dead here
				CurrInst->SetRegDead((size_t) MD_FLAGS_REG);
			}
		}
		else {
			assert(FlagNameIter != this->MyFunc->GetLastGlobalName());
			unsigned int RegIndex = ExtractGlobalIndex(*FlagNameIter);
			bool newCatch = this->IsGlobalRegDead(InstAddr, FlagsOp, RegIndex);
			if (newCatch)
				CurrInst->SetRegDead((size_t) MD_FLAGS_REG);
		}

		// Now, process all other local regs and skip EFLAGS.
		for (NameIter = this->LocalNames.begin(); NameIter != this->LocalNames.end(); ++NameIter) {
			if (NameIter->type != o_reg)
				continue;
			// We never want to consider ESP to be available for instrumentation.
			if (NameIter->is_reg(MD_STACK_POINTER_REG))
				continue;
			// Until we analyze interprocedural register use, it is safest to not
			//  use EBP for instrumentation. This could change with more analysis.
			if (NameIter->is_reg(MD_FRAME_POINTER_REG))
				continue;

			unsigned int RegIndex = ExtractGlobalIndex(*NameIter);
			uint16 RegNo = NameIter->reg;
			if (RegNo == MD_FLAGS_REG) {
				//  We moved EFLAGS to the beginning, per annotations spec
				continue;
			}
			if (this->IsRegDead(InstAddr, RegNo)) {
				CurrInst->SetRegDead((size_t) RegNo);
			}
		} // end for all local names

		// Now, process all other global regs and skip EFLAGS.
		//SMP_msg(" Done.  Analyzing global regs...");
		size_t NumGlobals = this->MyFunc->NumGlobalNames();
		if (NumGlobals > 0) {
			for (NameIter = this->MyFunc->GetFirstGlobalName(); NameIter != this->MyFunc->GetLastGlobalName(); ++NameIter) {
				op_t RegOp = InitOp;
				RegOp.type = o_reg;
				//SMP_msg(" i ");

				//SMP_msg("%d", NameIter->type);
				if (NameIter->type != o_reg)
					continue;
				//SMP_msg(" j ");
				// We never want to consider ESP to be available for instrumentation.
				if (NameIter->is_reg(MD_STACK_POINTER_REG))
					continue;
				//SMP_msg(" k ");
				// Until we analyze interprocedural register use, it is safest to not
				//  use EBP for instrumentation. This could change with more analysis.
				if (NameIter->is_reg(MD_FRAME_POINTER_REG))
					continue;

				//SMP_msg(" l ");
				unsigned int RegIndex = ExtractGlobalIndex(*NameIter);
				int RegNum = NameIter->reg;
				if (RegNum == X86_FLAGS_REG) {
					//  We moved EFLAGS to the beginning, per annotations spec
					continue;
				}
				//SMP_msg(" m ");
				RegOp.reg = NameIter->reg;
				RegOp.dtyp = CurrInst->GetOperandDtypField();
				//SMP_msg("%i", RegOp.reg);
				if (this->IsGlobalRegDead(InstAddr, RegOp, RegIndex)) {
					CurrInst->SetRegDead((size_t) RegNum);
				}
			} // end for all global names
		}
		//SMP_msg("Done.  Next instruction.\n");

	} // end for all instructions
	if (DebugFlag)
		SMP_msg("Exiting MarkDeadRegs()\n");
	return;
} // end of SMPBasicBlock::MarkDeadRegs()

#if STARS_BUILD_DEF_USE_CHAINS
// Does DefOp at DefAddr never get used?
bool SMPBasicBlock::IsDefDead(ea_t DefAddr, op_t DefOp) {
	set<op_t, LessOp>::iterator LocalIter = this->LocalNames.find(DefOp);
	bool LocalName = (LocalIter != this->LocalNames.end());
	bool DefDead = false;
	unsigned int DUIndex;
	size_t NumChains;

	if (LocalName) {
		DUIndex = ExtractGlobalIndex(*LocalIter);
		size_t SSAIndex;
		assert(DUIndex < this->GetNumDUChains(false));
		NumChains = this->GetNumLocalChains(DUIndex, false);
		for (SSAIndex = 0; SSAIndex < NumChains; ++SSAIndex) {
			if (DefAddr == this->GetFirstDefAddr(DUIndex, SSAIndex, false)) {
				break;
			}
		}
		assert(SSAIndex < NumChains); // found it
		// If it has no uses, it is dead. Being a local name, there is no LiveOut possibility.
		DefDead = (0 == this->GetNumLocalUses(DUIndex, SSAIndex, false));
	}
	else { // global name
		DUIndex = this->GetGlobalDUIndex(DefOp, DefAddr);
		NumChains = this->GetNumLocalChains(DUIndex, true);
		assert(0 < NumChains);
		bool FoundIndex = false;
		size_t ChainIndex;
		for (ChainIndex = 0; ChainIndex < NumChains; ++ChainIndex) {
			if (DefAddr == this->GetFirstDefAddr(DUIndex, ChainIndex, true)) {
				FoundIndex = true;
				break;
			}
		}
		assert(FoundIndex);
		if (0 == this->GetNumLocalUses(DUIndex, ChainIndex, true)) {
			// No uses in that chain. If it is not the last chain, then DefOp is redefined and this
			//  DEF is truly dead. If it is the last chain and DefOp is in the LiveOut set, then it
			//  is not dead.
			if (ChainIndex == (NumChains - 1)) { // No uses, last chain
				DefDead = (!(this->IsLiveOut(DefOp)));
			}
			else {
				// No uses, not last chain.
				DefDead = true;
			}
		}
	}

	return DefDead;
} // end of SMPBasicBlock::IsDefDead()

#else

// Does DefOp at DefAddr never get used?
bool SMPBasicBlock::IsDefDead(ea_t DefAddr, op_t DefOp) {
	vector<SMPInstr *>::iterator InstIter = this->GetInstIterFromAddr(DefAddr);

	++InstIter; // start with next instruction
	while (InstIter != this->GetLastInst()) {
		SMPInstr *CurrInst = (*InstIter);
		// Case 1: Not dead if reg is USE before it is a DEF.
		if (CurrInst->FindUse(DefOp) != CurrInst->GetLastUse()) {
			return false;
		}
		// Case 2: Dead if re-DEF before USE.
		if (CurrInst->FindDef(DefOp) != CurrInst->GetLastDef()) {
			return true;
		}
		++InstIter;
	}
	// Case 3: Reached end of block with no DEFs or USEs. If this is a local name,
	//  it was dead at the original DefAddr, else a global is dead if it is not LiveOut.
	set<op_t, LessOp>::iterator LocalIter = this->LocalNames.find(DefOp);
	bool LocalName = (LocalIter != this->LocalNames.end());
	return (LocalName || (!(this->IsLiveOut(DefOp))));
} // end of SMPBasicBlock::IsDefDead()

#endif

// Return true if DefOp at DefAddr is used in or redefined by addition; pass back AdditionAddr
bool SMPBasicBlock::IsDefInvolvedInAddition(ea_t DefAddr, op_t DefOp, ea_t &AdditionAddr) {
	set<op_t, LessOp>::iterator LocalIter = this->LocalNames.find(DefOp);
	bool LocalName = (LocalIter != this->LocalNames.end());
	unsigned int DUIndex;
	size_t NumChains, NumUses, UseIndex;
	bool LastChain = false;
	bool UseFP = this->GetFunc()->UsesFramePointer();
	vector<SMPInstr *>::iterator UseInstIter;

	if (!MDIsDataFlowOpnd(DefOp, UseFP)) {
		return false;
	}

	UseInstIter = this->GetInstIterFromAddr(DefAddr);
	++UseInstIter;
	while (UseInstIter != this->GetLastInst()) {
		SMPInstr *UseInst = (*UseInstIter);
		AdditionAddr = UseInst->GetAddr();
		if (UseInst->FindUse(DefOp) != UseInst->GetLastUse()) {
			if (UseInst->MDIsAddition()) {
				// hash function value is accumulating in another DEF via addition.
				return true;
			}
			else if (UseInst->MDIsMoveInstr() || UseInst->MDIsUnderflowingOpcode() || UseInst->MDIsLoadEffectiveAddressInstr()) {
				// Copied to another location via move or subtraction; could reach addition in that location.
				set<DefOrUse, LessDefUse>::iterator CopyDefIter = UseInst->GetFirstNonFlagsDef();
				op_t CopyDefOp = CopyDefIter->GetOp();
				ea_t CopyAdditionAddr;
				if (this->IsDefInvolvedInAddition(UseInst->GetAddr(), CopyDefOp, CopyAdditionAddr)) {
					AdditionAddr = CopyAdditionAddr;
					return true;
				}
			}
		}
		if (UseInst->FindDef(DefOp) != UseInst->GetLastDef()) {
			// re-DEF
			return (UseInst->MDIsAddition());
		}
		++UseInstIter;
	}
	return false; // reached end of block without returning true or false above
#if STARS_BUILD_DEF_USE_CHAINS
	if (LocalName) {
		DUIndex = ExtractGlobalIndex(*LocalIter);
		size_t SSAIndex;
		assert(DUIndex < this->GetNumDUChains(false));
		NumChains = this->GetNumLocalChains(DUIndex, false);
		for (SSAIndex = 0; SSAIndex < NumChains; ++SSAIndex) {
			if (DefAddr == this->GetFirstDefAddr(DUIndex, SSAIndex, false)) {
				break;
			}
		}
		assert(SSAIndex < NumChains); // found it
		// If it has no uses, or is the last DEF, it is not part of an addition re-definition.
		NumUses = this->GetNumLocalUses(DUIndex, SSAIndex, false);
		LastChain = (SSAIndex == (NumChains - 1));
		// Search for addition USEs.
		for (UseIndex = 0; UseIndex < NumUses; ++UseIndex) {
			AdditionAddr = this->GetDUChainUse(DUIndex, SSAIndex, UseIndex, false);
			UseInstIter = this->GetInstIterFromAddr(AdditionAddr);
			SMPInstr *UseInst = (*UseInstIter);
			if (UseInst->MDIsAddition()) {
				// hash function value is accumulating in another DEF via addition.
				return true;
			}
			else if (UseInst->MDIsMoveInstr() || UseInst->MDIsUnderflowingOpcode() || UseInst->MDIsLoadEffectiveAddressInstr()) {
				// Copied to another location via move or subtraction; could reach addition in that location.
				set<DefOrUse, LessDefUse>::iterator CopyDefIter = UseInst->GetFirstNonFlagsDef();
				op_t CopyDefOp = CopyDefIter->GetOp();
				ea_t CopyAdditionAddr;
				if (this->IsDefInvolvedInAddition(UseInst->GetAddr(), CopyDefOp, CopyAdditionAddr)) {
					AdditionAddr = CopyAdditionAddr;
					return true;
				}
			}
		}
		if ((0 == NumUses) || LastChain) {
			return false;
		}

		// Get next DEF, see if it is an addition.
		AdditionAddr = this->GetFirstDefAddr(DUIndex, SSAIndex + 1, false);
	}
	else {
		DUIndex = this->GetGlobalDUIndex(DefOp, DefAddr);
		NumChains = this->GetNumLocalChains(DUIndex, true);
		assert(0 < NumChains);
		bool FoundIndex = false;
		size_t ChainIndex;
		for (ChainIndex = 0; ChainIndex < NumChains; ++ChainIndex) {
			if (DefAddr == this->GetFirstDefAddr(DUIndex, ChainIndex, true)) {
				FoundIndex = true;
				break;
			}
		}
		assert(FoundIndex);
		NumUses = this->GetNumLocalUses(DUIndex, ChainIndex, true);
		LastChain = (ChainIndex == (NumChains - 1));
		// Search for addition USEs.
		for (UseIndex = 0; UseIndex < NumUses; ++UseIndex) {
			AdditionAddr = this->GetDUChainUse(DUIndex, ChainIndex, UseIndex, true);
			UseInstIter = this->GetInstIterFromAddr(AdditionAddr);
			SMPInstr *UseInst = (*UseInstIter);
			if (UseInst->MDIsAddition()) {
				// hash function value is accumulating in another DEF via addition.
				return true;
			}
			else if (UseInst->MDIsMoveInstr() || UseInst->MDIsUnderflowingOpcode() || UseInst->MDIsLoadEffectiveAddressInstr()) {
				// Copied to another location iva move or subtraction; could reach addition in that location.
				set<DefOrUse, LessDefUse>::iterator CopyDefIter = UseInst->GetFirstNonFlagsDef();
				op_t CopyDefOp = CopyDefIter->GetOp();
				ea_t CopyAdditionAddr;
				if (this->IsDefInvolvedInAddition(UseInst->GetAddr(), CopyDefOp, CopyAdditionAddr)) {
					AdditionAddr = CopyAdditionAddr;
					return true;
				}
			}
		}
		if ((0 == NumUses) || LastChain) {
			return false;
		}
		// Get next DEF, see if it is an addition.
		AdditionAddr = this->GetFirstDefAddr(DUIndex, ChainIndex + 1, true);
	}
	vector<SMPInstr *>::iterator RedefInstIter = this->GetInstIterFromAddr(AdditionAddr);
	return ((*RedefInstIter)->MDIsAddition());
#endif

} // end of SMPBasicBlock::IsDefInvolvedInAddition()

// Does value of DefOp/DefSSANum reach block end in any computation of any DEF at all?
bool SMPBasicBlock::DoesDefReachBlockEnd(ea_t DefAddr, op_t DefOp, int DefSSANum, set<int> &NonEscapingRegisterHashes) {
	set<op_t, LessOp>::iterator LocalIter = this->LocalNames.find(DefOp);
	bool LocalName = (LocalIter != this->LocalNames.end());
	unsigned int DUIndex;
	size_t NumChains, NumUses;
	bool DoesEscape = false;
	bool ReDEF = false;
	bool UseFP = this->GetFunc()->UsesFramePointer();
	// set<int> NonEscapingRegisterHashes; // memoization optimization: set of register/SSA# hashes that do not reach end of block

	// If we encounter indirect memory operands of any kind, we cannot track them and must
	//  assume they are loop-variant and reach outside this block. Ditto for non-reg,
	//  non-stack operands.
	if (MDIsIndirectMemoryOpnd(DefOp, UseFP) || (!MDIsDataFlowOpnd(DefOp, UseFP))) {
		return true;
	}

#if STARS_BUILD_DEF_USE_CHAINS
	if (LocalName) {
		DUIndex = ExtractGlobalIndex(*LocalIter);
		size_t SSAIndex;
		assert(DUIndex < this->GetNumDUChains(false));
		NumChains = this->GetNumLocalChains(DUIndex, false);
		for (SSAIndex = 0; SSAIndex < NumChains; ++SSAIndex) {
			if (DefAddr == this->GetFirstDefAddr(DUIndex, SSAIndex, false)) {
				break;
			}
		}
		assert(SSAIndex < NumChains); // found it
		// If it has no uses, it is dead. Being a local name, there is no LiveOut possibility.
		NumUses = this->GetNumLocalUses(DUIndex, SSAIndex, false); 
		if (0 == NumUses) {
			DoesEscape = false; // Local name with no uses; dead; cannot escape block.
		}
		else {
			// For each use, we need to see if the value gets incorporated into a new DEF via
			//  arithmetic or assignment, and that new DEF reaches the end of the block.

			for (size_t UseIndex = 0; UseIndex < NumUses; ++UseIndex) {
				ea_t UseAddr = this->GetDUChainUse(DUIndex, SSAIndex, UseIndex, false);
				SMPInstr *NextInst = this->FindInstr(UseAddr);
				set<DefOrUse, LessDefUse>::iterator NextDefIter = NextInst->GetFirstNonFlagsDef();
				if (NextDefIter != NextInst->GetLastDef()) {
					// Instruction does something besides define the flags. That does not prove that
					//  our DefOp argument is transferred in any way to the next DEF, because our DefOp
					//  could just be used as an addressing register in NextInst.
					if (NextInst->OperandTransfersValueToDef(DefOp)) {
						op_t NextDefOp = NextDefIter->GetOp();
						int NextDefSSANum = NextDefIter->GetSSANum();
						bool RegNextDef = (o_reg == NextDefOp.type);
						int NextDefHashValue;
						if (RegNextDef) {
							NextDefHashValue = HashGlobalNameAndSSA(NextDefOp, NextDefSSANum);
							if (NonEscapingRegisterHashes.find(NextDefHashValue) != NonEscapingRegisterHashes.end()) {
								// We have already determined that NextDef does not reach the end of the block.
								continue;
							}
						}
						ea_t NextDefAddr = UseAddr;
						if (this->DoesDefReachBlockEnd(NextDefAddr, NextDefOp, NextDefSSANum, NonEscapingRegisterHashes)) {
							DoesEscape = true;
							break;
						}
						else if (RegNextDef) {
							// Memoize this result to save time reanalyzing it for other def-use chains.
							pair<set<int>::iterator, bool> InsertResult;
							InsertResult = NonEscapingRegisterHashes.insert(NextDefHashValue);
							assert(InsertResult.second);
						}
					}
				}
			} // end for all uses in DU-chain
		}
	}
	else { // global name
		DUIndex = this->GetGlobalDUIndex(DefOp, DefAddr);
		NumChains = this->GetNumLocalChains(DUIndex, true);
		assert(0 < NumChains);
		bool FoundIndex = false;
		size_t ChainIndex;
		for (ChainIndex = 0; ChainIndex < NumChains; ++ChainIndex) {
			if (DefAddr == this->GetFirstDefAddr(DUIndex, ChainIndex, true)) {
				FoundIndex = true;
				break;
			}
		}
		assert(FoundIndex);
		NumUses = this->GetNumLocalUses(DUIndex, ChainIndex, true);
		bool LastChain = (ChainIndex == (NumChains - 1));
		if (LastChain) { // Last chain
			DoesEscape = this->IsLiveOut(DefOp);
		}
		else if (0 == NumUses) {
				// No uses in that chain. If it is not the last chain, then DefOp is redefined and this
				//  DEF is truly dead. If it is the last chain and DefOp is in the LiveOut set, then it
				//  was caught above and DoesEscape would already be true and this statement would not be reached.
				DoesEscape = false;
		}
		else {
			// For each use, we need to see if the value gets incorporated into a new DEF via
			//  arithmetic or assignment, and that new DEF reaches the end of the block.
			for (size_t UseIndex = 0; UseIndex < NumUses; ++UseIndex) {
				ea_t UseAddr = this->GetDUChainUse(DUIndex, ChainIndex, UseIndex, true);
				SMPInstr *NextInst = this->FindInstr(UseAddr);
				set<DefOrUse, LessDefUse>::iterator NextDefIter = NextInst->GetFirstNonFlagsDef();
				if (NextDefIter != NextInst->GetLastDef()) {
					// Instruction does something besides define the flags. That does not prove that
					//  our DefOp argument is transferred in any way to the next DEF, because our DefOp
					//  could just be used as an addressing register in NextInst.
					if (NextInst->OperandTransfersValueToDef(DefOp)) {
						op_t NextDefOp = NextDefIter->GetOp();
						int NextDefSSANum = NextDefIter->GetSSANum();
						bool RegNextDef = (o_reg == NextDefOp.type);
						int NextDefHashValue;
						if (RegNextDef) {
							NextDefHashValue = HashGlobalNameAndSSA(NextDefOp, NextDefSSANum);
							if (NonEscapingRegisterHashes.find(NextDefHashValue) != NonEscapingRegisterHashes.end()) {
								// We have already determined that NextDef does not reach the end of the block.
								continue;
							}
						}
						ea_t NextDefAddr = UseAddr;
						if (this->DoesDefReachBlockEnd(NextDefAddr, NextDefOp, NextDefSSANum, NonEscapingRegisterHashes)) {
							DoesEscape = true;
							break;
						}
						else if (RegNextDef) {
							// Memoize this result to save time reanalyzing it for other def-use chains.
							pair<set<int>::iterator, bool> InsertResult = NonEscapingRegisterHashes.insert(NextDefHashValue);
							assert(InsertResult.second);
						}
					}
				}
			} // end for all uses in DU-chain
		}
	}
#else
	vector<SMPInstr *>::iterator InstIter = this->GetInstIterFromAddr(DefAddr);
	++InstIter;
	while (InstIter != this->GetLastInst()) {
		SMPInstr *NextInst = (*InstIter);
		if (NextInst->FindUse(DefOp) != NextInst->GetLastUse()) { // NextInst uses DefOp
			set<DefOrUse, LessDefUse>::iterator NextDefIter = NextInst->GetFirstNonFlagsDef();
			if (NextDefIter != NextInst->GetLastDef()) {
				// Instruction does something besides define the flags. That does not prove that
				//  our DefOp argument is transferred in any way to the next DEF, because our DefOp
				//  could just be used as an addressing register in NextInst.
				if (NextInst->OperandTransfersValueToDef(DefOp)) {
					op_t NextDefOp = NextDefIter->GetOp();
					int NextDefSSANum = NextDefIter->GetSSANum();
					bool RegNextDef = (o_reg == NextDefOp.type);
					int NextDefHashValue;
					if (RegNextDef) {
						NextDefHashValue = HashGlobalNameAndSSA(NextDefOp, NextDefSSANum);
						if (NonEscapingRegisterHashes.find(NextDefHashValue) != NonEscapingRegisterHashes.end()) {
							// We have already determined that NextDef does not reach the end of the block.
							++InstIter;
							continue;
						}
					}
					ea_t NextDefAddr = NextInst->GetAddr();
					if (this->DoesDefReachBlockEnd(NextDefAddr, NextDefOp, NextDefSSANum, NonEscapingRegisterHashes)) {
						DoesEscape = true;
						break;
					}
					else if (RegNextDef) {
						// Memoize this result to save time reanalyzing it for other def-use chains.
						pair<set<int>::iterator, bool> InsertResult;
						InsertResult = NonEscapingRegisterHashes.insert(NextDefHashValue);
						assert(InsertResult.second);
					}
				}
			}
		} // end if FindUse() succeeds
		if (NextInst->FindDef(DefOp) != NextInst->GetLastDef()) {
			// Re-DEF.
			ReDEF = true;
			break;
		}
		++InstIter;
	}
	if (!(DoesEscape || LocalName || ReDEF)) {
		// Did not find an escape, but we have a global name that reaches the end of the block
		//  without being redefined. If it is LiveOut, it escapes.
		DoesEscape = this->IsLiveOut(DefOp);
	}
#endif

	NonEscapingRegisterHashes.clear();

	return DoesEscape;
} // end of SMPBasicBlock::DoesDefReachBlockEnd()

// DefOp/DefSSANum is only used in LoopNum (outside of DefAddr) as address reg or Phi USE
bool SMPBasicBlock::IsDefOnlyUsedAsAddressReg(ea_t DefAddr, op_t DefOp, size_t LoopNum, size_t &AddrUseCounter, SMPOperandType &MemType) {
	bool OnlyAddressReg = false;
	bool ReDefSeen = false;

	if (this->IsProcessed() || (!this->GetFunc()->IsBlockInLoop(this->GetNumber(), LoopNum))) {
		// Must have already passed the test, or is an irrelevant block outside the loop.
		return true;
	}

	if (o_reg == DefOp.type) {
		OnlyAddressReg = true;
		vector<SMPInstr *>::iterator InstIter;
		op_t SearchOp = DefOp;
		CanonicalizeOpnd(SearchOp);
		set<DefOrUse, LessDefUse>::iterator UseIter;
		for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
			SMPInstr *CurrInst = (*InstIter);
			ea_t InstAddr = CurrInst->GetAddr();
			if (InstAddr != DefAddr) { // Skip induction variable re-definition.
				UseIter = CurrInst->FindUse(SearchOp);
				if (UseIter != CurrInst->GetLastUse()) {
					// Found a USE of DefOp not at DefAddr.
					if (CurrInst->HasDestMemoryOperand() || CurrInst->HasSourceMemoryOperand()) {
						op_t MemOp = CurrInst->GetMemUse();
						if (o_void == MemOp.type) {
							MemOp = CurrInst->GetMemDef();
						}
						int BaseReg, IndexReg;
						ushort ScaleFactor;
						ea_t offset;
						MDExtractAddressFields(MemOp, BaseReg, IndexReg, ScaleFactor, offset);
						if ((BaseReg != DefOp.reg) && (IndexReg != DefOp.reg)) {
							OnlyAddressReg = false; // USEd somehow, but not as an address reg.
						}
						else {
							++AddrUseCounter;
						}
					}
					else {
						// Definitely not an addressing reg, as there are no memory operands.
						OnlyAddressReg = false;
					}
					if (!OnlyAddressReg)
						break;
				}
#if 1
				else if ((InstAddr > DefAddr) && (CurrInst->FindDef(SearchOp) != CurrInst->GetLastDef())) {
					// SearchOp is DEFed but not USEd in CurrInst. That means some re-DEF
					//  that does not depend on the previous value, e.g. SearchOp := OtherOp,
					//  in a simple move. No need to search the rest of the block, as there
					//  will be no more USEs of the original SearchOp.
					ReDefSeen = true;
					break;
				}
#endif
			}
		} // end for all insts
		// If we passed all instructions in block with no problems, recurse into successors.
		this->SetProcessed(true);
		if (OnlyAddressReg && (!ReDefSeen)) {
			list<SMPBasicBlock *>::iterator SuccIter;
			ea_t PseudoDefAddr; // To identify re-DEF instructions in successor blocks.
			for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) {
				PseudoDefAddr = (*SuccIter)->GetFirstAddr() - 1; // any DEF without USE will be seen as a re-DEF in successor.
				if (!(*SuccIter)->IsDefOnlyUsedAsAddressReg(PseudoDefAddr, DefOp, LoopNum, AddrUseCounter, MemType)) {
					OnlyAddressReg = false;
					break;
				}
			}
		}
	}

	if (OnlyAddressReg) {
		if (0 < AddrUseCounter) {
			// NOTE: Future work: extract pointer type of base register above.
			MemType = POINTER;
		}
	}

	return OnlyAddressReg;
} // end of SMPBasicBlock::IsDefOnlyUsedAsAddressReg()


// erase() block starting at FirstAddr from Preds list
void SMPBasicBlock::ErasePred(ea_t FirstAddr) {
	list<SMPBasicBlock *>::iterator PredIter;
	PredIter = this->Predecessors.begin();
	while (PredIter != this->Predecessors.end()) {
		if ((*PredIter)->GetFirstAddr() == FirstAddr) {
			PredIter = this->Predecessors.erase(PredIter);
			break; // can only appear once
		}
		else
			++PredIter;
	}
	return;
} // end of SMPBasicBlock::ErasePred()

// erase() block starting at FirstAddr from Successors list
void SMPBasicBlock::EraseSucc(ea_t FirstAddr) {
	list<SMPBasicBlock *>::iterator SuccIter;
	SuccIter = this->Successors.begin();
	while (SuccIter != this->Successors.end()) {
		if ((*SuccIter)->GetFirstAddr() == FirstAddr) {
			SuccIter = this->Successors.erase(SuccIter);
			break; // can only appear once
		}
		else
			++SuccIter;
	}
	return;
} // end of SMPBasicBlock::EraseSucc()

// Add ReachInDefn to the ReachesIn set. If it was not already present,
//  then update the ReachesOutStale flag.
void SMPBasicBlock::AddReachesIn(pair<op_t, ea_t> ReachInDefn) { 
	pair<set<pair<op_t, ea_t>, LessDefinition>::iterator, bool> InsertResult;
	InsertResult = ReachesInSet.insert(ReachInDefn);
	if (InsertResult.second) {
		// New element added; ReachesOut set might be stale.
		this->SetReachesOutStale();
	}
} // end of SMPBasicBlock::AddReachesIn()

// Add a new definition to the ReachesOut set. If it was not already
//  present in the ReachesOut set, then propagate it to the ReachesIn sets
//  of all successor blocks. NOTE: The policy here is to keep the ReachesIn
//  sets up to date at all times.
void SMPBasicBlock::AddReachesOut(pair<op_t, ea_t> ReachOutDefn) { 
	pair<set<pair<op_t, ea_t>, LessDefinition>::iterator, bool> InsertResult;
	InsertResult = ReachesOutSet.insert(ReachOutDefn); 
	if (InsertResult.second) {
		// Insertion was of a new element; propagate to ReachesIn of all successors.
		list<SMPBasicBlock *>::iterator SuccIter;
		for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) {
			(*SuccIter)->AddReachesIn(ReachOutDefn);
		}
	}
	return;
} // end of SMPBasicBlock::AddReachesOut()

// Erase a phi function from the list.
bool SMPBasicBlock::ErasePhi(op_t OldOp) {
	set<SMPPhiFunction, LessPhi>::iterator PhiIter;
	PhiIter = this->FindPhi(OldOp);
	if (PhiIter == this->PhiFunctions.end())
		return false; // did not find, cannot erase
	this->PhiFunctions.erase(PhiIter);
	return true;
} // end of SMPBasicBlock::ErasePhi()

// Add a phi function to the list of phi functions entering this block.
// If phi function for this global name already existed in the block,
//   return false because no new phi function was added; else return true.
bool SMPBasicBlock::AddPhi(SMPPhiFunction NewPhi) {
	if (this->PhiFunctions.end() == this->PhiFunctions.find(NewPhi)) {
		this->PhiFunctions.insert(NewPhi);
		return true;
	}
	else
		return false;
} // end of SMPBasicBlock::AddPhi()

// Change the SSA number of the Phi function DEF corresponding to DefOp.
bool SMPBasicBlock::SetPhiDefSSA(op_t DefOp, int SSANum) {
	bool updated = false;
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi;
	CurrPhi = this->FindPhi(DefOp);
	if (CurrPhi == this->PhiFunctions.end()) { // did not find
		SMP_msg("ERROR: SetPhiDefSSA for block %d did not find DefOp: ", this->GetNumber());
		PrintOperand(DefOp);
		SMP_msg("\n");
	}
	else { // found it
		// To change a set item, we must change a copy, remove the original item
		//  from the set, and then insert the modified copy of the item.
		SMPPhiFunction TempPhi = (*CurrPhi);
		TempPhi.SetSSADef(SSANum);
		bool erased = this->ErasePhi(DefOp);
		assert(erased);
		updated = this->AddPhi(TempPhi);
		assert(updated);
	}
	return updated;
} // end of SMPBasicBlock::SetPhiDefSSA()

// Change the SSA number of the Phi function USE corresponding to DefOp and index.
bool SMPBasicBlock::SetPhiUseSSA(op_t DefOp, size_t index, int SSANum) {
	bool updated = false;
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi;
	CurrPhi = this->FindPhi(DefOp);
	if (CurrPhi == this->PhiFunctions.end()) { // did not find
		SMP_msg("ERROR: SetPhiUseSSA for block %d did not find DefOp: ", this->GetNumber());
		PrintOperand(DefOp);
		SMP_msg("\n");
	}
	else { // found it
		// To change a set item, we must change a copy, remove the original item
		//  from the set, and then insert the modified copy of the item.
		SMPPhiFunction TempPhi = (*CurrPhi);
		TempPhi.SetSSARef(index, SSANum);
		bool erased = this->ErasePhi(DefOp);
		assert(erased);
		updated = this->AddPhi(TempPhi);
		assert(updated);
	}
	return updated;
} // end of SMPBasicBlock::SetPhiUseSSA()

// Change the SMP type of the Phi function DEF corresponding to DefOp.
set<SMPPhiFunction, LessPhi>::iterator SMPBasicBlock::SetPhiDefType(op_t DefOp, SMPOperandType Type) {
	bool updated = false;
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi;
	CurrPhi = this->FindPhi(DefOp);
	if (CurrPhi == this->PhiFunctions.end()) { // did not find
		SMP_msg("ERROR: SetPhiDefType for block %d did not find DefOp: ", this->GetNumber());
		PrintOperand(DefOp);
		SMP_msg("\n");
	}
	else { // found it
		// To change a set item, we must change a copy, remove the original item
		//  from the set, and then insert the modified copy of the item.
		SMPPhiFunction TempPhi = (*CurrPhi);
		const SMPInstr *FirstInst = (*(this->GetFirstInst()));
		TempPhi.SetDefType(Type, FirstInst);
		bool erased = this->ErasePhi(DefOp);
		assert(erased);
		pair<set<SMPPhiFunction, LessPhi>::iterator, bool> InsertResult;
		InsertResult = this->PhiFunctions.insert(TempPhi);
		CurrPhi = InsertResult.first;
		updated = InsertResult.second;
		assert(updated);
	}
	return CurrPhi;
} // end of SMPBasicBlock::SetPhiDefType()

// Change the SMP type of the Phi function USE corresponding to DefOp and index.
bool SMPBasicBlock::SetPhiUseType(op_t DefOp, size_t index, SMPOperandType Type) {
	bool updated = false;
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi;
	CurrPhi = this->FindPhi(DefOp);
	if (CurrPhi == this->PhiFunctions.end()) { // did not find
		SMP_msg("ERROR: SetPhiUseType for block %d did not find DefOp: ", this->GetNumber());
		PrintOperand(DefOp);
		SMP_msg("\n");
	}
	else { // found it
		// To change a set item, we must change a copy, remove the original item
		//  from the set, and then insert the modified copy of the item.
		SMPPhiFunction TempPhi = (*CurrPhi);
		const SMPInstr *FirstInst = (*(this->GetFirstInst()));
		TempPhi.SetRefType(index, Type, FirstInst);
		bool erased = this->ErasePhi(DefOp);
		assert(erased);
		updated = this->AddPhi(TempPhi);
		assert(updated);
	}
	return updated;
} // end of SMPBasicBlock::SetPhiUseType()

// Change the metadata type of the Phi function DEF corresponding to DefOp.
set<SMPPhiFunction, LessPhi>::iterator SMPBasicBlock::SetPhiDefMetadata(op_t DefOp, SMPMetadataType Status) {
	bool updated = false;
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi;
	CurrPhi = this->FindPhi(DefOp);
	if (CurrPhi == this->PhiFunctions.end()) { // did not find
		SMP_msg("ERROR: SetPhiDefMetadata for block %d did not find DefOp: ", this->GetNumber());
		PrintOperand(DefOp);
		SMP_msg("\n");
	}
	else { // found it
		// To change a set item, we must change a copy, remove the original item
		//  from the set, and then insert the modified copy of the item.
		SMPPhiFunction TempPhi = (*CurrPhi);
		TempPhi.SetDefMetadata(Status);
		bool erased = this->ErasePhi(DefOp);
		assert(erased);
		pair<set<SMPPhiFunction, LessPhi>::iterator, bool> InsertResult;
		InsertResult = this->PhiFunctions.insert(TempPhi);
		CurrPhi = InsertResult.first;
		updated = InsertResult.second;
		assert(updated);
	}
	return CurrPhi;
} // end of SMPBasicBlock::SetPhiDefMetadata()

// Insert SCCP value for local name; change if already found.
map<int, struct STARS_SCCP_Const_Struct>::iterator SMPBasicBlock::InsertLocalConstValue(int DefHashValue, struct STARS_SCCP_Const_Struct NewConstEntry) {
	map<int, struct STARS_SCCP_Const_Struct>::iterator MapIter = this->FindLocalConstValue(DefHashValue);
	if (MapIter == this->GetLastLocalConstValueIter()) { // no old entry; insert
		pair<int, struct STARS_SCCP_Const_Struct> InsertPair(DefHashValue, NewConstEntry);
		pair<map<int, struct STARS_SCCP_Const_Struct>::iterator, bool> InsertResult = this->ConstantLocalDefs.insert(InsertPair);
		assert(InsertResult.second);
		MapIter = InsertResult.first;
	}
	else { // old entry found; update
		MapIter->second = NewConstEntry;
	}
	return MapIter;
} // end of SMPBasicBlock::InsertLocalConstValue()

// Six methods to get values into the maps of local reg/SSA to FG info.
//  For global names, see corresponding methods in SMPFunction.
void SMPBasicBlock::UpdateDefSignMiscInfo(int DefHashValue, unsigned short NewInfo) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair< map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter == this->LocalDefFGInfoBySSA.end()) {
		// Not found; insert first.
		struct FineGrainedInfo NewFGInfo;
		NewFGInfo.SignMiscInfo = NewInfo;
		NewFGInfo.SizeInfo = 0;
		pair<int, struct FineGrainedInfo> MapItem(DefHashValue, NewFGInfo);
		MapResult = this->LocalDefFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just OR in the new bits.
		MapIter->second.SignMiscInfo |= NewInfo;
	}

	return;
} // end of SMPBasicBlock::UpdateDefSignMiscInfo()

void SMPBasicBlock::UpdateUseSignMiscInfo(int UseHashValue, unsigned short NewInfo) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter == this->LocalUseFGInfoBySSA.end()) {
		// Not found; insert first.
		struct FineGrainedInfo NewFGInfo;
		NewFGInfo.SignMiscInfo = NewInfo;
		NewFGInfo.SizeInfo = 0;
		pair<int, struct FineGrainedInfo> MapItem(UseHashValue, NewFGInfo);
		MapResult = this->LocalUseFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just OR in the new bits.
		MapIter->second.SignMiscInfo |= NewInfo;
	}

	return;
} // end of SMPBasicBlock::UpdateUseSignMiscInfo()

void SMPBasicBlock::UpdateDefWidthTypeInfo(int DefHashValue, unsigned short NewInfo) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter == this->LocalDefFGInfoBySSA.end()) {
		// Not found; insert first.
		struct FineGrainedInfo NewFGInfo;
		NewFGInfo.SignMiscInfo = 0;
		NewFGInfo.SizeInfo = NewInfo;
		pair<int, struct FineGrainedInfo> MapItem(DefHashValue, NewFGInfo);
		MapResult = this->LocalDefFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just OR in the new bits.
		MapIter->second.SizeInfo |= NewInfo;
	}

	return;
} // end of SMPBasicBlock::UpdateDefWidthTypeInfo()

void SMPBasicBlock::UpdateUseWidthTypeInfo(int UseHashValue, unsigned short NewInfo) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter == this->LocalUseFGInfoBySSA.end()) {
		// Not found; insert first.
		struct FineGrainedInfo NewFGInfo;
		NewFGInfo.SignMiscInfo = 0;
		NewFGInfo.SizeInfo = NewInfo;
		pair<int, struct FineGrainedInfo> MapItem(UseHashValue, NewFGInfo);
		MapResult = this->LocalUseFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just OR in the new bits.
		MapIter->second.SizeInfo |= NewInfo;
	}

	return;
} // end of SMPBasicBlock::UpdateUseWidthTypeInfo()

void SMPBasicBlock::UpdateDefFGInfo(int DefHashValue, struct FineGrainedInfo NewFG) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter == this->LocalDefFGInfoBySSA.end()) {
		// Not found; insert it.
		pair<int, struct FineGrainedInfo> MapItem(DefHashValue, NewFG);
		MapResult = this->LocalDefFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just put in the new bits.
		MapIter->second.SignMiscInfo |= NewFG.SignMiscInfo;
		MapIter->second.SizeInfo |= NewFG.SizeInfo;
	}

	return;
} // end of SMPBasicBlock::UpdateDefFGInfo()

void SMPBasicBlock::UpdateUseFGInfo(int UseHashValue, struct FineGrainedInfo NewFG) {
	map<int, struct FineGrainedInfo>::iterator MapIter;
	pair<map<int, struct FineGrainedInfo>::iterator, bool> MapResult;

	MapIter = this->LocalUseFGInfoBySSA.find(UseHashValue);
	if (MapIter == this->LocalUseFGInfoBySSA.end()) {
		// Not found; insert it.
		pair<int, struct FineGrainedInfo> MapItem(UseHashValue, NewFG);
		MapResult = this->LocalUseFGInfoBySSA.insert(MapItem);
		assert(MapResult.second); // Was not previously found, insertion must work.
	}
	else { // found; just put in the new bits.
		MapIter->second.SignMiscInfo |= NewFG.SignMiscInfo;
		MapIter->second.SizeInfo |= NewFG.SizeInfo;
	}

	return;
} // end of SMPBasicBlock::UpdateUseFGInfo()

// Reset the signedness bits to zero for DEF.
void SMPBasicBlock::ClearDefSignedness(int DefHashValue) {
	map<int, struct FineGrainedInfo>::iterator MapIter;

	MapIter = this->LocalDefFGInfoBySSA.find(DefHashValue);
	if (MapIter != this->LocalDefFGInfoBySSA.end()) {
		MapIter->second.SignMiscInfo &= (~FG_MASK_SIGNEDNESS_BITS);
	}
	return;
} // end of SMPBasicBlock::ClearDefSignedness()

// Ensure that the Phi DEFs have all the fine grained info from all Phi USEs.
void SMPBasicBlock::PropagatePhiFGInfo(void) {
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi;
	size_t PhiUseIndex;
	struct FineGrainedInfo UseFG;

	for (CurrPhi = this->GetFirstPhi(); CurrPhi != this->GetLastPhi(); ++CurrPhi) {
		op_t PhiOp = CurrPhi->GetAnyOp();
		int DefSSANum = CurrPhi->GetDefSSANum();
		if (!MDIsGeneralPurposeReg(PhiOp))   // !!!!****!!!! Add stack locations also
			continue;
		int DefHashValue = HashGlobalNameAndSSA(PhiOp, DefSSANum);
		for (PhiUseIndex = 0; PhiUseIndex < CurrPhi->GetPhiListSize(); ++PhiUseIndex) {
			int UseSSANum = CurrPhi->GetUseSSANum(PhiUseIndex);
			int UseHashValue = HashGlobalNameAndSSA(PhiOp, UseSSANum);
			UseFG = this->GetFunc()->GetUseFGInfo(UseHashValue);
#if 1
			if ((UseFG.SignMiscInfo == 0) && (UseFG.SizeInfo == 0)) {
				// If no info for USE, get info from DEF.
				UseFG = this->GetFunc()->GetDefFGInfo(UseHashValue);
			}
#endif
			this->GetFunc()->UpdateDefFGInfo(DefHashValue, UseFG);
		}
	}

	return;
} // end of SMPBasicBlock::PropagatePhiFGInfo()

// Find consecutive DEFs of the same name within the block, both having
//  live metadata, that have the same type, making the second DEF
//  redundant metadata.
bool SMPBasicBlock::FindRedundantLocalMetadata(bool SafeFunc) {
	bool changed = false;
	bool CallInst;
	bool UseFP = this->GetFunc()->UsesFramePointer();
	bool EligibleOperand;
	bool LeafFunc = this->GetFunc()->IsLeaf();
	set<op_t, LessOp>::iterator NameIter;
	vector<SMPInstr *>::iterator InstIter;
	SMPInstr *CurrInst;
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	size_t LocalNameLimit = this->LocalNames.size();
	size_t GlobalNameLimit = this->GetFunc()->NumGlobalNames();
	vector<SMPOperandType> LocalTypes;
	vector<SMPOperandType> GlobalTypes;

#if 0
	bool DebugFlag = false;
	if (0 == strcmp("__libc_start_main", this->GetFunc()->GetFuncName())) {
		DebugFlag = true;
	}
#endif

	// Initialize the most recently seen type for each possible DEF.
	for (size_t i = 0; i < LocalNameLimit; ++i)
		LocalTypes.push_back(UNINIT);
	for (size_t i = 0; i < GlobalNameLimit; ++i)
		GlobalTypes.push_back(UNINIT);

	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		CurrInst = (*InstIter);
		if (NN_fnop == CurrInst->GetCmd().itype)
			continue; // skip SSA marker instruction; has no normal DEFs
		CallInst = ((CurrInst->GetDataFlowType() == CALL)
			|| (CurrInst->GetDataFlowType() == INDIR_CALL));
		for (CurrDef = CurrInst->GetFirstDef(); CurrDef != CurrInst->GetLastDef(); ++CurrDef) {
			op_t DefOp = CurrDef->GetOp();
			// We limit our analysis to register DEFs, or stack memory DEFs
			//  in SAFE functions. ***!!!*** Could add o_mem direct accesses
			//  in SAFE functions.
			EligibleOperand = ((DefOp.type == o_reg) 
				&& !(MDIsStackOrFramePointerReg(DefOp, UseFP)));
			if (!EligibleOperand && (DefOp.type != o_reg) && SafeFunc) {
				// Make some exceptions for SAFE functions.
				EligibleOperand = MDIsDirectStackAccessOpnd(DefOp, UseFP)
					|| (LeafFunc && !MDIsIndirectMemoryOpnd(DefOp, UseFP));
			}
			if (!EligibleOperand)
				continue;
			// If the metadata is not live for the DEF it is irrelevant
			//  to redundancy analysis. We make an exception for the DEFs
			//  of caller-saved regs at a CALL instruction, because we have
			//  no idea what might have happened to the metadata in the callee.
			if ((CurrDef->GetMetadataStatus() != DEF_METADATA_USED)
				&& (!(CallInst && MDIsCallerSavedReg(DefOp))))
				continue;
			bool GlobalName = false;
			NameIter = this->GetFunc()->FindGlobalName(DefOp);
			unsigned int NameIndex;
			SMPOperandType CurrType = CurrDef->GetType();
			SMPOperandType OldType;
			if (NameIter != this->GetFunc()->GetLastGlobalName()) {
				// global name
				GlobalName = true;
				NameIndex = ExtractGlobalIndex(*NameIter);
				OldType = GlobalTypes.at(NameIndex); 
			}
			else { // local name
				NameIter = this->FindLocalName(DefOp);
				assert(NameIter != this->GetLastLocalName());
				NameIndex = ExtractGlobalIndex(*NameIter);
				OldType = LocalTypes.at(NameIndex); 
			}
			if (IsEqType(CurrType, OldType)) {
				// types agree; only redundant if NUMERIC or pointers with
				//  the same referent, which we cannot determine statically,
				//  so we stick to NUMERIC redundancy only.
				if (IsNumeric(CurrType)) {
					// Metadata is redundant; profiler-dependent or not?
					bool ProfDerived = IsProfDerived(CurrType)
						|| IsProfDerived(OldType);
					if (ProfDerived) {
						CurrDef = CurrInst->SetDefMetadata(DefOp, DEF_METADATA_PROF_REDUNDANT);
					}
					else {
						CurrDef = CurrInst->SetDefMetadata(DefOp, DEF_METADATA_REDUNDANT);
					}
					changed = true;
				}
			} // end if current type same as old type
			else {
				// Update latest type seen.
				if (GlobalName)
					GlobalTypes[NameIndex] = CurrType;
				else
					LocalTypes[NameIndex] = CurrType;
			}
		} // end for all DEFs in current instruction
	} // end for all instructions

	LocalTypes.clear();
	GlobalTypes.clear();
	return changed;
} // end of SMPBasicBlock::FindRedundantLocalMetadata()

#if STARS_BUILD_DEF_USE_CHAINS
// Mark chains that include the indirect mem write addr
void SMPBasicBlock::MarkIndWriteChains(ea_t InstAddr) {
    // Iterate through all local names that have DU chains.
	size_t NameIndex, SSAIndex, SSALimit;
	for (NameIndex = 0; NameIndex < this->GetNumDUChains(false); ++NameIndex) {
		SSALimit = this->GetNumLocalChains(NameIndex, false);
		for (SSAIndex = 0; SSAIndex < SSALimit; ++SSAIndex) {
			ea_t LastAddr = this->GetLastUseAddr(NameIndex, SSAIndex, false);
			if ((InstAddr > this->GetFirstDefAddr(NameIndex, SSAIndex, false))
				&& (InstAddr < LastAddr)
				&& (BADADDR != LastAddr)) {
				this->SetIndWrite(NameIndex, SSAIndex, false, true);
			}
		}
	}

    // Iterate through all global names that have DU chains.
	for (NameIndex = 0; NameIndex < this->GetNumDUChains(true); ++NameIndex) {
		SSALimit = this->GetNumLocalChains(NameIndex, true);
		for (SSAIndex = 0; SSAIndex < SSALimit; ++SSAIndex) {
			bool AfterDef = (InstAddr > this->GetFirstDefAddr(NameIndex, SSAIndex, true));
			bool BeforeLastUse = (InstAddr < this->GetLastUseAddr(NameIndex, SSAIndex, true));
			if (AfterDef) {
				if (BeforeLastUse) {
					this->SetIndWrite(NameIndex, SSAIndex, true, true);
				}
 				// If the chain is the last SSA index for this global name,
				//  and the global name is LiveOut, then the chain really
				//  extends to the end of the block.
				else if (SSAIndex == (SSALimit - 1)) { // last chain for name
					// Check for LiveOut
					op_t GlobalOp = this->GetDUName(NameIndex, true);
					if (this->IsLiveOut(GlobalOp)) { 
						// live out; indirect write inside chain
						this->SetIndWrite(NameIndex, SSAIndex, true, true);
					}
				}
			} // end if (AfterDef)
		} // end for all SSA indices in each global name
	} // end for all global names
	return;
} // end of SMPBasicBlock::MarkIndWriteChains()
#endif

// Does block infinitely loop back to itself?
bool SMPBasicBlock::IsInfiniteSelfLoop(void) {
	bool InfiniteLoop = false;
	size_t NumSucc = this->GetNumSuccessors();
	if (1 == NumSucc) {
		// Is the only successor this block, and there are no function calls?
		int MyNum = this->GetNumber();
		list<SMPBasicBlock *>::iterator SuccIter = this->GetFirstSucc();
		int SuccNum = (*SuccIter)->GetNumber();
		if ((SuccNum == MyNum) && (!(this->HasCallInstruction() || this->HasIndirJumpInstruction()))) {
			InfiniteLoop = true;
		}
	}
	return InfiniteLoop;
} // end of SMPBasicBlock::IsInfiniteSelfLoop()

// Does block call a function?
bool SMPBasicBlock::HasCallInstruction(void) {
	vector<SMPInstr *>::iterator InstIter;
	bool HasCall = false;
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPitype InstDataFlowType = (*InstIter)->GetDataFlowType();
		if ((CALL == InstDataFlowType) || (INDIR_CALL == InstDataFlowType)) {
			HasCall = true;
			break;
		}
	}
	return HasCall;
} // end of SMPBasicBlock::HasCallInstruction()

// Does block end with an indirect jump?
bool SMPBasicBlock::HasIndirJumpInstruction(void) {
	vector<SMPInstr *>::reverse_iterator InstIter = this->GetRevInstBegin();
	SMPInstr *LastInst = (*InstIter);

	bool HasIndirJump = (LastInst->GetDataFlowType() == INDIR_JUMP);

	return HasIndirJump;
} // end of SMPBasicBlock::HasIndirJumpInstruction()

// Does block end with a conditional branch?
bool SMPBasicBlock::HasConditionalBranch(void) {
	vector<SMPInstr *>::reverse_iterator InstIter = this->GetRevInstBegin();
	SMPInstr *LastInst = (*InstIter);

	bool HasCondBranch = (LastInst->GetDataFlowType() == COND_BRANCH);

	return HasCondBranch;
} // end of SMPBasicBlock::HasConditionalBranch()

// We don't care if we overflow computing some DEFs, because of how they are used.
//  Return true when we detect one of these cases.
bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAddr, bool UnderflowOpcode, int &IdiomCode) {
	bool benign = false;
	op_t UseOp;
	vector<SMPInstr *>::iterator InstIter;
	set<DefOrUse, LessDefUse>::iterator UseIter, DefIter;
	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) {
			// Local name, find in basic block maps.
			DefFGInfo = this->GetDefFGInfo(DefHashValue);
		}
		else { // Global name, find in global maps.
			DefFGInfo = this->GetFunc()->GetDefFGInfo(DefHashValue);
		}
	}
	else if (MDIsDirectStackAccessOpnd(DefOp, UseFP)) {
		bool success = this->GetFunc()->MDGetFGStackLocInfo(DefAddr, DefOp, DefFGInfo);
		assert(success);
	}
	else {
		return false; // we can only handle register and stack DefOp types.
	}
	bool DefIsUnsigned = (FG_MASK_UNSIGNED == (DefFGInfo.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS));

	// First, we find the USEs of the DEF.
	if (RegDef) {
		for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
			SMPInstr *CurrInst = (*InstIter);
			size_t InstAddr = CurrInst->GetAddr();
			if (InstAddr > DefAddr) {
				UseIter = CurrInst->FindUse(DefOp);
				if (UseIter != CurrInst->GetLastUse()) {
					if (UseIter->GetSSANum() == DefSSANum) {
						// Found use of same SSA name.
						if (CurrInst->IsSubRegUsedAsShiftCount(DefOp)) {
							// A subreg of DefOp is used as a shift counter.
							//  We don't care if we overflowed DefOp, because
							//  we don't mind tossing upper bits anyway, as we
							//  need an 8-bit shift count for this USE.
							benign = true;
							IdiomCode = 1;
						}
						else if (INDIR_JUMP == CurrInst->GetDataFlowType()) {
							// Lots of false positives on indirect jumps via switch tables, because if
							//  any switch index has a negative number, then the compiler makes the "base"
							//  address be the address of "case 0:" rather than the beginning address, and then
							//  uses negative offsets to reach the "case -1:" and "case -2:" etc. addresses.
							//  So, STARS infers CODEPOINTER type => UNSIGNED, but we have unsigned+negative offset
							//  which looks like an unsigned addition overflow. We need to change the signedness
							//  to UNKNOWNSIGN when the annotation is emitted. This is not a truly benign case,
							//  so we just use the IdiomCode to signal what is going on and leave benign set to false.
							//  In the cases that occur later, we will continue to process this code just in case
							//  a truly benign code pattern is detected that will override this IdiomCode.
							// NOTE: We could make this case less likely to produce false negatives by getting info
							//  from IDA Pro to see if we have a switch table with negative offsets.
							IdiomCode = 17;
						}
						break; // For now, stop at first USE.
					}
				}
			}
		}
	}
	if (benign) {
		return benign;
	}

	SMPInstr *DefInst = this->GetFunc()->GetInstFromAddr(DefAddr);
	ea_t SourceInstAddr = BADADDR;
	SMPInstr *SourceInst = NULL;
	int UseSSANum = SMP_SSA_UNINIT;
	bool SpecialSourceFound = false;
	bool LeaDef = DefInst->MDIsLoadEffectiveAddressInstr();
	UseIter = DefInst->FindUse(DefOp); // DEF is also USE in addition, subtraction, etc.
	if (MDIsDataFlowOpnd(DefOp, UseFP) && (UseIter != DefInst->GetLastUse())) {
		UseSSANum = UseIter->GetSSANum();
		this->GetFunc()->ResetProcessedBlocks();
		SpecialSourceFound = DefInst->IsOpSourceSpecial(DefOp, UseSSANum, false, SourceInstAddr);
		if (SpecialSourceFound) {
			SourceInst = this->GetFunc()->GetInstFromAddr(SourceInstAddr);
		}
	}

	// Second case: Subtraction of two values, each of which is just a condition code.
	//  This can happen in optimized code that tests for which of two condition codes
	//  has been set, e.g.:
	//  [arithmetic operation or comparison]
	//  seta al  ; if "above" flag then al := 1 else al := 0
	//  setb bl  ; if "below" flag then bl := 1 else bl := 0
	//  mov ecx,eax  ; make copy of eax (including al) into ecx
	//  sub al,bl ; al := al - bl
	//  The resulting value in al will be 1 if the above flag was set, -1 if below, 0 if neither.
	//  We see the seta/setb as implying unsigned values, which is true, but if al becomes -1
	//   we do not want to consider this to be an underflow.
	//  If the source of the minuend and subtrahend are one condition code and one small immediate,
	//   then we also want to suppress underflow false positives.
	//  The same logic applies to overflow opcodes: lea edx,[eax+eax-1] is hard to classify as
	//   potential underflow or overflow. If eax comes from a condition code (seta eax), the values
	//   will be small and no overflow check is needed.
	if (!benign) {
		if (UnderflowOpcode && MDIsDataFlowOpnd(DefOp, UseFP)) {
			// Prepare for possible recursive traversals through the function blocks.
			this->GetFunc()->ResetProcessedBlocks();
			if (SpecialSourceFound && DefInst->IsOpSourceConditionCode(DefOp, UseSSANum)) {
				// If we had a decrement opcode, we are done, and underflow is benign.
				if (DefInst->MDIsDecrement()) {
					benign = true;
				}
				else { // For subtraction, need to see if BOTH operands came from condition codes (flags).
					UseOp = DefInst->GetUseOnlyAddSubOp();
					if (MDIsDataFlowOpnd(UseOp, UseFP)) {
						CanonicalizeOpnd(UseOp);
						UseIter = DefInst->FindUse(UseOp);
						int SubtrahendSSANum = UseIter->GetSSANum();
						this->GetFunc()->ResetProcessedBlocks();
						benign = DefInst->IsOpSourceConditionCode(UseOp, SubtrahendSSANum);
					}
					else if (UseOp.type == o_imm) {
						uval_t ImmVal = UseOp.value;
						benign = (ImmVal <= 4); // small value is intentionally setting up bit pattern of mostly 1-bits
					}
				}
				if (benign) {
					IdiomCode = 3;
				}
			}
			// Prepare for possible recursive traversals through the function blocks.
			this->GetFunc()->ResetProcessedBlocks();
			if (!benign && SpecialSourceFound && (DefInst->IsOpSourceZeroExtendedMove(DefOp, UseSSANum, false))) {
				// If we had a decrement opcode, we are done, and underflow is not benign.
				if (DefInst->MDIsDecrement()) {
					benign = false;
				}
				else { // For subtraction, need to see if BOTH operands came from zero-extended moves.
					UseOp = DefInst->GetUseOnlyAddSubOp();
					if (MDIsDataFlowOpnd(UseOp, UseFP)) {
						CanonicalizeOpnd(UseOp);
						UseIter = DefInst->FindUse(UseOp);
						UseSSANum = UseIter->GetSSANum();
						this->GetFunc()->ResetProcessedBlocks();
						benign = DefInst->IsOpSourceZeroExtendedMove(UseOp, UseSSANum, false);
					}
				}
				if (benign) {
					IdiomCode = 12;
				}
			}
			// Third case: Subtract original value from shifted value, unsigned. If the shift reduced the original value,
			//  you will have an underflow. Right shifts always reduce the unsigned value, and left shifts reduce the unsigned
			//  value in many cases (but not for signed values).
			else if (!benign) {
				// Check for UNSIGNED.
				if (DefIsUnsigned) {
					// Does the subtraction use a value from a shift?
					UseIter = DefInst->FindUse(DefOp);
					if (UseIter != DefInst->GetLastUse()) {
						int UseSSANum = UseIter->GetSSANum();
						ea_t UseDefAddr = this->GetDefAddrFromUseAddr(DefOp, DefAddr, UseSSANum, LocalDefName);
						if (UseDefAddr >= this->GetFirstAddr()) {
							// Limit to the simple case in which UseDefAddr is in our block, not Phi function or function entry marker inst.
							SMPInstr *UseDefInst = this->GetFunc()->GetInstFromAddr(UseDefAddr);
							if (UseDefInst->MDIsShiftOrRotate()) {
								// Find USE that got shifted.
								UseIter = UseDefInst->FindUse(DefOp);
								if (UseIter != UseDefInst->GetLastUse()) {
									UseSSANum = UseIter->GetSSANum();
									// At this point, we might still have sequence:
									// mov edi,eax
									// shl edi,5
									// sub edi,eax
									//
									// We have backtracked from the subtraction to the USE of EDI in the shift. Now we need to
									//  find the move that is the DEF of this USE of EDI, i.e. we need to find EAX.
									UseDefAddr = this->GetDefAddrFromUseAddr(DefOp, UseDefAddr, UseSSANum, LocalDefName);
									if (UseDefAddr >= this->GetFirstAddr()) {
										SMPInstr *MoveInst = this->GetFunc()->GetInstFromAddr(UseDefAddr);
										if (MoveInst->MDIsMoveInstr()) {
											op_t MoveSourceOp = MoveInst->GetMoveSource();
											// Now for the $64,000 question: Is MoveSourceOp the same operand as
											//  is subtracted in DefInst?
											// NOTE: We should probably limit this check to register or direct stack operands.
											//  We are currently matching MoveSourceOp to the subtrahend operand on immediate
											//  value cases, e.g. 0x80a7884 in sudoku.exe with immediate value 1.
											UseIter = DefInst->FindUse(MoveSourceOp);
											if (UseIter != DefInst->GetLastUse()) {
												// Found it. The value that got shifted later had the unshifted
												//  original value subtracted from the shifted value, which will
												//  produce a benign unsigned underflow quite often.
												benign = true;
												IdiomCode = 16;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		} // 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.
		else if (DefInst->MDIsLoadEffectiveAddressInstr()) {
			UseOp = DefInst->GetLeaMemUseOp();
			int BaseReg, IndexReg;
			ushort ScaleFactor;
			ea_t offset;
			MDExtractAddressFields(UseOp, BaseReg, IndexReg, ScaleFactor, offset);
			bool SafeBaseReg = (BaseReg == R_none);
			bool SafeIndexReg = (IndexReg == R_none);
			op_t SearchOp = InitOp;
			SearchOp.type = o_reg;
			SearchOp.dtyp = DefInst->GetOperandDtypField();
			if (!SafeBaseReg) {
				SearchOp.reg = BaseReg;
				UseIter = DefInst->FindUse(SearchOp);
				assert(UseIter != DefInst->GetLastUse());
				UseSSANum = UseIter->GetSSANum();
				this->GetFunc()->ResetProcessedBlocks();
				SafeBaseReg = DefInst->IsOpSourceConditionCode(SearchOp, UseSSANum);
			}
			if (SafeBaseReg && (!SafeIndexReg)) {
				// We avoid redundant work when BaseReg == IndexReg.
				if (IndexReg == BaseReg) {
					SafeIndexReg = true;
				}
				else {
					SearchOp.reg = IndexReg;
					UseIter = DefInst->FindUse(SearchOp);
					assert(UseIter != DefInst->GetLastUse());
					UseSSANum = UseIter->GetSSANum();
					this->GetFunc()->ResetProcessedBlocks();
					SafeIndexReg = DefInst->IsOpSourceConditionCode(SearchOp, UseSSANum);
				}
			}
			if (SafeBaseReg && SafeIndexReg) { // We could check for huge offset values here (corner case) !!!!****!!!!
				benign = true;
				IdiomCode = 8;
			}
		}
	}

#if STARS_AGGRESSIVE_BENIGN_POINTER_ARITHMETIC
	if (!benign && UnderflowOpcode && DefIsUnsigned) {
		// Search for a sequence of SUB then ADD operations that
		//  are applied to a POINTER type.
		InstIter = this->GetInstIterFromAddr(DefAddr);
		assert(InstIter != this->GetLastInst());
		DefIter = DefInst->FindDef(DefOp);
		assert(DefIter != DefInst->GetLastDef());
		SMPOperandType DefType = DefIter->GetType();
#if 0  // Make it apply to all UNSIGNED; POINTERs are already IDIOM 18
		if (IsDataPtr(DefType)) {
#endif
			// Restrict pattern to POINTER -= [operand1]; POINTER += [operand2]
			//  in consecutive instructions. Both instructions could overflow, while
			//  producing a valid result after canceling each other out.
			++InstIter;
			if (InstIter != this->GetLastInst()) {
				SMPInstr *DefInst2 = (*InstIter);
				if (DefInst2->MDIsAddition()) {
					UseIter = DefInst2->FindUse(DefOp);
					if (UseIter != DefInst2->GetLastUse()) {
						// POINTER DefOp is USE (and also DEF, which we did not check explicitly)
						//  in addition after being re-DEFed by the original subtraction inst.
						benign = true;
						IdiomCode = 23;
						DefInst2->SetSuppressNumericAnnotation();
					}
				}
			}
#if 0
		}
#endif
	}
#endif

	if (!benign) {
		// Bitwise NOT is likely to produce an overflow/underflow for a subsequent add/subtract.
#if 0
		if (RegDef) {
#endif
			// DEF is also USE in addition or subtraction ...
			if (UseIter != DefInst->GetLastUse()) {   // ... but not always on lea opcode
				if (SpecialSourceFound && SourceInst->MDIsBitwiseNotOpcode()) {
					benign = true;
					IdiomCode = 21;
				}
			}
#if 0
		}
#endif
#if 0
		else if (MDIsDirectStackAccessOpnd(DefOp, this->GetFunc()->UsesFramePointer())){
			// We need the canonicalized stack operand as found in DEFs and USEs.
			UseOp = DefInst->MDGetMemUseOp(); // DEF is also USE in addition or subtraction ...
			UseIter = DefInst->FindUse(UseOp);
			if (UseIter != DefInst->GetLastUse()) {   // ... but not always on lea opcode
				UseSSANum = UseIter->GetSSANum();
				if (SourceInst->MDIsBitwiseNotOpcode()) {
					benign = true;
					IdiomCode = 21;
				}
			}
		}
#endif
	}

	if (!benign) {
		// Look for bitwise NOT idiom on USE-only addend or subtrahend.
		UseOp = DefInst->GetUseOnlyAddSubOp();
		if (UseOp.type == o_reg) {
			CanonicalizeOpnd(UseOp);
			UseIter = DefInst->FindUse(UseOp); 
			if (UseIter != DefInst->GetLastUse()) {
				UseSSANum = UseIter->GetSSANum();
				bool LocalName = this->IsLocalName(UseOp);
				this->GetFunc()->ResetProcessedBlocks();
				if (DefInst->IsOpSourceBitwiseNot(UseOp, UseSSANum)) {
						benign = true;
						IdiomCode = 21;
				}
			}
		}
		else if (MDIsDirectStackAccessOpnd(UseOp, this->GetFunc()->UsesFramePointer())) {
			// We need the canonicalized stack operand as found in DEFs and USEs.
			UseOp = DefInst->MDGetMemUseOp();
			assert(o_void != UseOp.type);
			UseIter = DefInst->FindUse(UseOp);
			assert(UseIter != DefInst->GetLastUse());
			UseSSANum = UseIter->GetSSANum();
			this->GetFunc()->ResetProcessedBlocks();
			if (DefInst->IsOpSourceBitwiseNot(UseOp, UseSSANum)) {
				benign = true;
				IdiomCode = 21;
			}
		}
	}

	if (!benign && !UnderflowOpcode && DefIsUnsigned) {
		// Search for a sequence of ADD, OR, and AND operations that
		//  use constant operands that add up to an UNSIGNED OVERFLOW.
		InstIter = this->GetInstIterFromAddr(DefAddr);
		assert(InstIter != this->GetLastInst());
		int32 ImmedValue = (int32) (*InstIter)->MDGetImmedUse();
		// NOTE: If ImmedValue is very large, we catch this elsewhere as IDIOM 11.
		if (ImmedValue > 0) {
			vector<SMPInstr *>::reverse_iterator RevInstIter(InstIter);
			int32 ConstLimit = 0x7fffffff - ImmedValue;
			while (RevInstIter != this->GetRevInstEnd()) {
				SMPInstr *SearchInst = (*RevInstIter);
				DefIter = SearchInst->FindDef(DefOp);
				if (DefIter != SearchInst->GetLastDef()) { // found previous DEF
					if (SearchInst->MDIsBitwiseAndOpcode() || SearchInst->MDIsBitwiseOrOpcode() || SearchInst->MDIsAddition()) {
						ImmedValue = (int32) SearchInst->MDGetImmedUse();
						if (0 < ImmedValue) {
							if (ImmedValue >= ConstLimit) {
								benign = true;
								IdiomCode = 22;
								break; // no need to search further
							}
							else {
								ConstLimit -= ImmedValue; // set new limiting value
							}
						}
						else {
							break; // not the pure chain we are searching for
						}
					}
					else {
						break; // not the pure chain we are searching for
					}
				}
				++RevInstIter;
			}
		}
	}

	return benign;
} // end of SMPBasicBlock::IsBenignOverflowDEF()

// Is subword of DefOp written later, before TruncAddr?
bool SMPBasicBlock::IsDEFWrittenWithTruncation(op_t DefOp, int DefSSANum, ea_t DefAddr, ea_t TruncAddr, bool PhiDEF) {
	assert(o_reg == DefOp.type);
	op_t SearchOp = DefOp;
	CanonicalizeOpnd(SearchOp);
	vector<SMPInstr *>::iterator InstIter;
	bool FoundSubwordWrite = false;

	InstIter = this->GetInstIterFromAddr(DefAddr);
	if (!PhiDEF) {
		// DefAddr is just first addr in block with PhiDEF, else it is real DefAddr that should be skipped.
		++InstIter;
	}
	while (InstIter != this->GetLastInst()) {
		// Search for subword write of DefOp/DefSSANum.
		SMPInstr *CurrInst = (*InstIter);
		ea_t InstAddr = CurrInst->GetAddr();
		if (InstAddr >= TruncAddr)
			break;  // else we will find the apparent truncation we started with!

		// Re-DEF of DefOp terminates search unless it is a right shift.
		//  A right shift often precedes a subword write, e.g.:
		//  edx := ...
		//  ecx := edx;   // need to recurse into ecx chain here
		//  ecx := ecx >> 8;  // don't terminate ecx chain search yet
		//  mem := cl (subword of ecx) // found subword write
		set<DefOrUse, LessDefUse>::iterator DefIter = CurrInst->FindDef(SearchOp);
		if (DefIter != CurrInst->GetLastDef()) { // found re-DEF
			if (CurrInst->MDIsShiftRight()) {
				// Reset DefSSANum and DefAddr and recurse.
				FoundSubwordWrite = this->IsDEFWrittenWithTruncation(DefOp, DefIter->GetSSANum(), InstAddr, TruncAddr, false);
			}
			break; // we always terminate after re-DEF; either we recursed or we failed our search.
		}

		set<DefOrUse, LessDefUse>::iterator UseIter = CurrInst->FindUse(SearchOp);
		if (UseIter != CurrInst->GetLastUse()) { // Used, so instruction might be relevant.
			if (CurrInst->MDIsMoveInstr()) { // register DefOp might be copied somewhere
				op_t MoveSourceOp = CurrInst->GetMoveSource();
				CanonicalizeOpnd(MoveSourceOp);
				if (IsEqOp(MoveSourceOp, SearchOp)) { // SearchOp is being copied.
					// Subword write of DefOp is successful detection.
					if (CurrInst->MDIsReducedWidthMove()) { // Subword of SearchOp is being copied.
						FoundSubwordWrite = true;
						break;
					}
					else { // full-width move
						DefIter = CurrInst->GetFirstNonFlagsDef();
						op_t MoveDestOp = DefIter->GetOp();
						if (o_reg == MoveDestOp.type) { // recurse into copy reg chain
							int MoveDestSSANum = DefIter->GetSSANum();
							FoundSubwordWrite = this->IsDEFWrittenWithTruncation(MoveDestOp, MoveDestSSANum, InstAddr, TruncAddr, false);
							if (FoundSubwordWrite)
								break; // success, else continue current chain
						}
						else { // copied to memory; do not recurse, but keep searching.
							;
						}
					}
				}
			} // end if Move instr
		} // end if USEd
		++InstIter;
	} // end while all insts

	return FoundSubwordWrite;
} // end of SMPBasicBlock::IsDEFWrittenWithTruncation()

// We don't care if we truncate computing some DEFs, because of how they are used.
//  Return true when we detect one of these cases.
bool SMPBasicBlock::IsBenignTruncationDEF(op_t DefOp, int DefSSANum, size_t DefAddr, int &IdiomCode) {
	bool benign = false;
	vector<SMPInstr *>::iterator InstIter;
	set<DefOrUse, LessDefUse>::iterator UseIter, UseIter2, DefIter;
	op_t UseOp, SearchOp = InitOp, UseOp2;
	unsigned short SignMask;
	bool FoundTruncationDef = false; // Found apparent truncation move
	SMPInstr *TruncationInst = NULL;
	size_t UseBitWidth;   // Bit width involved in truncation move
	size_t BytesMasked;
	bool FoundSubregUse = false;   // Found next use of truncated DEF, which appears to make truncation benign
	int UseSSANum = -1, UseSSANum2;

	// First, we find the USEs of the DEF.
	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		size_t InstAddr = CurrInst->GetAddr();
		if (InstAddr == DefAddr) {
			// In the truncating instruction, if we have a sub-register that was originally
			//  DEFed as its enclosing register, it appears to be a truncation. However, it
			//  could be that the rest of the register is used later, not discarded, e.g.:
			//   mov [ebp-12],ax  ; looks like EAX is being truncated to AX and stored
			//   shr eax,16       ; gets upper 16 bits into lower 16 bits
			//   mov [ebp-14],ax  ; store what used to be the upper 16 bits of EAX
			// The first instruction will trigger a CHECK TRUNCATION annotation that
			//  causes false positives. We need to analyze the context of the instruction
			//  to see that the whole register EAX was used, so no truncation occurred.
			//  The context analysis in the basic block will mark the second move as
			//  a "truncation" that should be ignored, so we can later avoid performing
			//  redundant analysis.
			if ((CurrInst->GetOptType() == 3) && (!CurrInst->MDIsSignedLoad(SignMask))) {
				// We have a regular load, not a sign-extended or zero-extended load.
				//  This is the kind of load that could look like a truncation, if the
				//  USE has smaller width than the DEF. Precise analysis of the width of
				//  the USE and DEF occurs in SMPInstr::EmitIntegerErrorAnnotations(), but
				//  we need only a good first cut here.
				UseOp = CurrInst->GetMoveSource();
				SearchOp = UseOp;
				if (UseOp.type == o_reg) {
					SearchOp = UseOp;
					CanonicalizeOpnd(SearchOp);
				}
				else {
					break;  // Not a sub-register, cannot fit the pattern
				}
				UseIter = CurrInst->FindUse(SearchOp);
				assert(UseIter != CurrInst->GetLastUse());
				UseSSANum = UseIter->GetSSANum();

				if (UseIter->DoesNotTruncate()) {
					benign = true; // already analyzed
					IdiomCode = 2;
					break;
				}

				FoundTruncationDef = true;
				TruncationInst = CurrInst;
				UseBitWidth = 8 * GetOpDataSize(UseOp);
				if (MD_NORMAL_MACHINE_BITWIDTH <= UseBitWidth) {
					// Cannot be truncation; exit.
					break;
				}
			}
		}
		else if (FoundTruncationDef) {
			if (!FoundSubregUse) {
				// Find next USE of SearchOp.
				UseIter2 = CurrInst->FindUse(SearchOp);
				if (UseIter2 != CurrInst->GetLastUse()) {
					int UseSSANum2 = UseIter2->GetSSANum();
					if (UseSSANum != UseSSANum2) {
						break; // have re-DEFed; stop following SearchOp
					}
					// Found use of SearchOp+DefSSANum. Must be shift or rotate to fit pattern.
					if (CurrInst->MDIsShiftOrRotate()) {
						// If we shift or rotate by UseBitWidth bits, even if we don't make
						//  an exact full circle, we can pattern match a simpler pattern, e.g.:
						//  mov <memory>,dl
						//  shr edx,8
						//  loop back to process next byte in edx
						//  If we see this pattern, we go ahead and mark the move as non-truncating.
						//  Passing false as the second argument makes the check less restrictive.
						if (CurrInst->ShiftMakesUpperBitsLower(UseBitWidth, false)) {
							// At least it matches the less restrictive two-inst sequence.
							benign = true;
							IdiomCode = 2;
							// Set the NoTruncate flag in the first instruction for the sub-reg UseOp.
							TruncationInst->SetUseNoTruncate(SearchOp, true);
							if (CurrInst->ShiftMakesUpperBitsLower(UseBitWidth, true)) {
								FoundSubregUse = true;
							}
						}
					} // end if shift or rotate
					else if (CurrInst->MDIsSubregMaskInst(BytesMasked)) {
						// If we are masking off subreg regions, then we are operating on
						//  less than the full register after the truncation, so the truncation
						//  is almost certainly benign.
						benign = true;
						IdiomCode = 14;
						break; // Masking inst is redefining SearchOp
					}
				} // end if found SearchOp in CurrInst
				else {
					DefIter = CurrInst->FindDef(SearchOp);
					if (DefIter != CurrInst->GetLastDef()) {
						// SearchOp is not used as subreg yet, but is re-DEFed. Failed to match.
						break;
					}
				}
			}
			else {
				// Found apparent truncation, found shift that seems to make it benign.
				//  Now we need to see the shifted bits (former upper bits) get stored
				//  so we can mark both store instructions as benign.
				UseIter2 = CurrInst->FindUse(SearchOp);
				if (UseIter2 != CurrInst->GetLastUse()) {
					if ((CurrInst->GetOptType() == 3) && (!CurrInst->MDIsSignedLoad(SignMask))) {
						UseOp2 = UseIter2->GetOp();
						size_t UseBitWidth2 = 8 * GetOpDataSize(UseOp2);
						if (UseBitWidth == UseBitWidth2) {
							// Entire pattern matched. Moved lower bits, shifted or rotated by
							//  stored bit width, then moved new lower bits.
							// Avoid redundant computation on sub-reg UseOp2 in 3rd instruction by setting its flag.
							CurrInst->SetUseNoTruncate(SearchOp, true);
						}
					}
					break; // Found whole pattern, or failed to find third inst in pattern.
				}
				else {
					DefIter = CurrInst->FindDef(SearchOp);
					if (DefIter != CurrInst->GetLastDef()) {
						// SearchOp is not written as subreg yet, but is re-DEFed. Failed to match.
						break;
					}
				}
			} // end if (!FoundSubregUse) ... else ...
		} // end if (InstAddr == DefAddr) ... else if (FoundTruncationDef) ...
	} // end for all insts in block

	if (benign)
		return true;

	SMPInstr *DefInst = this->GetFunc()->GetInstFromAddr(DefAddr);
	ea_t SourceInstAddr = BADADDR;
	SMPInstr *SourceInst = NULL;
	int DefUseSSANum = SMP_SSA_UNINIT;
	bool SpecialSourceFound = false;
	bool LeaDef = DefInst->MDIsLoadEffectiveAddressInstr();
	bool UseFP = this->GetFunc()->UsesFramePointer();
	UseIter = DefInst->FindUse(DefOp); // DEF is also USE in addition, subtraction, etc.
	if (MDIsDataFlowOpnd(DefOp, UseFP) && (UseIter != DefInst->GetLastUse())) {
		DefUseSSANum = UseIter->GetSSANum();
		this->GetFunc()->ResetProcessedBlocks();
		SpecialSourceFound = DefInst->IsOpSourceSpecial(DefOp, DefUseSSANum, true, SourceInstAddr);
		if (SpecialSourceFound) {
			SourceInst = this->GetFunc()->GetInstFromAddr(SourceInstAddr);
			if (SourceInst->IsReducedWidthDef()) {
				benign = true;
				IdiomCode = 24;
			}
		}
	}

	if (!benign && (o_reg == SearchOp.type) && (-1 != UseSSANum)) {
		// See if truncation use is a copy of another register that gets subword masked, which
		//  is a sign that the truncation use is also only valid for the lower bits.
		bool LocalName = this->IsLocalName(SearchOp);
		ea_t UseDefAddr = this->GetDefAddrFromUseAddr(SearchOp, DefAddr, UseSSANum, LocalName);
		if ((BADADDR != UseDefAddr) && (UseDefAddr > this->GetFunc()->GetNumBlocks())) {
			// We have a valid inst addr (not Phi block number). See if it is a reg to reg copy.
			SMPInstr *CopyInst = this->GetFunc()->GetInstFromAddr(UseDefAddr);
			if (CopyInst->MDIsMoveInstr()) {
				unsigned short SignMask;
				if (CopyInst->MDIsSignedLoad(SignMask)) {
					// Truncation use came from a zero-extended or sign-extended load. So,
					//  we know that the later truncation store is probably a benign truncation.
					IdiomCode = 14;
					benign = true;
				}
				else { // regular move. Is it reg to reg?
					UseOp2 = CopyInst->GetMoveSource();
					if (o_reg == UseOp2.type) {
						// If UseOp2, the source of our truncation store USE operand,
						//  ever has a subreg masked off, then our truncation is probably
						//  benign.
						CanonicalizeOpnd(UseOp2);
						SMPBasicBlock *CopyBlock = CopyInst->GetBlock();
						UseIter2 = CopyInst->FindUse(UseOp2);
						assert(UseIter2 != CopyInst->GetLastUse());
						int DefSSANum2 = UseIter2->GetSSANum();
						// NOTE: UseDefAddr is not actually the DefAddr of UseOp2; it
						//  is the addr at which UseOp2 was moved into our truncation move
						//  USE, SearchOp. But we only want to see the USEs of UseOp2 that
						//  come after the reg to reg copy.
						benign = CopyBlock->IsDefMasked(UseOp2, DefSSANum2, UseDefAddr);
						if (benign)
							IdiomCode = 14;
					}
				}
			}
		}
	}

	if (!benign && (o_reg == SearchOp.type) && (-1 != UseSSANum)) {
		// Check for case in which a copy of the DEF corresponding to the subword USE
		//  gets written as a subword. This occurs in patterns that write in pieces such as:
		//  edx := ...
		//  ecx : = edx; 
		//  write subword of ecx ; not a truncation
		//  ecx := edx; get original copy
		//  write different subword of ecx ; not a truncation
		//  etc.
		//  write subword of edx ; not really a truncation
		bool LocalName = this->IsLocalName(SearchOp);
		ea_t UseDefAddr = this->GetDefAddrFromUseAddr(SearchOp, DefAddr, UseSSANum, LocalName);
		if (BADADDR != UseDefAddr) {
			// Check for Phi DEF instead of inst DEF.
			bool PhiDEF = false;
			if (UseDefAddr <= this->GetFunc()->GetNumBlocks()) {
				// For our purposes, we just want to search the block for subword writes, so we can pretend
				//  the DEF addr is right before the block.
				PhiDEF = true;
				SMPBasicBlock *DefBlock = this->GetFunc()->GetBlockByNum(UseDefAddr);
				UseDefAddr = DefBlock->GetFirstAddr();
			}
			SMPInstr *UseDefInst = this->GetFunc()->GetInstFromAddr(UseDefAddr);
			benign = UseDefInst->GetBlock()->IsDEFWrittenWithTruncation(SearchOp, UseSSANum, UseDefAddr, DefAddr, PhiDEF);
			if (benign) 
				IdiomCode = 2;
		}
	}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
	if (benign) {
		++SuppressTruncationRegPiecesAllUsed;
	}
#endif

	return benign;
} // end of SMPBasicBlock::IsBenignTruncationDEF()

// Does DefOp+DefSSANum get subreg masked before it gets re-DEFined?
bool SMPBasicBlock::IsDefMasked(op_t DefOp, int DefSSANum, ea_t DefAddr) {
	bool MaskingDetected = false;

	vector<SMPInstr *>::iterator InstIter;
	set<DefOrUse, LessDefUse>::iterator UseIter, DefIter;
	op_t UseOp, SearchOp = DefOp;
	int UseSSANum;
	ea_t InstAddr;
	size_t BytesMasked;

	if (o_reg == DefOp.type) {
		CanonicalizeOpnd(SearchOp);
		for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
			SMPInstr *CurrInst = (*InstIter);
			InstAddr = CurrInst->GetAddr();
			if (InstAddr > DefAddr) {
				UseIter = CurrInst->FindUse(SearchOp);
				if (UseIter != CurrInst->GetLastUse()) {
					UseSSANum = UseIter->GetSSANum();
					if (UseSSANum == DefSSANum) {
						if (CurrInst->MDIsSubregMaskInst(BytesMasked)) {
							MaskingDetected = true;
							break;
						}
					}
					else {
						// Must have been re-DEFed.
						break;
					}
				}
				DefIter = CurrInst->FindDef(SearchOp);
				if (DefIter != CurrInst->GetLastDef()) {
					// Re-DEF. Did not find masking inst.
					break;
				}
			}
		}
	}

	return MaskingDetected;
} // end of SMPBasicBlock::IsDefMasked()

// Is DEF later passed as an argument to a critical system or lib call? If so, return true and put
//  the integer error info string in SinkString. If not, leave SinkString empty and return false.
//  Recurse through successor blocks if needed to find all USEs of the DEF.
bool SMPBasicBlock::IsCriticalSink(op_t DefOp, int DefSSANum, std::string &SinkString) {
	// Call recursive helper that finds argument-passing USEs of the DEF.
	op_t AlternateDefOp = InitOp;
	bool FoundSink = this->UseHasCriticalSink(DefOp, DefSSANum, AlternateDefOp, SMP_SSA_UNINIT, SinkString);

	return FoundSink;
} // end of SMPBasicBlock::IsCriticalSink()

// Can we find USE being passed to a critical system or library call?
bool SMPBasicBlock::UseHasCriticalSink(op_t DefOp, int DefSSANum, op_t DefOp2, int DefSSANum2, std::string &SinkString) {
	bool FoundSink = false;
	vector<SMPInstr *>::iterator InstIter;
	set<DefOrUse, LessDefUse>::iterator UseIter, DefIter;
	bool FoundArgPass = false;
	int SearchSSANum = DefSSANum;
	int SearchSSANum2 = DefSSANum2;
	ea_t InstAddr; // for debugging, breakpoints, etc.
	size_t ArgumentNumber = 7; // init to bad number

	// avoid infinite recursion
	if (this->IsProcessed()) {
		return false;
	}
	this->SetProcessed(true); 

	// We need to make the recursion robust by finding DefOp in Phi functions
	//  and altering the DefSSANum we are searching for.
	set<SMPPhiFunction, LessPhi>::iterator CurrPhi = this->FindPhi(DefOp);
	if (CurrPhi != this->GetLastPhi()) {
		// Found Phi function for DefOp. That means we will not be finding DefSSANum for
		//  DefOp in this block or its successors, because the Phi function will redefine
		//  to a new SSA number.
		size_t PhiNumUses = CurrPhi->GetPhiListSize();
		bool FoundPhiUse = false;
		for (size_t i = 0; i < PhiNumUses; ++i) {
			// Confirm that DefSSANum was actually a Phi USE in this block.
			if (CurrPhi->GetUseSSANum(i) == DefSSANum) {
				FoundPhiUse = true;
				break;
			}
		}
		if (FoundPhiUse) {
			SearchSSANum = CurrPhi->GetDefSSANum();  // new SSA name to search for is Phi DEF
		}
	}

	// Do the same for DefOp2/DefSSANum2.
	if (o_void != DefOp2.type) {
		CurrPhi = this->FindPhi(DefOp2);
		if (CurrPhi != this->GetLastPhi()) {
			// Found Phi function for DefOp2. That means we will not be finding DefSSANum2 for
			//  DefOp2 in this block or its successors, because the Phi function will redefine
			//  to a new SSA number.
			size_t PhiNumUses = CurrPhi->GetPhiListSize();
			bool FoundPhiUse = false;
			for (size_t i = 0; i < PhiNumUses; ++i) {
				// Confirm that DefSSANum2 was actually a Phi USE in this block.
				if (CurrPhi->GetUseSSANum(i) == DefSSANum2) {
					FoundPhiUse = true;
					break;
				}
			}
			if (FoundPhiUse) {
				SearchSSANum2 = CurrPhi->GetDefSSANum();  // new SSA name to search for is Phi DEF
			}
		}
	}


	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		InstAddr = CurrInst->GetAddr();
		// Two stage search: Find argument pass, then find next call instruction.
		if (!FoundArgPass) {
			UseIter = CurrInst->FindUse(DefOp);
			if (UseIter != CurrInst->GetLastUse()) {
				int UseSSANum = UseIter->GetSSANum();
				if (UseSSANum == SearchSSANum) {
					// Found a use that matches the DEF. Is it passed as an argument?
					if (CurrInst->MDIsArgumentPass(ArgumentNumber)) {
						FoundArgPass = true;
					}
					else if (CurrInst->MDIsMoveInstr() && (o_void == DefOp2.type)) {
						// DefOp is getting stored, but not as an argument pass.
						//  Hard to say if we should keep following DefOp or follow
						//  the stored copy. Let's try following the stored copy also if
						//  it is a register or stack location.
						DefIter = CurrInst->GetFirstNonFlagsDef();
						assert(DefIter != CurrInst->GetLastDef());
						op_t NewDefOp = DefIter->GetOp();
						if (MDIsDataFlowOpnd(NewDefOp, this->GetFunc()->UsesFramePointer())) {
							// Follow NewDefOp from now on in addition to DefOp.
							CanonicalizeOpnd(NewDefOp);
							DefOp2 = NewDefOp;
							SearchSSANum2 = DefIter->GetSSANum();
						}
					}
					else { // Stop searching for DefOp if it gets redefined.
						DefIter = CurrInst->FindDef(DefOp);
						if (DefIter != CurrInst->GetLastDef()) {
							// DefOp was USE and DEF in CurrInst.
							if (o_void != DefOp2.type) {
								// We have an alternate DEF to search for. Make it primary.
								DefOp = DefOp2;
								SearchSSANum = SearchSSANum2;
								DefOp2 = InitOp; // No more alternate.
								SearchSSANum2 = SMP_SSA_UNINIT;
							}
							else { // No alternate to search for; search has failed.
								DefOp = InitOp;
								SearchSSANum = SMP_SSA_UNINIT;
								break;
							}
						}
					}
				}
			}
			else if (o_void != DefOp2.type) { // DefOp is not used; search for DefOp2
				UseIter = CurrInst->FindUse(DefOp2);
				if (UseIter != CurrInst->GetLastUse()) {
					int UseSSANum = UseIter->GetSSANum();
					if (UseSSANum == SearchSSANum2) {
						// Found a use that matches the DEF. Is it passed as an argument?
						if (CurrInst->MDIsArgumentPass(ArgumentNumber)) {
							FoundArgPass = true;
						}
						else if (CurrInst->MDIsMoveInstr()) { // DefOp2 is copied somewhere
							// We cannot follow a third location currently, but we can see
							//  if DefOp2 is redefining DefOp in this move, and get a new
							//  SearchSSANum for DefOp in that case.
							DefIter = CurrInst->FindDef(DefOp);
							if (DefIter != CurrInst->GetLastDef()) {
								// DefOp2 was copied to DefOp.
								SearchSSANum = DefIter->GetSSANum(); // new DefOp/DefSSANum pair to search for.
							}
						}
						else { // Stop searching for DefOp2 if it gets redefined.
							DefIter = CurrInst->FindDef(DefOp2);
							if (DefIter != CurrInst->GetLastDef()) {
								// DefOp2 was USE and DEF in CurrInst.
								DefOp2 = InitOp; // No more alternate.
								SearchSSANum2 = SMP_SSA_UNINIT;
							}
						}
					}
				}
			}
		}
		else { // found arg pass, need to find call
			if (CurrInst->GetDataFlowType() == CALL) {
				string CalleeName = CurrInst->GetTrimmedCalledFunctionName();
				if (!(CalleeName.empty())) {
					GetSinkStringForCallName(CalleeName, SinkString);
					if (!(SinkString.empty())) {
						// ArgumentNumber needs to be 0 for malloc(), 0 or 1 for calloc(),
						//  and 1 for realloc.
						if (ArgumentNumber < 2) {
							bool FoundMalloc = (0 == CalleeName.compare("malloc"));
							bool FoundCalloc = (0 == CalleeName.compare("calloc"));
							bool FoundRealloc = (0 == CalleeName.compare("realloc"));
							if (((ArgumentNumber == 0) && (FoundMalloc || FoundCalloc))
								|| ((ArgumentNumber == 1) && (FoundCalloc || FoundRealloc))) {
								FoundSink = true;
							}
						}
					}
				}
				break;
			}
		}
	} // end for all instructions

	if (!FoundArgPass) {
		if (!this->IsLiveOut(DefOp2)) {
			// Cannot search for DefOp2 if not LiveOut.
			DefOp2 = InitOp;
			SearchSSANum2 = SMP_SSA_UNINIT;
		}
		if (!this->IsLiveOut(DefOp)) {
			// Search for DefOp2 instead of DefOp.
			DefOp = DefOp2;
			SearchSSANum = SearchSSANum2;
			DefOp2 = InitOp; // No more alternate.
			SearchSSANum2 = SMP_SSA_UNINIT;
		}

		if (o_void != DefOp.type) {
			// Need to recurse through successor blocks to keep searching for arg pass.
			list<SMPBasicBlock *>::iterator SuccIter;
			for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) {
				if ((*SuccIter)->UseHasCriticalSink(DefOp, SearchSSANum, DefOp2, SearchSSANum2, SinkString)) {
					FoundSink = true;
					break;
				}
			}
		}
	}

	return FoundSink;
} // end of SMPBasicBlock::UseHasCriticalSink()

// It is safe to emit signedness checks when the very next use of a stack DEF is as
//  a sign-extended or zero-extended load. Beyond a single basic block, we need to
//  do more analysis. This catches a simple case that is valid across all programs.
bool SMPBasicBlock::IsStackOpNextUsedWithSignedness(op_t StackDefOp, ea_t DefAddr, int SSANum) {
	bool SafeCheck = false;
	vector<SMPInstr *>::iterator InstIter;
	set<DefOrUse, LessDefUse>::iterator UseIter;
	ea_t InstAddr; // for debugging, breakpoints, etc.
	bool FoundDefInst = false;

	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		InstAddr = CurrInst->GetAddr();
		// Two stage search: Find DEF instruction, then find next USE;
		if (!FoundDefInst) {
			FoundDefInst = (InstAddr == DefAddr);
		}
		else {
			UseIter = CurrInst->FindUse(StackDefOp);
			if (UseIter != CurrInst->GetLastUse()) {
				int UseSSANum = UseIter->GetSSANum();
				if (UseSSANum == SSANum) {
					// Found next USE of matching SSA name.
					// Is it an extended load?
					unsigned short DummySignMask;
					SafeCheck = CurrInst->MDIsSignedLoad(DummySignMask);
					break;
				}
			}
		}
	} // end for all instructions

	return SafeCheck;
} // end of SMPBasicBlock::IsStackOpNextUsedWithSignedness()

// Find inc/add that makes small negative back into positive. e.g.:
//  sbb edx,edx  ; unsigned edx becomes 0 or -1; SMPInstr is suppressing underflow false positive.
//  add edx,1    ; converts 0 or -1 to 1 or 0 (looks like unsigned overflow); catch this here.
//  We also catch the case in which a "not edx" or "and edx,..." or "or edx,..." instruction 
//  is interposed between the sbb and the add.
void SMPBasicBlock::SuppressAnnotOnSignChangingAddition(op_t DefOp, int DefSSANum, size_t DefAddr) {
	vector<SMPInstr *>::iterator DefInstIter = this->GetInstIterFromAddr(DefAddr);
	op_t SearchOp = DefOp;
	CanonicalizeOpnd(SearchOp);
	int SearchSSANum = DefSSANum;
	set<DefOrUse, LessDefUse>::iterator UseIter, DefIter;

	++DefInstIter;
	while (DefInstIter != this->GetLastInst()) {
		SMPInstr *CurrInst = (*DefInstIter);
		ea_t InstAddr = CurrInst->GetAddr();
		if (CurrInst->MDIsSmallPositiveAddition()) {
			UseIter = CurrInst->FindUse(SearchOp);
			if (UseIter != CurrInst->GetLastUse()) {
				if (SearchSSANum == UseIter->GetSSANum()) {
					// Found the increment or small addition that will cause false positives.
					CurrInst->SetSuppressNumericAnnotation();
					break;
				}
				else {
					// We must have moved on past the original def-use chain.
					break;
				}
			}
		}
		else if (CurrInst->MDIsBitwiseNotOpcode() || CurrInst->MDIsBitwiseAndOpcode() || CurrInst->MDIsBitwiseOrOpcode()) {
			UseIter = CurrInst->FindUse(SearchOp);
			if (UseIter != CurrInst->GetLastUse()) {
				// Bitwise operation is performed on SearchOp.
				if (SearchSSANum == UseIter->GetSSANum()) {
					// Reset the SearchSSANum that we expect to see in the small addition.
					DefIter = CurrInst->GetFirstNonFlagsDef();
					op_t NewDefOp = DefIter->GetOp();
					if (IsEqOp(DefOp, NewDefOp)) {
						SearchSSANum = DefIter->GetSSANum();
					}
					else {
						// Must have an instruction such as "or dontcarereg,ourreg" which
						//  does not re-DEF ourreg and thus the chain is no longer the pattern
						//  we are looking for.
						break;
					}
				}
				else {
					// We must have moved on past the original def-use chain.
					break;
				}
			}
		}
		++DefInstIter;
	}

	return;
} // end of SMPBasicBlock::SuppressAnnotOnSignChangingAddition()

// Last-minute prep before emitting numeric annotations
void SMPBasicBlock::AnalyzePrepForNumericAnnotations(void) {

	if (this->HasCallInstruction()) {
		vector<SMPInstr *>::iterator InstIter;
		bool FoundTrustedCall = false;
		ea_t FirstTrustedCallAddr = 0xfffffff0;
		SMPInstr *CurrInst;
		ea_t InstAddr;
		// See if we have any calls to system calls that produce trusted output.
		for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
			CurrInst = (*InstIter);
			InstAddr = CurrInst->GetAddr();
			if (CurrInst->IsNumericTrustedSystemCall()) {
				FoundTrustedCall = true;
				if (InstAddr < FirstTrustedCallAddr) {
					FirstTrustedCallAddr = InstAddr;
				}
			}
			else if (FoundTrustedCall) {
				// Already found a trusted call; suppress numeric annotations.
				CurrInst->SetSuppressNumericAnnotation();
			}
		}
		if (FoundTrustedCall && this->GetFunc()->IsBlockInAnyLoop(this->GetNumber())) {
			// Overflows can occur as numeric values are used in next iteration of the
			//  loop, so we want to suppress annotations even for insts before the call.
			// FUTURE: Make more thorough by following def-use chains. As a first cut, we
			//  will just deal with the block that has the trusted call in it.
			for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
				CurrInst = (*InstIter);
				InstAddr = CurrInst->GetAddr();
				if (InstAddr <= FirstTrustedCallAddr) {
					CurrInst->SetSuppressNumericAnnotation();
				}
				else {
					break;
				}
			}
		}
	}
	return;
} // end of SMPBasicBlock::AnalyzePrepForNumericAnnotations()

// Unsigned branch should be treated as unknown signedness because of code idiom?
bool SMPBasicBlock::IsBranchSignednessUnreliable(void) {
	// There are two code patterns that make an unsigned branch an unreliable
	//  basis for inferring that the related operands were unsigned.
	//
	// First, we are looking for the pattern:
	// ja addr1
	// jb addr1
	// This is a stupid, inefficient way of saying jne addr1. The unsigned
	//  nature of the operands that produced the flags when compared cannot
	//  be reliably inferred, because this sequence is the same as a jne even
	//  for signed operands.
	//
	// Second, a typical pattern for optimizing compilers:
	// Source: if ((x >= 500) && (x <= 520)) where x is a signed int
	// Instead of generating two compares and two branches, only
	//  one branch is needed:
	//  sub ebx,500
	//  cmp ebx,20
	//  ja not_in_range
	// The jump-if-above is a trick to catch the less than 500 case (which
	//  is now a negative value in ebx) by pretending it is a large unsigned
	//  number, while also catching the greater than 520 case in the same
	//  conditional branch. One conditional branch is much faster than two
	//  in a pipelined machine, but it uses an unsigned conditional branch on
	//  signed data, which screws up our signedness inference.
	// Another variation is a small addition to get a range that spans zero to
	//  be all non-negative:
	//  add eax,1
	//  cmp eax,2  ; if ((eax < -1) || (eax > 1)) ...
	//  ja not_in_range
	//
	// Third, we look for a pattern such as:
	//  cmp eax,0xfffffffc
	//  ja loopexit
	// It is unlikely that an unsigned number is being compared to a value so
	//  close to the maximum unsigned value, with branching resulting. Instead,
	//  it is common for a decrementing counter to get cut off at a small negative
	//  value with this code pattern, giving a SIGNED var the false appearance of
	//  UNSIGNED.
	bool JumpAbove = false;
	bool JumpBelow = false;
	ea_t TargetAddr = BADADDR, BranchAddr = BADADDR;
	SMPInstr *BranchInst;
	unsigned short opcode;
	vector<SMPInstr *>::reverse_iterator InstRevIter;
	vector<SMPInstr *>::iterator InstIter;

	if (1 == this->InstVec.size()) {
		// Might be the second instruction in the sequence.
		InstIter = this->GetFirstInst();
		BranchInst = (*InstIter);
		BranchAddr = BranchInst->GetAddr();
		opcode = BranchInst->GetCmd().itype;
		JumpAbove = (opcode == NN_ja);
		JumpBelow = (opcode == NN_jb);
		if (JumpAbove || JumpBelow) {
			// We look for the simple pattern of fall-through-only from first block
			//  to second block.
			if (1 == this->Predecessors.size()) {
				TargetAddr = BranchInst->GetJumpTarget();
				list<SMPBasicBlock *>::iterator PredIter = this->GetFirstPred();
				InstRevIter = (*PredIter)->GetRevInstBegin();
				BranchInst = (*InstRevIter);
				opcode = BranchInst->GetCmd().itype;
				if (JumpBelow)
					JumpAbove = (opcode == NN_ja);
				else if (JumpAbove)
					JumpBelow = (opcode == NN_jb);
			}
		}
	}
	else {
		// Might be the first instruction in the sequence.
		InstRevIter = this->GetRevInstBegin();
		BranchInst = (*InstRevIter);
		BranchAddr = BranchInst->GetAddr();
		opcode = BranchInst->GetCmd().itype;
		JumpAbove = (opcode == NN_ja);
		JumpBelow = (opcode == NN_jb);
		if (JumpAbove || JumpBelow) {
			// We look for the simple pattern of fall-through-only from first block
			//  to second block, plus conditional branch target.
			if (2 == this->Successors.size()) {
				TargetAddr = BranchInst->GetJumpTarget();
				list<SMPBasicBlock *>::iterator SuccIter = this->GetFallThroughSucc();
				if (SuccIter != this->GetLastSucc()) {
					InstIter = (*SuccIter)->GetFirstInst();
					BranchInst = (*InstIter);
					opcode = BranchInst->GetCmd().itype;
					if (JumpBelow)
						JumpAbove = (opcode == NN_ja);
					else if (JumpAbove)
						JumpBelow = (opcode == NN_jb);
				}
			}
		}
	}
	if (JumpAbove && JumpBelow && (BranchInst->GetJumpTarget() == TargetAddr))
		return true;

#if STARS_DETECT_OPTIMIZED_RANGE_CHECK
	// Now, search for the second and third cases.
	bool OptimizedRangeComparison = false;
	bool TooLargeCompareConstant = false;
	InstRevIter = this->GetRevInstBegin();
	BranchInst = (*InstRevIter);
	// Find the flags USE.
	op_t UseOp;
	UseOp.type = o_reg; // set up a dummy op for searching
	UseOp.reg = X86_FLAGS_REG;
	set<DefOrUse, LessDefUse>::iterator UseIter = BranchInst->FindUse(UseOp);
	assert(UseIter != BranchInst->GetLastUse());
	UseOp = UseIter->GetOp(); // get full info in all fields
	int UseSSANum = UseIter->GetSSANum();
	bool LocalFlags = this->IsLocalName(UseOp);
	ea_t DefAddr = this->GetDefAddrFromUseAddr(UseOp, BranchInst->GetAddr(), UseSSANum, LocalFlags);
	// Phi DEFs are rarely or never found as the source of the flags for a branch, so keep it simple.
	if (DefAddr > this->GetFunc()->GetNumBlocks()) { // DefAddr is an inst, not a Phi DEF.
		// In order to fit the pattern, we need to see a comparison to a positive immediate constant.
		SMPInstr *CompareInst = this->GetFunc()->GetInstFromAddr(DefAddr);
		op_t CompareOperand = InitOp;
		uval_t CompareConstant, SubtractConstant;
		if (CompareInst->MDIsCompareToPositiveConstant(CompareOperand, CompareConstant)) {
			// For the third pattern, we just need to have a really large CompareConstant.
			if (CompareConstant >= 0xfffffff0) {
				TooLargeCompareConstant = true;
			}
			else {
				// To complete the second pattern, we need CompareOperand to have been DEFed by a 
				//  subtraction of a constant, or the addition of a small positive constant.
				if (o_reg == CompareOperand.type) {
					CanonicalizeOpnd(CompareOperand);
					UseIter = CompareInst->FindUse(CompareOperand);
					assert(UseIter != CompareInst->GetLastUse());
					UseSSANum = UseIter->GetSSANum();
					SMPBasicBlock *CompareBlock = CompareInst->GetBlock(); // just in case it's not this block
					bool LocalCompName = CompareBlock->IsLocalName(CompareOperand);
					ea_t SubtractAddr = CompareBlock->GetDefAddrFromUseAddr(CompareOperand, DefAddr, UseSSANum, LocalCompName);
					if (SubtractAddr > this->GetFunc()->GetNumBlocks()) {
						SMPInstr *SubtractInst = this->GetFunc()->GetInstFromAddr(SubtractAddr);
						op_t MinuendOp = InitOp;
						if (SubtractInst->MDIsSubtractionOfConstant(MinuendOp, SubtractConstant)) {
							OptimizedRangeComparison = true;
						}
						else if (SubtractInst->MDIsSmallPositiveAddition()) {
							OptimizedRangeComparison = true;
						}
					}
				}
			}
		}
	}

	return (OptimizedRangeComparison || TooLargeCompareConstant);
#else
	return false;
#endif


} // end of SMPBasicBlock::IsBranchSignednessUnreliable()

// Find stack adjustment code, if any, after CallAddr.
sval_t SMPBasicBlock::ComputeStackAdjustmentAfterCall(ea_t CallAddr) {
	sval_t AdjustmentBytes = 0;
	sval_t PriorAdjustmentBytes = 0; // stack deltas before the call
	vector<SMPInstr *>::iterator InstIter;
	ea_t InstAddr; // for debugging, breakpoints, etc.
	bool FoundCallInst = false;
	bool FirstBlock = (this->GetFirstAddr() == this->GetFunc()->GetFirstFuncAddr());

	for (InstIter = this->GetFirstInst(); InstIter != this->GetLastInst(); ++InstIter) {
		SMPInstr *CurrInst = (*InstIter);
		InstAddr = CurrInst->GetAddr();
		// Two stage search: Find CALL instruction, then find next stack adjustment.
		sval_t CurrentDelta = CurrInst->FindStackAdjustment();
		SMPitype DataFlowType = CurrInst->GetDataFlowType();
		if (!FoundCallInst) {
			FoundCallInst = (InstAddr == CallAddr);
			if (!FoundCallInst && !FirstBlock) {
				PriorAdjustmentBytes += CurrentDelta;
				if (JUMP <= DataFlowType) {
					// Reset PriorAdjustmentBytes and exit. Basic block is too confusing
					//  to analyze if multiple calls happen. We cannot tell if stack adjustments
					//  between the first call and the second call are related to the first call
					//  or the second call.
					PriorAdjustmentBytes = 0;
					break;
				}
			}
		}
		else {
			if (JUMP > DataFlowType) {
				if (SMP_STACK_DELTA_ERROR_CODE == CurrentDelta) {
					// An error will soon occur, no need for further computations.
					AdjustmentBytes = 0;
					SMP_msg("INFO: Stack adjustment set to zero due to error code at %lx\n", (unsigned long) InstAddr);
					break;
				}
				else if (SMP_STACK_POINTER_BITWISE_AND_CODE == CurrentDelta) {
					; // Ignore AND with stack pointer for now
				}
				else if (0 != CurrentDelta) {
					SMP_msg("INFO: Found stack adjustment of %ld bytes at %lx\n", 
						(long) CurrentDelta, (unsigned long) InstAddr);
					AdjustmentBytes += CurrentDelta;
				}
				// NOTE: ****!!!!****!!!! We want to find changes in stack direction and terminate
				//  in the future, in case we see code such as:
				//
				//  call foo
				//  pop eax  ; adjust stack after call to foo, grab return arg and put in eax
				//  push ebx ; caller-save before call to bar
				//  call bar
			}
			else if ((RETURN == DataFlowType) 
				|| ((!this->GetFunc()->HasExplicitReturnInstruction()) && ((INDIR_JUMP == DataFlowType) || (JUMP == DataFlowType)))) {
				// We have been counting up adjustment bytes that precede a RETURN. Those
				//  adjustments are expected before a RETURN and have nothing to do with
				//  the function call at CallAddr. If the function has no explicit return instructions, we will
				//  conservatively treat jumps as probable tail calls, which will later be given the RETURN
				//  data flow type but have not yet been analyzed and marked.
				AdjustmentBytes = 0;
				SMP_msg("INFO: Resetting stack adjustment to zero at return inst at %lx\n", 
					(unsigned long) InstAddr);
				break;
			}
			else {
				// We want to break at calls after CallAddr, and other instructions that
				//  hit this break would terminate the block anyway (e.g. jumps, branches).
				break;
			}
		}
	}

	if (AdjustmentBytes != 0) {
		// PriorAdjustmentBytes is usually negative (making stack space before the call)
		//  and AdjustmentBytes is usually positive (returning stack space after the call).
		//  Adding them gets the net adjustment after the call.
		AdjustmentBytes += PriorAdjustmentBytes;
	}
	return AdjustmentBytes;
} // end of SMPBasicBlock::ComputeStackAdjustmentAfterCall()