Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit b23add0

Browse files
Merge pull request #10936 from BruceForstall/TempRegApi
Introduce API for codegen getting temp registers from gtRsvdRegs
2 parents 3d7c803 + 950b090 commit b23add0

14 files changed

+200
-294
lines changed

src/jit/codegenarm.cpp

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre
166166
if (targetType == TYP_FLOAT)
167167
{
168168
// Get a temp integer register
169-
regMaskTP tmpRegMask = tree->gtRsvdRegs;
170-
regNumber tmpReg = genRegNumFromMask(tmpRegMask);
171-
assert(tmpReg != REG_NA);
169+
regNumber tmpReg = tree->GetSingleTempReg();
172170

173171
float f = forceCastToFloat(constValue);
174172
genSetRegToIcon(tmpReg, *((int*)(&f)));
@@ -181,15 +179,8 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre
181179
unsigned* cv = (unsigned*)&constValue;
182180

183181
// Get two temp integer registers
184-
regMaskTP tmpRegsMask = tree->gtRsvdRegs;
185-
regMaskTP tmpRegMask = genFindHighestBit(tmpRegsMask); // set tmpRegMsk to a one-bit mask
186-
regNumber tmpReg1 = genRegNumFromMask(tmpRegMask);
187-
assert(tmpReg1 != REG_NA);
188-
189-
tmpRegsMask &= ~genRegMask(tmpReg1); // remove the bit for 'tmpReg1'
190-
tmpRegMask = genFindHighestBit(tmpRegsMask); // set tmpRegMsk to a one-bit mask
191-
regNumber tmpReg2 = genRegNumFromMask(tmpRegMask);
192-
assert(tmpReg2 != REG_NA);
182+
regNumber tmpReg1 = tree->ExtractTempReg();
183+
regNumber tmpReg2 = tree->GetSingleTempReg();
193184

194185
genSetRegToIcon(tmpReg1, cv[0]);
195186
genSetRegToIcon(tmpReg2, cv[1]);
@@ -1129,7 +1120,6 @@ void CodeGen::genLclHeap(GenTreePtr tree)
11291120
// Also it used as temporary register in code generation
11301121
// for storing allocation size
11311122
regNumber regCnt = tree->gtRegNum;
1132-
regMaskTP tmpRegsMask = tree->gtRsvdRegs;
11331123
regNumber pspSymReg = REG_NA;
11341124
var_types type = genActualType(size->gtType);
11351125
emitAttr easz = emitTypeSize(type);
@@ -1198,10 +1188,7 @@ void CodeGen::genLclHeap(GenTreePtr tree)
11981188
stackAdjustment += STACK_ALIGN;
11991189

12001190
// Save a copy of PSPSym
1201-
assert(genCountBits(tmpRegsMask) >= 1);
1202-
regMaskTP pspSymRegMask = genFindLowestBit(tmpRegsMask);
1203-
tmpRegsMask &= ~pspSymRegMask;
1204-
pspSymReg = genRegNumFromMask(pspSymRegMask);
1191+
pspSymReg = tree->ExtractTempReg();
12051192
getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, pspSymReg, compiler->lvaPSPSym, 0);
12061193
}
12071194
#endif
@@ -1266,12 +1253,7 @@ void CodeGen::genLclHeap(GenTreePtr tree)
12661253
// Since we have to zero out the allocated memory AND ensure that RSP is always valid
12671254
// by tickling the pages, we will just push 0's on the stack.
12681255

1269-
assert(tmpRegsMask != RBM_NONE);
1270-
assert(genCountBits(tmpRegsMask) >= 1);
1271-
1272-
regMaskTP regCntMask = genFindLowestBit(tmpRegsMask);
1273-
tmpRegsMask &= ~regCntMask;
1274-
regNumber regTmp = genRegNumFromMask(regCntMask);
1256+
regNumber regTmp = tree->ExtractTempReg();
12751257
instGen_Set_Reg_To_Zero(EA_PTRSIZE, regTmp);
12761258

12771259
// Loop:
@@ -1323,9 +1305,7 @@ void CodeGen::genLclHeap(GenTreePtr tree)
13231305
//
13241306

