[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