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