13251307
// Setup the regTmp
1326-
assert(tmpRegsMask != RBM_NONE);
1327-
assert(genCountBits(tmpRegsMask) == 1);
1328-
regNumber regTmp = genRegNumFromMask(tmpRegsMask);
1308+
regNumber regTmp = tree->ExtractTempReg();
13291309

13301310
BasicBlock* loop = genCreateTempLabel();
13311311
BasicBlock* done = genCreateTempLabel();

src/jit/codegenarm64.cpp

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,9 +1441,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre
14411441
else
14421442
{
14431443
// Get a temp integer register to compute long address.
1444-
regMaskTP addrRegMask = tree->gtRsvdRegs;
1445-
regNumber addrReg = genRegNumFromMask(addrRegMask);
1446-
noway_assert(addrReg != REG_NA);
1444+
regNumber addrReg = tree->GetSingleTempReg();
14471445

14481446
// We must load the FP constant from the constant pool
14491447
// Emit a data section constant for the float or double constant.
@@ -2854,7 +2852,6 @@ void CodeGen::genLclHeap(GenTreePtr tree)
28542852
noway_assert((genActualType(size->gtType) == TYP_INT) || (genActualType(size->gtType) == TYP_I_IMPL));
28552853

28562854
regNumber targetReg = tree->gtRegNum;
2857-
regMaskTP tmpRegsMask = tree->gtRsvdRegs;
28582855
regNumber regCnt = REG_NA;
28592856
regNumber pspSymReg = REG_NA;
28602857
var_types type = genActualType(size->gtType);
@@ -2923,17 +2920,16 @@ void CodeGen::genLclHeap(GenTreePtr tree)
29232920
// since we don't need any internal registers.
29242921
if (!hasPspSym && compiler->info.compInitMem)
29252922
{
2926-
assert(genCountBits(tmpRegsMask) == 0);
2923+
assert(tree->AvailableTempRegCount() == 0);
29272924
regCnt = targetReg;
29282925
}
29292926
else
29302927
{
2931-
assert(genCountBits(tmpRegsMask) >= 1);
2932-
regMaskTP regCntMask = genFindLowestBit(tmpRegsMask);
2933-
tmpRegsMask &= ~regCntMask;
2934-
regCnt = genRegNumFromMask(regCntMask);
2928+
regCnt = tree->ExtractTempReg();
29352929
if (regCnt != targetReg)
2930+
{
29362931
inst_RV_RV(INS_mov, regCnt, targetReg, size->TypeGet());
2932+
}
29372933
}
29382934

29392935
// Align to STACK_ALIGN
@@ -2950,10 +2946,7 @@ void CodeGen::genLclHeap(GenTreePtr tree)
29502946
stackAdjustment += STACK_ALIGN;
29512947

29522948
// Save a copy of PSPSym
2953-
assert(genCountBits(tmpRegsMask) >= 1);
2954-
regMaskTP pspSymRegMask = genFindLowestBit(tmpRegsMask);
2955-
tmpRegsMask &= ~pspSymRegMask;
2956-
pspSymReg = genRegNumFromMask(pspSymRegMask);
2949+
pspSymReg = tree->ExtractTempReg();
29572950
getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, pspSymReg, compiler->lvaPSPSym, 0);
29582951
}
29592952
#endif
@@ -3021,15 +3014,12 @@ void CodeGen::genLclHeap(GenTreePtr tree)
30213014
assert(regCnt == REG_NA);
30223015
if (!hasPspSym && compiler->info.compInitMem)
30233016
{
3024-
assert(genCountBits(tmpRegsMask) == 0);
3017+
assert(tree->AvailableTempRegCount() == 0);
30253018
regCnt = targetReg;
30263019
}
30273020
else
30283021
{
3029-
assert(genCountBits(tmpRegsMask) >= 1);
3030-
regMaskTP regCntMask = genFindLowestBit(tmpRegsMask);
3031-
tmpRegsMask &= ~regCntMask;
3032-
regCnt = genRegNumFromMask(regCntMask);
3022+
regCnt = tree->ExtractTempReg();
30333023
}
30343024
genSetRegToIcon(regCnt, amount, ((int)amount == amount) ? TYP_INT : TYP_LONG);
30353025
}
@@ -3094,9 +3084,7 @@ void CodeGen::genLclHeap(GenTreePtr tree)
30943084
//
30953085

