[llvm] [llvm][AArch64] Eliminate redundant mov's sandwiching aut's in tail calls (PR #211105)

Jon Roelofs via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 23 09:00:21 PDT 2026


https://github.com/jroelofs updated https://github.com/llvm/llvm-project/pull/211105

>From dbc4dbe6092aa9627ab629d52937792edf3efd82 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 21 Jul 2026 13:28:52 -0700
Subject: [PATCH 1/2] [llvm][AArch64] Eliminate redundant mov's sandwiching
 aut's in tail calls

When the target has +pauth, we don't have to use the hint space compatible
encodings (auti[ab]1716), and instead can directly authenticate lr with
auti[ab].
---
 .../lib/Target/AArch64/AArch64PointerAuth.cpp | 55 +++++++++++++++----
 .../CodeGen/AArch64/arm64e-tail-call-autib.ll |  4 +-
 .../AArch64/pauth-lr-tail-call-fpdiff.ll      | 40 ++++++++++----
 .../test/CodeGen/AArch64/swifttail-ptrauth.ll | 10 +++-
 4 files changed, 79 insertions(+), 30 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp
index 7165c3bfed422..94cade25c4ffe 100644
--- a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp
+++ b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp
@@ -269,13 +269,13 @@ void AArch64PointerAuthImpl::authenticateLR(
                     StackOffset::getFixed(-ArgumentStackToRestore), TII,
                     MachineInstr::FrameDestroy);
 
-    BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
-        .addReg(AArch64::XZR)
-        .addReg(AArch64::LR)
-        .addImm(0)
-        .setMIFlag(MachineInstr::FrameDestroy);
-
     if (MFnI->branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) {
+      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
+          .addReg(AArch64::XZR)
+          .addReg(AArch64::LR)
+          .addImm(0)
+          .setMIFlag(MachineInstr::FrameDestroy);
+
       assert(PACSym && "No PAC instruction to refer to");
       emitEpiloguePACSymOffsetIntoReg(*TII, MBB, MBBI, DL, PACSym,
                                       AArch64::X15);
@@ -284,7 +284,19 @@ void AArch64PointerAuthImpl::authenticateLR(
       unsigned AutOpc = UseBKey ? AArch64::AUTIB171615 : AArch64::AUTIA171615;
       BuildMI(MBB, MBBI, DL, TII->get(AutOpc))
           .setMIFlag(MachineInstr::FrameDestroy);
+
+      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::LR)
+          .addReg(AArch64::XZR)
+          .addReg(AArch64::X17)
+          .addImm(0)
+          .setMIFlag(MachineInstr::FrameDestroy);
     } else if (MFnI->branchProtectionPAuthLR()) {
+      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
+          .addReg(AArch64::XZR)
+          .addReg(AArch64::LR)
+          .addImm(0)
+          .setMIFlag(MachineInstr::FrameDestroy);
+
       assert(PACSym && "No PAC instruction to refer to");
       emitEpiloguePACSymOffsetIntoReg(*TII, MBB, MBBI, DL, PACSym,
                                       AArch64::X15);
@@ -301,18 +313,37 @@ void AArch64PointerAuthImpl::authenticateLR(
       unsigned AutOpc = UseBKey ? AArch64::AUTIB1716 : AArch64::AUTIA1716;
       BuildMI(MBB, MBBI, DL, TII->get(AutOpc))
           .setMIFlag(MachineInstr::FrameDestroy);
+
+      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::LR)
+          .addReg(AArch64::XZR)
+          .addReg(AArch64::X17)
+          .addImm(0)
+          .setMIFlag(MachineInstr::FrameDestroy);
+    } else if (Subtarget->hasPAuth()) {
+      BuildMI(MBB, MBBI, DL,
+              TII->get(UseBKey ? AArch64::AUTIB : AArch64::AUTIA), AArch64::LR)
+          .addUse(AArch64::LR)
+          .addUse(AArch64::X16)
+          .setMIFlag(MachineInstr::FrameDestroy);
+      emitAUTCFI(MBB, MBBI, EmitAsyncCFI);
     } else {
+      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
+          .addReg(AArch64::XZR)
+          .addReg(AArch64::LR)
+          .addImm(0)
+          .setMIFlag(MachineInstr::FrameDestroy);
+
       unsigned AutOpc = UseBKey ? AArch64::AUTIB1716 : AArch64::AUTIA1716;
       BuildMI(MBB, MBBI, DL, TII->get(AutOpc))
           .setMIFlag(MachineInstr::FrameDestroy);
       emitAUTCFI(MBB, MBBI, EmitAsyncCFI);
-    }
 
-    BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::LR)
-        .addReg(AArch64::XZR)
-        .addReg(AArch64::X17)
-        .addImm(0)
-        .setMIFlag(MachineInstr::FrameDestroy);
+      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::LR)
+          .addReg(AArch64::XZR)
+          .addReg(AArch64::X17)
+          .addImm(0)
+          .setMIFlag(MachineInstr::FrameDestroy);
+    }
     return;
   }
 
