diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index cf79a6eef4330..d803ae8fcaff5 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -4818,6 +4818,12 @@ void LinearScan::allocateRegisters() copyRegsToFree = RBM_NONE; regsInUseThisLocation = regsInUseNextLocation; regsInUseNextLocation = RBM_NONE; +#ifdef TARGET_ARM64 + if (hasConsecutiveRegister) + { + consecutiveRegsInUseThisLocation = RBM_NONE; + } +#endif if ((regsToFree | delayRegsToFree) != RBM_NONE) { freeRegisters(regsToFree); @@ -5433,6 +5439,7 @@ void LinearScan::allocateRegisters() // It doesn't satisfy, so do a copyReg for the first RefPosition to such a register, so // it would be possible to allocate consecutive registers to the subsequent RefPositions. regNumber copyReg = assignCopyReg(¤tRefPosition); + assignConsecutiveRegisters(¤tRefPosition, copyReg); if (copyReg != assignedRegister) { @@ -5440,6 +5447,16 @@ void LinearScan::allocateRegisters() regMaskTP copyRegMask = getRegMask(copyReg, currentInterval->registerType); regMaskTP assignedRegMask = getRegMask(assignedRegister, currentInterval->registerType); + if ((consecutiveRegsInUseThisLocation & assignedRegMask) != RBM_NONE) + { + // If assigned register is one of the consecutive register we are about to assign + // to the subsequent RefPositions, do not mark it busy otherwise when we allocate + // for that particular subsequent RefPosition, we will not find any candidates + // available. Not marking it busy should be fine because we have already set the + // register assignments for all the consecutive refpositions. + assignedRegMask = RBM_NONE; + } + // For consecutive register, although it shouldn't matter what the assigned register was, // because we have just assigned it `copyReg` and that's the one in-use, and not the // one that was assigned previously. However, in situation where an upper-vector restore @@ -5480,7 +5497,6 @@ void LinearScan::allocateRegisters() currentRefPosition.registerAssignment = assignedRegBit; } - assignConsecutiveRegisters(¤tRefPosition, copyReg); continue; } } @@ -5538,6 +5554,16 @@ void LinearScan::allocateRegisters() // registers. assignConsecutiveRegisters(¤tRefPosition, copyReg); } + + if ((consecutiveRegsInUseThisLocation & assignedRegMask) != RBM_NONE) + { + // If assigned register is one of the consecutive register we are about to assign + // to the subsequent RefPositions, do not mark it busy otherwise when we allocate + // for that particular subsequent RefPosition, we will not find any candidates + // available. Not marking it busy should be fine because we have already set the + // register assignments for all the consecutive refpositions. + assignedRegMask = RBM_NONE; + } } #endif // For consecutive register, although it shouldn't matter what the assigned register was, diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index f9de491dfc199..d869f8f8a126c 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -1839,6 +1839,9 @@ class LinearScan : public LinearScanInterface regMaskTP regsBusyUntilKill; regMaskTP regsInUseThisLocation; regMaskTP regsInUseNextLocation; +#ifdef TARGET_ARM64 + regMaskTP consecutiveRegsInUseThisLocation; +#endif bool isRegBusy(regNumber reg, var_types regType) { regMaskTP regMask = getRegMask(reg, regType); diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index c8c6d96707938..40513da8e5656 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -67,6 +67,7 @@ void LinearScan::assignConsecutiveRegisters(RefPosition* firstRefPosition, regNu assert(firstRefPosition->assignedReg() == firstRegAssigned); assert(firstRefPosition->isFirstRefPositionOfConsecutiveRegisters()); assert(emitter::isVectorRegister(firstRegAssigned)); + assert(consecutiveRegsInUseThisLocation == RBM_NONE); RefPosition* consecutiveRefPosition = getNextConsecutiveRefPosition(firstRefPosition); regNumber regToAssign = firstRegAssigned == REG_FP_LAST ? REG_FP_FIRST : REG_NEXT(firstRegAssigned); @@ -75,7 +76,7 @@ void LinearScan::assignConsecutiveRegisters(RefPosition* firstRefPosition, regNu assert(firstRefPosition->refType != RefTypeUpperVectorRestore); INDEBUG(int refPosCount = 1); - regMaskTP busyConsecutiveRegMask = (((1ULL << firstRefPosition->regCount) - 1) << firstRegAssigned); + consecutiveRegsInUseThisLocation = (((1ULL << firstRefPosition->regCount) - 1) << firstRegAssigned); while (consecutiveRefPosition != nullptr) { @@ -95,7 +96,7 @@ void LinearScan::assignConsecutiveRegisters(RefPosition* firstRefPosition, regNu // RefTypeUpperVectorRestore positions of corresponding variables for which (another criteria) // we are trying to find consecutive registers. - consecutiveRefPosition->registerAssignment &= ~busyConsecutiveRegMask; + consecutiveRefPosition->registerAssignment &= ~consecutiveRegsInUseThisLocation; } consecutiveRefPosition = getNextConsecutiveRefPosition(consecutiveRefPosition); }