From e72764aafeb966be2537ebff10f7bf5f2a5f4e1a Mon Sep 17 00:00:00 2001 From: clc5q <clc5q@git.zephyr-software.com> Date: Sun, 18 May 2014 05:20:28 +0000 Subject: [PATCH] Interprocedural propagation of fine-grained numeric type info for registers. --- SMPDataFlowAnalysis.cpp | 2 +- SMPFunction.cpp | 22 ++++++++++++++++++++++ SMPFunction.h | 2 +- SMPInstr.cpp | 20 +++++++++++++++++++- SMPInstr.h | 8 ++++---- SMPProgram.cpp | 2 +- 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/SMPDataFlowAnalysis.cpp b/SMPDataFlowAnalysis.cpp index 4f5c936a..549bd451 100644 --- a/SMPDataFlowAnalysis.cpp +++ b/SMPDataFlowAnalysis.cpp @@ -124,7 +124,7 @@ const char *MDGetRegName(op_t RegOp) { return WordRegStrings[RegOp.reg]; } else if ((RegOp.dtyp == dt_qword) && (RegOp.reg >= R_ax) && (RegOp.reg <= R_di)) { - // 16-bit registers + // 64-bit registers return QWordRegStrings[RegOp.reg]; } else { diff --git a/SMPFunction.cpp b/SMPFunction.cpp index 5c9d281f..3b102d1b 100644 --- a/SMPFunction.cpp +++ b/SMPFunction.cpp @@ -2343,6 +2343,19 @@ void SMPFunction::MDFindIncomingTypes(void) { // Note this type meet function is used in an aggressive way here, as // a mixture of UNINIT and NUMERIC at various call sites will produce NUMERIC, for example. // We are not demanding that all call sites have a consistent type with no UNINIT instances. + + // Get the FGInfo (from call site in CallerFunc) for each USE as well. + int UseSSANum = CallSiteUseIter->GetSSANum(); + int DefHashIndex = HashGlobalNameAndSSA(MarkerDefOp, UseSSANum); + struct FineGrainedInfo RegDefFG; + if (CallerFunc->IsGlobalName(MarkerDefOp)) { + RegDefFG = CallerFunc->GetDefFGInfo(DefHashIndex); + } + else { + RegDefFG = CallSiteInst->GetBlock()->GetDefFGInfo(DefHashIndex); + } + // Meet function for FGInfo is a simple bitwise OR operation. + (void) MarkerInst->UpdateDefOpFGInfo(MarkerDefOp, RegDefFG); } } } @@ -7217,7 +7230,16 @@ bool SMPFunction::InferInterproceduralTypes(void) { // If that produced new incoming types, then see if new type inference can happen. if (change) { this->InferTypes(false); + for (list<SMPBasicBlock *>::iterator BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) { + SMPBasicBlock *CurrBlock = (*BlockIter); + CurrBlock->PropagatePhiFGInfo(); + } } +#if STARS_AGGRESSIVE_SIGNEDNESS_PROPAGATION + else { + change = this->PropagateSignedness(); + } +#endif return change; } // end of SMPFunction::InferInterproceduralTypes() diff --git a/SMPFunction.h b/SMPFunction.h index 22c1a40e..97c06713 100644 --- a/SMPFunction.h +++ b/SMPFunction.h @@ -168,7 +168,7 @@ public: inline int GetReturnRegType(uint16 RegNum) const { return ((RegNum < ReturnRegTypes.size()) ? (int) ReturnRegTypes[RegNum] : 0); }; inline struct FineGrainedInfo GetReturnRegFGInfo(uint16 RegNum) const { return ReturnRegFGInfo.at(RegNum); }; inline size_t GetReturnRegFGInfoSize(void) const { return ReturnRegFGInfo.size(); }; - SMPOperandType GetIncomingRegType(uint16 RegNum); // Get reg type from all call sites; compute if called for the first time. + SMPOperandType GetIncomingRegType(uint16 RegNum); // Get reg type from all call sites. inline map<ea_t, op_t>::iterator FindLeaOperand(ea_t addr) { return LeaInstOpMap.find(addr); }; inline map<int, struct STARS_SCCP_Const_Struct>::iterator FindConstValue(int DefHashValue) { return ConstantDefs.find(DefHashValue); }; inline map<int, struct STARS_SCCP_Const_Struct>::iterator GetLastConstValueIter(void) { return ConstantDefs.end(); }; diff --git a/SMPInstr.cpp b/SMPInstr.cpp index b1f63a08..241ff558 100644 --- a/SMPInstr.cpp +++ b/SMPInstr.cpp @@ -9921,7 +9921,8 @@ void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile, list<size_t> &Lo op_t SearchOp = UseOp; // Canonicalize sub-regs for searching DEFs and USEs. CanonicalizeOpnd(SearchOp); - UseHashValue = HashGlobalNameAndSSA(SearchOp, UseIter->GetSSANum()); + UseSSANum = UseIter->GetSSANum(); + UseHashValue = HashGlobalNameAndSSA(SearchOp, UseSSANum); if (this->BasicBlock->IsLocalName(SearchOp)) { // Local name, find in basic block maps. @@ -9941,6 +9942,17 @@ void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile, list<size_t> &Lo SourceDefSignInfo = SourceDefFGInfo.SignMiscInfo; SourceDefSignMask = (SourceDefSignInfo & FG_MASK_SIGNEDNESS_BITS); + // If the DEF is in the SSA marker instruction at the top of the function, + // then the register was live into the function. The register is canonicalized + // to full width in the DEF in the marker instruction, making it appear that it + // is now being truncated. In fact, what is more likely is that a subword reg + // was passed in to the function, zero-extended. We should detect this case and suppress + // truncation annotations, else they will increase when we pass interprocedural + // types and FG info into the marker instruction. + if (!SuppressTruncation && (0 == UseSSANum) && (this->GetBlock()->GetFunc()->IsLiveIn(SearchOp))) { + SuppressTruncation = true; + TruncationIdiomCode = 26; + } #if 1 // If we have no signedness info at all for the UseSignMask, but // the SourceDefSignMask has info, then we want to use the @@ -10057,6 +10069,12 @@ void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile, list<size_t> &Lo if (SourceDefBitWidth == 0) { // Convert for printing annotation. SourceDefBitWidth = 8 * GetOpDataSize(SearchOp); } + if ((SourceDefBitWidth == 64) && (SearchOp.dtyp < dt_qword)) { + // Unlike overflows, we don't have the original DefOp that is 64 bits; + // it is in a previous instruction. We don't want to print ESI instead of RSI, + // for example, so we fix the width field of SearchOp. + SearchOp.dtyp = dt_qword; + } // OK, we need to check for possible truncation. But, how we check depends on the // signedness combinations of the source and destination operands of the move. diff --git a/SMPInstr.h b/SMPInstr.h index 34169bed..e24513a6 100644 --- a/SMPInstr.h +++ b/SMPInstr.h @@ -438,6 +438,10 @@ public: inline void EraseUse(set<DefOrUse, LessDefUse>::iterator UseIter) { Uses.EraseRef(UseIter); }; void SetRegDead(size_t RegNum); // Set the DeadRegsBitmap entry for Regnum. inline void SetStackPtrOffset(sval_t Delta) { StackPtrOffset = Delta; }; + bool UpdateUseOpFGInfo(op_t UseOp, struct FineGrainedInfo NewFG); + // helper for InferOperatorFGInfo() to update USE maps, return true if changed maps + bool UpdateDefOpFGInfo(op_t DefOp, struct FineGrainedInfo NewFG); + // helper for InferOperatorFGInfo() to update DEF maps, return true if changed maps // Query methods bool HasDestMemoryOperand(void); // Does instruction write to memory? @@ -827,10 +831,6 @@ private: bool InferOperatorFGInfo(SMPRegTransfer *CurrRT, bool FirstIter, struct FineGrainedInfo &OpFG); // infer FG info, + width on FirstIter; pass out FG info, return true if changes to FG info maps - bool UpdateUseOpFGInfo(op_t UseOp, struct FineGrainedInfo NewFG); - // helper for InferOperatorFGInfo() to update USE maps, return true if changed maps - bool UpdateDefOpFGInfo(op_t DefOp, struct FineGrainedInfo NewFG); - // helper for InferOperatorFGInfo() to update DEF maps, return true if changed maps unsigned short GetDefSignInfoFromUseOp(op_t UseOp); // Helper to fetch DEF signedness info for UseOp that has none. diff --git a/SMPProgram.cpp b/SMPProgram.cpp index 97a29ed1..5561409f 100644 --- a/SMPProgram.cpp +++ b/SMPProgram.cpp @@ -78,7 +78,7 @@ // Perform interprocedural type inference and propagation? #define STARS_INTERPROCEDURAL_TYPE_INFERENCE 1 -#define STARS_INTERPROCEDURAL_ITERATION_LIMIT 5 +#define STARS_INTERPROCEDURAL_ITERATION_LIMIT 7 ea_t LowestGlobalVarAddress; ea_t HighestGlobalVarAddress; -- GitLab