@@ -1560,40 +1560,27 @@ void CodeGen::genLclHeap(GenTree* tree)
1560
1560
// case SP is on the last byte of the guard page. Thus you must
1561
1561
// touch SP-0 first not SP-0x1000.
1562
1562
//
1563
- //
1564
1563
// Note that we go through a few hoops so that SP never points to
1565
1564
// 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
- //
1583
1565
1584
1566
if (tempReg == REG_NA)
1585
1567
tempReg = internalRegisters.Extract (tree);
1586
1568
1587
1569
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
+ }
1597
1584
regNumber rPageSize = internalRegisters.GetSingle (tree);
1598
1585
1599
1586
noway_assert (rPageSize != tempReg);
@@ -1638,8 +1625,9 @@ void CodeGen::genLclHeap(GenTree* tree)
1638
1625
}
1639
1626
else // stackAdjustment == 0
1640
1627
{
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 );
1643
1631
}
1644
1632
1645
1633
BAILOUT:
0 commit comments