Skip to content
Snippets Groups Projects
SMPFunction.cpp 169 KiB
Newer Older
					continue;  // go to next instruction
				}
clc5q's avatar
clc5q committed
				CurrUse = CurrInst->GetFirstUse();
				while (CurrUse != CurrInst->GetLastUse()) {
					NextUse = CurrUse;
					++NextUse;
					UseOp = CurrUse->GetOp();
					// NOTE: **!!** To be less conservative, we
					//  should propagate less for exchange category
					//  instructions.
					if ((UseOp.type == o_reg) && (!UseOp.is_reg(R_sp))
						&& (!(this->UseFP && UseOp.is_reg(R_bp)))
						&& (!UseOp.is_reg(X86_FLAGS_REG))) {

						if (this->IsGlobalName(UseOp)) {
							changed |= this->PropagateGlobalMetadata(UseOp,
									DEF_METADATA_USED, CurrUse->GetSSANum());
						}
						else {
							changed |= CurrInst->GetBlock()->PropagateLocalMetadata(UseOp,
									DEF_METADATA_USED, CurrUse->GetSSANum());
						}
					} // end if register
					CurrUse = NextUse;
				} // end while all USEs
			} // end if call or return else if memdest ...
		} // end for all instructions
	} while (changed);

	// All DEFs that still have status DEF_METADATA_UNANALYZED can now
	//  be marked as DEF_METADATA_UNUSED.
	for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
		if (NN_fnop == CurrInst->GetCmd().itype)
			continue;
		CurrDef = CurrInst->GetFirstDef();
		while (CurrDef != CurrInst->GetLastDef()) {
			if (DEF_METADATA_UNANALYZED == CurrDef->GetMetadataStatus()) {
				CurrDef = CurrInst->SetDefMetadata(CurrDef->GetOp(),
					DEF_METADATA_UNUSED);
				assert(CurrDef != CurrInst->GetLastDef());
			}
			++CurrDef;
		}
	}

	return;
} // end of SMPFunction::AnalyzeMetadataLiveness() 

// Propagate the metadata Status for UseOp/SSANum to its global DEF.
// Return true if successful.
bool SMPFunction::PropagateGlobalMetadata(op_t UseOp, SMPMetadataType Status, int SSANum) {
	bool changed = false;

	if ((0 > SSANum) || (o_void == UseOp.type))
		return false;

	// Find the DEF of UseOp with SSANum.
	bool FoundDef = false;
	list<SMPInstr>::iterator CurrInst;

	for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
		set<DefOrUse, LessDefUse>::iterator CurrDef;
		set<DefOrUse, LessDefUse>::iterator CurrUse;
		CurrDef = CurrInst->FindDef(UseOp);
		if (CurrDef != CurrInst->GetLastDef()) {
			if (SSANum == CurrDef->GetSSANum()) {
				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,
					//  (with the same safe func EXCEPTION),
					//  but the register is both DEF and USE and we need
					//  to propagate through the register.
					if (CurrInst->HasSourceMemoryOperand()) {
						if (this->SafeFunc) {
							op_t MemSrcOp = CurrInst->MDGetMemUseOp();
							assert(o_void != MemSrcOp.type);
							if (MDIsStackAccessOpnd(MemSrcOp, this->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->IsGlobalName(MemSrcOp)) {
									changed |= this->PropagateGlobalMetadata(MemSrcOp,
										Status, CurrUse->GetSSANum());
								}
								else {
									changed |= CurrInst->GetBlock()->PropagateLocalMetadata(MemSrcOp,
										Status, CurrUse->GetSSANum());
								}
							} // end if stack access operand
						} // end if SafeFunc
						if (3 == CurrInst->GetOptType()) { // move inst
							break; // load 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->PropagateGlobalMetadata(UseOp,
								Status, CurrUse->GetSSANum());
							break;
						}
					} // 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()) {
						op_t UseOp = CurrUse->GetOp();
clc5q's avatar
clc5q committed
						// NOTE: **!!** To be less conservative, we
						//  should propagate less for exchange category
						//  instructions.
						if ((UseOp.type == o_reg) && (!UseOp.is_reg(R_sp))
							&& (!(this->UseFP && UseOp.is_reg(R_bp)))
							&& (!UseOp.is_reg(X86_FLAGS_REG))) {
clc5q's avatar
clc5q committed

							if (this->IsGlobalName(UseOp)) {
								changed |= this->PropagateGlobalMetadata(UseOp,
									Status, CurrUse->GetSSANum());
clc5q's avatar
clc5q committed
							}
							else {
								changed |= CurrInst->GetBlock()->PropagateLocalMetadata(UseOp,
									Status, CurrUse->GetSSANum());
							}
clc5q's avatar
clc5q committed
					} // end while all USEs
				}
				break;
			}
		}
	}

	if (!FoundDef) {
		// Check the Phi functions
		list<SMPBasicBlock>::iterator CurrBlock;
		for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
			set<SMPPhiFunction, LessPhi>::iterator DefPhi;
			DefPhi = CurrBlock->FindPhi(UseOp);
			if (DefPhi != CurrBlock->GetLastPhi()) {
				if (SSANum == DefPhi->GetDefSSANum()) {
					if (Status != DefPhi->GetDefMetadata()) {
						DefPhi = CurrBlock->SetPhiDefMetadata(UseOp, Status);
						changed = true;
						// If the Phi DEF has live metadata, then the Phi
						//  USEs each have live metadata. Propagate.
						int UseSSANum;
						for (size_t index = 0; index < DefPhi->GetPhiListSize(); ++index) {
							UseSSANum = DefPhi->GetUseSSANum(index);
							// UseSSANum can be -1 in some cases because
							//  we conservatively make EAX and EDX be USEs
							//  of all return instructions, when the function
							//  might have a void return type, making it
							//  appear as if an uninitialized EAX or EDX
							//  could make it to the return block.
							if (0 <= UseSSANum) {
								changed |= this->PropagateGlobalMetadata(UseOp,
									Status, UseSSANum);
							}
						}
					}
					FoundDef = true;
					break;
				}
			}
		} // end for all blocks
	} // end if !FoundDef

	if (!FoundDef) {
		msg("ERROR: Could not find DEF of SSANum %d for: ", SSANum);
		PrintOperand(UseOp);
		msg(" in function %s\n", this->GetFuncName());
	}

	return changed;
} // end of SMPFunction::PropagateGlobalMetadata()

