Skip to content

Commit 7b8a1b4

Browse files
Updating LSRA to prevent eGPR use as GC tracked regs. (#117991)
* Prevent eGPRs from being used as GC tracked regs.
1 parent f9ce5db commit 7b8a1b4

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/coreclr/jit/lsra.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,35 @@ RegRecord* LinearScan::getRegisterRecord(regNumber regNum)
498498
return &physRegs[regNum];
499499
}
500500

501+
//------------------------------------------------------------------------
502+
// getAvailableGPRsForType: Returns available general-purpose registers for the given type,
503+
// with platform-specific restrictions applied.
504+
//
505+
// Arguments:
506+
// candidates - The candidate register mask to be filtered
507+
// regType - The register type for which we need available registers
508+
//
509+
// Return Value:
510+
// A filtered register mask with platform-specific restrictions applied.
511+
// For AMD64: GC types and long types are restricted to low GPRs only.
512+
// For other platforms: Returns the original candidates unchanged.
513+
//
514+
// Notes:
515+
// On AMD64, we don't use extended GPRs (R16-R31) for GC types to ensure
516+
// proper GC tracking and code generation compatibility.
517+
//
518+
SingleTypeRegSet LinearScan::getAvailableGPRsForType(SingleTypeRegSet candidates, var_types regType)
519+
{
520+
#ifdef TARGET_AMD64
521+
if (varTypeIsGC(regType) || varTypeIsLong(regType))
522+
{
523+
// For AMD64, we don't use eGPR for GC types.
524+
candidates &= (SingleTypeRegSet)RBM_LOWINT.getLow();
525+
}
526+
#endif // TARGET_AMD64
527+
return candidates;
528+
}
529+
501530
#ifdef DEBUG
502531

503532
//----------------------------------------------------------------------------
@@ -8694,6 +8723,9 @@ regNumber LinearScan::getTempRegForResolution(BasicBlock* fromBlock,
86948723
}
86958724
#else // !TARGET_ARM
86968725
SingleTypeRegSet freeRegs = allRegs(type);
8726+
// We call getTempRegForResolution() with only either TYP_INT or TYP_FLOAT.
8727+
// We are being conservative with eGPR usage when type is TYP_INT since it could be a reference type.
8728+
freeRegs = getAvailableGPRsForType(freeRegs, (type == TYP_INT) ? TYP_REF : type);
86978729
#endif // !TARGET_ARM
86988730

86998731
#ifdef DEBUG
@@ -13466,7 +13498,7 @@ SingleTypeRegSet LinearScan::RegisterSelection::select(Interval*
1346613498
{
1346713499
preferences = candidates;
1346813500
}
13469-
13501+
candidates = linearScan->getAvailableGPRsForType(candidates, regType);
1347013502
#ifdef DEBUG
1347113503
candidates = linearScan->stressLimitRegs(refPosition, regType, candidates);
1347213504
#endif
@@ -13934,7 +13966,7 @@ SingleTypeRegSet LinearScan::RegisterSelection::selectMinimal(
1393413966
}
1393513967
}
1393613968
}
13937-
13969+
candidates = linearScan->getAvailableGPRsForType(candidates, regType);
1393813970
#ifdef DEBUG
1393913971
candidates = linearScan->stressLimitRegs(refPosition, regType, candidates);
1394013972
#endif

src/coreclr/jit/lsra.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,8 @@ class LinearScan : public LinearScanInterface
11421142
return getIntervalForLocalVar(varDsc->lvVarIndex);
11431143
}
11441144

1145-
RegRecord* getRegisterRecord(regNumber regNum);
1145+
RegRecord* getRegisterRecord(regNumber regNum);
1146+
SingleTypeRegSet getAvailableGPRsForType(SingleTypeRegSet candidates, var_types regType);
11461147

11471148
RefPosition* newRefPositionRaw(LsraLocation nodeLocation, GenTree* treeNode, RefType refType);
11481149

0 commit comments

Comments
 (0)