[llvm-branch-commits] [llvm] [AArch64][PAC] Prevent PAUTH_EPILOGUE from overwriting live registers (PR #220191)

Anatoly Trosinenko via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Sep 2 09:01:18 PDT 2026


================
@@ -11771,23 +11771,82 @@ unsigned llvm::getBLRCallOpcode(const MachineFunction &MF) {
 void AArch64InstrInfo::createPauthEpilogueInstr(MachineBasicBlock &MBB,
                                                 DebugLoc DL) const {
   MachineBasicBlock::iterator InsertPt = MBB.getFirstTerminator();
-  auto Builder = BuildMI(MBB, InsertPt, DL, get(AArch64::PAUTH_EPILOGUE))
-                     .setMIFlag(MachineInstr::FrameDestroy);
-
   MachineFunction &MF = *MBB.getParent();
+  MachineRegisterInfo &MRI = MF.getRegInfo();
   const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
   auto &AFL = *static_cast<const AArch64FrameLowering *>(
       MF.getSubtarget().getFrameLowering());
+
+  SmallVector<Register, 3> ImplicitDefs;
   if (AFL.getArgumentStackToRestore(MF, MBB)) {
-    Builder.addReg(AArch64::X17, RegState::ImplicitDefine);
-    Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
+    ImplicitDefs.push_back(AArch64::X17);
+    ImplicitDefs.push_back(AArch64::X16);
     if (AFI->branchProtectionPAuthLR())
-      Builder.addReg(AArch64::X15, RegState::ImplicitDefine);
-    return;
+      ImplicitDefs.push_back(AArch64::X15);
+  } else if (AFI->branchProtectionPAuthLR() && !Subtarget.hasPAuthLR()) {
+    ImplicitDefs.push_back(AArch64::X16);
+  }
+
+  // If the scratch registers we plan using are alive at this point,
+  // try spilling them to other registers.
+
+  assert(MF.getProperties().hasTracksLiveness());
+  LivePhysRegs LiveRegs(TRI);
+  LiveRegs.addLiveOuts(MBB);
+  for (auto &MI : llvm::reverse(llvm::make_range(InsertPt, MBB.end())))
----------------
atrosinenko wrote:

> Is this intentionally skipping InsertPt itself

No, my intention is the opposite: to iterate over the "suffix" of MBB in reverse order and stop right after processing the `InsertPt` (i.e. at the insertion point of `PAUTH_EPILOGUE` right before `InsertPt`). Intuitively, I construct a range from `InsertPt` (including) to `MBB.end()` (excluding), and then iterate over the same set of elements but in reverse order. Just in case, I tried artificially inserting a few `RET`s before initializing `InsertPt = MBB.getFirstTerminator()` and modifying this loop like this:
```cpp
  dbgs() << "###\nMBB is\n";
  MBB.dump();
  dbgs() << "InsertPt is "; InsertPt->dump();
  dbgs() << "---\n";
  for (auto &MI : llvm::reverse(llvm::make_range(InsertPt, MBB.end()))) {
    MI.dump();
    LiveRegs.stepBackward(MI);
  }
  dbgs() << "===\n";
```
This seems to confirm my intuition:
```
###
MBB is
bb.1.if.then:
; predecessors: %bb.0
  successors: %bb.2(0x80000000); %bb.2(100.00%)
  liveins: $x16, $x17, $lr
  frame-setup PAUTH_PROLOGUE implicit-def $lr, implicit $lr, implicit $sp
  early-clobber $sp = frame-setup STRXpre killed $lr, $sp(tied-def 0), -16 :: (store (s64) into %stack.0)
  frame-setup CFI_INSTRUCTION def_cfa_offset 16
  frame-setup CFI_INSTRUCTION offset $w30, -16
  INLINEASM &"mov x30, 12345" [sideeffect] [attdialect], $0:[clobber], implicit-def dead early-clobber $lr
  early-clobber $sp, $lr = frame-destroy LDRXpost $sp(tied-def 0), 16 :: (load (s64) from %stack.0)
  [ edit: PAUTH_EPILOGUE is to be inserted here ]
  RET $x1
  RET $x2
  RET $x3
InsertPt is   RET $x1
---
  RET $x3
  RET $x2
  RET $x1
===
```

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


More information about the llvm-branch-commits mailing list