diff options
author | Sivarv <sivarv@microsoft.com> | 2016-12-12 13:36:43 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-12 13:36:43 -0800 |
commit | f26796f07f933f0b67fd15fdc5d2a21d5652908b (patch) | |
tree | bdfcf8be649baf9f7f87cfdcf80f6556c1f67c68 /src/jit | |
parent | d18d199ae7cfd7b3377712bfa30bf7baca12bf0f (diff) | |
parent | 55b082233de4e434fb4c82e3805d981c97f0ba0c (diff) | |
download | coreclr-f26796f07f933f0b67fd15fdc5d2a21d5652908b.tar.gz coreclr-f26796f07f933f0b67fd15fdc5d2a21d5652908b.tar.bz2 coreclr-f26796f07f933f0b67fd15fdc5d2a21d5652908b.zip |
Merge pull request #8532 from sivarv/fixedRegFix
Fix to issue 8286.
Diffstat (limited to 'src/jit')
-rw-r--r-- | src/jit/lsra.cpp | 82 |
1 files changed, 39 insertions, 43 deletions
diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp index f298af0c0c..10f58dddba 100644 --- a/src/jit/lsra.cpp +++ b/src/jit/lsra.cpp @@ -7236,59 +7236,44 @@ void LinearScan::allocateRegisters() assert(currentInterval != nullptr); // It's already in a register, but not one we need. - // If it is a fixed use that is not marked "delayRegFree", there is already a FixedReg to ensure that - // the needed reg is not otherwise in use, so we can simply ignore it and codegen will do the copy. - // The reason we need special handling for the "delayRegFree" case is that we need to mark the - // fixed-reg as in-use and delayed (the FixedReg RefPosition doesn't handle the delay requirement). - // Otherwise, if this is a pure use localVar or tree temp, we assign a copyReg, but must free both regs - // if it is a last use. - if (!currentRefPosition->isFixedRegRef || currentRefPosition->delayRegFree) - { - if (!RefTypeIsDef(currentRefPosition->refType)) + if (!RefTypeIsDef(currentRefPosition->refType)) + { + regNumber copyReg = assignCopyReg(currentRefPosition); + assert(copyReg != REG_NA); + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_COPY_REG, currentInterval, copyReg)); + lastAllocatedRefPosition = currentRefPosition; + if (currentRefPosition->lastUse) { - regNumber copyReg = assignCopyReg(currentRefPosition); - assert(copyReg != REG_NA); - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_COPY_REG, currentInterval, copyReg)); - lastAllocatedRefPosition = currentRefPosition; - if (currentRefPosition->lastUse) + if (currentRefPosition->delayRegFree) { - if (currentRefPosition->delayRegFree) - { - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE_DELAYED, currentInterval, - assignedRegister)); - delayRegsToFree |= - (genRegMask(assignedRegister) | currentRefPosition->registerAssignment); - } - else - { - INDEBUG( - dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE, currentInterval, assignedRegister)); - regsToFree |= (genRegMask(assignedRegister) | currentRefPosition->registerAssignment); - } + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE_DELAYED, currentInterval, + assignedRegister)); + delayRegsToFree |= (genRegMask(assignedRegister) | currentRefPosition->registerAssignment); } - // If this is a tree temp (non-localVar) interval, we will need an explicit move. - if (!currentInterval->isLocalVar) + else { - currentRefPosition->moveReg = true; - currentRefPosition->copyReg = false; + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE, currentInterval, assignedRegister)); + regsToFree |= (genRegMask(assignedRegister) | currentRefPosition->registerAssignment); } - continue; } - else + // If this is a tree temp (non-localVar) interval, we will need an explicit move. + if (!currentInterval->isLocalVar) { - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_NEEDS_NEW_REG, nullptr, assignedRegister)); - regsToFree |= genRegMask(assignedRegister); - // We want a new register, but we don't want this to be considered a spill. - assignedRegister = REG_NA; - if (physRegRecord->assignedInterval == currentInterval) - { - unassignPhysRegNoSpill(physRegRecord); - } + currentRefPosition->moveReg = true; + currentRefPosition->copyReg = false; } + continue; } else { - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KEPT_ALLOCATION, nullptr, assignedRegister)); + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_NEEDS_NEW_REG, nullptr, assignedRegister)); + regsToFree |= genRegMask(assignedRegister); + // We want a new register, but we don't want this to be considered a spill. + assignedRegister = REG_NA; + if (physRegRecord->assignedInterval == currentInterval) + { + unassignPhysRegNoSpill(physRegRecord); + } } } } @@ -11770,9 +11755,18 @@ void LinearScan::verifyFinalAllocation() { if (VERBOSE) { + // If refPos is marked as copyReg, then the reg that is spilled + // is the homeReg of the interval not the reg currently assigned + // to refPos. + regNumber spillReg = regNum; + if (currentRefPosition->copyReg) + { + assert(interval != nullptr); + spillReg = interval->physReg; + } dumpRegRecords(); dumpEmptyRefPosition(); - printf("Spill %-4s ", getRegName(regNum)); + printf("Spill %-4s ", getRegName(spillReg)); } } else if (currentRefPosition->copyReg) @@ -11946,6 +11940,8 @@ void LinearScan::verifyResolutionMove(GenTree* resolutionMove, LsraLocation curr assert(leftInterval->physReg == leftRegNum && rightInterval->physReg == rightRegNum); leftInterval->physReg = rightRegNum; rightInterval->physReg = leftRegNum; + leftInterval->assignedReg = &physRegs[rightRegNum]; + rightInterval->assignedReg = &physRegs[leftRegNum]; physRegs[rightRegNum].assignedInterval = leftInterval; physRegs[leftRegNum].assignedInterval = rightInterval; if (VERBOSE) |