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

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Sep 1 03:01:55 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Anatoly Trosinenko (atrosinenko)

<details>
<summary>Changes</summary>

With shrink-wrapping, it is possible for PAUTH_EPILOGUE to be inserted
in the middle of the function where X15/X16/X17 may be alive and must
not be clobbered.

This commit implements ad-hoc spilling of the scratch registers used by
PAUTH_EPILOGUE to other GPRs. If no such registers is available at the
insertion point, an explicit compiler error is triggered.

---

Patch is 23.74 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/220191.diff


2 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.cpp (+68-9) 
- (added) llvm/test/CodeGen/AArch64/sign-return-address-epilogue-regs.ll (+541) 


``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 92b4d21454048..bcff007a00a90 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -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())))
+    LiveRegs.stepBackward(MI);
+
+  auto FindAvailableRegister = [&LiveRegs, &MRI]() {
+    for (Register Reg : AArch64::GPR64RegClass) {
+      if (LiveRegs.available(MRI, Reg))
+        return Reg;
+    }
+    reportFatalUsageError("Cannot insert PAUTH_EPILOGUE: ran out of registers");
+  };
+
+  // Find out which scratch registers have to be spilled to other GPRs,
+  // mark the rest as unavailable to be spilled-to.
+  SmallVector<std::pair<Register, Register>, 3> Spills;
+  for (Register ScratchReg : ImplicitDefs) {
+    // With Speculative Load Hardening, X16 is reported as reserved by MRI,
+    // but a fallback to DSB+ISB is actually supported as long as implicit-defs
+    // are set appropriately.
+    if (ScratchReg == AArch64::X16 &&
+        MF.getFunction().hasFnAttribute(Attribute::SpeculativeLoadHardening))
+      continue;
+
+    assert(!MRI.isReserved(ScratchReg));
+
+    if (LiveRegs.available(MRI, ScratchReg))
+      LiveRegs.addReg(ScratchReg);
+    else
+      Spills.emplace_back(ScratchReg, AArch64::NoRegister);
   }
 
-  if (AFI->branchProtectionPAuthLR() && !Subtarget.hasPAuthLR())
-    Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
+  for (auto &[ScratchReg, SpillReg] : Spills) {
+    (void)ScratchReg;
+    SpillReg = FindAvailableRegister();
+    LiveRegs.addReg(SpillReg);
+  }
+
+  auto EmitMOV = [&](Register DstReg, Register SrcReg) {
+    BuildMI(MBB, InsertPt, DL, get(AArch64::ORRXrs), DstReg)
+        .addReg(AArch64::XZR)
+        .addReg(SrcReg)
+        .addImm(0)
+        .setMIFlag(MachineInstr::FrameDestroy);
+  };
+
+  for (auto [ScratchReg, SpillReg] : Spills)
+    EmitMOV(SpillReg, ScratchReg);
+
+  auto Builder = BuildMI(MBB, InsertPt, DL, get(AArch64::PAUTH_EPILOGUE))
+                     .setMIFlag(MachineInstr::FrameDestroy);
+  for (auto ScratchReg : ImplicitDefs)
+    Builder.addReg(ScratchReg, RegState::ImplicitDefine);
+
+  for (auto [ScratchReg, SpillReg] : llvm::reverse(Spills))
+    EmitMOV(ScratchReg, SpillReg);
 }
 
 MachineBasicBlock::iterator
