From 929c079f61a4c3ca240eecc7c18dc3a36cdb9c6b Mon Sep 17 00:00:00 2001 From: sivarv Date: Tue, 6 Dec 2016 16:19:55 -0800 Subject: [PATCH] Fix to issue 8356. Commit migrated from https://github.com/dotnet/coreclr/commit/bdfe0ed89115ab8b52e7450c607701f5d6e31e75 --- src/coreclr/src/jit/lsra.cpp | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/coreclr/src/jit/lsra.cpp b/src/coreclr/src/jit/lsra.cpp index bb8c190..6813beb 100644 --- a/src/coreclr/src/jit/lsra.cpp +++ b/src/coreclr/src/jit/lsra.cpp @@ -3931,7 +3931,7 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, { // Build RefPositions for saving any live large vectors. // This must be done after the kills, so that we know which large vectors are still live. - VarSetOps::AssignNoCopy(compiler, liveLargeVectors, buildUpperVectorSaveRefPositions(tree, currentLoc)); + VarSetOps::AssignNoCopy(compiler, liveLargeVectors, buildUpperVectorSaveRefPositions(tree, currentLoc + 1)); } #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE @@ -4015,7 +4015,8 @@ void LinearScan::buildRefPositionsForNode(GenTree* tree, } #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE - buildUpperVectorRestoreRefPositions(tree, currentLoc, liveLargeVectors); + // SaveDef position must be at the same location as Def position of call node. + buildUpperVectorRestoreRefPositions(tree, defLocation, liveLargeVectors); #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE bool isContainedNode = !noAdd && consume == 0 && produce == 0 && @@ -7279,23 +7280,39 @@ void LinearScan::allocateRegisters() // then find a register to spill if (assignedRegister == REG_NA) { -#ifdef FEATURE_SIMD +#if FEATURE_PARTIAL_SIMD_CALLEE_SAVE if (refType == RefTypeUpperVectorSaveDef) { // TODO-CQ: Determine whether copying to two integer callee-save registers would be profitable. - currentRefPosition->registerAssignment = (allRegs(TYP_FLOAT) & RBM_FLT_CALLEE_TRASH); - assignedRegister = tryAllocateFreeReg(currentInterval, currentRefPosition); + + // SaveDef position occurs after the Use of args and at the same location as Kill/Def + // positions of a call node. But SaveDef position cannot use any of the arg regs as + // they are needed for call node. + currentRefPosition->registerAssignment = + (allRegs(TYP_FLOAT) & RBM_FLT_CALLEE_TRASH & ~RBM_FLTARG_REGS); + assignedRegister = tryAllocateFreeReg(currentInterval, currentRefPosition); + // There MUST be caller-save registers available, because they have all just been killed. + // Amd64 Windows: xmm4-xmm5 are guaranteed to be available as xmm0-xmm3 are used for passing args. + // Amd64 Unix: xmm8-xmm15 are guaranteed to be avilable as xmm0-xmm7 are used for passing args. + // X86 RyuJIT Windows: xmm4-xmm7 are guanrateed to be available. assert(assignedRegister != REG_NA); + // Now, spill it. - // (These will look a bit backward in the dump, but it's a pain to dump the alloc before the spill). + // Note: + // i) The reason we have to spill is that SaveDef position is allocated after the Kill positions + // of the call node are processed. Since callee-trash registers are killed by call node + // we explicity spill and unassign the register. + // ii) These will look a bit backward in the dump, but it's a pain to dump the alloc before the + // spill). unassignPhysReg(getRegisterRecord(assignedRegister), currentRefPosition); INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_ALLOC_REG, currentInterval, assignedRegister)); + // Now set assignedRegister to REG_NA again so that we don't re-activate it. assignedRegister = REG_NA; } else -#endif // FEATURE_SIMD +#endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE if (currentRefPosition->RequiresRegister() || currentRefPosition->AllocateIfProfitable()) { if (allocateReg) -- 2.7.4