[llvm] [AArch64] Use a frame record for non-leaf outlined functions on MachO (PR #213711)

Jon Roelofs via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 7 08:53:27 PDT 2026


================
@@ -11213,32 +11235,80 @@ void AArch64InstrInfo::buildOutlinedFrame(
         OF.FrameConstructionID == MachineOutlinerThunk)
       Et = std::prev(MBB.end());
 
-    // Insert a save before the outlined region
-    MachineInstr *STRXpre = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
-                                .addReg(AArch64::SP, RegState::Define)
-                                .addReg(AArch64::LR)
+    // There is a call in the range, so we must save LR. On MachO, saving only
+    // LR cannot be described by compact unwind. Saving FP and LR as a frame
+    // record lets the compact-unwind encoder use the FRAME encoding, at the
+    // cost of one extra mov.
+    bool NeedsDwarf =
+        MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF);
+    bool UseFrameRecord = shouldUseCompactUnwindFrameRecordForOutlinedFunction(
+        MF, NeedsDwarf, isFPAvailableInsideOutlinedSeq(MBB, getRegisterInfo()));
+
+    if (UseFrameRecord) {
+      // FP is saved here, so it must be live-in.
+      if (!MBB.isLiveIn(AArch64::FP))
+        MBB.addLiveIn(AArch64::FP);
+
+      // stp x29, x30, [sp, #-16]!   (STP pre-index imm is scaled by 8: -2 * 8)
+      MachineInstr *STPXpre = BuildMI(MF, DebugLoc(), get(AArch64::STPXpre))
+                                  .addReg(AArch64::SP, RegState::Define)
+                                  .addReg(AArch64::FP)
+                                  .addReg(AArch64::LR)
+                                  .addReg(AArch64::SP)
+                                  .addImm(-2);
+      It = MBB.insert(It, STPXpre);
+
+      // mov x29, sp  (add x29, sp, #0) so x29 points at the saved frame record.
+      MachineInstr *SetFP = BuildMI(MF, DebugLoc(), get(AArch64::ADDXri))
+                                .addReg(AArch64::FP, RegState::Define)
                                 .addReg(AArch64::SP)
-                                .addImm(-16);
-    It = MBB.insert(It, STRXpre);
-
-    if (MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
-      CFIInstBuilder CFIBuilder(MBB, It, MachineInstr::FrameSetup);
-
-      // Add a CFI saying the stack was moved 16 B down.
-      CFIBuilder.buildDefCFAOffset(16);
+                                .addImm(0)
+                                .addImm(0);
+      MBB.insertAfter(It, SetFP);
+
+      // Standard frame-record CFI (FP is the CFA) so the encoder emits FRAME.
+      CFIInstBuilder CFIBuilder(MBB, std::next(SetFP->getIterator()),
+                                MachineInstr::FrameSetup);
+      CFIBuilder.buildDefCFA(AArch64::FP, 16);
+      CFIBuilder.buildOffset(AArch64::LR, -8);
+      CFIBuilder.buildOffset(AArch64::FP, -16);
----------------
jroelofs wrote:

oh, never mind, we don't need the "needs dwarf" check here, since that's subsumed by the `shouldUseCompactUnwindFrameRecordForOutlinedFunction` check.

https://github.com/llvm/llvm-project/pull/213711


More information about the llvm-commits mailing list