summaryrefslogtreecommitdiff
path: root/src/jit
diff options
context:
space:
mode:
authorsivarv <sivarv@microsoft.com>2016-12-06 16:19:55 -0800
committersivarv <sivarv@microsoft.com>2016-12-06 16:49:37 -0800
commitbdfe0ed89115ab8b52e7450c607701f5d6e31e75 (patch)
treeec36e41a5cbed583e7048dc5b6ae34ca725857f6 /src/jit
parentfd976d67c775ea4820279bfd7236c42b06b1d774 (diff)
downloadcoreclr-bdfe0ed89115ab8b52e7450c607701f5d6e31e75.tar.gz
coreclr-bdfe0ed89115ab8b52e7450c607701f5d6e31e75.tar.bz2
coreclr-bdfe0ed89115ab8b52e7450c607701f5d6e31e75.zip
Fix to issue 8356.
Diffstat (limited to 'src/jit')
-rw-r--r--src/jit/lsra.cpp31
1 files changed, 24 insertions, 7 deletions
diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp
index bb8c190e9a..6813beb288 100644
--- a/src/jit/lsra.cpp
+++ b/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)