Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NativeAOT/Apple] Emit prologs/epilogs compatible with compact unwinding #107617

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,7 @@ class CodeGen final : public CodeGenInterface
virtual bool IsSaveFpLrWithAllCalleeSavedRegisters() const;
bool genSaveFpLrWithAllCalleeSavedRegisters;
bool genForceFuncletFrameType5;
bool genReverseAndPairCalleeSavedRegisters;
#endif // TARGET_ARM64

//-------------------------------------------------------------------------
Expand Down
46 changes: 38 additions & 8 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -845,12 +845,19 @@ void CodeGen::genSaveCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta, i

for (int i = 0; i < regStack.Height(); ++i)
{
RegPair regPair = regStack.Bottom(i);
RegPair regPair = genReverseAndPairCalleeSavedRegisters ? regStack.Top(i) : regStack.Bottom(i);
if (regPair.reg2 != REG_NA)
{
// We can use a STP instruction.
genPrologSaveRegPair(regPair.reg1, regPair.reg2, spOffset, spDelta, regPair.useSaveNextPair, REG_IP0,
nullptr);
if (genReverseAndPairCalleeSavedRegisters)
{
genPrologSaveRegPair(regPair.reg2, regPair.reg1, spOffset, spDelta, false, REG_IP0, nullptr);
}
else
{
genPrologSaveRegPair(regPair.reg1, regPair.reg2, spOffset, spDelta, regPair.useSaveNextPair, REG_IP0,
nullptr);
}

spOffset += 2 * slotSize;
}
Expand Down Expand Up @@ -926,8 +933,9 @@ void CodeGen::genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowe

// Save integer registers at higher addresses than floating-point registers.

regMaskTP maskSaveRegsFrame = regsToSaveMask & (RBM_FP | RBM_LR);
regMaskTP maskSaveRegsFloat = regsToSaveMask & RBM_ALLFLOAT;
regMaskTP maskSaveRegsInt = regsToSaveMask & ~maskSaveRegsFloat;
regMaskTP maskSaveRegsInt = regsToSaveMask & ~maskSaveRegsFloat & ~maskSaveRegsFrame;

if (maskSaveRegsFloat != RBM_NONE)
{
Expand All @@ -939,6 +947,13 @@ void CodeGen::genSaveCalleeSavedRegistersHelp(regMaskTP regsToSaveMask, int lowe
if (maskSaveRegsInt != RBM_NONE)
{
genSaveCalleeSavedRegisterGroup(maskSaveRegsInt, spDelta, lowestCalleeSavedOffset);
spDelta = 0;
lowestCalleeSavedOffset += genCountBits(maskSaveRegsInt) * FPSAVE_REGSIZE_BYTES;
}

if (maskSaveRegsFrame != RBM_NONE)
{
genPrologSaveRegPair(REG_FP, REG_LR, lowestCalleeSavedOffset, spDelta, false, REG_IP0, nullptr);
// No need to update spDelta, lowestCalleeSavedOffset since they're not used after this.
}
}
Expand Down Expand Up @@ -970,13 +985,20 @@ void CodeGen::genRestoreCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta
stackDelta = spDelta;
}

RegPair regPair = regStack.Top(i);
RegPair regPair = genReverseAndPairCalleeSavedRegisters ? regStack.Bottom(i) : regStack.Top(i);
if (regPair.reg2 != REG_NA)
{
spOffset -= 2 * slotSize;

genEpilogRestoreRegPair(regPair.reg1, regPair.reg2, spOffset, stackDelta, regPair.useSaveNextPair, REG_IP1,
nullptr);
if (genReverseAndPairCalleeSavedRegisters)
{
genEpilogRestoreRegPair(regPair.reg2, regPair.reg1, spOffset, stackDelta, false, REG_IP1, nullptr);
}
else
{
genEpilogRestoreRegPair(regPair.reg1, regPair.reg2, spOffset, stackDelta, regPair.useSaveNextPair,
REG_IP1, nullptr);
}
}
else
{
Expand Down Expand Up @@ -1043,11 +1065,19 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in

// Save integer registers at higher addresses than floating-point registers.

regMaskTP maskRestoreRegsFrame = regsToRestoreMask & (RBM_FP | RBM_LR);
regMaskTP maskRestoreRegsFloat = regsToRestoreMask & RBM_ALLFLOAT;
regMaskTP maskRestoreRegsInt = regsToRestoreMask & ~maskRestoreRegsFloat;
regMaskTP maskRestoreRegsInt = regsToRestoreMask & ~maskRestoreRegsFloat & ~maskRestoreRegsFrame;

// Restore in the opposite order of saving.

if (maskRestoreRegsFrame != RBM_NONE)
{
int spFrameDelta = (maskRestoreRegsFloat != RBM_NONE || maskRestoreRegsInt != RBM_NONE) ? 0 : spDelta;
spOffset -= 2 * REGSIZE_BYTES;
genEpilogRestoreRegPair(REG_FP, REG_LR, spOffset, spFrameDelta, false, REG_IP1, nullptr);
}

if (maskRestoreRegsInt != RBM_NONE)
{
int spIntDelta = (maskRestoreRegsFloat != RBM_NONE) ? 0 : spDelta; // should we delay the SP adjustment?
Expand Down
24 changes: 24 additions & 0 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ CodeGen::CodeGen(Compiler* theCompiler)
#ifdef TARGET_ARM64
genSaveFpLrWithAllCalleeSavedRegisters = false;
genForceFuncletFrameType5 = false;
genReverseAndPairCalleeSavedRegisters = false;
#endif // TARGET_ARM64
}

Expand Down Expand Up @@ -4846,6 +4847,29 @@ void CodeGen::genFinalizeFrame()
}
#endif // TARGET_ARM

#ifdef TARGET_ARM64
if (compiler->IsTargetAbi(CORINFO_NATIVEAOT_ABI) && TargetOS::IsApplePlatform)
{
JITDUMP("Setting genReverseAndPairCalleeSavedRegisters = true");

genReverseAndPairCalleeSavedRegisters = true;

// Make sure we push the registers in pairs if possible. If we only allocate a contiguous
// block of registers this should add at most one integer and at most one floating point
// register to the list. The stack has to be 16-byte aligned, so in worst case it results
// in allocating 16 bytes more space on stack if odd number of integer and odd number of
// FP registers were occupied. Same number of instructions will be generated, just the
// STR instructions are replaced with STP (store pair).
regMaskTP maskModifiedRegs = regSet.rsGetModifiedRegsMask();
regMaskTP maskPairRegs = ((maskModifiedRegs & (RBM_V8 | RBM_V10 | RBM_V12 | RBM_V14)).getLow() << 1) |
((maskModifiedRegs & (RBM_R19 | RBM_R21 | RBM_R23 | RBM_R25 | RBM_R27)).getLow() << 1);
if (maskPairRegs != RBM_NONE)
{
regSet.rsSetRegsModified(maskPairRegs);
}
}
#endif

#ifdef DEBUG
if (verbose)
{
Expand Down
17 changes: 17 additions & 0 deletions src/coreclr/jit/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2807,6 +2807,23 @@ inline
{
*pBaseReg = REG_SPBASE;
}
#elif defined(TARGET_ARM64)
if (FPbased && !codeGen->isFramePointerRequired() && varOffset < 0 &&
lvaDoneFrameLayout == Compiler::FINAL_FRAME_LAYOUT && codeGen->IsSaveFpLrWithAllCalleeSavedRegisters())
{
int spVarOffset = varOffset + codeGen->genSPtoFPdelta();
FPbased = false;
varOffset = spVarOffset;
}
else
{
JITDUMP(
"skipping lvaFrameAddress opt skipped - compLocallocUsed: %s lvaDoneFrameLayout: %d saveFpLr: %s funCurrentFunc()->funKind: %d\n",
dspBool(compLocallocUsed), lvaDoneFrameLayout, dspBool(codeGen->IsSaveFpLrWithAllCalleeSavedRegisters()),
funCurrentFunc()->funKind);
}
JITDUMP("lvaFrameAddress %d FPbased: %s varOffset: %d\n", varNum, dspBool(FPbased), varOffset);
*pFPbased = FPbased;
#else
*pFPbased = FPbased;
#endif
Expand Down
20 changes: 17 additions & 3 deletions src/coreclr/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7869,6 +7869,8 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
{
emitAttr size = EA_SIZE(attr);
insFormat fmt = IF_NONE;
insOpts opt = INS_OPTS_NONE;
regNumber reg3 = REG_NA;
unsigned scale = 0;
bool isLdrStr = false;
bool isSimple = true;
Expand Down Expand Up @@ -7934,7 +7936,17 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
{
regNumber rsvdReg = codeGen->rsGetRsvdReg();
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
imm = 0;
if (encodingZRtoSP(reg2) == REG_SP)
{
fmt = IF_DR_3C; // add reg1,sp,rsvdReg
opt = INS_OPTS_LSL;
reg3 = rsvdReg;
}
else
{
fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
}
}
break;

Expand Down Expand Up @@ -8043,10 +8055,11 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va

id->idIns(ins);
id->idInsFmt(fmt);
id->idInsOpt(INS_OPTS_NONE);
id->idInsOpt(opt);

id->idReg1(reg1);
id->idReg2(reg2);
id->idReg3(reg3);
id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
id->idSetIsLclVar();

Expand Down Expand Up @@ -8085,7 +8098,6 @@ void emitter::emitIns_R_R_S_S(

// TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
reg3 = encodingSPtoZR(reg3);

bool useRegForAdr = true;
ssize_t imm = disp;
Expand Down Expand Up @@ -8117,6 +8129,8 @@ void emitter::emitIns_R_R_S_S(
imm = 0;
}

reg3 = encodingSPtoZR(reg3);

assert(fmt != IF_NONE);

instrDesc* id = emitNewInstrCns(attr1, imm);
Expand Down
Loading
Loading