From 15690118463f18adc6411c3c4fb839e824e61a61 Mon Sep 17 00:00:00 2001 From: Brian Sullivan Date: Thu, 9 Jun 2016 10:46:57 -0700 Subject: Code review cleanup items and moved some items into LEGACY_BACKEND ifdefs From Codereview feedback: Use BAD_VAR_NUM in a couple places instead of (unsigned)-1 In struct InitVarDscInfo Renamed hasRetBuf to hasRetBufArg In struct RegState: Moved field rsCurRegArmNum into LEGACY_BACKEND ifdef Removed instance field RegState::rsMaxRegArgNum as it is unnecessary Reordered the fields from largest to smallest In struct GenTreeCall node: Moved field gtCallRegUsedMask into LEGACY_BACKEND ifdef Changes to genRegArgNext to work correct for X64/UNIX (where it is not currently used) Document the behavaior when given REG_ARG_LAST --- src/jit/codegencommon.cpp | 19 ++++++++++------- src/jit/codegeninterface.h | 9 ++++---- src/jit/compiler.hpp | 9 +++++--- src/jit/gentree.cpp | 10 +++++++-- src/jit/gentree.h | 2 ++ src/jit/lclvars.cpp | 2 +- src/jit/lsra.cpp | 11 +++++----- src/jit/morph.cpp | 11 ++++++++-- src/jit/regalloc.cpp | 2 -- src/jit/register_arg_convention.h | 10 ++++----- src/jit/regset.cpp | 45 +++++++++++++++++++++++++++++++++------ 11 files changed, 92 insertions(+), 38 deletions(-) diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index ae590e3924..aa2e8de45d 100755 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -129,10 +129,12 @@ CodeGen::CodeGen(Compiler * theCompiler) : instInit(); +#ifdef LEGACY_BACKEND // TODO-Cleanup: These used to be set in rsInit() - should they be moved to RegSet?? // They are also accessed by the register allocators and fgMorphLclVar(). intRegState.rsCurRegArgNum = 0; floatRegState.rsCurRegArgNum = 0; +#endif // LEGACY_BACKEND #ifdef LATE_DISASM getDisAssembler().disInit(compiler); @@ -3765,7 +3767,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, // No need further action. return; } -#endif +#endif unsigned argMax; // maximum argNum value plus 1, (including the RetBuffArg) unsigned argNum; // current argNum, always in [0..argMax-1] @@ -4086,12 +4088,14 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, #ifdef _TARGET_ARM_ int lclSize = compiler->lvaLclSize(varNum); + if (lclSize > REGSIZE_BYTES) { + unsigned maxRegArgNum = doingFloat ? MAX_FLOAT_REG_ARG : MAX_REG_ARG; slots = lclSize / REGSIZE_BYTES; - if (regArgNum + slots > regState->rsMaxRegArgNum) + if (regArgNum + slots > maxRegArgNum) { - slots = regState->rsMaxRegArgNum - regArgNum; + slots = maxRegArgNum - regArgNum; } } C_ASSERT((char)MAX_REG_ARG == MAX_REG_ARG); @@ -10434,11 +10438,6 @@ void CodeGen::genRestoreCalleeSavedFltRegs(unsigned lclFrameSize) } #endif // defined(_TARGET_XARCH_) && !FEATURE_STACK_FP_X87 - -//------------------------------------------------------------------------ -// Methods used to support FEATURE_MULTIREG_ARGS_OR_RET and HFA support for ARM32 -//------------------------------------------------------------------------ - #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING bool Compiler::IsRegisterPassable(CORINFO_CLASS_HANDLE hClass) { @@ -10478,6 +10477,10 @@ bool Compiler::IsMultiRegReturnedType(CORINFO_CLASS_HANDLE hClass) } #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +//---------------------------------------------- +// Methods that support HFA's for ARM32/ARM64 +//---------------------------------------------- + bool Compiler::IsHfa(CORINFO_CLASS_HANDLE hClass) { #ifdef FEATURE_HFA diff --git a/src/jit/codegeninterface.h b/src/jit/codegeninterface.h index 1b1196d2be..cb4774d240 100644 --- a/src/jit/codegeninterface.h +++ b/src/jit/codegeninterface.h @@ -35,11 +35,12 @@ class emitter; struct RegState { - unsigned rsCurRegArgNum; // current argument register (for caller) - unsigned rsCalleeRegArgCount; // total number of incoming register arguments regMaskTP rsCalleeRegArgMaskLiveIn; // mask of register arguments (live on entry to method) - bool rsIsFloat; - unsigned rsMaxRegArgNum; // maximum register argument number + 1 (that is, exclusive of end of range) +#ifdef LEGACY_BACKEND + unsigned rsCurRegArgNum; // current argument number (for caller) +#endif + unsigned rsCalleeRegArgCount; // total number of incoming register arguments of this kind (int or float) + bool rsIsFloat; // true for float argument registers, false for integer argument registers }; //-------------------- CodeGenInterface --------------------------------- diff --git a/src/jit/compiler.hpp b/src/jit/compiler.hpp index 734e051e14..fd0154d35e 100644 --- a/src/jit/compiler.hpp +++ b/src/jit/compiler.hpp @@ -3278,7 +3278,7 @@ unsigned genMapIntRegNumToRegArgNum(regNumber regNum) #endif default: assert(!"invalid register arg register"); - return (unsigned)-1; + return BAD_VAR_NUM; } } @@ -3311,10 +3311,13 @@ unsigned genMapFloatRegNumToRegArgNum(regNumber regNum) #endif #endif #endif - default: assert(!"invalid register arg register"); return (unsigned)-1; + default: + assert(!"invalid register arg register"); + return BAD_VAR_NUM; } #else - assert(!"flt reg args not allowed"); return (unsigned)-1; + assert(!"flt reg args not allowed"); + return BAD_VAR_NUM; #endif #endif // !arm } diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index 92b39a9e55..304f34b888 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -5563,9 +5563,12 @@ GenTreeCall* Compiler::gtNewCallNode(gtCallTypes callType, node->gtInlineCandidateInfo = NULL; } node->gtCallLateArgs = nullptr; - node->gtCallRegUsedMask = RBM_NONE; node->gtReturnType = type; +#ifdef LEGACY_BACKEND + node->gtCallRegUsedMask = RBM_NONE; +#endif // LEGACY_BACKEND + #ifdef FEATURE_READYTORUN_COMPILER node->gtCall.gtEntryPoint.addr = nullptr; #endif @@ -6715,7 +6718,6 @@ GenTreePtr Compiler::gtCloneExpr(GenTree * tree, // because the inlinee still uses the inliner's memory allocator anyway.) copy->gtCall.callSig = tree->gtCall.callSig; - copy->gtCall.gtCallRegUsedMask = tree->gtCall.gtCallRegUsedMask; copy->gtCall.gtCallType = tree->gtCall.gtCallType; copy->gtCall.gtReturnType = tree->gtCall.gtReturnType; copy->gtCall.gtControlExpr = tree->gtCall.gtControlExpr; @@ -6752,6 +6754,10 @@ GenTreePtr Compiler::gtCloneExpr(GenTree * tree, copy->gtCall.gtReturnTypeDesc = tree->gtCall.gtReturnTypeDesc; #endif +#ifdef LEGACY_BACKEND + copy->gtCall.gtCallRegUsedMask = tree->gtCall.gtCallRegUsedMask; +#endif // LEGACY_BACKEND + #ifdef FEATURE_READYTORUN_COMPILER copy->gtCall.setEntryPoint(tree->gtCall.gtEntryPoint); #endif diff --git a/src/jit/gentree.h b/src/jit/gentree.h index 862558eead..48c77b521e 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -2519,7 +2519,9 @@ struct GenTreeCall final : public GenTree // FEATURE_FIXED_OUT_ARGS was enabled, so this makes GenTreeCall 4 bytes bigger on x86). CORINFO_SIG_INFO* callSig; // Used by tail calls and to register callsites with the EE +#ifdef LEGACY_BACKEND regMaskTP gtCallRegUsedMask; // mask of registers used to pass parameters +#endif // LEGACY_BACKEND // State required to support multi-reg returning call nodes. // For now it is enabled only for x64 unix. diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp index 8160950f1a..72d7672225 100644 --- a/src/jit/lclvars.cpp +++ b/src/jit/lclvars.cpp @@ -453,7 +453,7 @@ void Compiler::lvaInitRetBuffArg(InitVarDscInfo * varDscInfo) bool hasRetBuffArg = impMethodInfo_hasRetBuffArg(info.compMethodInfo); // These two should always match - noway_assert(hasRetBuffArg == varDscInfo->hasRetBuf); + noway_assert(hasRetBuffArg == varDscInfo->hasRetBufArg); if (hasRetBuffArg) { diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp index 09d6d5efdc..07ef30d521 100644 --- a/src/jit/lsra.cpp +++ b/src/jit/lsra.cpp @@ -1026,8 +1026,6 @@ LinearScan::LinearScan(Compiler * theCompiler) compiler->codeGen->intRegState.rsIsFloat = false; compiler->codeGen->floatRegState.rsIsFloat = true; - compiler->codeGen->intRegState.rsMaxRegArgNum = MAX_REG_ARG; - compiler->codeGen->floatRegState.rsMaxRegArgNum = MAX_FLOAT_REG_ARG; // Block sequencing (the order in which we schedule). // Note that we don't initialize the bbVisitedSet until we do the first traversal @@ -3463,8 +3461,8 @@ LinearScan::updateRegStateForArg(LclVarDsc* argDsc) else #endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) { - RegState * intRegState = &compiler->codeGen->intRegState; - RegState * floatRegState = &compiler->codeGen->floatRegState; + RegState* intRegState = &compiler->codeGen->intRegState; + RegState* floatRegState = &compiler->codeGen->floatRegState; // In the case of AMD64 we'll still use the floating point registers // to model the register usage for argument on vararg calls, so // we will ignore the varargs condition to determine whether we use @@ -3684,7 +3682,10 @@ LinearScan::buildIntervals() continue; } - if (argDsc->lvIsRegArg) updateRegStateForArg(argDsc); + if (argDsc->lvIsRegArg) + { + updateRegStateForArg(argDsc); + } if (isCandidateVar(argDsc)) { diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 37798a5994..5e6493b55f 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -210,11 +210,14 @@ GenTreePtr Compiler::fgMorphIntoHelperCall(GenTreePtr tree, tree->gtCall.gtCallLateArgs = NULL; tree->gtCall.fgArgInfo = NULL; tree->gtCall.gtRetClsHnd = NULL; - tree->gtCall.gtCallRegUsedMask = RBM_NONE; tree->gtCall.gtCallMoreFlags = 0; tree->gtCall.gtInlineCandidateInfo = NULL; tree->gtCall.gtControlExpr = NULL; +#ifdef LEGACY_BACKEND + tree->gtCall.gtCallRegUsedMask = RBM_NONE; +#endif // LEGACY_BACKEND + #ifdef FEATURE_READYTORUN_COMPILER tree->gtCall.gtEntryPoint.addr = nullptr; #endif @@ -2340,7 +2343,9 @@ void fgArgInfo::EvalArgsToTemps() argReg = genRegArgNext(argReg); allUsedRegs |= genRegMask(argReg); } +#ifdef LEGACY_BACKEND callTree->gtCall.gtCallRegUsedMask |= allUsedRegs; +#endif // LEGACY_BACKEND } #endif // _TARGET_ARM_ } @@ -4043,13 +4048,15 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) if (!lateArgsComputed) { call->fgArgInfo->ArgsComplete(); +#ifdef LEGACY_BACKEND call->gtCallRegUsedMask = genIntAllRegArgMask(intArgRegNum) & ~argSkippedRegMask; if (fltArgRegNum > 0) { -#if defined(_TARGET_ARM_) || defined(_TARGET_AMD64_) +#if defined(_TARGET_ARM_) call->gtCallRegUsedMask |= genFltAllRegArgMask(fltArgRegNum) & ~fltArgSkippedRegMask; #endif } +#endif // LEGACY_BACKEND } if (call->gtCallArgs) diff --git a/src/jit/regalloc.cpp b/src/jit/regalloc.cpp index b491747da3..0c7ae21702 100644 --- a/src/jit/regalloc.cpp +++ b/src/jit/regalloc.cpp @@ -78,8 +78,6 @@ void Compiler::raInit() #endif codeGen->intRegState.rsIsFloat = false; codeGen->floatRegState.rsIsFloat = true; - codeGen->intRegState.rsMaxRegArgNum = MAX_REG_ARG; - codeGen->floatRegState.rsMaxRegArgNum = MAX_FLOAT_REG_ARG; rpReverseEBPenreg = false; rpAsgVarNum = -1; diff --git a/src/jit/register_arg_convention.h b/src/jit/register_arg_convention.h index 41d829619d..40db9b8136 100644 --- a/src/jit/register_arg_convention.h +++ b/src/jit/register_arg_convention.h @@ -18,7 +18,7 @@ struct InitVarDscInfo unsigned maxIntRegArgNum; unsigned maxFloatRegArgNum; - bool hasRetBuf; + bool hasRetBufArg; #ifdef _TARGET_ARM_ // Support back-filling of FP parameters. This is similar to code in gtMorphArgs() that @@ -30,11 +30,11 @@ struct InitVarDscInfo public: // set to initial values - void Init(LclVarDsc *lvaTable, bool _hasRetBuf) + void Init(LclVarDsc *lvaTable, bool _hasRetBufArg) { - hasRetBuf = _hasRetBuf; - varDsc = lvaTable; - varNum = 0; + hasRetBufArg = _hasRetBufArg; + varDsc = &lvaTable[0]; // the first argument LclVar 0 + varNum = 0; // the first argument varNum 0 intRegArgNum = 0; floatRegArgNum = 0; maxIntRegArgNum = MAX_REG_ARG; diff --git a/src/jit/regset.cpp b/src/jit/regset.cpp index a188461450..79846e92c5 100644 --- a/src/jit/regset.cpp +++ b/src/jit/regset.cpp @@ -3458,19 +3458,52 @@ bool genIsProperRegPair(regPairNo regPair) * * Given a register that is an argument register * returns the next argument register + * + * Note: that this method will return a non arg register + * when given REG_ARG_LAST + * */ regNumber genRegArgNext(regNumber argReg) { - assert(isValidIntArgReg(argReg)); + assert(isValidIntArgReg(argReg)); + + regNumber result = REG_NA; #ifdef _TARGET_AMD64_ - if (argReg == REG_ARG_1) - return REG_ARG_2; -#endif +#ifdef UNIX_AMD64_ABI + // Windows X64 ABI: + // REG_EDI, REG_ESI, REG_ECX, REG_EDX, REG_R8, REG_R9 + // + if (argReg == REG_ARG_1) // REG_ESI + { + result = REG_ARG_2; // REG_ECX + } + else if (argReg == REG_ARG_3) // REG_EDX + { + result = REG_ARG_4; // REG_R8 + } +#else // Windows ABI + // Windows X64 ABI: + // REG_ECX, REG_EDX, REG_R8, REG_R9 + // + if (argReg == REG_ARG_1) // REG_EDX + { + result = REG_ARG_2; // REG_R8 + } +#endif // UNIX or Windows ABI +#endif _TARGET_AMD64_ - // Otherwise we can iterate the argument registers by using +1 - return REG_NEXT(argReg); + // If we didn't set 'result' to valid register above + // then we will just iterate 'argReg' using REG_NEXT + // + if (result == REG_NA) + { + // Otherwise we just iterate the argument registers by using REG_NEXT + result = REG_NEXT(argReg); + } + + return result; } #if !defined(_TARGET_X86_) -- cgit v1.2.3