diff --git a/llvm/test/CodeGen/AArch64/arm64e-tail-call-autib.ll b/llvm/test/CodeGen/AArch64/arm64e-tail-call-autib.ll
index d8e22b0c3cb04..bb478b0358c40 100644
--- a/llvm/test/CodeGen/AArch64/arm64e-tail-call-autib.ll
+++ b/llvm/test/CodeGen/AArch64/arm64e-tail-call-autib.ll
@@ -39,9 +39,7 @@ define swifttailcc void @test_async_tail_call(ptr swiftasync %ctx) "ptrauth-retu
 ; CHECK-NEXT:    and x29, x29, #0xefffffffffffffff
 ; CHECK-NEXT:    add sp, sp, #32
 ; CHECK-NEXT:    add x16, sp, #16
-; CHECK-NEXT:    mov x17, x30
-; CHECK-NEXT:    autib1716
-; CHECK-NEXT:    mov x30, x17
+; CHECK-NEXT:    autib x30, x16
 ; CHECK-NEXT:    eor x16, x30, x30, lsl #1
 ; CHECK-NEXT:    tbz x16, #62, Lauth_success_0
 ; CHECK-NEXT:    brk #0xc471
diff --git a/llvm/test/CodeGen/AArch64/pauth-lr-tail-call-fpdiff.ll b/llvm/test/CodeGen/AArch64/pauth-lr-tail-call-fpdiff.ll
index fac71d5ec4a59..04e0585a50593 100644
--- a/llvm/test/CodeGen/AArch64/pauth-lr-tail-call-fpdiff.ll
+++ b/llvm/test/CodeGen/AArch64/pauth-lr-tail-call-fpdiff.ll
@@ -61,26 +61,30 @@ define swifttailcc void @tail_call_fpdiff_a_key(ptr swiftasync %ctx) "branch-pro
 ; CHECK-NEXT:    .cfi_restore w30
 ; CHECK-NEXT:    .cfi_restore w29
 ; CHECK-NEXT:    add x16, sp, #16
-; CHECK-NEXT:    mov x17, x30
 
+; COMPAT-NEXT:   mov x17, x30
 ; COMPAT-NEXT:   adrp x15, .Ltmp0
 ; COMPAT-NEXT:   add x15, x15, :lo12:.Ltmp0
 ; COMPAT-NEXT:   hint #39
 ; COMPAT-NEXT:   hint #12
+; COMPAT-NEXT:   mov x30, x17
 
+; V83A-NEXT:     mov x17, x30
 ; V83A-NEXT:     adrp x15, .Ltmp0
 ; V83A-NEXT:     add x15, x15, :lo12:.Ltmp0
 ; V83A-NEXT:     hint #39
 ; V83A-NEXT:     autia1716
+; V83A-NEXT:     mov x30, x17
 
+; V9A-NEXT:      mov x17, x30
 ; V9A-NEXT:      adrp x15, .Ltmp0
 ; V9A-NEXT:      add x15, x15, :lo12:.Ltmp0
 ; V9A-NEXT:      autia171615
