[llvm] [AArch64][SME] Handle SME state around Darwin TLS-descriptor calls (PR #216017)

Benjamin Maxwell via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 19 04:06:07 PDT 2026


https://github.com/MacDue updated https://github.com/llvm/llvm-project/pull/216017

>From 09d7571685b10c6d13839dfbce236aa0982fe262 Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Thu, 13 Aug 2026 11:33:25 +0000
Subject: [PATCH 1/3] Precommit tests

---
 llvm/lib/Target/AArch64/MachineSMEABIPass.cpp |  2 +
 llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll  | 57 +++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/llvm/lib/Target/AArch64/MachineSMEABIPass.cpp b/llvm/lib/Target/AArch64/MachineSMEABIPass.cpp
index feceed10d9a95..076917d242c79 100644
--- a/llvm/lib/Target/AArch64/MachineSMEABIPass.cpp
+++ b/llvm/lib/Target/AArch64/MachineSMEABIPass.cpp
@@ -439,6 +439,8 @@ static void setPhysLiveRegs(LiveRegUnits &LiveUnits, LiveRegs PhysLiveRegs) {
 
 [[maybe_unused]] bool isCallStartOpcode(unsigned Opc) {
   switch (Opc) {
+  case AArch64::BLR:
+  case AArch64::BLRA:
   case AArch64::TLSDESC_CALLSEQ:
   case AArch64::TLSDESC_AUTH_CALLSEQ:
   case AArch64::ADJCALLSTACKDOWN:
diff --git a/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll b/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll
index 49d163e966837..c9df7c58c60ee 100644
--- a/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll
+++ b/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
 ; RUN: llc -mtriple=aarch64-unknown-linux-gnu -mattr=+sme2 -relocation-model=pic < %s | FileCheck %s
+; RUN: llc -mtriple=arm64-apple-macosx12.0.0 -mattr=+sme2 -relocation-model=pic < %s | FileCheck %s -check-prefix=CHECK-DARWIN
 
 @x = external thread_local local_unnamed_addr global i32, align 4
 
@@ -33,6 +34,20 @@ define i32 @load_tls_streaming_compat() nounwind "aarch64_pstate_sm_compatible"
 ; CHECK-NEXT:    ldr x30, [sp, #64] // 8-byte Reload
 ; CHECK-NEXT:    ldp d15, d14, [sp], #80 // 16-byte Folded Reload
 ; CHECK-NEXT:    ret
+;
+; CHECK-DARWIN-LABEL: load_tls_streaming_compat:
+; CHECK-DARWIN:       ; %bb.0: ; %entry
+; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:  Lloh0:
+; CHECK-DARWIN-NEXT:    adrp x0, _x at TLVPPAGE
+; CHECK-DARWIN-NEXT:  Lloh1:
+; CHECK-DARWIN-NEXT:    ldr x0, [x0, _x at TLVPPAGEOFF]
+; CHECK-DARWIN-NEXT:    ldr x8, [x0]
+; CHECK-DARWIN-NEXT:    blr x8
+; CHECK-DARWIN-NEXT:    ldr w0, [x0]
+; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ret
+; CHECK-DARWIN-NEXT:    .loh AdrpLdr Lloh0, Lloh1
 entry:
   %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @x)
   %1 = load i32, ptr %0, align 4
@@ -62,6 +77,20 @@ define i32 @load_tls_streaming() nounwind "aarch64_pstate_sm_enabled" {
 ; CHECK-NEXT:    ldr x30, [sp, #64] // 8-byte Reload
 ; CHECK-NEXT:    ldp d15, d14, [sp], #80 // 16-byte Folded Reload
 ; CHECK-NEXT:    ret
+;
+; CHECK-DARWIN-LABEL: load_tls_streaming:
+; CHECK-DARWIN:       ; %bb.0: ; %entry
+; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:  Lloh2:
+; CHECK-DARWIN-NEXT:    adrp x0, _x at TLVPPAGE
+; CHECK-DARWIN-NEXT:  Lloh3:
+; CHECK-DARWIN-NEXT:    ldr x0, [x0, _x at TLVPPAGEOFF]
+; CHECK-DARWIN-NEXT:    ldr x8, [x0]
+; CHECK-DARWIN-NEXT:    blr x8
+; CHECK-DARWIN-NEXT:    ldr w0, [x0]
+; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ret
+; CHECK-DARWIN-NEXT:    .loh AdrpLdr Lloh2, Lloh3
 entry:
   %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @x)
   %1 = load i32, ptr %0, align 4
@@ -100,6 +129,20 @@ define i32 @load_tls_shared_za() nounwind "aarch64_inout_za" {
 ; CHECK-NEXT:    mov sp, x29
 ; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
 ; CHECK-NEXT:    ret
+;
+; CHECK-DARWIN-LABEL: load_tls_shared_za:
+; CHECK-DARWIN:       ; %bb.0: ; %entry
+; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:  Lloh4:
+; CHECK-DARWIN-NEXT:    adrp x0, _x at TLVPPAGE
+; CHECK-DARWIN-NEXT:  Lloh5:
+; CHECK-DARWIN-NEXT:    ldr x0, [x0, _x at TLVPPAGEOFF]
+; CHECK-DARWIN-NEXT:    ldr x8, [x0]
+; CHECK-DARWIN-NEXT:    blr x8
+; CHECK-DARWIN-NEXT:    ldr w0, [x0]
+; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ret
+; CHECK-DARWIN-NEXT:    .loh AdrpLdr Lloh4, Lloh5
 entry:
   %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @x)
   %1 = load i32, ptr %0, align 4
@@ -150,6 +193,20 @@ define i32 @load_tls_streaming_shared_za() nounwind "aarch64_inout_za" "aarch64_
 ; CHECK-NEXT:    ldp d13, d12, [sp, #16] // 16-byte Folded Reload
 ; CHECK-NEXT:    ldp d15, d14, [sp], #96 // 16-byte Folded Reload
 ; CHECK-NEXT:    ret
+;
+; CHECK-DARWIN-LABEL: load_tls_streaming_shared_za:
+; CHECK-DARWIN:       ; %bb.0: ; %entry
+; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:  Lloh6:
+; CHECK-DARWIN-NEXT:    adrp x0, _x at TLVPPAGE
+; CHECK-DARWIN-NEXT:  Lloh7:
+; CHECK-DARWIN-NEXT:    ldr x0, [x0, _x at TLVPPAGEOFF]
+; CHECK-DARWIN-NEXT:    ldr x8, [x0]
+; CHECK-DARWIN-NEXT:    blr x8
+; CHECK-DARWIN-NEXT:    ldr w0, [x0]
+; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ret
+; CHECK-DARWIN-NEXT:    .loh AdrpLdr Lloh6, Lloh7
 entry:
   %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @x)
   %1 = load i32, ptr %0, align 4

>From 5351a1d79319e06648781368da72f6e2983c42c5 Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Thu, 13 Aug 2026 11:35:39 +0000
Subject: [PATCH 2/3] [AArch64][SME] Handle SME state around Darwin
 TLS-descriptor calls

Handle Darwin TLS descriptor calls like we handle ELF/Linux calls
(see #155608).

Fixes #215824
---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  22 ++++
 llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll  | 105 +++++++++++++++---
 2 files changed, 113 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index d0fc6c064e31d..f6ad545725e68 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -11492,6 +11492,17 @@ AArch64TargetLowering::LowerDarwinGlobalTLSAddress(SDValue Op,
   // returns the address of the variable in this thread.
   Chain = DAG.getCopyToReg(Chain, DL, AArch64::X0, DescAddr, SDValue());
 
+  auto &MF = DAG.getMachineFunction();
+  auto *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
+
+  SMECallAttrs TLSCallAttrs(FuncInfo->getSMEFnAttrs(), {}, SMEAttrs::Normal);
+  bool RequiresSMChange = TLSCallAttrs.requiresSMChange();
+
+  if (RequiresSMChange)
+    Chain =
+        changeStreamingMode(DAG, DL, /*Enable=*/false, Chain, Chain.getValue(1),
+                            getSMToggleCondition(TLSCallAttrs));
+
   unsigned Opcode = AArch64ISD::CALL;
   SmallVector<SDValue, 8> Ops;
   Ops.push_back(Chain);
@@ -11509,6 +11520,17 @@ AArch64TargetLowering::LowerDarwinGlobalTLSAddress(SDValue Op,
   Ops.push_back(DAG.getRegisterMask(Mask));
   Ops.push_back(Chain.getValue(1));
   Chain = DAG.getNode(Opcode, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops);
+
+  if (TLSCallAttrs.requiresLazySave())
+    Chain = DAG.getNode(AArch64ISD::REQUIRES_ZA_SAVE, DL,
+                        DAG.getVTList(MVT::Other, MVT::Glue),
+                        {Chain, Chain.getValue(1)});
+
+  if (RequiresSMChange)
+    Chain =
+        changeStreamingMode(DAG, DL, /*Enable=*/true, Chain, Chain.getValue(1),
+                            getSMToggleCondition(TLSCallAttrs));
+
   return DAG.getCopyFromReg(Chain, DL, AArch64::X0, PtrVT, Chain.getValue(1));
 }
 
diff --git a/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll b/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll
index c9df7c58c60ee..97ef68882dd16 100644
--- a/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll
+++ b/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll
@@ -37,15 +37,32 @@ define i32 @load_tls_streaming_compat() nounwind "aarch64_pstate_sm_compatible"
 ;
 ; CHECK-DARWIN-LABEL: load_tls_streaming_compat:
 ; CHECK-DARWIN:       ; %bb.0: ; %entry
-; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp d15, d14, [sp, #-80]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp d13, d12, [sp, #16] ; 16-byte Folded Spill
 ; CHECK-DARWIN-NEXT:  Lloh0:
 ; CHECK-DARWIN-NEXT:    adrp x0, _x at TLVPPAGE
+; CHECK-DARWIN-NEXT:    stp d11, d10, [sp, #32] ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp d9, d8, [sp, #48] ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #64] ; 16-byte Folded Spill
 ; CHECK-DARWIN-NEXT:  Lloh1:
 ; CHECK-DARWIN-NEXT:    ldr x0, [x0, _x at TLVPPAGEOFF]
-; CHECK-DARWIN-NEXT:    ldr x8, [x0]
-; CHECK-DARWIN-NEXT:    blr x8
+; CHECK-DARWIN-NEXT:    mrs x8, SVCR
+; CHECK-DARWIN-NEXT:    ldr x9, [x0]
+; CHECK-DARWIN-NEXT:    tbz w8, #0, LBB0_2
+; CHECK-DARWIN-NEXT:  ; %bb.1: ; %entry
+; CHECK-DARWIN-NEXT:    smstop sm
+; CHECK-DARWIN-NEXT:  LBB0_2: ; %entry
+; CHECK-DARWIN-NEXT:    blr x9
+; CHECK-DARWIN-NEXT:    tbz w8, #0, LBB0_4
+; CHECK-DARWIN-NEXT:  ; %bb.3: ; %entry
+; CHECK-DARWIN-NEXT:    smstart sm
+; CHECK-DARWIN-NEXT:  LBB0_4: ; %entry
+; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp, #64] ; 16-byte Folded Reload
 ; CHECK-DARWIN-NEXT:    ldr w0, [x0]
-; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d9, d8, [sp, #48] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d11, d10, [sp, #32] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d13, d12, [sp, #16] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d15, d14, [sp], #80 ; 16-byte Folded Reload
 ; CHECK-DARWIN-NEXT:    ret
 ; CHECK-DARWIN-NEXT:    .loh AdrpLdr Lloh0, Lloh1
 entry:
@@ -80,15 +97,25 @@ define i32 @load_tls_streaming() nounwind "aarch64_pstate_sm_enabled" {
 ;
 ; CHECK-DARWIN-LABEL: load_tls_streaming:
 ; CHECK-DARWIN:       ; %bb.0: ; %entry
-; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp d15, d14, [sp, #-80]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp d13, d12, [sp, #16] ; 16-byte Folded Spill
 ; CHECK-DARWIN-NEXT:  Lloh2:
 ; CHECK-DARWIN-NEXT:    adrp x0, _x at TLVPPAGE
+; CHECK-DARWIN-NEXT:    stp d11, d10, [sp, #32] ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp d9, d8, [sp, #48] ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #64] ; 16-byte Folded Spill
 ; CHECK-DARWIN-NEXT:  Lloh3:
 ; CHECK-DARWIN-NEXT:    ldr x0, [x0, _x at TLVPPAGEOFF]
 ; CHECK-DARWIN-NEXT:    ldr x8, [x0]
+; CHECK-DARWIN-NEXT:    smstop sm
 ; CHECK-DARWIN-NEXT:    blr x8
+; CHECK-DARWIN-NEXT:    smstart sm
+; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp, #64] ; 16-byte Folded Reload
 ; CHECK-DARWIN-NEXT:    ldr w0, [x0]
-; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d9, d8, [sp, #48] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d11, d10, [sp, #32] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d13, d12, [sp, #16] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d15, d14, [sp], #80 ; 16-byte Folded Reload
 ; CHECK-DARWIN-NEXT:    ret
 ; CHECK-DARWIN-NEXT:    .loh AdrpLdr Lloh2, Lloh3
 entry:
@@ -133,13 +160,32 @@ define i32 @load_tls_shared_za() nounwind "aarch64_inout_za" {
 ; CHECK-DARWIN-LABEL: load_tls_shared_za:
 ; CHECK-DARWIN:       ; %bb.0: ; %entry
 ; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    mov x29, sp
+; CHECK-DARWIN-NEXT:    sub sp, sp, #16
+; CHECK-DARWIN-NEXT:    rdsvl x8, #1
+; CHECK-DARWIN-NEXT:    mov x9, sp
+; CHECK-DARWIN-NEXT:    msub x9, x8, x8, x9
+; CHECK-DARWIN-NEXT:    mov sp, x9
 ; CHECK-DARWIN-NEXT:  Lloh4:
 ; CHECK-DARWIN-NEXT:    adrp x0, _x at TLVPPAGE
+; CHECK-DARWIN-NEXT:    sub x11, x29, #16
 ; CHECK-DARWIN-NEXT:  Lloh5:
 ; CHECK-DARWIN-NEXT:    ldr x0, [x0, _x at TLVPPAGEOFF]
-; CHECK-DARWIN-NEXT:    ldr x8, [x0]
-; CHECK-DARWIN-NEXT:    blr x8
-; CHECK-DARWIN-NEXT:    ldr w0, [x0]
+; CHECK-DARWIN-NEXT:    stp x9, x8, [x29, #-16]
+; CHECK-DARWIN-NEXT:    msr TPIDR2_EL0, x11
+; CHECK-DARWIN-NEXT:    ldr x10, [x0]
+; CHECK-DARWIN-NEXT:    blr x10
+; CHECK-DARWIN-NEXT:    ldr w8, [x0]
+; CHECK-DARWIN-NEXT:    smstart za
+; CHECK-DARWIN-NEXT:    mrs x9, TPIDR2_EL0
+; CHECK-DARWIN-NEXT:    sub x0, x29, #16
+; CHECK-DARWIN-NEXT:    cbnz x9, LBB2_2
+; CHECK-DARWIN-NEXT:  ; %bb.1: ; %entry
+; CHECK-DARWIN-NEXT:    bl ___arm_tpidr2_restore
+; CHECK-DARWIN-NEXT:  LBB2_2: ; %entry
+; CHECK-DARWIN-NEXT:    mov w0, w8
+; CHECK-DARWIN-NEXT:    msr TPIDR2_EL0, xzr
+; CHECK-DARWIN-NEXT:    mov sp, x29
 ; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
 ; CHECK-DARWIN-NEXT:    ret
 ; CHECK-DARWIN-NEXT:    .loh AdrpLdr Lloh4, Lloh5
@@ -196,15 +242,46 @@ define i32 @load_tls_streaming_shared_za() nounwind "aarch64_inout_za" "aarch64_
 ;
 ; CHECK-DARWIN-LABEL: load_tls_streaming_shared_za:
 ; CHECK-DARWIN:       ; %bb.0: ; %entry
-; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp d15, d14, [sp, #-96]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp d13, d12, [sp, #16] ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp d11, d10, [sp, #32] ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp d9, d8, [sp, #48] ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp x20, x19, [sp, #64] ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #80] ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    add x29, sp, #80
+; CHECK-DARWIN-NEXT:    sub sp, sp, #16
+; CHECK-DARWIN-NEXT:    rdsvl x8, #1
+; CHECK-DARWIN-NEXT:    mov x9, sp
+; CHECK-DARWIN-NEXT:    msub x9, x8, x8, x9
+; CHECK-DARWIN-NEXT:    mov sp, x9
 ; CHECK-DARWIN-NEXT:  Lloh6:
 ; CHECK-DARWIN-NEXT:    adrp x0, _x at TLVPPAGE
 ; CHECK-DARWIN-NEXT:  Lloh7:
 ; CHECK-DARWIN-NEXT:    ldr x0, [x0, _x at TLVPPAGEOFF]
-; CHECK-DARWIN-NEXT:    ldr x8, [x0]
-; CHECK-DARWIN-NEXT:    blr x8
-; CHECK-DARWIN-NEXT:    ldr w0, [x0]
-; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    stp x9, x8, [x29, #-96]
+; CHECK-DARWIN-NEXT:    ldr x10, [x0]
+; CHECK-DARWIN-NEXT:    smstop sm
+; CHECK-DARWIN-NEXT:    sub x8, x29, #96
+; CHECK-DARWIN-NEXT:    msr TPIDR2_EL0, x8
+; CHECK-DARWIN-NEXT:    blr x10
+; CHECK-DARWIN-NEXT:    smstart sm
+; CHECK-DARWIN-NEXT:    ldr w8, [x0]
+; CHECK-DARWIN-NEXT:    smstart za
+; CHECK-DARWIN-NEXT:    mrs x9, TPIDR2_EL0
+; CHECK-DARWIN-NEXT:    sub x0, x29, #96
+; CHECK-DARWIN-NEXT:    cbnz x9, LBB3_2
+; CHECK-DARWIN-NEXT:  ; %bb.1: ; %entry
+; CHECK-DARWIN-NEXT:    bl ___arm_tpidr2_restore
+; CHECK-DARWIN-NEXT:  LBB3_2: ; %entry
+; CHECK-DARWIN-NEXT:    mov w0, w8
+; CHECK-DARWIN-NEXT:    msr TPIDR2_EL0, xzr
+; CHECK-DARWIN-NEXT:    sub sp, x29, #80
+; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp, #80] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp x20, x19, [sp, #64] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d9, d8, [sp, #48] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d11, d10, [sp, #32] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d13, d12, [sp, #16] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ldp d15, d14, [sp], #96 ; 16-byte Folded Reload
 ; CHECK-DARWIN-NEXT:    ret
 ; CHECK-DARWIN-NEXT:    .loh AdrpLdr Lloh6, Lloh7
 entry:

>From 1065cdeb77ac721c32f6c0be9feed4be4adbf790 Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Wed, 19 Aug 2026 11:05:37 +0000
Subject: [PATCH 3/3] Rebase

---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  5 +-
 llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll  | 47 +++++++++++++++++++
 2 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index f6ad545725e68..36a86241fe3b2 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -11521,9 +11521,8 @@ AArch64TargetLowering::LowerDarwinGlobalTLSAddress(SDValue Op,
   Ops.push_back(Chain.getValue(1));
   Chain = DAG.getNode(Opcode, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops);
 
-  if (TLSCallAttrs.requiresLazySave())
-    Chain = DAG.getNode(AArch64ISD::REQUIRES_ZA_SAVE, DL,
-                        DAG.getVTList(MVT::Other, MVT::Glue),
+  if (std::optional<unsigned> ZAMarkerNode = getZAMarkerForCall(TLSCallAttrs))
+    Chain = DAG.getNode(*ZAMarkerNode, DL, DAG.getVTList(MVT::Other, MVT::Glue),
                         {Chain, Chain.getValue(1)});
 
   if (RequiresSMChange)
diff --git a/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll b/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll
index 97ef68882dd16..b7fd06adef3fc 100644
--- a/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll
+++ b/llvm/test/CodeGen/AArch64/sme-dynamic-tls.ll
@@ -313,6 +313,32 @@ define i32 @load_tls_agnostic_za() nounwind "aarch64_za_state_agnostic" {
 ; CHECK-NEXT:    mov sp, x29
 ; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
 ; CHECK-NEXT:    ret
+;
+; CHECK-DARWIN-LABEL: load_tls_agnostic_za:
+; CHECK-DARWIN:       ; %bb.0: ; %entry
+; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:    mov x29, sp
+; CHECK-DARWIN-NEXT:    bl ___arm_sme_state_size
+; CHECK-DARWIN-NEXT:    sub sp, sp, x0
+; CHECK-DARWIN-NEXT:  Lloh8:
+; CHECK-DARWIN-NEXT:    adrp x0, _x at TLVPPAGE
+; CHECK-DARWIN-NEXT:    mov x8, sp
+; CHECK-DARWIN-NEXT:  Lloh9:
+; CHECK-DARWIN-NEXT:    ldr x0, [x0, _x at TLVPPAGEOFF]
+; CHECK-DARWIN-NEXT:    mov x9, x0
+; CHECK-DARWIN-NEXT:    ldr x10, [x0]
+; CHECK-DARWIN-NEXT:    mov x0, x8
+; CHECK-DARWIN-NEXT:    bl ___arm_sme_save
+; CHECK-DARWIN-NEXT:    mov x0, x9
+; CHECK-DARWIN-NEXT:    blr x10
+; CHECK-DARWIN-NEXT:    ldr w9, [x0]
+; CHECK-DARWIN-NEXT:    mov x0, x8
+; CHECK-DARWIN-NEXT:    bl ___arm_sme_restore
+; CHECK-DARWIN-NEXT:    mov w0, w9
+; CHECK-DARWIN-NEXT:    mov sp, x29
+; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    ret
+; CHECK-DARWIN-NEXT:    .loh AdrpLdr Lloh8, Lloh9
 entry:
   %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @x)
   %1 = load i32, ptr %0, align 4
@@ -339,6 +365,27 @@ define i32 @load_tls_shared_zt0() nounwind "aarch64_inout_zt0" {
 ; CHECK-NEXT:    ldr x30, [sp, #64] // 8-byte Reload
 ; CHECK-NEXT:    add sp, sp, #80
 ; CHECK-NEXT:    ret
+;
+; CHECK-DARWIN-LABEL: load_tls_shared_zt0:
+; CHECK-DARWIN:       ; %bb.0: ; %entry
+; CHECK-DARWIN-NEXT:    sub sp, sp, #80
+; CHECK-DARWIN-NEXT:    stp x29, x30, [sp, #64] ; 16-byte Folded Spill
+; CHECK-DARWIN-NEXT:  Lloh10:
+; CHECK-DARWIN-NEXT:    adrp x0, _x at TLVPPAGE
+; CHECK-DARWIN-NEXT:    mov x9, sp
+; CHECK-DARWIN-NEXT:  Lloh11:
+; CHECK-DARWIN-NEXT:    ldr x0, [x0, _x at TLVPPAGEOFF]
+; CHECK-DARWIN-NEXT:    str zt0, [x9]
+; CHECK-DARWIN-NEXT:    ldr x8, [x0]
+; CHECK-DARWIN-NEXT:    smstop za
+; CHECK-DARWIN-NEXT:    blr x8
+; CHECK-DARWIN-NEXT:    ldr w0, [x0]
+; CHECK-DARWIN-NEXT:    smstart za
+; CHECK-DARWIN-NEXT:    ldr zt0, [x9]
+; CHECK-DARWIN-NEXT:    ldp x29, x30, [sp, #64] ; 16-byte Folded Reload
+; CHECK-DARWIN-NEXT:    add sp, sp, #80
+; CHECK-DARWIN-NEXT:    ret
+; CHECK-DARWIN-NEXT:    .loh AdrpLdr Lloh10, Lloh11
 entry:
   %0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @x)
   %1 = load i32, ptr %0, align 4



More information about the llvm-commits mailing list