From 7f24c64895638fc22530da8f5fae878433e14465 Mon Sep 17 00:00:00 2001 From: Brian Sullivan Date: Wed, 22 Jun 2016 19:37:59 -0700 Subject: [PATCH] Changes to ReturnTypeDesc support more than two return registers Changed m_regType into an array Renamed the Initialize method to InitializeReturnType --- src/jit/codegenxarch.cpp | 4 +-- src/jit/gentree.cpp | 24 +++++++---------- src/jit/gentree.h | 67 ++++++++++++++++++++++++++---------------------- src/jit/importer.cpp | 18 +++++++------ src/jit/lclvars.cpp | 2 +- src/jit/morph.cpp | 2 +- 6 files changed, 59 insertions(+), 58 deletions(-) diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp index d45c181..e464bd0 100755 --- a/src/jit/codegenxarch.cpp +++ b/src/jit/codegenxarch.cpp @@ -186,7 +186,7 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) if (compiler->compMethodReturnsMultiRegRetType()) { ReturnTypeDesc retTypeDesc; - retTypeDesc.Initialize(compiler, compiler->info.compMethodInfo->args.retTypeClass); + retTypeDesc.InitializeReturnType(compiler, compiler->info.compMethodInfo->args.retTypeClass); unsigned regCount = retTypeDesc.GetReturnRegCount(); // Only x86 and x64 Unix ABI allows multi-reg return and @@ -1516,7 +1516,7 @@ CodeGen::genStructReturn(GenTreePtr treeNode) assert(varDsc->lvIsMultiRegArgOrRet); ReturnTypeDesc retTypeDesc; - retTypeDesc.Initialize(compiler, varDsc->lvVerTypeInfo.GetClassHandle()); + retTypeDesc.InitializeReturnType(compiler, varDsc->lvVerTypeInfo.GetClassHandle()); unsigned regCount = retTypeDesc.GetReturnRegCount(); assert(regCount == MAX_RET_REG_COUNT); diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index ba4dabd..3e77e17 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -14082,9 +14082,7 @@ bool GenTree::isCommutativeSIMDIntrinsic() // Return Value // None // -// Note: -// Right now it is implemented only for x64 unix. -void ReturnTypeDesc::Initialize(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd) +void ReturnTypeDesc::InitializeReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd) { assert(!m_inited); @@ -14096,23 +14094,19 @@ void ReturnTypeDesc::Initialize(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd) if (structDesc.passedInRegisters) { - if (structDesc.eightByteCount == 1) - { - m_regType0 = comp->GetEightByteType(structDesc, 0); - } - else + for (int i=0; iGetEightByteType(structDesc, 0); - m_regType1 = comp->GetEightByteType(structDesc, 1); + assert(i < MAX_RET_REG_COUNT); + m_regType[i] = comp->GetEightByteType(structDesc, i); } } #elif defined(_TARGET_X86_) - // TODO-X86: Assumes we are only using ReturnTypeDesc for longs on x86. Will - // need to be updated in the future to handle other return types - m_regType0 = TYP_INT; - m_regType1 = TYP_INT; + // TODO-X86: Assumes we are only using ReturnTypeDesc for longs on x86. + // Will need to be updated in the future to handle other return types + assert(MAX_RET_REG_COUNT == 2); + m_regType[0] = TYP_INT; + m_regType[1] = TYP_INT; #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING #ifdef DEBUG diff --git a/src/jit/gentree.h b/src/jit/gentree.h index ed3ef94..3e7c988 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -2395,8 +2395,7 @@ enum class InlineObservation; struct ReturnTypeDesc { private: - var_types m_regType0; - var_types m_regType1; + var_types m_regType[MAX_RET_REG_COUNT]; #ifdef DEBUG bool m_inited; @@ -2408,15 +2407,16 @@ public: Reset(); } - // Initialize type descriptor given its type handle - void Initialize(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd); + // Initialize the return type descriptor given its type handle + void InitializeReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd); // Reset type descriptor to defaults void Reset() { - m_regType0 = TYP_UNKNOWN; - m_regType1 = TYP_UNKNOWN; - + for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i) + { + m_regType[i] = TYP_UNKNOWN; + } #ifdef DEBUG m_inited = false; #endif @@ -2436,20 +2436,24 @@ public: assert(m_inited); int regCount = 0; - if (m_regType0 != TYP_UNKNOWN) + for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i) { - ++regCount; - - if (m_regType1 != TYP_UNKNOWN) + if (m_regType[i] == TYP_UNKNOWN) { - ++regCount; + break; } + // otherwise + regCount++; } - else + +#ifdef DEBUG + // Any remaining elements in m_regTypes[] should also be TYP_UNKNOWN + for (unsigned i = regCount+1; i < MAX_RET_REG_COUNT; ++i) { - // If regType0 is TYP_UNKNOWN then regType1 must also be TYP_UNKNOWN. - assert(m_regType1 == TYP_UNKNOWN); + assert(m_regType[i] == TYP_UNKNOWN); } +#endif + return regCount; } @@ -2463,9 +2467,19 @@ public: // Return Value: // Returns true if the type is returned in multiple return registers. // False otherwise. + // Note that we only have to examine the first two values to determine this + // bool IsMultiRegRetType() const { - return GetReturnRegCount() > 1; + if (MAX_RET_REG_COUNT < 2) + { + return false; + } + else + { + return ((m_regType[0] != TYP_UNKNOWN) && + (m_regType[1] != TYP_UNKNOWN)); + } } //-------------------------------------------------------------------------- @@ -2477,21 +2491,14 @@ public: // // Return Value: // var_type of the return register specified by its index. - // Return TYP_UNKNOWN if index > number of return registers. + // asserts if the index does not have a valid register return type. + var_types GetReturnRegType(unsigned index) { - assert(index < GetReturnRegCount()); - - if (index == 0) - { - return m_regType0; - } - else if (index == 1) - { - return m_regType1; - } + var_types result = m_regType[index]; + assert(result != TYP_UNKNOWN); - return TYP_UNKNOWN; + return result; } // Get ith ABI return register @@ -4051,8 +4058,6 @@ struct GenTreeCopyOrReload : public GenTreeUnOp // Return Value: // None. // - // TODO-ARM: Implement this routine for Arm64 and Arm32 - // TODO-X86: Implement this routine for x86 void SetRegNumByIdx(regNumber reg, unsigned idx) { assert(idx < MAX_RET_REG_COUNT); @@ -4061,7 +4066,7 @@ struct GenTreeCopyOrReload : public GenTreeUnOp { gtRegNum = reg; } -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING +#if FEATURE_MULTIREG_RET else { gtOtherRegs[idx - 1] = reg; diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index 7410147..b786cab 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -7376,6 +7376,14 @@ GenTreePtr Compiler::impFixupCallStructReturn(GenTreePtr call call->gtCall.gtRetClsHnd = retClsHnd; + GenTreeCall* callNode = call->AsCall(); + +#if FEATURE_MULTIREG_RET + // Initialize Return type descriptor of call node + ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc(); + retTypeDesc->InitializeReturnType(this, retClsHnd); +#endif // FEATURE_MULTIREG_RET + #if FEATURE_MULTIREG_RET && defined(FEATURE_HFA) // There is no fixup necessary if the return type is a HFA struct. // HFA structs are returned in registers for ARM32 and ARM64 @@ -7407,8 +7415,6 @@ GenTreePtr Compiler::impFixupCallStructReturn(GenTreePtr call } #elif defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) - GenTreeCall* callNode = call->AsCall(); - // Not allowed for FEATURE_CORCLR which is the only SKU available for System V OSs. assert(!callNode->IsVarargs() && "varargs not allowed for System V OSs."); @@ -7416,10 +7422,6 @@ GenTreePtr Compiler::impFixupCallStructReturn(GenTreePtr call // single eightbyte return type below. callNode->gtReturnType = call->gtType; - // Initialize Return type descriptor of call node - ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc(); - retTypeDesc->Initialize(this, retClsHnd); - unsigned retRegCount = retTypeDesc->GetReturnRegCount(); if (retRegCount != 0) { @@ -7501,7 +7503,7 @@ GenTreePtr Compiler::impInitCallReturnTypeDesc(GenTreePtr cal // Initialize Return type descriptor of call node ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc(); - retTypeDesc->Initialize(this, retClsHnd); + retTypeDesc->InitializeReturnType(this, retClsHnd); unsigned retRegCount = retTypeDesc->GetReturnRegCount(); // must be a long returned in two registers @@ -14236,7 +14238,7 @@ bool Compiler::impReturnInstruction(BasicBlock *block, int prefixFlags, OPCODE & // Same as !IsHfa but just don't bother with impAssignStructPtr. #else // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) ReturnTypeDesc retTypeDesc; - retTypeDesc.Initialize(this, retClsHnd); + retTypeDesc.InitializeReturnType(this, retClsHnd); unsigned retRegCount = retTypeDesc.GetReturnRegCount(); if (retRegCount != 0) diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp index 2d21856..f129bff 100644 --- a/src/jit/lclvars.cpp +++ b/src/jit/lclvars.cpp @@ -144,7 +144,7 @@ void Compiler::lvaInitTypeRef() { #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING ReturnTypeDesc retTypeDesc; - retTypeDesc.Initialize(this, info.compMethodInfo->args.retTypeClass); + retTypeDesc.InitializeReturnType(this, info.compMethodInfo->args.retTypeClass); if (retTypeDesc.GetReturnRegCount() > 1) { diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index c4336de..510d1e1 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -89,7 +89,7 @@ GenTreePtr Compiler::fgMorphIntoHelperCall(GenTreePtr tree, GenTreeCall* callNode = tree->AsCall(); ReturnTypeDesc* retTypeDesc = callNode->GetReturnTypeDesc(); retTypeDesc->Reset(); - retTypeDesc->Initialize(this, callNode->gtRetClsHnd); + retTypeDesc->InitializeReturnType(this, callNode->gtRetClsHnd); callNode->ClearOtherRegs(); NYI("Helper with TYP_LONG return type"); -- 2.7.4