30963086
// Setup the regTmp
3097-
assert(tmpRegsMask != RBM_NONE);
3098-
assert(genCountBits(tmpRegsMask) == 1);
3099-
regNumber regTmp = genRegNumFromMask(tmpRegsMask);
3087+
regNumber regTmp = tree->GetSingleTempReg();
31003088

31013089
BasicBlock* loop = genCreateTempLabel();
31023090
BasicBlock* done = genCreateTempLabel();
@@ -3391,13 +3379,11 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode)
33913379
unsigned offset = 0;
33923380

33933381
// Grab the integer temp register to emit the loads and stores.
3394-
regMaskTP tmpMask = genFindLowestBit(cpBlkNode->gtRsvdRegs & RBM_ALLINT);
3395-
regNumber tmpReg = genRegNumFromMask(tmpMask);
3382+
regNumber tmpReg = cpBlkNode->ExtractTempReg(RBM_ALLINT);
33963383

33973384
if (size >= 2 * REGSIZE_BYTES)
33983385
{
3399-
regMaskTP tmp2Mask = cpBlkNode->gtRsvdRegs & RBM_ALLINT & ~tmpMask;
3400-
regNumber tmp2Reg = genRegNumFromMask(tmp2Mask);
3386+
regNumber tmp2Reg = cpBlkNode->ExtractTempReg(RBM_ALLINT);
34013387

34023388
size_t slots = size / (2 * REGSIZE_BYTES);
34033389

@@ -3498,13 +3484,8 @@ void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode)
34983484
gcInfo.gcMarkRegPtrVal(REG_WRITE_BARRIER_DST_BYREF, dstAddr->TypeGet());
34993485

35003486
// Temp register used to perform the sequence of loads and stores.
3501-
regNumber tmpReg = genRegNumFromMask(cpObjNode->gtRsvdRegs);
3502-
3503-
#ifdef DEBUG
3504-
assert(cpObjNode->gtRsvdRegs != RBM_NONE);
3505-
assert(genCountBits(cpObjNode->gtRsvdRegs) == 1);
3487+
regNumber tmpReg = cpObjNode->GetSingleTempReg();
35063488
assert(genIsValidIntReg(tmpReg));
3507-
#endif // DEBUG
35083489

35093490
unsigned slots = cpObjNode->gtSlots;
35103491
emitter* emit = getEmitter();
@@ -3571,7 +3552,7 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode)
35713552
regNumber idxReg = treeNode->gtOp.gtOp1->gtRegNum;
35723553
regNumber baseReg = treeNode->gtOp.gtOp2->gtRegNum;
35733554

3574-
regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs);
3555+
regNumber tmpReg = treeNode->GetSingleTempReg();
35753556

35763557
// load the ip-relative offset (which is relative to start of fgFirstBB)
35773558
getEmitter()->emitIns_R_R_R(INS_ldr, EA_4BYTE, baseReg, baseReg, idxReg, INS_OPTS_LSL);
@@ -4022,9 +4003,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
40224003

