Skip to content

Commit 4c3d41f

Browse files
committed
Improve clamped subtract for localloc
1 parent c993ba2 commit 4c3d41f

File tree

1 file changed

+17
-29
lines changed

1 file changed

+17
-29
lines changed

src/coreclr/jit/codegenriscv64.cpp

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,40 +1560,27 @@ void CodeGen::genLclHeap(GenTree* tree)
15601560
// case SP is on the last byte of the guard page. Thus you must
15611561
// touch SP-0 first not SP-0x1000.
15621562
//
1563-
//
15641563
// Note that we go through a few hoops so that SP never points to
15651564
// illegal pages at any time during the tickling process.
1566-
//
1567-
// sltu RA, SP, regCnt
1568-
// sub regCnt, SP, regCnt // regCnt now holds ultimate SP
1569-
// beq RA, REG_R0, Skip
1570-
// addi regCnt, REG_R0, 0
1571-
//
1572-
// Skip:
1573-
// lui regPageSize, eeGetPageSize()>>12
1574-
// addi regTmp, SP, 0
1575-
// Loop:
1576-
// lw r0, 0(regTmp) // tickle the page - read from the page
1577-
// sub regTmp, regTmp, regPageSize
1578-
// bgeu regTmp, regCnt, Loop
1579-
//
1580-
// Done:
1581-
// addi SP, regCnt, 0
1582-
//
15831565

15841566
if (tempReg == REG_NA)
15851567
tempReg = internalRegisters.Extract(tree);
15861568

15871569
assert(regCnt != tempReg);
1588-
emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, tempReg, REG_SPBASE, regCnt);
1589-
1590-
// sub regCnt, SP, regCnt // regCnt now holds ultimate SP
1591-
emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, regCnt, REG_SPBASE, regCnt);
1592-
1593-
// Overflow, set regCnt to lowest possible value
1594-
emit->emitIns_R_R_I(INS_beq, EA_PTRSIZE, tempReg, REG_R0, 2 << 2);
1595-
emit->emitIns_R_R(INS_mov, EA_PTRSIZE, regCnt, REG_R0);
1596-
1570+
// regCnt now holds the number of bytes to localloc, after the sequence it will be set to the ultimate SP
1571+
if (compiler->compOpportunisticallyDependsOn(InstructionSet_Zbb))
1572+
{
1573+
emit->emitIns_R_R_R(INS_maxu, EA_PTRSIZE, tempReg, REG_SPBASE, regCnt); // temp = max(sp, cnt);
1574+
emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, regCnt, tempReg, regCnt); // cnt = temp - cnt;
1575+
}
1576+
else
1577+
{
1578+
emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, regCnt, REG_SPBASE, regCnt); // cnt = sp - cnt; // ultimate SP
1579+
// If the subtraction above overflowed (i.e. sp < ultimateSP), set regCnt to lowest possible value (i.e. 0)
1580+
emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, tempReg, REG_SPBASE, regCnt); // temp = overflow ? 1 : 0;
1581+
emit->emitIns_R_R_I(INS_addi, EA_PTRSIZE, tempReg, tempReg, -1); // temp = overflow ? 0 : full_mask;
1582+
emit->emitIns_R_R_R(INS_and, EA_PTRSIZE, regCnt, regCnt, tempReg); // cnt = overflow ? 0 : cnt;
1583+
}
15971584
regNumber rPageSize = internalRegisters.GetSingle(tree);
15981585

15991586
noway_assert(rPageSize != tempReg);
@@ -1638,8 +1625,9 @@ void CodeGen::genLclHeap(GenTree* tree)
16381625
}
16391626
else // stackAdjustment == 0
16401627
{
1641-
// Move the final value of SP to targetReg
1642-
emit->emitIns_R_R(INS_mov, EA_PTRSIZE, targetReg, REG_SPBASE);
1628+
// Move the final value of SP to targetReg (if necessary; targetReg may be same as regCnt which also holds SP)
1629+
regNumber spSrc = (regCnt == REG_NA) ? REG_SPBASE : regCnt;
1630+
emit->emitIns_Mov(EA_PTRSIZE, targetReg, spSrc, true);
16431631
}
16441632

16451633
BAILOUT:

0 commit comments

Comments
 (0)