Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ac9e948

Browse files
committedMar 18, 2025·
Reduce tpdiff when regMaskTP has more than 64 registers by working on SingleTypeRegSet instead.
1 parent 97db32f commit ac9e948

File tree

3 files changed

+87
-11
lines changed

3 files changed

+87
-11
lines changed
 

‎src/coreclr/jit/lsra.cpp

+79-11
Original file line numberDiff line numberDiff line change
@@ -3856,9 +3856,37 @@ void LinearScan::processKills(RefPosition* killRefPosition)
38563856
RefPosition* nextKill = killRefPosition->nextRefPosition;
38573857

38583858
regMaskTP killedRegs = killRefPosition->getKilledRegisters();
3859-
while (killedRegs.IsNonEmpty())
3859+
3860+
freeKilledRegs(killRefPosition, killedRegs.getLow(), nextKill, REG_LOW_BASE);
3861+
3862+
#ifdef HAS_MORE_THAN_64_REGISTERS
3863+
freeKilledRegs(killRefPosition, killedRegs.getHigh(), nextKill, REG_HIGH_BASE);
3864+
#endif
3865+
3866+
regsBusyUntilKill &= ~killRefPosition->getKilledRegisters();
3867+
INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KILL_REGS, nullptr, REG_NA, nullptr, NONE,
3868+
killRefPosition->getKilledRegisters()));
3869+
}
3870+
3871+
//------------------------------------------------------------------------
3872+
// freeKilledRegs: Handle registers that are being killed.
3873+
//
3874+
// Arguments:
3875+
// killRefPosition - The RefPosition for the kill
3876+
// killedRegs - Registers to kill
3877+
// nextKill - The RefPosition for next kill
3878+
// regBase - `0` or `64` based on the `killedRegs` being processed
3879+
//
3880+
void LinearScan::freeKilledRegs(RefPosition* killRefPosition,
3881+
regMaskSmall killedRegs,
3882+
RefPosition* nextKill,
3883+
int regBase)
3884+
{
3885+
3886+
while (killedRegs != RBM_NONE)
38603887
{
3861-
regNumber killedReg = genFirstRegNumFromMaskAndToggle(killedRegs);
3888+
regNumber killedReg = (regNumber)(BitOperations::BitScanForward(killedRegs) + regBase);
3889+
killedRegs ^= genSingleTypeRegMask(killedReg);
38623890
RegRecord* regRecord = getRegisterRecord(killedReg);
38633891
Interval* assignedInterval = regRecord->assignedInterval;
38643892
if (assignedInterval != nullptr)
@@ -3874,10 +3902,6 @@ void LinearScan::processKills(RefPosition* killRefPosition)
38743902
: regRecord->recentRefPosition->nextRefPosition;
38753903
updateNextFixedRef(regRecord, regNextRefPos, nextKill);
38763904
}
3877-
3878-
regsBusyUntilKill &= ~killRefPosition->getKilledRegisters();
3879-
INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_KILL_REGS, nullptr, REG_NA, nullptr, NONE,
3880-
killRefPosition->getKilledRegisters()));
38813905
}
38823906

38833907
//------------------------------------------------------------------------
@@ -4555,14 +4579,35 @@ void LinearScan::processBlockStartLocations(BasicBlock* currentBlock)
45554579
}
45564580
}
45574581
#else
4582+
45584583
regMaskTP deadCandidates = ~liveRegs;
45594584

45604585
// Only focus on actual registers present
45614586
deadCandidates &= actualRegistersMask;
4587+
handleDeadCandidates(deadCandidates.getLow(), REG_LOW_BASE, inVarToRegMap);
4588+
#ifdef HAS_MORE_THAN_64_REGISTERS
4589+
handleDeadCandidates(deadCandidates.getHigh(), REG_HIGH_BASE, inVarToRegMap);
4590+
#endif // HAS_MORE_THAN_64_REGISTERS
4591+
#endif // TARGET_ARM
4592+
}
45624593

4563-
while (deadCandidates.IsNonEmpty())
4594+
//------------------------------------------------------------------------
4595+
// handleDeadCandidates: Handle registers thata re assigned to local variables.
4596+
//
4597+
// Arguments:
4598+
// deadCandidates - mask of registers.
4599+
// regBase - base register number.
4600+
// inVarToRegMap - variable to register map.
4601+
//
4602+
// Return Value:
4603+
// None
4604+
//
4605+
void LinearScan::handleDeadCandidates(regMaskSmall deadCandidates, int regBase, VarToRegMap inVarToRegMap)
4606+
{
4607+
while (deadCandidates != RBM_NONE)
45644608
{
4565-
regNumber reg = genFirstRegNumFromMaskAndToggle(deadCandidates);
4609+
regNumber reg = (regNumber)(BitOperations::BitScanForward(deadCandidates) + regBase);
4610+
deadCandidates ^= genSingleTypeRegMask(reg);
45664611
RegRecord* physRegRecord = getRegisterRecord(reg);
45674612

45684613
makeRegAvailable(reg, physRegRecord->registerType);
@@ -4592,7 +4637,6 @@ void LinearScan::processBlockStartLocations(BasicBlock* currentBlock)
45924637
}
45934638
}
45944639
}
4595-
#endif // TARGET_ARM
45964640
}
45974641