+; V9A-NEXT:      mov x30, x17
 
-; PAUTH-NEXT:    autia1716
+; PAUTH-NEXT:    autia x30, x16
 ; PAUTH-NEXT:    .cfi_negate_ra_state
 
-; CHECK-NEXT:    mov x30, x17
 ; CHECK-NEXT:    b callee_stack_args
   musttail call swifttailcc void @callee_stack_args(ptr swiftasync %ctx, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9)
   ret void
@@ -136,26 +140,30 @@ define swifttailcc void @tail_call_fpdiff_b_key(ptr swiftasync %ctx) "branch-pro
 ; CHECK-NEXT:    .cfi_restore w30
 ; CHECK-NEXT:    .cfi_restore w29
 ; CHECK-NEXT:    add x16, sp, #16
-; CHECK-NEXT:    mov x17, x30
 
+; COMPAT-NEXT:   mov x17, x30
 ; COMPAT-NEXT:   adrp x15, .Ltmp1
 ; COMPAT-NEXT:   add x15, x15, :lo12:.Ltmp1
 ; COMPAT-NEXT:   hint #39
 ; COMPAT-NEXT:   hint #14
+; COMPAT-NEXT:   mov x30, x17
 
+; V83A-NEXT:     mov x17, x30
 ; V83A-NEXT:     adrp x15, .Ltmp1
 ; V83A-NEXT:     add x15, x15, :lo12:.Ltmp1
 ; V83A-NEXT:     hint #39
 ; V83A-NEXT:     autib1716
+; V83A-NEXT:     mov x30, x17
 
+; V9A-NEXT:      mov x17, x30
 ; V9A-NEXT:      adrp x15, .Ltmp1
 ; V9A-NEXT:      add x15, x15, :lo12:.Ltmp1
 ; V9A-NEXT:      autib171615
+; V9A-NEXT:      mov x30, x17
 
-; PAUTH-NEXT:    autib1716
+; PAUTH-NEXT:    autib x30, x16
 ; PAUTH-NEXT:    .cfi_negate_ra_state
 
-; CHECK-NEXT:    mov x30, x17
 ; CHECK-NEXT:    b callee_stack_args
   musttail call swifttailcc void @callee_stack_args(ptr swiftasync %ctx, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9)
   ret void