40234004
if (offset != 0)
40244005
{
4025-
regMaskTP tmpRegMask = lea->gtRsvdRegs;
4026-
regNumber tmpReg = genRegNumFromMask(tmpRegMask);
4027-
noway_assert(tmpReg != REG_NA);
4006+
regNumber tmpReg = lea->GetSingleTempReg();
40284007

40294008
if (emitter::emitIns_valid_imm_for_add(offset, EA_8BYTE))
40304009
{
@@ -4041,7 +4020,6 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
40414020

40424021
// Then compute target reg from [tmpReg + offset]
40434022
emit->emitIns_R_R_I(INS_add, size, lea->gtRegNum, tmpReg, offset);
4044-
;
40454023
}
40464024
else // large offset
40474025
{
@@ -4091,9 +4069,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
40914069
else
40924070
{
40934071
// We require a tmpReg to hold the offset
4094-
regMaskTP tmpRegMask = lea->gtRsvdRegs;
4095-
regNumber tmpReg = genRegNumFromMask(tmpRegMask);
4096-
noway_assert(tmpReg != REG_NA);
4072+
regNumber tmpReg = lea->GetSingleTempReg();
40974073

40984074
// First load tmpReg with the large offset constant
40994075
instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
@@ -4484,9 +4460,8 @@ void CodeGen::genCkfinite(GenTreePtr treeNode)
44844460
emitter* emit = getEmitter();
44854461

44864462
// Extract exponent into a register.
4487-
regNumber intReg = genRegNumFromMask(treeNode->gtRsvdRegs);
4463+
regNumber intReg = treeNode->GetSingleTempReg();
44884464
regNumber fpReg = genConsumeReg(op1);
4489-
assert(intReg != REG_NA);
44904465

44914466
emit->emitIns_R_R(ins_Copy(targetType), emitTypeSize(treeNode), intReg, fpReg);
44924467
emit->emitIns_R_R_I(INS_lsr, emitTypeSize(targetType), intReg, intReg, shiftAmount);

src/jit/codegenarmarch.cpp

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,10 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
212212
// We will copy this struct to the stack, possibly using a ldp instruction
213213
// Setup loReg and hiReg from the internal registers that we reserved in lower.
214214
//
215-
regNumber loReg = REG_NA;
216-
regNumber hiReg = REG_NA;
215+
regNumber loReg = treeNode->ExtractTempReg();
216+
regNumber hiReg = treeNode->GetSingleTempReg();
217217
regNumber addrReg = REG_NA;
218218

219-
// In lowerArm64/TreeNodeInfoInitPutArgStk we have reserved two internal integer registers
220-
genGetRegPairFromMask(treeNode->gtRsvdRegs, &loReg, &hiReg);
221-
222219
GenTreeLclVarCommon* varNode = nullptr;
223220
GenTreePtr addrNode = nullptr;
224221

@@ -709,15 +706,19 @@ void CodeGen::genCodeForArrIndex(GenTreeArrIndex* arrIndex)
709706
regNumber tgtReg = arrIndex->gtRegNum;
710707
noway_assert(tgtReg != REG_NA);
711708

712-
// We will use a temp register to load the lower bound and dimension size values
709+
// We will use a temp register to load the lower bound and dimension size values.
713710
//
714-
regMaskTP tmpRegsMask = arrIndex->gtRsvdRegs; // there will be two bits set
715-
tmpRegsMask &= ~genRegMask(tgtReg); // remove the bit for 'tgtReg' from 'tmpRegsMask'
716-
717-
regMaskTP tmpRegMask = genFindLowestBit(tmpRegsMask); // set tmpRegMsk to a one-bit mask
718-
regNumber tmpReg = genRegNumFromMask(tmpRegMask); // set tmpReg from that mask
719-
noway_assert(tmpReg != REG_NA);
720-
711+
// This should be simply:
712+
// regNumber tmpReg = arrIndex->GetSingleTempReg();
713+
//
714+
// However, since LSRA might give us an internal temp register that is the same as the dst
715+
// register, and the codegen here reuses the temp register after a definition of the target
716+
// register, we requested two internal registers. If one is the target register, we simply
717+
// use the other one. We can use ExtractTempReg() since it only asserts that there is at
718+
// least one available temporary register (not that there is exactly one, for instance).
719+
// Here, masking out tgtReg, there will be either 1 or 2.
720+
721+
regNumber tmpReg = arrIndex->ExtractTempReg(~genRegMask(tgtReg));
721722
assert(tgtReg != tmpReg);
722723

723724
unsigned dim = arrIndex->gtCurrDim;
@@ -773,9 +774,7 @@ void CodeGen::genCodeForArrOffset(GenTreeArrOffs* arrOffset)
773774
noway_assert(indexReg != REG_NA);
774775
noway_assert(arrReg != REG_NA);
775776

776-
regMaskTP tmpRegMask = arrOffset->gtRsvdRegs;
777-
regNumber tmpReg = genRegNumFromMask(tmpRegMask);
778-
noway_assert(tmpReg != REG_NA);
777+
regNumber tmpReg = arrOffset->GetSingleTempReg();
779778

780779
unsigned dim = arrOffset->gtCurrDim;
781780
unsigned rank = arrOffset->gtArrRank;
@@ -1073,12 +1072,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call)
10731072
const regNumber regThis = genGetThisArgReg(call);
10741073

10751074
#if defined(_TARGET_ARM_)
1076-
regMaskTP tempMask = genFindLowestBit(call->gtRsvdRegs);
1077-
const regNumber tmpReg = genRegNumFromMask(tempMask);
1078-
if (genCountBits(call->gtRsvdRegs) > 1)
1079-
{
1080-
call->gtRsvdRegs &= ~tempMask;
1081-
}
1075+
const regNumber tmpReg = call->ExtractTempReg();
10821076
getEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, tmpReg, regThis, 0);
10831077
#elif defined(_TARGET_ARM64_)
10841078
getEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, REG_ZR, regThis, 0);
@@ -1239,7 +1233,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call)
12391233
#ifdef _TARGET_ARM_
12401234
if (!arm_Valid_Imm_For_BL((ssize_t)addr))
12411235
{
1242-
regNumber tmpReg = genRegNumFromMask(call->gtRsvdRegs);
1236+
regNumber tmpReg = call->GetSingleTempReg();
12431237
instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, tmpReg, (ssize_t)addr);
12441238
genEmitCall(emitter::EC_INDIR_R, methHnd, INDEBUG_LDISASM_COMMA(sigInfo) NULL, retSize, ilOffset, tmpReg);
12451239
}
@@ -1388,7 +1382,7 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
13881382
regNumber sourceReg = castOp->gtRegNum;
13891383