diff --git a/llvm/test/CodeGen/AArch64/sign-return-address-epilogue-regs.ll b/llvm/test/CodeGen/AArch64/sign-return-address-epilogue-regs.ll
new file mode 100644
index 0000000000000..a389219e06dae
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sign-return-address-epilogue-regs.ll
@@ -0,0 +1,541 @@
+; RUN: rm -rf %t && split-file %s %t
+
+;--- ok.ll
+
+; RUN: llc -mtriple=aarch64 -asm-verbose=0                            < %t/ok.ll | FileCheck --check-prefixes=COMPAT  %s
+; RUN: llc -mtriple=aarch64 -asm-verbose=0 -mattr=v8.3a               < %t/ok.ll | FileCheck --check-prefixes=V83A    %s
+; RUN: llc -mtriple=aarch64 -asm-verbose=0 -mattr=v9a -mattr=pauth-lr < %t/ok.ll | FileCheck --check-prefixes=PAUTHLR %s
+
+define i64 @test_x16_available(i64 %arg) "branch-protection-pauth-lr" "sign-return-address"="non-leaf" {
+; COMPAT-LABEL: test_x16_available:
+; COMPAT:         cbz x0, .LBB0_2
+; COMPAT-NEXT:    hint #39
+; COMPAT-NEXT:  .Ltmp0:
+; COMPAT-NEXT:    hint #25
+; COMPAT-NEXT:    .cfi_set_ra_state 2, .Ltmp0
+; COMPAT-NEXT:    str x30, [sp, #-16]!
+; COMPAT-NEXT:    .cfi_def_cfa_offset 16
+; COMPAT-NEXT:    .cfi_offset w30, -16
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    mov x30, #12345
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    ldr x30, [sp], #16
+; COMPAT-NEXT:    adrp x16, .Ltmp0
+; COMPAT-NEXT:    add x16, x16, :lo12:.Ltmp0
+; COMPAT-NEXT:    hint #39
+; COMPAT-NEXT:    hint #29
+; COMPAT-NEXT:  .LBB0_2:
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    mov x0, #42
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    ret
+;
+; V83A-LABEL: test_x16_available:
+; V83A:         cbz x0, .LBB0_2
+; V83A-NEXT:    hint #39
+; V83A-NEXT:  .Ltmp0:
+; V83A-NEXT:    paciasp
+; V83A-NEXT:    .cfi_set_ra_state 2, .Ltmp0
+; V83A-NEXT:    str x30, [sp, #-16]!
+; V83A-NEXT:    .cfi_def_cfa_offset 16
+; V83A-NEXT:    .cfi_offset w30, -16
+; V83A-NEXT:    //APP
+; V83A-NEXT:    mov x30, #12345
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    ldr x30, [sp], #16
+; V83A-NEXT:    adrp x16, .Ltmp0
+; V83A-NEXT:    add x16, x16, :lo12:.Ltmp0
+; V83A-NEXT:    hint #39
+; V83A-NEXT:    autiasp
+; V83A-NEXT:  .LBB0_2:
+; V83A-NEXT:    //APP
+; V83A-NEXT:    mov x0, #42
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    ret
+;
+; PAUTHLR-LABEL: test_x16_available:
+; PAUTHLR:         cbz x0, .LBB0_2
+; PAUTHLR-NEXT:  .Ltmp0:
+; PAUTHLR-NEXT:    paciasppc
+; PAUTHLR-NEXT:    .cfi_set_ra_state 2, .Ltmp0
+; PAUTHLR-NEXT:    str x30, [sp, #-16]!
+; PAUTHLR-NEXT:    .cfi_def_cfa_offset 16
+; PAUTHLR-NEXT:    .cfi_offset w30, -16
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    mov x30, #12345
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    ldr x30, [sp], #16
+; PAUTHLR-NEXT:    autiasppc .Ltmp0
+; PAUTHLR-NEXT:  .LBB0_2:
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    mov x0, #42
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    ret
+  %cond = icmp eq i64 %arg, 0
+  br i1 %cond, label %if.end, label %if.then
+
+if.then:
+  tail call void asm sideeffect "mov x30, 12345", "~{lr}"()
+  br label %if.end
+
+if.end:
+  %result = tail call i64 asm sideeffect "mov $0, 42", "=r"()
+  ret i64 %result
+}
+
+; Make sure the scratch registers that are alive at the insertion point of
+; PAUTH_EPILOGUE are spilled to the free registers.
+;
+; The LLVM IR below roughly corresponds to the following C source:
+;
+; void callee();
+; int64_t test(int64_t arg) {
+;   register int64_t live_x16 asm("x16");
+;   register int64_t live_x17 asm("x17");
+;   // Put some values into x16 and x17.
+;   asm volatile("mov %0, 42\n\tmov %1, 123" : "=r"(live_x16), "=r"(live_x17));
+;
+;   // Force conditional call frame creation.
+;   // Check that the shrink-wrapped epilogue keeps the contents of x16 and x17
+;   // intact if these registers are alive.
+;   if (arg) {
+;     // --- prologue goes here ---
+;     asm volatile("" : : : "lr");
+;     // --- epilogue goes here ---
+;   }
+;
+;   // Use the values stored in x16 and x17 at the beginning of the function.
+;   int64_t res;
+;   asm volatile("add %0, %1, %2" : "=r"(res) : "r"(live_x16), "r"(live_x17));
+;   return res;
+; }
+;
+; If FEAT_PAuth_LR is not available, PAUTH_EPILOGUE has to use X16 as a scratch
+; register, thus X16 has to be spilled to another GPR. On the other hand, X17
+; is known not to be clobbered by PAUTH_EPILOGUE as SP adjustment is not needed,
+; thus spilling X17 is not required.
+
+define i64 @test_x16_alive(i64 %arg) "branch-protection-pauth-lr" "sign-return-address"="non-leaf" {
+; COMPAT-LABEL: test_x16_alive:
+; COMPAT:         //APP
+; COMPAT-NEXT:    mov x16, #42
+; COMPAT-NEXT:    mov x17, #123
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    cbz x0, .LBB1_2
+; COMPAT-NEXT:    hint #39
+; COMPAT-NEXT:  .Ltmp1:
+; COMPAT-NEXT:    hint #25
+; COMPAT-NEXT:    .cfi_set_ra_state 2, .Ltmp1
+; COMPAT-NEXT:    str x30, [sp, #-16]!
+; COMPAT-NEXT:    .cfi_def_cfa_offset 16
+; COMPAT-NEXT:    .cfi_offset w30, -16
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    mov x30, #12345
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    ldr x30, [sp], #16
+; COMPAT-NEXT:    mov x0, x16
+; COMPAT-NEXT:    adrp x16, .Ltmp1
+; COMPAT-NEXT:    add x16, x16, :lo12:.Ltmp1
+; COMPAT-NEXT:    hint #39
+; COMPAT-NEXT:    hint #29
+; COMPAT-NEXT:    mov x16, x0
+; COMPAT-NEXT:  .LBB1_2:
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    add x0, x16, x17
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    ret
+;
+; V83A-LABEL: test_x16_alive:
+; V83A:         //APP
+; V83A-NEXT:    mov x16, #42
+; V83A-NEXT:    mov x17, #123
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    cbz x0, .LBB1_2
+; V83A-NEXT:    hint #39
+; V83A-NEXT:  .Ltmp1:
+; V83A-NEXT:    paciasp
+; V83A-NEXT:    .cfi_set_ra_state 2, .Ltmp1
+; V83A-NEXT:    str x30, [sp, #-16]!
+; V83A-NEXT:    .cfi_def_cfa_offset 16
+; V83A-NEXT:    .cfi_offset w30, -16
+; V83A-NEXT:    //APP
+; V83A-NEXT:    mov x30, #12345
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    ldr x30, [sp], #16
+; V83A-NEXT:    mov x0, x16
+; V83A-NEXT:    adrp x16, .Ltmp1
+; V83A-NEXT:    add x16, x16, :lo12:.Ltmp1
+; V83A-NEXT:    hint #39
+; V83A-NEXT:    autiasp
+; V83A-NEXT:    mov x16, x0
+; V83A-NEXT:  .LBB1_2:
+; V83A-NEXT:    //APP
+; V83A-NEXT:    add x0, x16, x17
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    ret
+;
+; PAUTHLR-LABEL: test_x16_alive:
+; PAUTHLR:         //APP
+; PAUTHLR-NEXT:    mov x16, #42
+; PAUTHLR-NEXT:    mov x17, #123
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    cbz x0, .LBB1_2
+; PAUTHLR-NEXT:  .Ltmp1:
+; PAUTHLR-NEXT:    paciasppc
+; PAUTHLR-NEXT:    .cfi_set_ra_state 2, .Ltmp1
+; PAUTHLR-NEXT:    str x30, [sp, #-16]!
+; PAUTHLR-NEXT:    .cfi_def_cfa_offset 16
+; PAUTHLR-NEXT:    .cfi_offset w30, -16
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    mov x30, #12345
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    ldr x30, [sp], #16
+; PAUTHLR-NEXT:    autiasppc .Ltmp1
+; PAUTHLR-NEXT:  .LBB1_2:
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    add x0, x16, x17
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    ret
+  %regs = tail call { i64, i64 } asm sideeffect "mov $0, 42\0A\09mov $1, 123", "={x16},={x17}"()
+  %live_x16 = extractvalue { i64, i64 } %regs, 0
+  %live_x17 = extractvalue { i64, i64 } %regs, 1
+  %cond = icmp eq i64 %arg, 0
+  br i1 %cond, label %if.end, label %if.then
+
+if.then:
+  tail call void asm sideeffect "mov x30, 12345", "~{lr}"()
+  br label %if.end
+
+if.end:
+  %result = tail call i64 asm sideeffect "add $0, $1, $2", "=r,{x16},{x17}"(i64 %live_x16, i64 %live_x17)
+  ret i64 %result
+}
+
+define i32 @test_w16_alive(i64 %arg) "branch-protection-pauth-lr" "sign-return-address"="non-leaf" {
+; COMPAT-LABEL: test_w16_alive:
+; COMPAT:         //APP
+; COMPAT-NEXT:    mov w16, #42
+; COMPAT-NEXT:    mov w17, #123
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    cbz x0, .LBB2_2
+; COMPAT-NEXT:    hint #39
+; COMPAT-NEXT:  .Ltmp2:
+; COMPAT-NEXT:    hint #25
+; COMPAT-NEXT:    .cfi_set_ra_state 2, .Ltmp2
+; COMPAT-NEXT:    str x30, [sp, #-16]!
+; COMPAT-NEXT:    .cfi_def_cfa_offset 16
+; COMPAT-NEXT:    .cfi_offset w30, -16
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    mov x30, #12345
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    ldr x30, [sp], #16
+; COMPAT-NEXT:    mov x0, x16
+; COMPAT-NEXT:    adrp x16, .Ltmp2
+; COMPAT-NEXT:    add x16, x16, :lo12:.Ltmp2
+; COMPAT-NEXT:    hint #39
+; COMPAT-NEXT:    hint #29
+; COMPAT-NEXT:    mov x16, x0
+; COMPAT-NEXT:  .LBB2_2:
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    add w0, w16, w17
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    ret
+;
+; V83A-LABEL: test_w16_alive:
+; V83A:         //APP
+; V83A-NEXT:    mov w16, #42
+; V83A-NEXT:    mov w17, #123
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    cbz x0, .LBB2_2
+; V83A-NEXT:    hint #39
+; V83A-NEXT:  .Ltmp2:
+; V83A-NEXT:    paciasp
+; V83A-NEXT:    .cfi_set_ra_state 2, .Ltmp2
+; V83A-NEXT:    str x30, [sp, #-16]!
+; V83A-NEXT:    .cfi_def_cfa_offset 16
+; V83A-NEXT:    .cfi_offset w30, -16
+; V83A-NEXT:    //APP
+; V83A-NEXT:    mov x30, #12345
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    ldr x30, [sp], #16
+; V83A-NEXT:    mov x0, x16
+; V83A-NEXT:    adrp x16, .Ltmp2
+; V83A-NEXT:    add x16, x16, :lo12:.Ltmp2
+; V83A-NEXT:    hint #39
+; V83A-NEXT:    autiasp
+; V83A-NEXT:    mov x16, x0
+; V83A-NEXT:  .LBB2_2:
+; V83A-NEXT:    //APP
+; V83A-NEXT:    add w0, w16, w17
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    ret
+;
+; PAUTHLR-LABEL: test_w16_alive:
+; PAUTHLR:         //APP
+; PAUTHLR-NEXT:    mov w16, #42
+; PAUTHLR-NEXT:    mov w17, #123
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    cbz x0, .LBB2_2
+; PAUTHLR-NEXT:  .Ltmp2:
+; PAUTHLR-NEXT:    paciasppc
+; PAUTHLR-NEXT:    .cfi_set_ra_state 2, .Ltmp2
+; PAUTHLR-NEXT:    str x30, [sp, #-16]!
+; PAUTHLR-NEXT:    .cfi_def_cfa_offset 16
+; PAUTHLR-NEXT:    .cfi_offset w30, -16
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    mov x30, #12345
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    ldr x30, [sp], #16
+; PAUTHLR-NEXT:    autiasppc .Ltmp2
+; PAUTHLR-NEXT:  .LBB2_2:
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    add w0, w16, w17
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    ret
+  %regs = tail call { i32, i32 } asm sideeffect "mov ${0:w}, 42\0A\09mov ${1:w}, 123",  "={w16},={w17}"()
+  %live_w16 = extractvalue { i32, i32 } %regs, 0
+  %live_w17 = extractvalue { i32, i32 } %regs, 1
+  %cond = icmp eq i64 %arg, 0
+  br i1 %cond, label %if.end, label %if.then
+
+if.then:
+  tail call void asm sideeffect "mov x30, 12345", "~{lr}"()
+  br label %if.end
+
+if.end:
+  %result = tail call i32 asm sideeffect "add ${0:w}, ${1:w}, ${2:w}", "=r,{w16},{w17}"(i32 %live_w16, i32 %live_w17)
+  ret i32 %result
+}
+
+; Request multiple scratch registers to check that both implicit-defs and "spill
+; slot" registers are marked as used appropriately when searching for available
+; registers.
+;
+; SwiftTail has the same set of CSRs as the C calling convention except for
+; X20 and X22. At the insertion point of PAUTH_EPILOGUE,
+; * keep X15 available to be used as a scratch register
+; * make X16 and X17 require spilling to other registers
+;   (same as in @test_no_clobber_x16)
+; * make sure X0-X14 and X18 are alive, so that they cannot be spilled-to
+;
+; This way, X20 and X22 are the only available registers left.
+; See also @test_multiple_scratch_regs_fail.
+
+%large_struct = type { i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 }
+
+%regs_t = type { i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 }
+
+define swifttailcc i64 @test_multiple_scratch_regs(i64 %arg, %large_struct %s) "branch-protection-pauth-lr" "sign-return-address"="non-leaf" {
+; COMPAT-LABEL: test_multiple_scratch_regs:
+; COMPAT:         mov x15, x0
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    mov x16, #42
+; COMPAT-NEXT:    mov x17, #123
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    cbz x15, .LBB3_2
+; COMPAT-NEXT:    hint #39
+; COMPAT-NEXT:  .Ltmp3:
+; COMPAT-NEXT:    hint #25
+; COMPAT-NEXT:    .cfi_set_ra_state 2, .Ltmp3
+; COMPAT-NEXT:    sub sp, sp, #80
+; COMPAT-NEXT:    str x30, [sp, #64]
+; COMPAT-NEXT:    .cfi_def_cfa_offset 80
+; COMPAT-NEXT:    .cfi_offset w30, -16
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    mov x30, #12345
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    ldr x30, [sp, #64]
+; COMPAT-NEXT:    mov x20, x17
+; COMPAT-NEXT:    mov x22, x16
+; COMPAT-NEXT:    add x16, sp, #80
+; COMPAT-NEXT:    mov x17, x30
+; COMPAT-NEXT:    adrp x15, .Ltmp3
+; COMPAT-NEXT:    add x15, x15, :lo12:.Ltmp3
+; COMPAT-NEXT:    hint #39
+; COMPAT-NEXT:    hint #12
+; COMPAT-NEXT:    mov x30, x17
+; COMPAT-NEXT:    add sp, sp, #160
+; COMPAT-NEXT:    mov x16, x22
+; COMPAT-NEXT:    mov x17, x20
+; COMPAT-NEXT:  .LBB3_2:
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    //APP
+; COMPAT-NEXT:    add x0, x16, x17
+; COMPAT-NEXT:    //NO_APP
+; COMPAT-NEXT:    ret
+;
+; V83A-LABEL: test_multiple_scratch_regs:
+; V83A:         mov x15, x0
+; V83A-NEXT:    //APP
+; V83A-NEXT:    mov x16, #42
+; V83A-NEXT:    mov x17, #123
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    //APP
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    cbz x15, .LBB3_2
+; V83A-NEXT:    hint #39
+; V83A-NEXT:  .Ltmp3:
+; V83A-NEXT:    paciasp
+; V83A-NEXT:    .cfi_set_ra_state 2, .Ltmp3
+; V83A-NEXT:    sub sp, sp, #80
+; V83A-NEXT:    str x30, [sp, #64]
+; V83A-NEXT:    .cfi_def_cfa_offset 80
+; V83A-NEXT:    .cfi_offset w30, -16
+; V83A-NEXT:    //APP
+; V83A-NEXT:    mov x30, #12345
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    ldr x30, [sp, #64]
+; V83A-NEXT:    mov x20, x17
+; V83A-NEXT:    mov x22, x16
+; V83A-NEXT:    add x16, sp, #80
+; V83A-NEXT:    mov x17, x30
+; V83A-NEXT:    adrp x15, .Ltmp3
+; V83A-NEXT:    add x15, x15, :lo12:.Ltmp3
+; V83A-NEXT:    hint #39
+; V83A-NEXT:    autia1716
+; V83A-NEXT:    mov x30, x17
+; V83A-NEXT:    add sp, sp, #160
+; V83A-NEXT:    mov x16, x22
+; V83A-NEXT:    mov x17, x20
+; V83A-NEXT:  .LBB3_2:
+; V83A-NEXT:    //APP
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    //APP
+; V83A-NEXT:    add x0, x16, x17
+; V83A-NEXT:    //NO_APP
+; V83A-NEXT:    ret
+;
+; PAUTHLR-LABEL: test_multiple_scratch_regs:
+; PAUTHLR:         mov x15, x0
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    mov x16, #42
+; PAUTHLR-NEXT:    mov x17, #123
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    cbz x15, .LBB3_2
+; PAUTHLR-NEXT:  .Ltmp3:
+; PAUTHLR-NEXT:    paciasppc
+; PAUTHLR-NEXT:    .cfi_set_ra_state 2, .Ltmp3
+; PAUTHLR-NEXT:    sub sp, sp, #80
+; PAUTHLR-NEXT:    str x30, [sp, #64]
+; PAUTHLR-NEXT:    .cfi_def_cfa_offset 80
+; PAUTHLR-NEXT:    .cfi_offset w30, -16
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    mov x30, #12345
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    ldr x30, [sp, #64]
+; PAUTHLR-NEXT:    mov x20, x17
+; PAUTHLR-NEXT:    mov x22, x16
+; PAUTHLR-NEXT:    add x16, sp, #80
+; PAUTHLR-NEXT:    mov x17, x30
+; PAUTHLR-NEXT:    adrp x15, .Ltmp3
+; PAUTHLR-NEXT:    add x15, x15, :lo12:.Ltmp3
+; PAUTHLR-NEXT:    autia171615
+; PAUTHLR-NEXT:    mov x30, x17
+; PAUTHLR-NEXT:    add sp, sp, #160
+; PAUTHLR-NEXT:    mov x16, x22
+; PAUTHLR-NEXT:    mov x17, x20
+; PAUTHLR-NEXT:  .LBB3_2:
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    //APP
+; PAUTHLR-NEXT:    add x0, x16, x17
+; PAUTHLR-NEXT:    //NO_APP
+; PAUTHLR-NEXT:    ret
+  %local = alloca [64 x i8], align 8
+  %regs = tail call { i64, i64 } asm sideeffect "mov $0, 42\0A\09mov $1, 123", "={x16},={x17}"()
+  %live_x16 = extractvalue { i64, i64 } %regs, 0
+  %live_x17 = extractvalue { i64, i64 } %regs, 1
+
+  %other.regs.def = tail call %regs_t asm sideeffect "", "={x0},={x1},={x2},={x3},={x4},={x5},={x6},={x7},={x8},={x9},={x10},={x11},={x12},={x13},={x14},={x18}"()
+  %live_x0 = extractvalue %regs_t %other.regs.def, 0
+  %live_x1 = extractvalue %regs_t %other.regs.def, 1
+  %live_x2 = extractvalue %regs_t %other.regs.def, 2
+  %live_x3 = extractvalue %regs_t %other.regs.def, 3
+  %live_x4 = extractvalue %regs_t %other.regs.def, 4
+  %live_x5 = extractvalue %regs_t %other.regs.def, 5
+  %live_x6 = extractvalue %regs_t %other.regs.def, 6
+  %live_x7 = extractvalue %regs_t %other.regs.def, 7
+  %live_x8 = extractvalue %regs_t %other.regs.def, 8
+  %live_x9 = extractvalue %regs_t %other.regs.def, 9
+  %live_x10 = extractvalue %regs_t %other.regs.def, 10
+  %live_x11 = extractvalue %regs_t %other.regs.def, 11
+  %live_x12 = extractvalue %regs_t %other.regs.def, 12
+  %live_x13 = extractvalue %regs_t %other.regs.def, 13
+  %live_x14 = extractvalue %regs_t %other.regs.def, 14
+
+  %live_x18 = extractvalue %regs_t %other.regs.de...
[truncated]

``````````

</details>


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


More information about the llvm-branch-commits mailing list