From 56dc7fc6d3119375950db4275379326db03c060d Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Thu, 10 Aug 2017 19:21:15 +0000
Subject: [PATCH] Fix constant tracing for func ptrs and handle conditional
 move tracing.

Former-commit-id: 8b168e63aac8ff541f7a3e3899be1800087469d4
---
 src/base/SMPFunction.cpp | 49 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp
index ba8d70e4..929b2b5e 100644
--- a/src/base/SMPFunction.cpp
+++ b/src/base/SMPFunction.cpp
@@ -13528,7 +13528,52 @@ bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool T
 				break; // cannot follow chain any higher, but previous chain info is still valid.
 			}
 			STARSOpndTypePtr NewUseOp = nullptr;
-			if (!CurrInst->IsSimpleCopy(NewUseOp)) {
+			// If we have a conditional move instruction, then there will be two USEs. One is the
+			//  operand that will be copied to the DEF if the condition is true, and the other is
+			//  the operand that represents the unchanged DEF if the copy does not happen, e.g.
+			//  if (guard) RDX5 := RAX3;  will have USEs RAX3 and RDX4, where RDX4 is the value
+			//  that becomes RDX5 when the guard is not true. We need to treat this instruction as
+			//  a Phi DEF with two Phi USEs and trace both USEs.
+			if (CurrInst->MDIsConditionalMoveInstr()) {
+				// For each USE other than the flags register, recurse.
+				ShadowSet TempShadowAddrSet; // only union these into ShadowAddrSet if all Phi USE recursions succeed.
+				for (STARSDefUseIter UseIter = CurrInst->GetFirstUse(); UseIter != CurrInst->GetLastUse(); ++UseIter) {
+					int UseSSANum = UseIter->GetSSANum();
+					if (0 > UseSSANum) {
+						SMP_msg("ERROR: FindShadowingPoint2() cannot trace uninitialized CondMove USE at CurrShadowAddr %p in func at %p\n",
+							CurrShadowAddr, this->GetFirstFuncAddr());
+						ValidShadowing = false;
+						break;
+					}
+					STARSOpndTypePtr CondMoveUseOp = UseIter->GetOp()->clone();
+					bool FlagsReg = (CondMoveUseOp->IsRegOp() && (CondMoveUseOp->MatchesReg(MD_FLAGS_REG)));
+					if (!FlagsReg) {
+						this->TempShadowList.SetRef(CondMoveUseOp, UseIter->GetType(), UseSSANum);
+						ShadowPoint UsePoint(CurrShadowAddr, this->TempShadowList.GetSize() - 1);
+						ValidShadowing = this->FindShadowingPoint2(UsePoint, TracingMemWrite, TempShadowAddrSet, MemUnsafe, NewCriticalOps, NonConstSourceFound, ConstValues);
+						if (!ValidShadowing) {
+							break;  // we must succeed on all conditional move USEs
+						}
+					}
+				}
+				if (ValidShadowing) { // All USEs succeeded
+					//  Remove current CriticalOp from ShadowAddrSet (if present); let the UseOps logically take its place
+					ShadowSet::iterator OldIter = ShadowAddrSet.find(CriticalOp);
+					if (OldIter != ShadowAddrSet.end()) { // found it
+						OldIter = ShadowAddrSet.erase(OldIter);
+					}
+					// Insert the shadow points for all the USEs now that all USE recursions succeeded.
+#if 0
+					ShadowAddrSet.insert(TempShadowAddrSet.begin(), TempShadowAddrSet.end());
+#else
+					for (ShadowSet::const_iterator TempIter = TempShadowAddrSet.cbegin(); TempIter != TempShadowAddrSet.cend(); ++TempIter) {
+						pair<ShadowSet::iterator, bool> InsertResult = ShadowAddrSet.insert(*TempIter);
+					}
+#endif
+				}
+				break; // success if ValidShadowing is true, failure otherwise
+			}
+			else if (!CurrInst->IsSimpleCopy(NewUseOp)) {
 				NonConstSourceFound = true;
 				// We could have something like [rsp+32] := [rsp+32] + 8.
 				//  The DEF is the DEF of our CriticalOp, and we cannot trace any farther for this shadowing index.
@@ -13689,7 +13734,7 @@ bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool T
 					}
 					else {
 						// Save in the set of constant values we traced back to.
-						pair<set<STARS_uval_t>::iterator, bool> InsertResult = ConstValues.insert(ShadowCheckUseOp->GetImmedValue());
+						pair<set<STARS_uval_t>::iterator, bool> InsertResult = ConstValues.insert(NewUseOp->GetImmedValue());
 						assert(InsertResult.first != ConstValues.end());
 					}
 					break;
-- 
GitLab