[llvm] [ARM] R11 not pushed adjacent to link register with PAC-M and AAPCS frame chain fix (PR #82801)

Eli Friedman via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 29 14:32:48 PST 2024


================
@@ -494,11 +494,55 @@ bool ARMSubtarget::ignoreCSRForAllocationOrder(const MachineFunction &MF,
          ARM::GPRRegClass.contains(PhysReg);
 }
 
-bool ARMSubtarget::splitFramePointerPush(const MachineFunction &MF) const {
+ARMSubtarget::PushPopSplitVariation
+ARMSubtarget::getPushPopSplitVariation(const MachineFunction &MF) const {
   const Function &F = MF.getFunction();
-  if (!MF.getTarget().getMCAsmInfo()->usesWindowsCFI() ||
-      !F.needsUnwindTableEntry())
-    return false;
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-  return MFI.hasVarSizedObjects() || getRegisterInfo()->hasStackRealignment(MF);
+  const std::vector<CalleeSavedInfo> CSI =
+      MF.getFrameInfo().getCalleeSavedInfo();
+  // Returns R7Split if the frame setup must be split into two separate pushes
+  // of r0-r7,lr and another containing r8-r11 (+r12 if necessary). This is
+  // always required on Thumb1-only targets, as the push and pop instructions
+  // can't access the high registers. This is also required when R7 is the frame
+  // pointer and frame pointer elimiination is disabled, or branch signing is
+  // enabled and AAPCS is disabled.
+  if ((MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress() &&
+       !createAAPCSFrameChain()) ||
+      ((getFramePointerReg() == ARM::R7 &&
+        MF.getTarget().Options.DisableFramePointerElim(MF)) ||
+       isThumb1Only()))
+    return R7Split;
+  // Returns R11SplitWindowsSEHUnwind when the stack pointer needs to be
+  // restored from the frame pointer r11 + an offset and Windows CFI is enabled.
+  // This stack unwinding cannot be expressed with SEH unwind opcodes when done
+  // with a single push, making it necessary to split the push into r4-r10, and
+  // another containing r11+lr.
+  if (MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
+      F.needsUnwindTableEntry() &&
+      (MFI.hasVarSizedObjects() || getRegisterInfo()->hasStackRealignment(MF)))
+    return R11SplitWindowsSEHUnwind;
+  // Returns R11SplitAAPCSBranchSigning if R11 and lr are not adjacent to each
+  // other in the list of callee saved registers in a frame, and branch
+  // signing is enabled.
+  if (CSI.size() > 1 &&
----------------
efriedma-quic wrote:

Can we simplify this code?  It seems sort of awkward to dig through the callee-saves here. And given the normal way this works, the only register that can show up between R11 and LR (R14), is R12.

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


More information about the llvm-commits mailing list