// Find consecutive DEFs of the same type and mark the second one redundant.
void SMPFunction::FindRedundantMetadata(void) {
	list<SMPBasicBlock>::iterator CurrBlock;
	bool changed = false;

	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		changed |= CurrBlock->FindRedundantLocalMetadata(this->SafeFunc);
	}
	return;
} // end of SMPFunction::FindRedundantMetadata()

// Compute SSA form data structures across the function.
void SMPFunction::ComputeSSA(void) {
clc5q's avatar
clc5q committed
	bool DebugFlag = false;
#if SMP_DEBUG_DATAFLOW
	DumpFlag |= (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
	DebugFlag |= (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
clc5q's avatar
clc5q committed
#endif
	if (DumpFlag)
		this->Dump();
#endif
	if (DebugFlag) msg("Computing IDoms.\n");
	this->ComputeIDoms();
	if (DebugFlag) msg("Computing Dom frontiers.\n");
	this->ComputeDomFrontiers();
	if (DebugFlag) msg("Computing global names.\n");
	this->ComputeGlobalNames();
	if (DebugFlag) msg("Computing blocks defined in.\n");
	this->ComputeBlocksDefinedIn();
	if (DebugFlag) msg("Inserting Phi functions.\n");
	this->InsertPhiFunctions();
	if (DebugFlag) msg("Building dominator tree.\n");
	this->BuildDominatorTree();
	if (DebugFlag) msg("Computing SSA renumbering.\n");
	this->SSARenumber();
	list<SMPBasicBlock>::iterator CurrBlock;
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		if (DumpFlag) CurrBlock->Dump();

		if (DebugFlag) msg("Computing local names.\n");
		if (DebugFlag) msg("Computing local SSA renumbering.\n");
		if (DumpFlag) CurrBlock->Dump();

#if SMP_FULL_LIVENESS_ANALYSIS
		if (DebugFlag) msg("Computing global chains.\n");
		CurrBlock->CreateGlobalChains();
#endif
		if (DebugFlag) msg("Marking dead registers.\n");
#if SMP_DEBUG_DATAFLOW
	if (DumpFlag)
		this->Dump();
#endif
	return;
} // end of SMPFunction::ComputeSSA()

// Find memory writes (DEFs) with possible aliases
void SMPFunction::AliasAnalysis(void) {
	// First task: Mark which memory DEFs MIGHT be aliased because an
	//  indirect memory write occurs somewhere in the DEF-USE chain.
	//  Memory DEF-USE chains with no possible aliasing can be subjected
	//  to type inference and type-based optimizing annotations, e.g. a
	//  register spill to memory followed by retrieval from spill memory
	//  followed by NUMERIC USEs should be typed as a continuous NUMERIC
	//  chain if there is no possibility of aliasing.

	// Preparatory step: For each indirect write, mark all def-use chains
	//  (maintained at the basic block level) that include the indirect
	//  write instruction. If there are no indirect writes in the function,
	//  leave all DEFs marked as unaliased and exit.
	if (!(this->HasIndirectWrites))
		return;

	list<SMPBasicBlock>::iterator CurrBlock;
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		list<list<SMPInstr>::iterator>::iterator CurrInst;
		for (CurrInst = CurrBlock->GetFirstInstr();
			CurrInst != CurrBlock->GetLastInstr();
			++CurrInst) {
			if ((*CurrInst)->HasIndirectMemoryWrite()) {
				CurrBlock->MarkIndWriteChains((*CurrInst)->GetAddr());
				// Until we get true aliasing analysis, any indirect write
				//  is classified as may-be-aliased.
				CurrBlock->SetMaybeAliased(true);
			}
		} // end for all insts in block
	} // end for all blocks in function

	// Step one: Find only the memory DEFs to start with.
	list<SMPInstr>::iterator CurrInst;
	bool FoundIndWrite = false;
	for (CurrInst = this->Instrs.begin(); CurrInst != this->Instrs.end(); ++CurrInst) {
		if (CurrInst->HasDestMemoryOperand()) {
			// Starting with the DEF instruction, traverse the control flow
			//  until we run into (A) the re-definition of the operand, including
			//  a re-definition of any of its addressing registers, or (B) an
			//  indirect write. Return false if condition A terminates the
			//  search, and true if condition B terminates the search.
			this->ResetProcessedBlocks();
			op_t MemDefOp = CurrInst->MDGetMemDefOp();
			assert(o_void != MemDefOp.type);
			set<DefOrUse, LessDefUse>::iterator CurrMemDef = CurrInst->FindDef(MemDefOp);
			assert(CurrMemDef != CurrInst->GetLastDef());
			int SSANum = CurrMemDef->GetSSANum();
			FoundIndWrite = this->FindPossibleChainAlias(CurrInst, MemDefOp, SSANum);
			if (FoundIndWrite) {
				// Mark the DEF as aliased.
				CurrMemDef = CurrInst->SetDefIndWrite(CurrMemDef->GetOp(), true);
				break; // Don't waste time after first alias found
			}
		} // end if inst has dest memory operand
	} // end for all instructions

	return;
} // end of SMPFunction::AliasAnalysis()

// Does the DefOp DEF_USE chain have an indirect mem write starting at CurrInst?
bool SMPFunction::FindPossibleChainAlias(list<SMPInstr>::iterator CurrInst, op_t DefOp, int SSANum) {
	bool DebugFlag = false;
	if (0 == strcmp("sdissect", this->GetFuncName())) {
		// Next line is just a good place to set a break point.
		DebugFlag = true;
	}

	// Starting with the DEF instruction, traverse the control flow
	//  until we run into (A) the re-definition of the operand, including
	//  a re-definition of any of its addressing registers, or (B) an
	//  indirect write. Return false if condition A terminates the
	//  search, and true if condition B terminates the search.
	SMPBasicBlock *CurrBlock = CurrInst->GetBlock();
	if (!(CurrBlock->IsProcessed())) {
		CurrBlock->SetProcessed(true);
	}
	else
		return false; // block already processed

	// Proceed by cases:
	ea_t DefAddr = CurrInst->GetAddr();
	// Case 1: Local name. Return the IndWrite flag for the local Def-Use
	//  chain begun by CurrInst.
	if (CurrBlock->IsLocalName(DefOp)) {
		return CurrBlock->GetLocalDUChainIndWrite(DefOp, SSANum);
	}

	// Case 2: Global name.
	// Case 2A: If Def-Use chain within this block for this memory operand
	//  has its IndWrite flag set to true, then stop and return true.
	else if (CurrBlock->GetGlobalDUChainIndWrite(DefOp, DefAddr)) {
		return true;
	}

	// Case 2B: Else if Def-Use chain is not the last chain in this block
	//  for this operand, then there must be a later redefinition of the
	//  memory operand (with new SSA number assigned) later in this block.
	//  Because we did not fall into case 2A, we know there is no IndWrite
	//  within the current memory operand's chain, so we return false.
	else if (CurrBlock->IsLastGlobalChain(DefOp, DefAddr)) {
		return false;
	}

	// Case 2C: Else if current memory operand is NOT LiveOut, even though
	//  this is the last def-use chain in the block, then there is no more
	//  traversing of the control flow graph to be done. The chain has ended
	//  without encountering an IndWrite, so return false.
	else if (!(CurrBlock->IsLiveOut(DefOp))) {
		return false;
	}

	// Case 2D: We have passed all previous checks, so we must have a memory
	//  operand that reaches the end of the block without encountering an
	//  IndWrite and is LiveOut. Its may-alias status will be determined by
	//  following the control flow graph for all successor blocks and examining
	//  the def-use chains in those blocks.
	list<list<SMPBasicBlock>::iterator>::iterator SuccBlock;
	SuccBlock = CurrBlock->GetFirstSucc();
		FoundAliasedWrite = this->FindChainAliasHelper((*SuccBlock), DefOp);
	} while (!FoundAliasedWrite && (SuccBlock != CurrBlock->GetLastSucc()));
} // end of SMPFunction::FindPossibleChainAlias()

