summaryrefslogtreecommitdiff
path: root/src/jit/lsra.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/lsra.cpp')
-rw-r--r--src/jit/lsra.cpp75
1 files changed, 67 insertions, 8 deletions
diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp
index 0db1ab0659..ebac7cd4ac 100644
--- a/src/jit/lsra.cpp
+++ b/src/jit/lsra.cpp
@@ -950,6 +950,41 @@ LinearScan::LinearScan(Compiler * theCompiler)
// Get the value of the environment variable that controls stress for register allocation
static ConfigDWORD fJitStressRegs;
lsraStressMask = fJitStressRegs.val(CLRConfig::INTERNAL_JitStressRegs);
+#if 0
+#ifdef DEBUG
+ if (lsraStressMask != 0)
+ {
+ // The code in this #if can be used to debug JitStressRegs issues according to
+ // method hash. To use, simply set environment variables JitStressRegsHashLo and JitStressRegsHashHi
+ unsigned methHash = compiler->info.compMethodHash();
+ char* lostr = getenv("JitStressRegsHashLo");
+ unsigned methHashLo = 0;
+ bool dump = false;
+ if (lostr != nullptr)
+ {
+ sscanf_s(lostr, "%x", &methHashLo);
+ dump = true;
+ }
+ char* histr = getenv("JitStressRegsHashHi");
+ unsigned methHashHi = UINT32_MAX;
+ if (histr != nullptr)
+ {
+ sscanf_s(histr, "%x", &methHashHi);
+ dump = true;
+ }
+ if (methHash < methHashLo || methHash > methHashHi)
+ {
+ lsraStressMask = 0;
+ }
+ else if (dump == true)
+ {
+ printf("JitStressRegs = %x for method %s, hash = 0x%x.\n",
+ lsraStressMask, compiler->info.compFullName, compiler->info.compMethodHash());
+ printf(""); // in our logic this causes a flush
+ }
+ }
+#endif // DEBUG
+#endif
static ConfigDWORD fJitDumpTerseLsra;
dumpTerse = (fJitDumpTerseLsra.val(CLRConfig::INTERNAL_JitDumpTerseLsra) != 0);
@@ -2638,17 +2673,34 @@ LinearScan::buildInternalRegisterDefsForNode(GenTree *tree,
{
int count;
int internalIntCount = tree->gtLsraInfo.internalIntCount;
+ regMaskTP internalCands = tree->gtLsraInfo.getInternalCandidates(this);
+
+ // If this is a varArgs call, the internal candidates represent the integer registers that
+ // floating point arguments must be copied into. These must be handled as fixed regs.
+ bool fixedRegs = false;
+ if ((internalIntCount != 0) && (tree->OperGet() == GT_CALL))
+ {
+ assert(tree->gtCall.IsVarargs());
+ fixedRegs = true;
+ assert((int)genCountBits(internalCands) == internalIntCount);
+ }
+
for (count = 0; count < internalIntCount; count++)
{
- regMaskTP internalCands = (tree->gtLsraInfo.getInternalCandidates(this) & allRegs(TYP_INT));
- temps[count] = defineNewInternalTemp(tree, IntRegisterType, currentLoc, internalCands);
+ regMaskTP internalIntCands = (internalCands & allRegs(TYP_INT));
+ if (fixedRegs)
+ {
+ internalIntCands = genFindLowestBit(internalIntCands);
+ internalCands &= ~internalIntCands;
+ }
+ temps[count] = defineNewInternalTemp(tree, IntRegisterType, currentLoc, internalIntCands);
}
int internalFloatCount = tree->gtLsraInfo.internalFloatCount;
for (int i = 0; i < internalFloatCount; i++)
{
- regMaskTP internalCands = (tree->gtLsraInfo.getInternalCandidates(this) & internalFloatRegCandidates());
- temps[count++] = defineNewInternalTemp(tree, FloatRegisterType, currentLoc, internalCands);
+ regMaskTP internalFPCands = (internalCands & internalFloatRegCandidates());
+ temps[count++] = defineNewInternalTemp(tree, FloatRegisterType, currentLoc, internalFPCands);
}
noway_assert(count < MaxInternalRegisters);
@@ -3185,7 +3237,11 @@ LinearScan::buildRefPositionsForNode(GenTree *tree,
LsraLocation defLocation = (i == produce-1) ? lastDefLocation : currentLoc;
RefPosition *pos = newRefPosition(interval, defLocation, defRefType, defNode, currCandidates);
- pos->isLocalDefUse = info.isLocalDefUse;
+ if (info.isLocalDefUse)
+ {
+ pos->isLocalDefUse = true;
+ pos->lastUse = true;
+ }
DBEXEC(VERBOSE, pos->dump());
interval->updateRegisterPreferences(currCandidates);
interval->updateRegisterPreferences(useCandidates);
@@ -4384,8 +4440,9 @@ LinearScan::tryAllocateFreeReg(Interval *currentInterval, RefPosition *refPositi
continue;
}
- // If this is a constant interval, check to see if its value is already in this register.
+ // If this is a definition of a constant interval, check to see if its value is already in this register.
if (currentInterval->isConstant &&
+ RefTypeIsDef(refPosition->refType) &&
(physRegRecord->assignedInterval != nullptr) &&
physRegRecord->assignedInterval->isConstant)
{
@@ -4398,7 +4455,8 @@ LinearScan::tryAllocateFreeReg(Interval *currentInterval, RefPosition *refPositi
switch (otherTreeNode->OperGet())
{
case GT_CNS_INT:
- if (refPosition->treeNode->AsIntCon()->IconValue() == otherTreeNode->AsIntCon()->IconValue())
+ if ((refPosition->treeNode->AsIntCon()->IconValue() == otherTreeNode->AsIntCon()->IconValue()) &&
+ (varTypeGCtype(refPosition->treeNode) == varTypeGCtype(otherTreeNode)))
{
score |= VALUE_AVAILABLE;
}
@@ -6812,6 +6870,7 @@ LinearScan::resolveRegisters()
lclNum++)
{
localVarIntervals[lclNum]->recentRefPosition = nullptr;
+ localVarIntervals[lclNum]->isActive = false;
}
// handle incoming arguments and special temps
@@ -10010,7 +10069,7 @@ LinearScan::verifyFinalAllocation()
assert(interval->assignedReg != nullptr);
regRecord = interval->assignedReg;
}
- if (currentRefPosition->spillAfter || currentRefPosition->lastUse || currentRefPosition->isLocalDefUse)
+ if (currentRefPosition->spillAfter || currentRefPosition->lastUse)
{
interval->physReg = REG_NA;
interval->assignedReg = nullptr;