@@ -330,26 +338,30 @@ define swifttailcc void @indirect_tail_call_fpdiff_a_key(ptr swiftasync %ctx, pt
 ; CHECK-NEXT:    .cfi_restore w30
 ; CHECK-NEXT:    .cfi_restore w29
 ; CHECK-NEXT:    add x16, sp, #16
-; CHECK-NEXT:    mov x17, x30
 
+; COMPAT-NEXT:   mov x17, x30
 ; COMPAT-NEXT:   adrp x15, .Ltmp4
 ; COMPAT-NEXT:   add x15, x15, :lo12:.Ltmp4
 ; COMPAT-NEXT:   hint #39
 ; COMPAT-NEXT:   hint #12
+; COMPAT-NEXT:   mov x30, x17
 
+; V83A-NEXT:     mov x17, x30
 ; V83A-NEXT:     adrp x15, .Ltmp4
 ; V83A-NEXT:     add x15, x15, :lo12:.Ltmp4
 ; V83A-NEXT:     hint #39
 ; V83A-NEXT:     autia1716
+; V83A-NEXT:     mov x30, x17
 
+; V9A-NEXT:      mov x17, x30
 ; V9A-NEXT:      adrp x15, .Ltmp4
 ; V9A-NEXT:      add x15, x15, :lo12:.Ltmp4
 ; V9A-NEXT:      autia171615
+; V9A-NEXT:      mov x30, x17
 
-; PAUTH-NEXT:    autia1716
+; PAUTH-NEXT:    autia x30, x16
 ; PAUTH-NEXT:    .cfi_negate_ra_state
 
-; CHECK-NEXT:    mov x30, x17
 ; CHECK-NEXT:    br x8
   musttail call swifttailcc void %callee(ptr swiftasync %ctx, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9)
   ret void
@@ -406,26 +418,30 @@ define swifttailcc void @indirect_tail_call_fpdiff_b_key(ptr swiftasync %ctx, pt
 ; CHECK-NEXT:    .cfi_restore w30
 ; CHECK-NEXT:    .cfi_restore w29
 ; CHECK-NEXT:    add x16, sp, #16
-; CHECK-NEXT:    mov x17, x30
 
+; COMPAT-NEXT:   mov x17, x30
 ; COMPAT-NEXT:   adrp x15, .Ltmp5
 ; COMPAT-NEXT:   add x15, x15, :lo12:.Ltmp5
 ; COMPAT-NEXT:   hint #39
 ; COMPAT-NEXT:   hint #14
+; COMPAT-NEXT:   mov x30, x17
 
+; V83A-NEXT:     mov x17, x30
 ; V83A-NEXT:     adrp x15, .Ltmp5
 ; V83A-NEXT:     add x15, x15, :lo12:.Ltmp5
 ; V83A-NEXT:     hint #39
 ; V83A-NEXT:     autib1716
+; V83A-NEXT:     mov x30, x17
 
+; V9A-NEXT:      mov x17, x30
 ; V9A-NEXT:      adrp x15, .Ltmp5
 ; V9A-NEXT:      add x15, x15, :lo12:.Ltmp5
 ; V9A-NEXT:      autib171615
+; V9A-NEXT:      mov x30, x17
 
-; PAUTH-NEXT:    autib1716
+; PAUTH-NEXT:    autib x30, x16
 ; PAUTH-NEXT:    .cfi_negate_ra_state
 
-; CHECK-NEXT:    mov x30, x17
 ; CHECK-NEXT:    br x8
   musttail call swifttailcc void %callee(ptr swiftasync %ctx, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9)
   ret void
diff --git a/llvm/test/CodeGen/AArch64/swifttail-ptrauth.ll b/llvm/test/CodeGen/AArch64/swifttail-ptrauth.ll
index bf074c4966e4b..18466af6894e0 100644
--- a/llvm/test/CodeGen/AArch64/swifttail-ptrauth.ll
+++ b/llvm/test/CodeGen/AArch64/swifttail-ptrauth.ll
@@ -167,26 +167,30 @@ define swifttailcc void @caller_to8_from0() "branch-protection-pauth-lr" "sign-r
 ; CHECK-NEXT:    .cfi_restore w30
 ; CHECK-NEXT:    .cfi_restore w29
 ; CHECK-NEXT:    add x16, sp, #16
-; CHECK-NEXT:    mov x17, x30
 
+; COMPAT-NEXT:   mov x17, x30
 ; COMPAT-NEXT:   adrp x15, .Ltmp2
 ; COMPAT-NEXT:   add x15, x15, :lo12:.Ltmp2
 ; COMPAT-NEXT:   hint #39
 ; COMPAT-NEXT:   hint #12
+; COMPAT-NEXT:   mov x30, x17
 
+; V83A-NEXT:     mov x17, x30
 ; V83A-NEXT:     adrp x15, .Ltmp2
 ; V83A-NEXT:     add x15, x15, :lo12:.Ltmp2
 ; V83A-NEXT:     hint #39
 ; V83A-NEXT:     autia1716
+; V83A-NEXT:     mov x30, x17
 
+; V9A-NEXT:      mov x17, x30
 ; V9A-NEXT:      adrp x15, .Ltmp2
 ; V9A-NEXT:      add x15, x15, :lo12:.Ltmp2
 ; V9A-NEXT:      autia171615
+; V9A-NEXT:      mov x30, x17
 
-; PAUTH-NEXT:    autia1716
+; PAUTH-NEXT:    autia x30, x16
 ; PAUTH-NEXT:    .cfi_negate_ra_state
 
-; CHECK-NEXT:    mov x30, x17
 ; CHECK-NEXT:    b callee_stack8
   tail call swifttailcc void @callee_stack8([8 x i64] poison, i64 42)
   ret void

>From e95cea77d6c844be4ff92fd57215c17ef6b0e6c9 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Thu, 23 Jul 2026 09:00:01 -0700
Subject: [PATCH 2/2] mov lambda

---
 .../lib/Target/AArch64/AArch64PointerAuth.cpp | 40 ++++++-------------
 1 file changed, 12 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp
index 94cade25c4ffe..a6dc926950d71 100644
--- a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp
+++ b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp
@@ -269,12 +269,16 @@ void AArch64PointerAuthImpl::authenticateLR(
                     StackOffset::getFixed(-ArgumentStackToRestore), TII,
                     MachineInstr::FrameDestroy);
 
-    if (MFnI->branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) {
-      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
+    auto emitMOV = [&](Register Dst, Register Src) {
+      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), Dst)
           .addReg(AArch64::XZR)
-          .addReg(AArch64::LR)
+          .addReg(Src)
           .addImm(0)
           .setMIFlag(MachineInstr::FrameDestroy);
+    };
+
+    if (MFnI->branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) {
+      emitMOV(AArch64::X17, AArch64::LR);
 
       assert(PACSym && "No PAC instruction to refer to");
       emitEpiloguePACSymOffsetIntoReg(*TII, MBB, MBBI, DL, PACSym,
@@ -285,17 +289,9 @@ void AArch64PointerAuthImpl::authenticateLR(
       BuildMI(MBB, MBBI, DL, TII->get(AutOpc))
           .setMIFlag(MachineInstr::FrameDestroy);
 
-      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::LR)
-          .addReg(AArch64::XZR)
-          .addReg(AArch64::X17)
-          .addImm(0)
-          .setMIFlag(MachineInstr::FrameDestroy);
+      emitMOV(AArch64::LR, AArch64::X17);
     } else if (MFnI->branchProtectionPAuthLR()) {
-      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
-          .addReg(AArch64::XZR)
-          .addReg(AArch64::LR)
-          .addImm(0)
-          .setMIFlag(MachineInstr::FrameDestroy);
+      emitMOV(AArch64::X17, AArch64::LR);
 
       assert(PACSym && "No PAC instruction to refer to");
       emitEpiloguePACSymOffsetIntoReg(*TII, MBB, MBBI, DL, PACSym,
@@ -314,11 +310,7 @@ void AArch64PointerAuthImpl::authenticateLR(
       BuildMI(MBB, MBBI, DL, TII->get(AutOpc))
           .setMIFlag(MachineInstr::FrameDestroy);
 
-      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::LR)
-          .addReg(AArch64::XZR)
-          .addReg(AArch64::X17)
-          .addImm(0)
-          .setMIFlag(MachineInstr::FrameDestroy);
+      emitMOV(AArch64::LR, AArch64::X17);
     } else if (Subtarget->hasPAuth()) {
       BuildMI(MBB, MBBI, DL,
               TII->get(UseBKey ? AArch64::AUTIB : AArch64::AUTIA), AArch64::LR)
@@ -327,22 +319,14 @@ void AArch64PointerAuthImpl::authenticateLR(
           .setMIFlag(MachineInstr::FrameDestroy);
       emitAUTCFI(MBB, MBBI, EmitAsyncCFI);
     } else {
-      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
-          .addReg(AArch64::XZR)
-          .addReg(AArch64::LR)
-          .addImm(0)
-          .setMIFlag(MachineInstr::FrameDestroy);
+      emitMOV(AArch64::X17, AArch64::LR);
 
       unsigned AutOpc = UseBKey ? AArch64::AUTIB1716 : AArch64::AUTIA1716;
       BuildMI(MBB, MBBI, DL, TII->get(AutOpc))
           .setMIFlag(MachineInstr::FrameDestroy);
       emitAUTCFI(MBB, MBBI, EmitAsyncCFI);
 
-      BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::LR)
-          .addReg(AArch64::XZR)
-          .addReg(AArch64::X17)
-          .addImm(0)
-          .setMIFlag(MachineInstr::FrameDestroy);
+      emitMOV(AArch64::LR, AArch64::X17);
     }
     return;
   }



More information about the llvm-commits mailing list