13901384
// For Long to Int conversion we will have a reserved integer register to hold the immediate mask
1391-
regNumber tmpReg = (treeNode->gtRsvdRegs == RBM_NONE) ? REG_NA : genRegNumFromMask(treeNode->gtRsvdRegs);
1385+
regNumber tmpReg = (treeNode->AvailableTempRegCount() == 0) ? REG_NA : treeNode->GetSingleTempReg();
13921386

13931387
assert(genIsValidIntReg(targetReg));
13941388
assert(genIsValidIntReg(sourceReg));

src/jit/codegencommon.cpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -557,30 +557,6 @@ regMaskTP CodeGenInterface::genGetRegMask(GenTreePtr tree)
557557
return regMask;
558558
}
559559

560-
//------------------------------------------------------------------------
561-
// getRegistersFromMask: Given a register mask return the two registers
562-
// specified by the mask.
563-
//
564-
// Arguments:
565-
// regPairMask: a register mask that has exactly two bits set
566-
// Return values:
567-
// pLoReg: the address of where to write the first register
568-
// pHiReg: the address of where to write the second register
569-
//
570-
void CodeGenInterface::genGetRegPairFromMask(regMaskTP regPairMask, regNumber* pLoReg, regNumber* pHiReg)
571-
{
572-
assert(genCountBits(regPairMask) == 2);
573-
574-
regMaskTP loMask = genFindLowestBit(regPairMask); // set loMask to a one-bit mask
575-
regMaskTP hiMask = regPairMask - loMask; // set hiMask to the other bit that was in tmpRegMask
576-
577-
regNumber loReg = genRegNumFromMask(loMask); // set loReg from loMask
578-
regNumber hiReg = genRegNumFromMask(hiMask); // set hiReg from hiMask
579-
580-
*pLoReg = loReg;
581-
*pHiReg = hiReg;
582-
}
583-
584560
// The given lclVar is either going live (being born) or dying.
585561
// It might be both going live and dying (that is, it is a dead store) under MinOpts.
586562
// Update regSet.rsMaskVars accordingly.

src/jit/codegeninterface.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ class CodeGenInterface
149149
regMaskTP genLiveMask(VARSET_VALARG_TP liveSet);
150150
#endif
151151

152-
void genGetRegPairFromMask(regMaskTP regPairMask, regNumber* pLoReg, regNumber* pHiReg);
153-
154152
// The following property indicates whether the current method sets up
155153
// an explicit stack frame or not.
156154
private:

0 commit comments

Comments
 (0)