Skip to content

Commit 63e07f5

Browse files
Fix LSRA handling of arm32 double registers and spilling (#94947)
* Fix LSRA handling of arm32 double registers and spilling If LSRA uses `regsBusyUntilKill` to eliminate registers from consideration for spilling, for spilling arm32 double type registers, it needs to remove the even registers from the candidates. For example, if `regsBusyUntilKill` contains `f3`, candidates also needs to remove `f2`, since double register candidates only contains the even registers to represent to pair of registers for an arm32 double. * Updated comment to be more descriptive. * Add new RBM_ALLDOUBLE_HIGH mask for referring to high odd register part of ARM double registers even/odd pairs. * Fix disasm of arm32 double registers d10-d15
1 parent 30ef449 commit 63e07f5

File tree

6 files changed

+25
-6
lines changed

6 files changed

+25
-6
lines changed

src/coreclr/jit/codegencommon.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4025,7 +4025,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
40254025
// Don't process the double until both halves of the destination are clear.
40264026
if (genActualType(destMemType) == TYP_DOUBLE)
40274027
{
4028-
assert((destMask & RBM_DBL_REGS) != 0);
4028+
assert((destMask & RBM_ALLDOUBLE) != 0);
40294029
destMask |= genRegMask(REG_NEXT(destRegNum));
40304030
}
40314031
#endif

src/coreclr/jit/compiler.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3290,7 +3290,7 @@ __forceinline regMaskTP genMapArgNumToRegMask(unsigned argNum, var_types type)
32903290
#ifdef TARGET_ARM
32913291
if (type == TYP_DOUBLE)
32923292
{
3293-
assert((result & RBM_DBL_REGS) != 0);
3293+
assert((result & RBM_ALLDOUBLE) != 0);
32943294
result |= (result << 1);
32953295
}
32963296
#endif

src/coreclr/jit/emitarm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6934,7 +6934,7 @@ void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
69346934
else
69356935
{
69366936
assert(regIndex < 100);
6937-
printf("d%c%c", (regIndex / 10), (regIndex % 10));
6937+
printf("d%c%c", (regIndex / 10) + '0', (regIndex % 10) + '0');
69386938
}
69396939
}
69406940
else

src/coreclr/jit/lsra.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7946,8 +7946,9 @@ regNumber LinearScan::getTempRegForResolution(BasicBlock* fromBlock,
79467946
#ifdef TARGET_ARM
79477947
if (type == TYP_DOUBLE)
79487948
{
7949-
// Exclude any doubles for which the odd half isn't in freeRegs.
7950-
freeRegs = freeRegs & ((freeRegs << 1) & RBM_ALLDOUBLE);
7949+
// Exclude any doubles for which the odd half isn't in freeRegs,
7950+
// and restrict down to just the even part of the even/odd pair.
7951+
freeRegs &= (freeRegs & RBM_ALLDOUBLE_HIGH) >> 1;
79517952
}
79527953
#endif
79537954

@@ -12457,6 +12458,18 @@ regMaskTP LinearScan::RegisterSelection::select(Interval* currentInterval,
1245712458
regMaskTP busyRegs = linearScan->regsBusyUntilKill | linearScan->regsInUseThisLocation;
1245812459
candidates &= ~busyRegs;
1245912460

12461+
#ifdef TARGET_ARM
12462+
// For TYP_DOUBLE on ARM, we can only use an even floating-point register for which the odd half
12463+
// is also available. Thus, for every busyReg that is an odd floating-point register, we need to
12464+
// remove from candidates the corresponding even floating-point register. For example, if busyRegs
12465+
// contains `f3`, we need to remove `f2` from the candidates for a double register interval. The
12466+
// clause below creates a mask to do this.
12467+
if (currentInterval->registerType == TYP_DOUBLE)
12468+
{
12469+
candidates &= ~((busyRegs & RBM_ALLDOUBLE_HIGH) >> 1);
12470+
}
12471+
#endif // TARGET_ARM
12472+
1246012473
#ifdef DEBUG
1246112474
inUseOrBusyRegsMask |= busyRegs;
1246212475
#endif

src/coreclr/jit/targetarm.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ const regNumber fltArgRegs [] = {REG_F0, REG_F1, REG_F2, REG_F3, REG_F4, REG_F5,
2424
const regMaskTP fltArgMasks[] = {RBM_F0, RBM_F1, RBM_F2, RBM_F3, RBM_F4, RBM_F5, RBM_F6, RBM_F7, RBM_F8, RBM_F9, RBM_F10, RBM_F11, RBM_F12, RBM_F13, RBM_F14, RBM_F15 };
2525
// clang-format on
2626

27+
static_assert_no_msg(RBM_ALLDOUBLE == (RBM_ALLDOUBLE_HIGH >> 1));
28+
2729
#endif // TARGET_ARM

src/coreclr/jit/targetarm.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@
7171
#define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH)
7272
#define RBM_ALLDOUBLE (RBM_F0|RBM_F2|RBM_F4|RBM_F6|RBM_F8|RBM_F10|RBM_F12|RBM_F14|RBM_F16|RBM_F18|RBM_F20|RBM_F22|RBM_F24|RBM_F26|RBM_F28|RBM_F30)
7373

74+
// Double registers on ARM take two registers in odd/even pairs, e.g. f0 and f1, f2 and f3, etc. Mostly, we refer
75+
// to double registers by their low, even, part. Sometimes we need to know that the high, odd, part is unused in
76+
// a bitmask, say, hence we have this definition.
77+
#define RBM_ALLDOUBLE_HIGH (RBM_F1|RBM_F3|RBM_F5|RBM_F7|RBM_F9|RBM_F11|RBM_F13|RBM_F15|RBM_F17|RBM_F19|RBM_F21|RBM_F23|RBM_F25|RBM_F27|RBM_F29|RBM_F31)
78+
7479
#define REG_VAR_ORDER REG_R3,REG_R2,REG_R1,REG_R0,REG_R4,REG_LR,REG_R12,\
7580
REG_R5,REG_R6,REG_R7,REG_R8,REG_R9,REG_R10
7681

@@ -281,7 +286,6 @@
281286

282287
#define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3)
283288
#define RBM_FLTARG_REGS (RBM_F0|RBM_F1|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7|RBM_F8|RBM_F9|RBM_F10|RBM_F11|RBM_F12|RBM_F13|RBM_F14|RBM_F15)
284-
#define RBM_DBL_REGS RBM_ALLDOUBLE
285289

286290
extern const regNumber fltArgRegs [MAX_FLOAT_REG_ARG];
287291
extern const regMaskTP fltArgMasks[MAX_FLOAT_REG_ARG];

0 commit comments

Comments
 (0)