// recursive helper for global DU-chains that traverse CFG
bool SMPFunction::FindChainAliasHelper(list<SMPBasicBlock>::iterator CurrBlock, op_t DefOp) {
	bool DebugFlag = false;
	if (0 == strcmp("mem2chunk_check", this->GetFuncName())) {
		// Next line is just a good place to set a break point.
		DebugFlag = true;
	}

	if (!(CurrBlock->IsProcessed())) {
		CurrBlock->SetProcessed(true);
	}
	else
		return false; // block already processed

	// The LVA sets can be used to decide whether it is possible that
	//  the incoming DU chain overlaps a may-alias write. We can express
	//  the decision making in a truth table:
	//
	//  Case #    LiveIn?   Killed?   AliasedWrite in block?  Action to take
	//  -------   -------   -------   ----------------------  --------------
	//    1          N          N                N             return false
	//    2          N          N                Y             return false
	//    3          N          Y                N             return false
	//    4          N          Y                Y             return false
	//    5          Y          N                N             recurse into successors
	//    6          Y          N                Y             return true
	//    7          Y          Y                N             return false
	//    8          Y          Y                Y             check location of aliased write
	//
	// In the last case, if there is an aliased write before the
	// incoming DEF is killed and after it is used, then the
	// incoming DU chain overlaps an aliased write, otherwise
	// it does not.


	// If not LiveIn, incoming DU chain does not run through this block
	//  at all, so return false.
	if (!(CurrBlock->IsLiveIn(DefOp)))
		return false;  // cases 1-4

	bool killed = CurrBlock->IsVarKill(DefOp);
	bool BlockHasAliasedWrite = CurrBlock->MaybeAliasedWrite();

	if (BlockHasAliasedWrite) {
		// If DefOp is LiveIn and is not killed, then any aliased
		//  write in the block overlaps the incoming DU chain.
		if (!killed) {
			return true;  // case 6
		}
		// If DefOp is LiveIn and is killed, then the location
		//  of the aliased write is the determining factor.
		else {
			// Incoming global DU chains get a new global DU chain
			//  built within the block with a pseudo-DefAddr of
			//  one byte before the first address of the block.
			ea_t PseudoDefAddr = CurrBlock->GetFirstAddr() - 1;
			return CurrBlock->GetGlobalDUChainIndWrite(DefOp, PseudoDefAddr); // case 8
		}
	else {
		// If killed, no aliased write, then cannot overlap an aliased write.
		if (killed)
			return false; // case 7
		else {
			// Need to recurse into all successors, because we passed through
			//  the block without seeing an aliased write and without killing
			//  the DefOp.
			list<list<SMPBasicBlock>::iterator>::iterator SuccBlock;
			SuccBlock = CurrBlock->GetFirstSucc();
			bool FoundAliasedWrite = false;
			while (!FoundAliasedWrite && (SuccBlock != CurrBlock->GetLastSucc())) {
				FoundAliasedWrite = this->FindChainAliasHelper((*SuccBlock), DefOp);
				++SuccBlock;
			};
			if (DebugFlag) {
				msg("FindChainAliasHelper is returning %d\n", FoundAliasedWrite);
			}
			return FoundAliasedWrite;
		}
	assert(false); // statement should be unreachable
	return false;
} // end of SMPFunction::FindChainAliasHelper()

// Link basic blocks to their predecessors and successors, and build the map
//  of instruction addresses to basic blocks.
void SMPFunction::SetLinks(void) {
	list<SMPBasicBlock>::iterator CurrBlock;
	msg("SetLinks called for %s\n", this->GetFuncName());
#endif
	// First, set up the map of instructions to basic blocks.
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		list<list<SMPInstr>::iterator>::iterator CurrInst;
		for (CurrInst = CurrBlock->GetFirstInstr();
			CurrInst != CurrBlock->GetLastInstr();
			++CurrInst) {
				pair<ea_t, list<SMPBasicBlock>::iterator> MapItem((*CurrInst)->GetAddr(),CurrBlock);
				InstBlockMap.insert(MapItem);
		}
	}

	msg("SetLinks finished mapping: %s\n", this->GetFuncName());
#endif
	// Next, set successors of each basic block, also setting up the predecessors in the
	//  process.
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		list<SMPInstr>::iterator CurrInst = *(--(CurrBlock->GetLastInstr()));
		bool CondTailCall = false;
		if (CurrBlock->HasReturn()) {
			if (!(CurrInst->IsCondTailCall())) {
				// We either have a return instruction or an unconditional
				//  tail call instruction. We don't want to link to the
				//  tail call target, and there is no link for a return
				continue;
			}
			else {
				// We have a conditional tail call. We don't want to
				//  link to the tail call target, but we do want fall
				//  through to the next instruction.
				CondTailCall = true;
			}
		}

		// Last instruction in block; set successors
		bool CallFlag = (CALL == CurrInst->GetDataFlowType());
		bool IndirCallFlag = (INDIR_CALL == CurrInst->GetDataFlowType());
		bool TailCallFlag = CondTailCall && CurrInst->IsCondTailCall();
		bool IndirJumpFlag = (INDIR_JUMP == CurrInst->GetDataFlowType());
		xrefblk_t CurrXrefs;
		bool LinkedToTarget = false;
		for (bool ok = CurrXrefs.first_from(CurrInst->GetAddr(), XREF_ALL);
			ok;
			ok = CurrXrefs.next_from()) {
				if ((CurrXrefs.to != 0) && (CurrXrefs.iscode)) {
					// Found a code target, with its address in CurrXrefs.to
					if ((CallFlag || IndirCallFlag || TailCallFlag) 
						&& (CurrXrefs.to != (CurrInst->GetAddr() + CurrInst->GetCmd().size))) {
						// A call instruction will have two targets: the fall through to the
						//  next instruction, and the called function. We want to link to the
						//  fall-through instruction, but not to the called function.
						// Some blocks end with a call just because the fall-through instruction
						//  is a jump target from elsewhere.
						continue;
					}
					map<ea_t, list<SMPBasicBlock>::iterator>::iterator MapEntry;
					MapEntry = this->InstBlockMap.find(CurrXrefs.to);
					if (MapEntry == this->InstBlockMap.end()) {
						msg("WARNING: addr %x not found in map for %s\n", CurrXrefs.to,
							this->GetFuncName());
						msg(" Referenced from %s\n", CurrInst->GetDisasm());
					}
					else {
						list<SMPBasicBlock>::iterator Target = MapEntry->second;
						// Make target block a successor of current block.
						CurrBlock->LinkToSucc(Target);
						// Make current block a predecessor of target block.
						Target->LinkToPred(CurrBlock);
						LinkedToTarget = true;
#if SMP_USE_SWITCH_TABLE_INFO
						if (IndirJumpFlag) {
clc5q's avatar
clc5q committed
#if SMP_DEBUG_SWITCH_TABLE_INFO
							msg("Switch table link: jump at %x target at %x\n",
								CurrInst->GetAddr(), CurrXrefs.to);
clc5q's avatar
clc5q committed
#else
							;
#endif
		if (IndirJumpFlag && (!LinkedToTarget)) {
			this->UnresolvedIndirectJumps = true;
			msg("WARNING: Unresolved indirect jump at %x\n", CurrInst->GetAddr());
		}
		else if (IndirCallFlag && (!LinkedToTarget)) {
			this->UnresolvedIndirectCalls = true;
			msg("WARNING: Unresolved indirect call at %x\n", CurrInst->GetAddr());
	} // end for all blocks

	// If we have any blocks that are all no-ops and have no predecessors, remove those
	//  blocks. They are dead and make the CFG no longer a lattice. Any blocks that have
	//  no predecessors but are not all no-ops should also be removed with a different
	//  log message.
	// NOTE: Prior to construction of hell nodes in functions with unresolved indirect jumps,
	//  we cannot conclude that a block with no predecessors is unreachable. Also, the block
	//  order might be such that removal of a block makes an already processed block
	//  unreachable, so we have to iterate until there are no more changes.
	// NOTE: An odd new gcc recursion optimization uses indirect calls within the function, so
	//  they can behave like indirect jumps.
#if SMP_USE_SWITCH_TABLE_INFO
	if (!(this->HasUnresolvedIndirectJumps() || this->HasUnresolvedIndirectCalls())) {
	if (!(this->HasIndirectJumps())) {
		bool NoPredecessors;
		bool OnlyPredIsItself;
		list<list<SMPBasicBlock>::iterator>::iterator CurrPred;
		do {
			changed = false;
			CurrBlock = this->Blocks.begin();
			++CurrBlock; // don't delete the top block, no matter what.
			while (CurrBlock != this->Blocks.end()) {
				OnlyPredIsItself = false;
				CurrPred = CurrBlock->GetFirstPred();
				NoPredecessors = (CurrPred == CurrBlock->GetLastPred());
				if (!NoPredecessors) {
					if ((*CurrPred)->GetFirstAddr() == CurrBlock->GetFirstAddr()) { // self-recursion
						++CurrPred; // any more preds besides itself?
						OnlyPredIsItself = (CurrPred == CurrBlock->GetLastPred());
							// Only predecessor was the self-recursion if no more preds
					}
				}
				if (NoPredecessors || OnlyPredIsItself) {
					if (CurrBlock->AllNops())
						msg("Removing all nops block at %x\n", CurrBlock->GetFirstAddr());
					else
						msg("Removing block with no predecessors at %x\n", CurrBlock->GetFirstAddr());
					// Remove this block from the predecessors list of its successors.
					list<list<SMPBasicBlock>::iterator>::iterator SuccIter;
					ea_t TempAddr = CurrBlock->GetFirstAddr();
					for (SuccIter = CurrBlock->GetFirstSucc(); SuccIter != CurrBlock->GetLastSucc(); ++SuccIter) {
						(*SuccIter)->ErasePred(TempAddr);
					}
					// Remove the unreachable instructions from the function inst list.
					list<list<SMPInstr>::iterator>::iterator InstIter;
					for (InstIter = CurrBlock->GetFirstInstr(); InstIter != CurrBlock->GetLastInstr(); ++InstIter) {
						list<SMPInstr>::iterator DummyIter = this->Instrs.erase(*InstIter);
					}
					// Finally, remove the block from the blocks list.
					CurrBlock = this->Blocks.erase(CurrBlock);
					this->BlockCount -= 1;
					changed = true;
				}
				else
					++CurrBlock;
			} // end while all blocks after the first one
		} while (changed);
	} // end if not indirect jumps

	return;
} // end of SMPFunction::SetLinks()

// Number all basic blocks in reverse postorder (RPO) and set RPOBlocks vector to
//  access them.
void SMPFunction::RPONumberBlocks(void) {
	DebugFlag = (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
	if (DebugFlag) msg("Entered RPONumberBlocks\n");
#endif
	int CurrNum = 0;
	list<list<SMPBasicBlock>::iterator> WorkList;

	// Number the first block with 0.
	list<SMPBasicBlock>::iterator CurrBlock = this->Blocks.begin();
#if 0
	if (this->RPOBlocks.capacity() <= (size_t) this->BlockCount) {
		msg("Reserving %d RPOBlocks old value: %d\n", 2+this->BlockCount, this->RPOBlocks.capacity());
		this->RPOBlocks.reserve(2 + this->BlockCount);
		this->RPOBlocks.assign(2 + this->BlockCount, this->Blocks.end());
	}
#endif
	CurrBlock->SetNumber(CurrNum);
	this->RPOBlocks.push_back(CurrBlock);
	++CurrNum;
	// Push the first block's successors onto the work list.
	list<list<SMPBasicBlock>::iterator>::iterator CurrSucc = CurrBlock->GetFirstSucc();
	while (CurrSucc != CurrBlock->GetLastSucc()) {
		WorkList.push_back(*CurrSucc);
		++CurrSucc;
	}

	// Use the WorkList to iterate through all blocks in the function
	list<list<SMPBasicBlock>::iterator>::iterator CurrListItem = WorkList.begin();
	bool change;
	while (!WorkList.empty()) {
		change = false;
		while (CurrListItem != WorkList.end()) {
			if ((*CurrListItem)->GetNumber() != SMP_BLOCKNUM_UNINIT) {
				// Duplicates get pushed onto the WorkList because a block
				//  can be the successor of multiple other blocks. If it is
				//  already numbered, it is a duplicate and can be removed
				//  from the list.
				CurrListItem = WorkList.erase(CurrListItem);
				change = true;
				continue;
			}
			if ((*CurrListItem)->AllPredecessorsNumbered()) {
				// Ready to be numbered.
				(*CurrListItem)->SetNumber(CurrNum);
#if 0
				msg("Set RPO number %d\n", CurrNum);
				if (DebugFlag && (7 == CurrNum))
					this->Dump();
#endif
				this->RPOBlocks.push_back(*CurrListItem);
				++CurrNum;
				change = true;
				// Push its unnumbered successors onto the work list.
				CurrSucc = (*CurrListItem)->GetFirstSucc();
				while (CurrSucc != (*CurrListItem)->GetLastSucc()) {
					if ((*CurrSucc)->GetNumber() == SMP_BLOCKNUM_UNINIT)
						WorkList.push_back(*CurrSucc);
					++CurrSucc;
				}
				CurrListItem = WorkList.erase(CurrListItem);
			}
			else {
				++CurrListItem;
			}
		} // end while (CurrListItem != WorkList.end())
		if (change) {
			// Reset CurrListItem to beginning of work list for next iteration.
			CurrListItem = WorkList.begin();
		}
		else {
			// Loops can cause us to not be able to find a WorkList item that has
			//  all predecessors numbered. Take the WorkList item with the lowest address
			//  and number it so we can proceed.
			CurrListItem = WorkList.begin();
			ea_t LowAddr = (*CurrListItem)->GetFirstAddr();
			list<list<SMPBasicBlock>::iterator>::iterator SaveItem = CurrListItem;
			++CurrListItem;
			while (CurrListItem != WorkList.end()) {
				if (LowAddr > (*CurrListItem)->GetFirstAddr()) {
					SaveItem = CurrListItem;
					LowAddr = (*CurrListItem)->GetFirstAddr();
				}
				++CurrListItem;
			}
			// SaveItem should now be numbered.
			(*SaveItem)->SetNumber(CurrNum);
			msg("Picked LowAddr %x and set RPO number %d\n", LowAddr, CurrNum);
			this->RPOBlocks.push_back(*SaveItem);
			++CurrNum;
			// Push its unnumbered successors onto the work list.
			CurrSucc = (*SaveItem)->GetFirstSucc();
			while (CurrSucc != (*SaveItem)->GetLastSucc()) {
				if ((*CurrSucc)->GetNumber() == SMP_BLOCKNUM_UNINIT)
					WorkList.push_back(*CurrSucc);
				++CurrSucc;
			}
			CurrListItem = WorkList.erase(SaveItem);
			CurrListItem = WorkList.begin();
		} // end if (change) ... else ...
	} // end while work list is nonempty

	// Prior to construction of hell nodes for functions with indirect jumps, there
	//  could still be unnumbered blocks because they appear to be unreachable
	//  (no predecessors from SetLinks() because they are reached only via indirect
	//  jumps). We need to number these and push them on the RPOBlocks vector so
	//  that the vector contains all the blocks.
	// NOTE: Odd new gcc recursion optimization seems to use indirect calls to reach
	//  some blocks within a recursive function, operating somewhat like an indirect
	//  jump.
	if (this->HasIndirectJumps() || this->HasIndirectCalls()) {
		for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
			if (SMP_BLOCKNUM_UNINIT == CurrBlock->GetNumber()) {
				msg("WARNING: Numbering indirectly reachable block at %x\n", CurrBlock->GetFirstAddr());
				CurrBlock->SetNumber(CurrNum);
				this->RPOBlocks.push_back(CurrBlock);
				++CurrNum;
			}
		}
	}
	// If we still have unnumbered blocks, it is not because of indirect jumps or calls.
	//  We have some mysterious dead code.
	if (this->BlockCount > this->RPOBlocks.size()) {
		msg("SERIOUS WARNING: RPONumberBlocks method: Function %s has BlockCount %d and RPOBlocks size %d\n",
			this->FuncName, this->BlockCount, this->RPOBlocks.size());
		for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
			if (SMP_BLOCKNUM_UNINIT == CurrBlock->GetNumber()) {
				msg("WARNING: Numbering apparently unreachable block at %x\n", CurrBlock->GetFirstAddr());
				CurrBlock->SetNumber(CurrNum);
				this->RPOBlocks.push_back(CurrBlock);
				++CurrNum;
			}
		}
	}
	return;
} // end of SMPFunction::RPONumberBlocks()

// Perform live variable analysis on all blocks in the function.
// See chapter 9 of Cooper/Torczon, Engineering a Compiler, for the algorithm.
void SMPFunction::LiveVariableAnalysis(void) {
	list<SMPBasicBlock>::iterator CurrBlock;
	bool DebugFlag = (0 == strcmp("uw_frame_state_for", this->GetFuncName()));
#endif
#if SMP_DEBUG_DATAFLOW_VERBOSE
	msg("LiveVariableAnalysis for %s\n", this->GetFuncName());

	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		// Initialize the Killed and UpwardExposed sets for each block.
		CurrBlock->InitKilledExposed();
	}

	bool changed;
	// Iterate over each block, updating LiveOut sets until no more changes are made.
	// NOTE: LVA is more efficient when computed over a reverse post-order list of blocks
	//  from the inverted CFG. We have an RPO list from the forward CFG, so it is just as
	//  good to simply iterate through the blocks in layout order.
#if 1
	do {
		changed = false;
		for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
			changed |= CurrBlock->UpdateLiveOut();
		}
	} while (changed);
#else // Use reverse postorder
	do {
		changed = false;
		for (size_t index = 0; index < this->RPOBlocks.size(); ++index) {
			CurrBlock = this->RPOBlocks[index];
			changed |= CurrBlock->UpdateLiveOut();
		}
	} while (changed);
	// Create DEFs in the marker instruction for all names in the LiveInSet
	//  of the first block. These are the names for the function that
	//  would otherwise look like USEs of uninitialized variables later.
	// Note that the LiveVariableAnalysis work does not actually populate
	//  a LiveInSet for the first block, so we simulate it with its
	//  dataflow equation, UpExposed union (LiveOut minus VarKill).
	set<op_t, LessOp>::iterator UpExposedIter, LiveOutIter;
	list<SMPInstr>::iterator MarkerInst = this->Instrs.begin();
	for (UpExposedIter = this->Blocks.begin()->GetFirstUpExposed();
		UpExposedIter != this->Blocks.begin()->GetLastUpExposed();
		++UpExposedIter) {
			// Add DEF with SSANum of 0.
			MarkerInst->AddDef(*UpExposedIter, UNINIT, 0);
			this->Blocks.begin()->AddVarKill(*UpExposedIter);
			this->Blocks.begin()->AddLiveIn(*UpExposedIter);
	}
	for (LiveOutIter = this->Blocks.begin()->GetFirstLiveOut();
		LiveOutIter != this->Blocks.begin()->GetLastLiveOut();
		++LiveOutIter) {
			if (!(this->Blocks.begin()->IsVarKill(*LiveOutIter))) {
				// Add DEF with SSANum of 0.
				MarkerInst->AddDef(*LiveOutIter, UNINIT, 0);
				this->Blocks.begin()->AddVarKill(*LiveOutIter);
				this->Blocks.begin()->AddLiveIn(*LiveOutIter);
	if (DebugFlag) msg("Exiting LiveVariableAnalysis\n");
#endif
	return;
} // end of SMPFunction::LiveVariableAnalysis()

// Return the IDom index that is the end of the intersection prefix of the Dom sets of
//  the two blocks designated by the RPO numbers passed in.
// See Cooper & Torczon, "Engineering a Compiler" 1st edition figure 9.8.
int SMPFunction::IntersectDoms(int block1, int block2) const {
	int finger1 = block1;
	int finger2 = block2;
	while (finger1 != finger2) {
		while (finger1 > finger2)
			finger1 = this->IDom.at(finger1);
		while (finger2 > finger1)
			finger2 = this->IDom.at(finger2);
	}
	return finger1;
} // end of SMPFunction::IntersectDoms()

// Compute immediate dominators of all blocks into IDom[] vector.
void SMPFunction::ComputeIDoms(void) {
	bool DebugFlag = false;
#if SMP_DEBUG_DATAFLOW
	DebugFlag = (0 == strcmp("_ZN6soplex7NameSetC2Eiidd", this->GetFuncName()));
	if (DebugFlag) msg("Entered ComputeIDoms\n");
#endif
	// Initialize the IDom[] vector to uninitialized values for all blocks.
	this->IDom.reserve(this->BlockCount);
	this->IDom.assign(this->BlockCount, SMP_BLOCKNUM_UNINIT);
	if (DebugFlag) {
		msg("BlockCount = %d RPOBlocks size = %d\n", this->BlockCount, this->RPOBlocks.size());
	}
	if (this->BlockCount != this->RPOBlocks.size()) {
		msg("SERIOUS WARNING: Function %s has BlockCount of %d and RPOBlocks size of %d\n",
			this->FuncName, this->BlockCount, this->RPOBlocks.size());
	}
	this->IDom[0] = 0; // Start block dominated only by itself
	bool changed;
	do {
		changed = false;
		for (size_t RPONum = 1; RPONum < (size_t) this->BlockCount; ++RPONum) {
			if (DebugFlag) msg("RPONum %d\n", RPONum);
			if (DebugFlag) {
				msg("RPOBlocks vector size: %d\n", this->RPOBlocks.size());
				for (size_t index = 0; index < this->RPOBlocks.size(); ++index) {
					msg("RPOBlocks entry %d is %d\n", index, RPOBlocks[index]->GetNumber());
				}
			}
			// To avoid infinite loops on blocks that dominate themselves but otherwise have no 
			//  predecessors (probably reachable only through indirect jumps), we stop processing
			//  the blocks once the IDom becomes the top (entry) block. This probably saves time
			//  on other blocks as well.
			if (0 == this->IDom[RPONum])
				continue;

			list<SMPBasicBlock>::iterator CurrBlock = this->RPOBlocks.at(RPONum);
			// if (DebugFlag) msg("CurrBlock: %x\n", CurrBlock._Ptr);
			list<list<SMPBasicBlock>::iterator>::iterator CurrPred;
			// Initialize NewIdom to the first processed predecessor of block RPONum.
			int NewIdom = SMP_BLOCKNUM_UNINIT;
			for (CurrPred = CurrBlock->GetFirstPred(); CurrPred != CurrBlock->GetLastPred(); ++CurrPred) {
				int PredNum = (*CurrPred)->GetNumber();
				if (DebugFlag) msg("Pred: %d\n", PredNum);
				// **!!** See comment below about unreachable blocks.
				if (SMP_BLOCKNUM_UNINIT == PredNum)
					continue;
				int PredIDOM = this->IDom.at(PredNum);
				if (DebugFlag) msg("Pred IDom: %d\n", PredIDOM);
				if (SMP_BLOCKNUM_UNINIT != PredIDOM) {
			if (NewIdom == SMP_BLOCKNUM_UNINIT) {
				msg("Failure on NewIdom in ComputeIDoms for %s\n", this->GetFuncName());
				if (this->HasIndirectJumps() || this->HasIndirectCalls()) {
					// Might be reachable only through indirect jumps.
					NewIdom = 0; // make it dominated by entry block
					msg("Assuming block %d at address %d is reachable indirectly.\n",
						CurrBlock->GetNumber(), CurrBlock->GetFirstAddr());
				}
				else {
					// Might be exception handling code, reachable only by call stack walking.
					NewIdom = 0; // make it be dominated by entry block
					msg("Assuming block %d at address %d is reachable by exception handling.\n",
						CurrBlock->GetNumber(), CurrBlock->GetFirstAddr());
			assert(NewIdom != SMP_BLOCKNUM_UNINIT);
			// Loop through all predecessors of block RPONum except block NewIdom.
			//  Set NewIdom to the intersection of its Dom set and the Doms set of
			//  each predecessor that has had its Doms set computed.
			for (CurrPred = CurrBlock->GetFirstPred(); CurrPred != CurrBlock->GetLastPred(); ++CurrPred) {
				int PredNum = (*CurrPred)->GetNumber();
				if (DebugFlag) msg("PredNum: %d\n", PredNum);
				// **!!** We can avoid failure on unreachable basic blocks
				//  by executing a continue statement if PredNum is -1. Long term solution
				//  is to prune out unreachable basic blocks, or better yet, create hell nodes
				//  if the function has indirect jumps.
				if (PredNum == SMP_BLOCKNUM_UNINIT)
					continue;
				int PredIDOM = this->IDom.at(PredNum);
				if (DebugFlag) msg("PredIDOM: %d\n", PredIDOM);
				if ((SMP_BLOCKNUM_UNINIT == PredIDOM) || (NewIdom == PredIDOM)) {
					// Skip predecessors that have uncomputed Dom sets, or are the
					//  current NewIdom.
					continue;
				}
				if (DebugFlag) msg("Old NewIdom value: %d\n", NewIdom);
				NewIdom = this->IntersectDoms(PredNum, NewIdom);
				if (DebugFlag) msg("New NewIdom value: %d\n", NewIdom);
			}
			// If NewIdom is not the value currently in vector IDom[], update the
			//  vector entry and set changed to true.
			if (NewIdom != this->IDom.at(RPONum)) {
				if (DebugFlag) msg("IDOM changed from %d to %d\n", this->IDom.at(RPONum), NewIdom);
				this->IDom[RPONum] = NewIdom;
				changed = true;
			}
		}
	} while (changed);
	return;
} // end of SMPFunction::ComputeIDoms()

// Compute dominance frontier sets for each block.
void SMPFunction::ComputeDomFrontiers(void) {
	list<SMPBasicBlock>::iterator CurrBlock;
	list<SMPBasicBlock>::iterator RunnerBlock;
	for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) {
		// We look only at join points in the CFG, as per Cooper/Torczon chapter 9.
		if (1 < CurrBlock->GetNumPreds()) { // join point; more than 1 predecessor
			int runner;
			list<list<SMPBasicBlock>::iterator>::iterator CurrPred;
			for (CurrPred = CurrBlock->GetFirstPred(); CurrPred != CurrBlock->GetLastPred(); ++CurrPred) {
				// For each predecessor, we run up the IDom[] vector and add CurrBlock to the
				//  DomFrontier for all blocks that are between CurrPred and IDom[CurrBlock],
				//  not including IDom[CurrBlock] itself.
				runner = (*CurrPred)->GetNumber();
				while (runner != this->IDom.at(CurrBlock->GetNumber())) {
					// Cooper/Harvey/Kennedy paper does not quite agree with the later
					//  text by Cooper/Torczon. Text says that the start node has no IDom
					//  in the example on pages 462-463, but it shows an IDOM for the
					//  root node in Figure 9.9 of value == itself. The first edition text
					//  on p.463 seems correct, as the start node dominates every node and
					//  thus should have no dominance frontier.
					if (SMP_TOP_BLOCK == runner)