45984642
//------------------------------------------------------------------------
@@ -4741,6 +4785,24 @@ void LinearScan::freeRegister(RegRecord* physRegRecord)
47414785
}
47424786
}
47434787

4788+
//------------------------------------------------------------------------
4789+
// LinearScan::freeRegisters: Free the registers in 'regsToFree'
4790+
//
4791+
// Arguments:
4792+
// regsToFree - the mask of registers to free, separated into low and high parts.
4793+
// regBase - `0` or `64` depending on if the registers to be freed are in the lower or higher bank.
4794+
//
4795+
void LinearScan::freeRegistersNoMask(SingleTypeRegSet regsToFree, int regBase)
4796+
{
4797+
while (regsToFree != RBM_NONE)
4798+
{
4799+
regNumber nextReg = (regNumber)(BitOperations::BitScanForward(regsToFree) + regBase);
4800+
regsToFree ^= genSingleTypeRegMask(nextReg);
4801+
4802+
RegRecord* regRecord = getRegisterRecord(nextReg);
4803+
freeRegister(regRecord);
4804+
}
4805+
}
47444806
//------------------------------------------------------------------------
47454807
// LinearScan::freeRegisters: Free the registers in 'regsToFree'
47464808
//
@@ -4756,20 +4818,26 @@ void LinearScan::freeRegisters(regMaskTP regsToFree)
47564818

47574819
INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FREE_REGS));
47584820
makeRegsAvailable(regsToFree);
4821+
#ifdef TARGET_ARM
47594822
while (regsToFree.IsNonEmpty())
47604823
{
47614824
regNumber nextReg = genFirstRegNumFromMaskAndToggle(regsToFree);
47624825

47634826
RegRecord* regRecord = getRegisterRecord(nextReg);
4764-
#ifdef TARGET_ARM
47654827
if (regRecord->assignedInterval != nullptr && (regRecord->assignedInterval->registerType == TYP_DOUBLE))
47664828
{
47674829
assert(genIsValidDoubleReg(nextReg));
47684830
regsToFree.RemoveRegNumFromMask(regNumber(nextReg + 1));
47694831
}
4770-
#endif
47714832
freeRegister(regRecord);
47724833
}
4834+
#else
4835+
freeRegistersNoMask(regsToFree.getLow(), REG_LOW_BASE);
4836+
#ifdef HAS_MORE_THAN_64_REGISTERS
4837+
freeRegistersNoMask(regsToFree.getHigh(), REG_HIGH_BASE);
4838+
#endif
4839+
4840+
#endif
47734841
}
47744842

47754843
//------------------------------------------------------------------------

‎src/coreclr/jit/lsra.h

+4
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,8 @@ class LinearScan : public LinearScanInterface
10051005

10061006
// Record variable locations at start/end of block
10071007
void processBlockStartLocations(BasicBlock* current);
1008+
1009+
FORCEINLINE void handleDeadCandidates(regMaskSmall deadCandidates, int regBase, VarToRegMap inVarToRegMap);
10081010
void processBlockEndLocations(BasicBlock* current);
10091011
void resetAllRegistersState();
10101012

@@ -1082,6 +1084,7 @@ class LinearScan : public LinearScanInterface
10821084
void makeRegisterInactive(RegRecord* physRegRecord);
10831085
void freeRegister(RegRecord* physRegRecord);
10841086
void freeRegisters(regMaskTP regsToFree);
1087+
FORCEINLINE void freeRegistersNoMask(SingleTypeRegSet regsToFree, int regBase);
10851088

10861089
// Get the type that this tree defines.
10871090
var_types getDefType(GenTree* tree)
@@ -1193,6 +1196,7 @@ class LinearScan : public LinearScanInterface
11931196
void spillInterval(Interval* interval, RefPosition* fromRefPosition DEBUGARG(RefPosition* toRefPosition));
11941197

11951198
void processKills(RefPosition* killRefPosition);
1199+
FORCEINLINE void freeKilledRegs(RefPosition* killRefPosition, regMaskSmall killedRegs, RefPosition* nextKill, int regBase);
11961200
void spillGCRefs(RefPosition* killRefPosition);
11971201

11981202
/*****************************************************************************

‎src/coreclr/jit/target.h

+4
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ typedef uint64_t regMaskSmall;
239239
#define HAS_MORE_THAN_64_REGISTERS 1
240240
#endif // TARGET_ARM64
241241

242+
#define REG_LOW_BASE 0
243+
#ifdef HAS_MORE_THAN_64_REGISTERS
244+
#define REG_HIGH_BASE 64
245+
#endif
242246
// TODO: Rename regMaskSmall as RegSet64 (at least for 64-bit)
243247
typedef regMaskSmall SingleTypeRegSet;
244248
inline SingleTypeRegSet genSingleTypeRegMask(regNumber reg);

0 commit comments

Comments
 (0)
Please sign in to comment.