@@ -5639,9 +5639,7 @@ void Compiler::lvaFixVirtualFrameOffsets()
56395639#endif
56405640
56415641 // The delta to be added to virtual offset to adjust it relative to frame pointer or SP
5642- int delta = 0 ;
5643- int frameLocalsDelta = 0 ;
5644- int frameBoundary = 0 ;
5642+ int delta = 0 ;
56455643
56465644#ifdef TARGET_XARCH
56475645 delta += REGSIZE_BYTES; // pushed PC (return address) for x86/x64
@@ -5666,25 +5664,7 @@ void Compiler::lvaFixVirtualFrameOffsets()
56665664 // We set FP to be after LR, FP
56675665 delta += 2 * REGSIZE_BYTES;
56685666 }
5669- #elif defined(TARGET_ARM64)
5670- else
5671- {
5672- // FP is used.
5673- delta += codeGen->genTotalFrameSize () - codeGen->genSPtoFPdelta ();
5674-
5675- // If we placed FP/LR at the bottom of the frame we need to shift all the variables
5676- // on the new frame to account for it. See lvaAssignVirtualFrameOffsetsToLocals.
5677- if (!codeGen->IsSaveFpLrWithAllCalleeSavedRegisters ())
5678- {
5679- // We set FP to be after LR, FP
5680- frameLocalsDelta = 2 * REGSIZE_BYTES;
5681- frameBoundary = opts.IsOSR () ? -info.compPatchpointInfo ->TotalFrameSize () : 0 ;
5682- if (info.compIsVarArgs )
5683- frameBoundary -= MAX_REG_ARG * REGSIZE_BYTES;
5684- }
5685- JITDUMP (" --- delta bump %d for FP frame, %d inside frame for FP/LR relocation\n " , delta, frameLocalsDelta);
5686- }
5687- #elif defined(TARGET_AMD64)
5667+ #elif defined(TARGET_AMD64) || defined(TARGET_ARM64)
56885668 else
56895669 {
56905670 // FP is used.
@@ -5752,7 +5732,7 @@ void Compiler::lvaFixVirtualFrameOffsets()
57525732
57535733#if defined(TARGET_X86)
57545734 // On x86, we set the stack offset for a promoted field
5755- // to match a struct parameter in lvaAssignFrameOffsetsToPromotedStructs .
5735+ // to match a struct parameter in lvAssignFrameOffsetsToPromotedStructs .
57565736 if ((!varDsc->lvIsParam || parentvarDsc->lvIsParam ) && promotionType == PROMOTION_TYPE_DEPENDENT)
57575737#else
57585738 if (!varDsc->lvIsParam && promotionType == PROMOTION_TYPE_DEPENDENT)
@@ -5772,23 +5752,15 @@ void Compiler::lvaFixVirtualFrameOffsets()
57725752
57735753 if (doAssignStkOffs)
57745754 {
5775- int localDelta = delta;
5776-
5777- if (frameLocalsDelta != 0 && varDsc->GetStackOffset () < frameBoundary)
5778- {
5779- localDelta += frameLocalsDelta;
5780- }
5781-
5782- JITDUMP (" -- V%02u was %d, now %d\n " , lclNum, varDsc->GetStackOffset (),
5783- varDsc->GetStackOffset () + localDelta);
5784- varDsc->SetStackOffset (varDsc->GetStackOffset () + localDelta);
5755+ JITDUMP (" -- V%02u was %d, now %d\n " , lclNum, varDsc->GetStackOffset (), varDsc->GetStackOffset () + delta);
5756+ varDsc->SetStackOffset (varDsc->GetStackOffset () + delta);
57855757
57865758#if DOUBLE_ALIGN
57875759 if (genDoubleAlign () && !codeGen->isFramePointerUsed ())
57885760 {
57895761 if (varDsc->lvFramePointerBased )
57905762 {
5791- varDsc->SetStackOffset (varDsc->GetStackOffset () - localDelta );
5763+ varDsc->SetStackOffset (varDsc->GetStackOffset () - delta );
57925764
57935765 // We need to re-adjust the offsets of the parameters so they are EBP
57945766 // relative rather than stack/frame pointer relative
@@ -5810,13 +5782,9 @@ void Compiler::lvaFixVirtualFrameOffsets()
58105782 assert (codeGen->regSet .tmpAllFree ());
58115783 for (TempDsc* temp = codeGen->regSet .tmpListBeg (); temp != nullptr ; temp = codeGen->regSet .tmpListNxt (temp))
58125784 {
5813- temp->tdAdjustTempOffs (delta + frameLocalsDelta );
5785+ temp->tdAdjustTempOffs (delta);
58145786 }
58155787
5816- if (lvaCachedGenericContextArgOffs < frameBoundary)
5817- {
5818- lvaCachedGenericContextArgOffs += frameLocalsDelta;
5819- }
58205788 lvaCachedGenericContextArgOffs += delta;
58215789
58225790#if FEATURE_FIXED_OUT_ARGS
@@ -6072,6 +6040,30 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
60726040 codeGen->setFramePointerUsed (codeGen->isFramePointerRequired ());
60736041 }
60746042
6043+ #ifdef TARGET_ARM64
6044+ // Decide where to save FP and LR registers. We store FP/LR registers at the bottom of the frame if there is
6045+ // a frame pointer used (so we get positive offsets from the frame pointer to access locals), but not if we
6046+ // need a GS cookie AND localloc is used, since we need the GS cookie to protect the saved return value,
6047+ // and also the saved frame pointer. See CodeGen::genPushCalleeSavedRegisters() for more details about the
6048+ // frame types. Since saving FP/LR at high addresses is a relatively rare case, force using it during stress.
6049+ // (It should be legal to use these frame types for every frame).
6050+
6051+ if (opts.compJitSaveFpLrWithCalleeSavedRegisters == 0 )
6052+ {
6053+ // Default configuration
6054+ codeGen->SetSaveFpLrWithAllCalleeSavedRegisters ((getNeedsGSSecurityCookie () && compLocallocUsed) ||
6055+ opts.compDbgEnC || compStressCompile (STRESS_GENERIC_VARN, 20 ));
6056+ }
6057+ else if (opts.compJitSaveFpLrWithCalleeSavedRegisters == 1 )
6058+ {
6059+ codeGen->SetSaveFpLrWithAllCalleeSavedRegisters (false ); // Disable using new frames
6060+ }
6061+ else if ((opts.compJitSaveFpLrWithCalleeSavedRegisters == 2 ) || (opts.compJitSaveFpLrWithCalleeSavedRegisters == 3 ))
6062+ {
6063+ codeGen->SetSaveFpLrWithAllCalleeSavedRegisters (true ); // Force using new frames
6064+ }
6065+ #endif // TARGET_ARM64
6066+
60756067#ifdef TARGET_XARCH
60766068 // On x86/amd64, the return address has already been pushed by the call instruction in the caller.
60776069 stkOffs -= TARGET_POINTER_SIZE; // return address;
@@ -6120,13 +6112,9 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
61206112#endif // !TARGET_ARM
61216113
61226114#ifdef TARGET_ARM64
6123- // If the frame pointer is used, then we'll save FP/LR either at the bottom of the stack
6124- // or at the top of the stack depending on frame type. We make the decision after assigning
6125- // the variables on the frame and then fix up the offsets in lvaFixVirtualFrameOffsets.
6126- // For now, we proceed as if FP/LR were saved with the callee registers. If we later
6127- // decide to move the FP/LR to the bottom of the frame it shifts all the assigned
6128- // variables and temporaries by 16 bytes. The largest alignment we currently make is 16
6129- // bytes for SIMD.
6115+ // If the frame pointer is used, then we'll save FP/LR at the bottom of the stack.
6116+ // Otherwise, we won't store FP, and we'll store LR at the top, with the other callee-save
6117+ // registers (if any).
61306118
61316119 int initialStkOffs = 0 ;
61326120 if (info.compIsVarArgs )
@@ -6137,7 +6125,17 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
61376125 stkOffs -= initialStkOffs;
61386126 }
61396127
6140- stkOffs -= compCalleeRegsPushed * REGSIZE_BYTES;
6128+ if (codeGen->IsSaveFpLrWithAllCalleeSavedRegisters () || !isFramePointerUsed ()) // Note that currently we always have
6129+ // a frame pointer
6130+ {
6131+ stkOffs -= compCalleeRegsPushed * REGSIZE_BYTES;
6132+ }
6133+ else
6134+ {
6135+ // Subtract off FP and LR.
6136+ assert (compCalleeRegsPushed >= 2 );
6137+ stkOffs -= (compCalleeRegsPushed - 2 ) * REGSIZE_BYTES;
6138+ }
61416139
61426140#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
61436141
@@ -6807,6 +6805,15 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
68076805 }
68086806#endif // TARGET_AMD64
68096807
6808+ #ifdef TARGET_ARM64
6809+ if (!codeGen->IsSaveFpLrWithAllCalleeSavedRegisters () && isFramePointerUsed ()) // Note that currently we always have
6810+ // a frame pointer
6811+ {
6812+ // Create space for saving FP and LR.
6813+ stkOffs -= 2 * REGSIZE_BYTES;
6814+ }
6815+ #endif // TARGET_ARM64
6816+
68106817#if FEATURE_FIXED_OUT_ARGS
68116818 if (lvaOutgoingArgSpaceSize > 0 )
68126819 {
@@ -6844,44 +6851,6 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
68446851
68456852 noway_assert (compLclFrameSize + originalFrameSize ==
68466853 (unsigned )-(stkOffs + (pushedCount * (int )TARGET_POINTER_SIZE)));
6847-
6848- #ifdef TARGET_ARM64
6849- // Decide where to save FP and LR registers. We store FP/LR registers at the bottom of the frame if there is
6850- // a frame pointer used (so we get positive offsets from the frame pointer to access locals), but not if we
6851- // need a GS cookie AND localloc is used, since we need the GS cookie to protect the saved return value,
6852- // and also the saved frame pointer. See CodeGen::genPushCalleeSavedRegisters() for more details about the
6853- // frame types. Since saving FP/LR at high addresses is a relatively rare case, force using it during stress.
6854- // (It should be legal to use these frame types for every frame).
6855- //
6856- // For Apple NativeAOT ABI we try to save the FP/LR registers on top to get canonical frame layout that can
6857- // be represented with compact unwinding information. In order to maintain code quality we only do it when
6858- // we can use SP-based addressing (!isFramePointerRequired) through lvaFrameAddress optimization, or if the
6859- // whole frame is small enough that the negative FP-based addressing can address the whole frame.
6860-
6861- if (opts.compJitSaveFpLrWithCalleeSavedRegisters == 0 )
6862- {
6863- if (IsTargetAbi (CORINFO_NATIVEAOT_ABI) && TargetOS::IsApplePlatform &&
6864- (!codeGen->isFramePointerRequired () || codeGen->genTotalFrameSize () < 0x100 ))
6865- {
6866- codeGen->SetSaveFpLrWithAllCalleeSavedRegisters (true );
6867- }
6868- else
6869- {
6870- // Default configuration
6871- codeGen->SetSaveFpLrWithAllCalleeSavedRegisters ((getNeedsGSSecurityCookie () && compLocallocUsed) ||
6872- opts.compDbgEnC ||
6873- compStressCompile (Compiler::STRESS_GENERIC_VARN, 20 ));
6874- }
6875- }
6876- else if (opts.compJitSaveFpLrWithCalleeSavedRegisters == 1 )
6877- {
6878- codeGen->SetSaveFpLrWithAllCalleeSavedRegisters (false ); // Disable using new frames
6879- }
6880- else if ((opts.compJitSaveFpLrWithCalleeSavedRegisters == 2 ) || (opts.compJitSaveFpLrWithCalleeSavedRegisters == 3 ))
6881- {
6882- codeGen->SetSaveFpLrWithAllCalleeSavedRegisters (true ); // Force using new frames
6883- }
6884- #endif // TARGET_ARM64
68856854}
68866855
68876856// ------------------------------------------------------------------------
0 commit comments