From 8ff7959e11c6743ec70b83a72b54c6124875a12d Mon Sep 17 00:00:00 2001 From: clc5q <clc5q@git.zephyr-software.com> Date: Tue, 25 Jun 2013 18:38:15 +0000 Subject: [PATCH] IDIOM 24 for truncations. --- SMPBasicBlock.cpp | 29 ++++++++++++++++++++++++++++- SMPBasicBlock.h | 2 +- SMPInstr.cpp | 23 ++++++++++++++++------- SMPInstr.h | 1 + 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/SMPBasicBlock.cpp b/SMPBasicBlock.cpp index 35db7cb3..d6ea98cf 100644 --- a/SMPBasicBlock.cpp +++ b/SMPBasicBlock.cpp @@ -4084,7 +4084,7 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd // 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) { +bool SMPBasicBlock::IsBenignTruncationDEF(op_t DefOp, int DefSSANum, size_t DefAddr, int &IdiomCode) { bool benign = false; list<SMPInstr *>::iterator InstIter, NextIter; set<DefOrUse, LessDefUse>::iterator UseIter, UseIter2, DefIter; @@ -4135,6 +4135,7 @@ bool SMPBasicBlock::IsBenignTruncationDEF(op_t DefOp, int DefSSANum, size_t DefA if (UseIter->DoesNotTruncate()) { benign = true; // already analyzed + IdiomCode = 2; break; } @@ -4168,6 +4169,7 @@ bool SMPBasicBlock::IsBenignTruncationDEF(op_t DefOp, int DefSSANum, size_t DefA 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)) { @@ -4180,6 +4182,7 @@ bool SMPBasicBlock::IsBenignTruncationDEF(op_t DefOp, int DefSSANum, size_t DefA // less than the full register after the truncation, so the truncation // is almost certainly benign. benign = true; + IdiomCode = 4; break; // Masking inst is redefining SearchOp } } // end if found SearchOp in CurrInst @@ -4220,6 +4223,30 @@ bool SMPBasicBlock::IsBenignTruncationDEF(op_t DefOp, int DefSSANum, size_t DefA } // 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)) { // 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. diff --git a/SMPBasicBlock.h b/SMPBasicBlock.h index 22bb4ba8..5f8ae1dc 100644 --- a/SMPBasicBlock.h +++ b/SMPBasicBlock.h @@ -302,7 +302,7 @@ public: bool IsInfiniteSelfLoop(void); // return true if block loops infinitely to itself bool IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAddr, bool UnderflowOpcode, int &IdiomCode); // Do we not care if DEF overflowed, due to how it is used? - bool IsBenignTruncationDEF(op_t DefOp, int DefSSANum, size_t DefAddr); // Do we not care if DEF overflowed, due to how it is used? + bool IsBenignTruncationDEF(op_t DefOp, int DefSSANum, size_t DefAddr, int &IdiomCode); // Do we not care if DEF overflowed, due to how it is used? bool IsDefMasked(op_t DefOp, int DefSSANum, ea_t DefAddr); // Does DefOp+DefSSANum get subreg masked before it gets re-DEFined? bool IsCriticalSink(op_t DefOp, int DefSSANum, string &SinkString); // What is ultimate use of DEF that might have integer error? bool IsStackOpNextUsedWithSignedness(op_t StackDefOp, ea_t DefAddr, int SSANum); // Is next use of stack DEF a sign- or zero-extended load? diff --git a/SMPInstr.cpp b/SMPInstr.cpp index 9caccd1d..f44a0680 100644 --- a/SMPInstr.cpp +++ b/SMPInstr.cpp @@ -3477,6 +3477,7 @@ bool SMPInstr::IsNonAddressReg(op_t UseOp) const { } return FoundUse; } // end of SMPInstr::IsNonAddressReg() + uval_t SMPInstr::MDGetShiftCount(void) const { uval_t ShiftCount = 0; @@ -3493,6 +3494,13 @@ uval_t SMPInstr::MDGetShiftCount(void) const { return ShiftCount; } // end of SMPInstr::MDGetShiftCount() +// RTL shows DEF operand is subreg. +bool SMPInstr::IsReducedWidthDef(void) const { + SMPRegTransfer *CurrRT = this->RTL.GetRT(0); + op_t DefOp = CurrRT->GetLeftOperand(); + return ((o_void != DefOp.type) && (DefOp.dtyp < 2)); +} + // Is a sub-register of UseOp used as a shift counter in the RTL? // For example, UseOp could be ECX on an x86 machine, and CL // could be used as a shift or rotate counter. @@ -4054,8 +4062,12 @@ bool SMPInstr::IsOpSourceSpecial(op_t UseOp, int UseSSANum, bool TruncationCheck FoundMoveNotZXCCSubreg = DefInst->IsOpSourceSpecial(UseOp, BitUseSSANum, true, SourceInstAddr); // recurse up the chain } } - else { - FoundMoveNotZXCCSubreg = false; + else if (TruncationCheck) { + // Check for reduced-width arithmetic. + if (DefInst->IsReducedWidthDef()) { // chain like sub cl,3; mov eax,ecx; then "truncating" move of al + FoundMoveNotZXCCSubreg = true; + SourceInstAddr = DefInst->GetAddr(); + } } } @@ -4876,11 +4888,8 @@ bool SMPInstr::IsBenignTruncation(int &IdiomCode) { set<DefOrUse, LessDefUse>::iterator DefIter = this->GetFirstNonFlagsDef(); assert(DefIter != this->GetLastDef()); int DefSSANum = DefIter->GetSSANum(); - benign = this->GetBlock()->IsBenignTruncationDEF(DefIter->GetOp(), DefSSANum, this->GetAddr()); - if (benign) { - IdiomCode = 2; - } - else { + benign = this->GetBlock()->IsBenignTruncationDEF(DefIter->GetOp(), DefSSANum, this->GetAddr(), IdiomCode); + if (!benign) { // Third case: value gets zero-extended, AND/OR instructions manipulate it, then // the lower bits get written. No adds, subtracts, etc. in the chain of operations. // This is just the typical unwillingness of compiler to do less than 32-bit arithmetic, diff --git a/SMPInstr.h b/SMPInstr.h index 0310d038..136f2c7a 100644 --- a/SMPInstr.h +++ b/SMPInstr.h @@ -473,6 +473,7 @@ public: bool AllDEFsTyped(void); // No DEF is UNINIT bool AllUSEsTyped(void); // No USE is UNINIT bool IsNonAddressReg(op_t UseOp) const; // UseOp is a USE reg, not just an address reg in a memory USE + bool IsReducedWidthDef(void) const; // RTL shows DEF operand is subreg. bool IsSubRegUsedAsShiftCount(op_t UseOp); // Is a subreg of UseOp used as a shift counter? bool IsOpSourceSmallPositiveConstant(op_t UseOp, int UseSSANum); // Does UseOp ultimately come from a small positive constant? bool IsOpSourceBitwiseNot(op_t UseOp, int UseSSANum); // Does UseOp ultimately come from a bitwise not instruction? -- GitLab