[llvm] 8890be3 - [AArch64][GISel][FastISel] Fix Windows "sret inreg". (#225190)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 15:46:00 PDT 2026


Author: Eli Friedman
Date: 2026-09-22T15:45:53-07:00
New Revision: 8890be35705834c5af8e21424d7900639be03180

URL: https://github.com/llvm/llvm-project/commit/8890be35705834c5af8e21424d7900639be03180
DIFF: https://github.com/llvm/llvm-project/commit/8890be35705834c5af8e21424d7900639be03180.diff

LOG: [AArch64][GISel][FastISel] Fix Windows "sret inreg". (#225190)

5dc8aeb26d2896c65cbea0d3b87f090241444bb6 added a special case to
SelectionDAG ISel for "sret inreg" parameters: they are copied to x0 on
return. There was a review comment suggesting that GISel and FastISel
also needed fixes, but through some mixup the followup never happened.

Fixes #225060

Added: 
    

Modified: 
    llvm/lib/Target/AArch64/AArch64FastISel.cpp
    llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
    llvm/test/CodeGen/AArch64/arm64-windows-calls.ll
    llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp
index b6deb703893fd..caa0983ca5fb1 100644
--- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp
@@ -3851,6 +3851,9 @@ bool AArch64FastISel::selectRet(const Instruction *I) {
   if (!FuncInfo.CanLowerReturn)
     return false;
 
+  if (FuncInfo.MF->getInfo<AArch64FunctionInfo>()->getSRetReturnReg())
+    return false;
+
   if (F.isVarArg())
     return false;
 

diff  --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
index 6561b322deb55..ef86fea2acba6 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
@@ -768,9 +768,14 @@ bool AArch64CallLowering::lowerFormalArguments(
       F.getCallingConv() == CallingConv::ARM64EC_Thunk_X64)
     return false;
 
-  bool IsWin64 =
-      Subtarget.isCallingConvWin64(F.getCallingConv(), F.isVarArg()) &&
-      !Subtarget.isWindowsArm64EC();
+  bool IsWin64 = Subtarget.isCallingConvWin64(F.getCallingConv(), F.isVarArg());
+
+  // If an argument is marked "sret" and "inreg", it must be returned in x0.
+  // Bail for now.
+  if (IsWin64 && any_of(F.args(), [](const Argument &A) {
+        return A.hasStructRetAttr() && A.hasInRegAttr();
+      }))
+    return false;
 
   SmallVector<ArgInfo, 8> SplitArgs;
   SmallVector<std::pair<Register, Register>> BoolArgs;

diff  --git a/llvm/test/CodeGen/AArch64/arm64-windows-calls.ll b/llvm/test/CodeGen/AArch64/arm64-windows-calls.ll
index 41f00a6c41b3b..3305a6dce3029 100644
--- a/llvm/test/CodeGen/AArch64/arm64-windows-calls.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-windows-calls.ll
@@ -1,15 +1,95 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
-; FIXME: Add tests for global-isel/fast-isel.
 
-; RUN: llc < %s -mtriple=arm64-windows | FileCheck %s
+; RUN: llc < %s -mtriple=arm64-windows | FileCheck -check-prefixes=CHECK,CHECK-NOTGISEL,CHECK-SD %s
+; RUN: llc < %s -mtriple=arm64ec-windows-msvc -arm64ec-generate-thunks=false | FileCheck -check-prefixes=CHECK,CHECK-NOTGISEL,CHECK-EC-SD %s
+; RUN: llc < %s -mtriple=arm64-windows -fast-isel=0 -global-isel=1 -global-isel-abort=0 | FileCheck -check-prefixes=CHECK,CHECK-GI %s
+; RUN: llc < %s -mtriple=arm64-windows -fast-isel=1 -global-isel=0 | FileCheck -check-prefixes=CHECK,CHECK-NOTGISEL,CHECK-FAST %s
+; RUN: llc < %s -mtriple=arm64ec-windows-msvc -arm64ec-generate-thunks=false -fast-isel=0 -global-isel=1 -global-isel-abort=0 | FileCheck -check-prefixes=CHECK,CHECK-EC-GI %s
 
 ; Returns <= 8 bytes should be in X0.
 %struct.S1 = type { i32, i32 }
-define dso_local i64 @"?f1"() {
+define dso_local i64 @f1() {
+; CHECK-SD-LABEL: f1:
+; CHECK-SD:       .seh_proc f1
+; CHECK-SD-NEXT:  // %bb.0: // %entry
+; CHECK-SD-NEXT:    sub sp, sp, #16
+; CHECK-SD-NEXT:    .seh_stackalloc 16
+; CHECK-SD-NEXT:    .seh_endprologue
+; CHECK-SD-NEXT:    mov x0, xzr
+; CHECK-SD-NEXT:    str xzr, [sp, #8]
+; CHECK-SD-NEXT:    .seh_startepilogue
+; CHECK-SD-NEXT:    add sp, sp, #16
+; CHECK-SD-NEXT:    .seh_stackalloc 16
+; CHECK-SD-NEXT:    .seh_endepilogue
+; CHECK-SD-NEXT:    ret
+; CHECK-SD-NEXT:    .seh_endfunclet
+; CHECK-SD-NEXT:    .seh_endproc
+;
+; CHECK-EC-SD-LABEL: f1:
+; CHECK-EC-SD:       .seh_proc f1
+; CHECK-EC-SD-NEXT:  // %bb.0: // %entry
+; CHECK-EC-SD-NEXT:    sub sp, sp, #16
+; CHECK-EC-SD-NEXT:    .seh_stackalloc 16
+; CHECK-EC-SD-NEXT:    .seh_endprologue
+; CHECK-EC-SD-NEXT:    mov x0, xzr
+; CHECK-EC-SD-NEXT:    str xzr, [sp, #8]
+; CHECK-EC-SD-NEXT:    .seh_startepilogue
+; CHECK-EC-SD-NEXT:    add sp, sp, #16
+; CHECK-EC-SD-NEXT:    .seh_stackalloc 16
+; CHECK-EC-SD-NEXT:    .seh_endepilogue
+; CHECK-EC-SD-NEXT:    ret
+; CHECK-EC-SD-NEXT:    .seh_endfunclet
+; CHECK-EC-SD-NEXT:    .seh_endproc
+;
+; CHECK-GI-LABEL: f1:
+; CHECK-GI:       .seh_proc f1
+; CHECK-GI-NEXT:  // %bb.0: // %entry
+; CHECK-GI-NEXT:    sub sp, sp, #16
+; CHECK-GI-NEXT:    .seh_stackalloc 16
+; CHECK-GI-NEXT:    .seh_endprologue
+; CHECK-GI-NEXT:    str xzr, [sp, #8]
+; CHECK-GI-NEXT:    mov x0, xzr
+; CHECK-GI-NEXT:    .seh_startepilogue
+; CHECK-GI-NEXT:    add sp, sp, #16
+; CHECK-GI-NEXT:    .seh_stackalloc 16
+; CHECK-GI-NEXT:    .seh_endepilogue
+; CHECK-GI-NEXT:    ret
+; CHECK-GI-NEXT:    .seh_endfunclet
+; CHECK-GI-NEXT:    .seh_endproc
+;
+; CHECK-FAST-LABEL: f1:
+; CHECK-FAST:       .seh_proc f1
+; CHECK-FAST-NEXT:  // %bb.0: // %entry
+; CHECK-FAST-NEXT:    sub sp, sp, #16
+; CHECK-FAST-NEXT:    .seh_stackalloc 16
+; CHECK-FAST-NEXT:    .seh_endprologue
+; CHECK-FAST-NEXT:    str xzr, [sp, #8]
+; CHECK-FAST-NEXT:    ldr x0, [sp, #8]
+; CHECK-FAST-NEXT:    .seh_startepilogue
+; CHECK-FAST-NEXT:    add sp, sp, #16
+; CHECK-FAST-NEXT:    .seh_stackalloc 16
+; CHECK-FAST-NEXT:    .seh_endepilogue
+; CHECK-FAST-NEXT:    ret
+; CHECK-FAST-NEXT:    .seh_endfunclet
+; CHECK-FAST-NEXT:    .seh_endproc
+;
+; CHECK-EC-GI-LABEL: f1:
+; CHECK-EC-GI:       .seh_proc f1
+; CHECK-EC-GI-NEXT:  // %bb.0: // %entry
+; CHECK-EC-GI-NEXT:    sub sp, sp, #16
+; CHECK-EC-GI-NEXT:    .seh_stackalloc 16
+; CHECK-EC-GI-NEXT:    .seh_endprologue
+; CHECK-EC-GI-NEXT:    str xzr, [sp, #8]
+; CHECK-EC-GI-NEXT:    mov x0, xzr
+; CHECK-EC-GI-NEXT:    .seh_startepilogue
+; CHECK-EC-GI-NEXT:    add sp, sp, #16
+; CHECK-EC-GI-NEXT:    .seh_stackalloc 16
+; CHECK-EC-GI-NEXT:    .seh_endepilogue
+; CHECK-EC-GI-NEXT:    ret
+; CHECK-EC-GI-NEXT:    .seh_endfunclet
+; CHECK-EC-GI-NEXT:    .seh_endproc
+
 entry:
-; CHECK-LABEL: f1
-; CHECK-DAG: str xzr, [sp, #8]
-; CHECK-DAG: mov x0, xzr
 
   %retval = alloca %struct.S1, align 4
   store i32 0, ptr %retval, align 4
@@ -21,18 +101,60 @@ entry:
 
 ; Returns <= 16 bytes should be in X0/X1.
 %struct.S2 = type { i32, i32, i32, i32 }
-define dso_local [2 x i64] @"?f2"() {
+define dso_local [2 x i64] @f2() {
+; CHECK-NOTGISEL-LABEL: f2:
+; CHECK-NOTGISEL:       .seh_proc f2
+; CHECK-NOTGISEL-NEXT:  // %bb.0: // %entry
+; CHECK-NOTGISEL-NEXT:    sub sp, sp, #16
+; CHECK-NOTGISEL-NEXT:    .seh_stackalloc 16
+; CHECK-NOTGISEL-NEXT:    .seh_endprologue
+; CHECK-NOTGISEL-NEXT:    mov x0, xzr
+; CHECK-NOTGISEL-NEXT:    mov x1, xzr
+; CHECK-NOTGISEL-NEXT:    stp xzr, xzr, [sp]
+; CHECK-NOTGISEL-NEXT:    .seh_startepilogue
+; CHECK-NOTGISEL-NEXT:    add sp, sp, #16
+; CHECK-NOTGISEL-NEXT:    .seh_stackalloc 16
+; CHECK-NOTGISEL-NEXT:    .seh_endepilogue
+; CHECK-NOTGISEL-NEXT:    ret
+; CHECK-NOTGISEL-NEXT:    .seh_endfunclet
+; CHECK-NOTGISEL-NEXT:    .seh_endproc
+;
+; CHECK-GI-LABEL: f2:
+; CHECK-GI:       .seh_proc f2
+; CHECK-GI-NEXT:  // %bb.0: // %entry
+; CHECK-GI-NEXT:    sub sp, sp, #16
+; CHECK-GI-NEXT:    .seh_stackalloc 16
+; CHECK-GI-NEXT:    .seh_endprologue
+; CHECK-GI-NEXT:    stp xzr, xzr, [sp]
+; CHECK-GI-NEXT:    mov x0, xzr
+; CHECK-GI-NEXT:    mov x1, xzr
+; CHECK-GI-NEXT:    .seh_startepilogue
+; CHECK-GI-NEXT:    add sp, sp, #16
+; CHECK-GI-NEXT:    .seh_stackalloc 16
+; CHECK-GI-NEXT:    .seh_endepilogue
+; CHECK-GI-NEXT:    ret
+; CHECK-GI-NEXT:    .seh_endfunclet
+; CHECK-GI-NEXT:    .seh_endproc
+;
+; CHECK-EC-GI-LABEL: f2:
+; CHECK-EC-GI:       .seh_proc f2
+; CHECK-EC-GI-NEXT:  // %bb.0: // %entry
+; CHECK-EC-GI-NEXT:    sub sp, sp, #16
+; CHECK-EC-GI-NEXT:    .seh_stackalloc 16
+; CHECK-EC-GI-NEXT:    .seh_endprologue
+; CHECK-EC-GI-NEXT:    stp xzr, xzr, [sp]
+; CHECK-EC-GI-NEXT:    mov x0, xzr
+; CHECK-EC-GI-NEXT:    mov x1, xzr
+; CHECK-EC-GI-NEXT:    .seh_startepilogue
+; CHECK-EC-GI-NEXT:    add sp, sp, #16
+; CHECK-EC-GI-NEXT:    .seh_stackalloc 16
+; CHECK-EC-GI-NEXT:    .seh_endepilogue
+; CHECK-EC-GI-NEXT:    ret
+; CHECK-EC-GI-NEXT:    .seh_endfunclet
+; CHECK-EC-GI-NEXT:    .seh_endproc
+
 entry:
 ; FIXME: Missed optimization, the entire SP push/pop could be removed
-; CHECK-LABEL: f2
-; CHECK:         sub     sp, sp, #16
-; CHECK-NEXT:    .seh_stackalloc 16
-; CHECK-NEXT:    .seh_endprologue
-; CHECK-DAG:     stp     xzr, xzr, [sp]
-; CHECK-DAG:     mov     x0, xzr
-; CHECK-DAG:     mov     x1, xzr
-; CHECK:         .seh_startepilogue
-; CHECK-NEXT:    add     sp, sp, #16
 
   %retval = alloca %struct.S2, align 4
   store i32 0, ptr %retval, align 4
@@ -48,11 +170,13 @@ entry:
 
 ; Arguments > 16 bytes should be passed in X8.
 %struct.S3 = type { i32, i32, i32, i32, i32 }
-define dso_local void @"?f3"(ptr noalias sret(%struct.S3) %agg.result) {
+define dso_local void @f3(ptr noalias sret(%struct.S3) %agg.result) {
+; CHECK-LABEL: f3:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    stp xzr, xzr, [x8]
+; CHECK-NEXT:    str wzr, [x8, #16]
+; CHECK-NEXT:    ret
 entry:
-; CHECK-LABEL: f3
-; CHECK: stp xzr, xzr, [x8]
-; CHECK: str wzr, [x8, #16]
 
   store i32 0, ptr %agg.result, align 4
   %b = getelementptr inbounds %struct.S3, ptr %agg.result, i32 0, i32 1
@@ -69,11 +193,13 @@ entry:
 ; InReg arguments to non-instance methods must be passed in X0 and returns in
 ; X0.
 %class.B = type { i32 }
-define dso_local void @"?f4"(ptr inreg noalias nocapture sret(%class.B) %agg.result) {
+define dso_local void @f4(ptr inreg noalias nocapture sret(%class.B) %agg.result) {
+; CHECK-LABEL: f4:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    mov w8, #1 // =0x1
+; CHECK-NEXT:    str w8, [x0]
+; CHECK-NEXT:    ret
 entry:
-; CHECK-LABEL: f4
-; CHECK: mov w8, #1
-; CHECK: str w8, [x0]
   store i32 1, ptr %agg.result, align 4
   ret void
 }
@@ -82,11 +208,24 @@ entry:
 %class.C = type { i8 }
 %class.A = type { i8 }
 
-define dso_local void @"?inst at C"(ptr %this, ptr inreg noalias sret(%class.A) %agg.result) {
+define dso_local void @inst(ptr %this, ptr inreg noalias sret(%class.A) %agg.result) {
+; CHECK-LABEL: inst:
+; CHECK:       .seh_proc inst
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    sub sp, sp, #16
+; CHECK-NEXT:    .seh_stackalloc 16
+; CHECK-NEXT:    .seh_endprologue
+; CHECK-NEXT:    mov x8, x0
+; CHECK-NEXT:    mov x0, x1
+; CHECK-NEXT:    str x8, [sp, #8]
+; CHECK-NEXT:    .seh_startepilogue
+; CHECK-NEXT:    add sp, sp, #16
+; CHECK-NEXT:    .seh_stackalloc 16
+; CHECK-NEXT:    .seh_endepilogue
+; CHECK-NEXT:    ret
+; CHECK-NEXT:    .seh_endfunclet
+; CHECK-NEXT:    .seh_endproc
 entry:
-; CHECK-LABEL: inst at C
-; CHECK-DAG: mov x0, x1
-; CHECK-DAG: str x8, [sp, #8]
 
   %this.addr = alloca ptr, align 8
   store ptr %this, ptr %this.addr, align 8
@@ -140,28 +279,131 @@ define dso_local [2 x i64] @copy_notpod(ptr %x) {
 @Pod = external global %struct.Pod
 
 define void @call_copy_pod() {
-; CHECK-LABEL: call_copy_pod:
-; CHECK:       .seh_proc call_copy_pod
-; CHECK-NEXT:  // %bb.0:
-; CHECK-NEXT:    sub sp, sp, #16
-; CHECK-NEXT:    .seh_stackalloc 16
-; CHECK-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
-; CHECK-NEXT:    .seh_save_lrpair x19, 0
-; CHECK-NEXT:    .seh_endprologue
-; CHECK-NEXT:    adrp x19, Pod
-; CHECK-NEXT:    add x19, x19, :lo12:Pod
-; CHECK-NEXT:    mov x0, x19
-; CHECK-NEXT:    bl copy_pod
-; CHECK-NEXT:    stp d0, d1, [x19]
-; CHECK-NEXT:    .seh_startepilogue
-; CHECK-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
-; CHECK-NEXT:    .seh_save_lrpair x19, 0
-; CHECK-NEXT:    add sp, sp, #16
-; CHECK-NEXT:    .seh_stackalloc 16
-; CHECK-NEXT:    .seh_endepilogue
-; CHECK-NEXT:    ret
-; CHECK-NEXT:    .seh_endfunclet
-; CHECK-NEXT:    .seh_endproc
+; CHECK-SD-LABEL: call_copy_pod:
+; CHECK-SD:       .seh_proc call_copy_pod
+; CHECK-SD-NEXT:  // %bb.0:
+; CHECK-SD-NEXT:    sub sp, sp, #16
+; CHECK-SD-NEXT:    .seh_stackalloc 16
+; CHECK-SD-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
+; CHECK-SD-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-SD-NEXT:    .seh_endprologue
+; CHECK-SD-NEXT:    adrp x19, Pod
+; CHECK-SD-NEXT:    add x19, x19, :lo12:Pod
+; CHECK-SD-NEXT:    mov x0, x19
+; CHECK-SD-NEXT:    bl copy_pod
+; CHECK-SD-NEXT:    stp d0, d1, [x19]
+; CHECK-SD-NEXT:    .seh_startepilogue
+; CHECK-SD-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
+; CHECK-SD-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-SD-NEXT:    add sp, sp, #16
+; CHECK-SD-NEXT:    .seh_stackalloc 16
+; CHECK-SD-NEXT:    .seh_endepilogue
+; CHECK-SD-NEXT:    ret
+; CHECK-SD-NEXT:    .seh_endfunclet
+; CHECK-SD-NEXT:    .seh_endproc
+;
+; CHECK-EC-SD-LABEL: call_copy_pod:
+; CHECK-EC-SD:       .seh_proc call_copy_pod
+; CHECK-EC-SD-NEXT:  // %bb.0:
+; CHECK-EC-SD-NEXT:    sub sp, sp, #16
+; CHECK-EC-SD-NEXT:    .seh_stackalloc 16
+; CHECK-EC-SD-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
+; CHECK-EC-SD-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-EC-SD-NEXT:    .seh_endprologue
+; CHECK-EC-SD-NEXT:    adrp x19, Pod
+; CHECK-EC-SD-NEXT:    add x19, x19, :lo12:Pod
+; CHECK-EC-SD-NEXT:    mov x0, x19
+; CHECK-EC-SD-NEXT:    .weak_anti_dep copy_pod
+; CHECK-EC-SD-NEXT:  copy_pod = "#copy_pod"
+; CHECK-EC-SD-NEXT:    .weak_anti_dep "#copy_pod"
+; CHECK-EC-SD-NEXT:  "#copy_pod" = copy_pod
+; CHECK-EC-SD-NEXT:    bl "#copy_pod"
+; CHECK-EC-SD-NEXT:    stp d0, d1, [x19]
+; CHECK-EC-SD-NEXT:    .seh_startepilogue
+; CHECK-EC-SD-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
+; CHECK-EC-SD-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-EC-SD-NEXT:    add sp, sp, #16
+; CHECK-EC-SD-NEXT:    .seh_stackalloc 16
+; CHECK-EC-SD-NEXT:    .seh_endepilogue
+; CHECK-EC-SD-NEXT:    ret
+; CHECK-EC-SD-NEXT:    .seh_endfunclet
+; CHECK-EC-SD-NEXT:    .seh_endproc
+;
+; CHECK-GI-LABEL: call_copy_pod:
+; CHECK-GI:       .seh_proc call_copy_pod
+; CHECK-GI-NEXT:  // %bb.0:
+; CHECK-GI-NEXT:    stp x19, x20, [sp, #-32]! // 16-byte Folded Spill
+; CHECK-GI-NEXT:    .seh_save_regp_x x19, 32
+; CHECK-GI-NEXT:    str x30, [sp, #16] // 8-byte Spill
+; CHECK-GI-NEXT:    .seh_save_reg x30, 16
+; CHECK-GI-NEXT:    .seh_endprologue
+; CHECK-GI-NEXT:    adrp x19, Pod
+; CHECK-GI-NEXT:    add x19, x19, :lo12:Pod
+; CHECK-GI-NEXT:    adrp x20, Pod
+; CHECK-GI-NEXT:    mov x0, x19
+; CHECK-GI-NEXT:    bl copy_pod
+; CHECK-GI-NEXT:    str d0, [x20, :lo12:Pod]
+; CHECK-GI-NEXT:    str d1, [x19, #8]
+; CHECK-GI-NEXT:    .seh_startepilogue
+; CHECK-GI-NEXT:    ldr x30, [sp, #16] // 8-byte Reload
+; CHECK-GI-NEXT:    .seh_save_reg x30, 16
+; CHECK-GI-NEXT:    ldp x19, x20, [sp], #32 // 16-byte Folded Reload
+; CHECK-GI-NEXT:    .seh_save_regp_x x19, 32
+; CHECK-GI-NEXT:    .seh_endepilogue
+; CHECK-GI-NEXT:    ret
+; CHECK-GI-NEXT:    .seh_endfunclet
+; CHECK-GI-NEXT:    .seh_endproc
+;
+; CHECK-FAST-LABEL: call_copy_pod:
+; CHECK-FAST:       .seh_proc call_copy_pod
+; CHECK-FAST-NEXT:  // %bb.0:
+; CHECK-FAST-NEXT:    sub sp, sp, #16
+; CHECK-FAST-NEXT:    .seh_stackalloc 16
+; CHECK-FAST-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
+; CHECK-FAST-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-FAST-NEXT:    .seh_endprologue
+; CHECK-FAST-NEXT:    adrp x19, Pod
+; CHECK-FAST-NEXT:    add x19, x19, :lo12:Pod
+; CHECK-FAST-NEXT:    mov x0, x19
+; CHECK-FAST-NEXT:    bl copy_pod
+; CHECK-FAST-NEXT:    stp d0, d1, [x19]
+; CHECK-FAST-NEXT:    .seh_startepilogue
+; CHECK-FAST-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
+; CHECK-FAST-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-FAST-NEXT:    add sp, sp, #16
+; CHECK-FAST-NEXT:    .seh_stackalloc 16
+; CHECK-FAST-NEXT:    .seh_endepilogue
+; CHECK-FAST-NEXT:    ret
+; CHECK-FAST-NEXT:    .seh_endfunclet
+; CHECK-FAST-NEXT:    .seh_endproc
+;
+; CHECK-EC-GI-LABEL: call_copy_pod:
+; CHECK-EC-GI:       .seh_proc call_copy_pod
+; CHECK-EC-GI-NEXT:  // %bb.0:
+; CHECK-EC-GI-NEXT:    sub sp, sp, #16
+; CHECK-EC-GI-NEXT:    .seh_stackalloc 16
+; CHECK-EC-GI-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
+; CHECK-EC-GI-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-EC-GI-NEXT:    .seh_endprologue
+; CHECK-EC-GI-NEXT:    adrp x19, Pod
+; CHECK-EC-GI-NEXT:    add x19, x19, :lo12:Pod
+; CHECK-EC-GI-NEXT:    mov x0, x19
+; CHECK-EC-GI-NEXT:    .weak_anti_dep copy_pod
+; CHECK-EC-GI-NEXT:  copy_pod = "#copy_pod"
+; CHECK-EC-GI-NEXT:    .weak_anti_dep "#copy_pod"
+; CHECK-EC-GI-NEXT:  "#copy_pod" = copy_pod
+; CHECK-EC-GI-NEXT:    bl "#copy_pod"
+; CHECK-EC-GI-NEXT:    stp d0, d1, [x19]
+; CHECK-EC-GI-NEXT:    .seh_startepilogue
+; CHECK-EC-GI-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
+; CHECK-EC-GI-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-EC-GI-NEXT:    add sp, sp, #16
+; CHECK-EC-GI-NEXT:    .seh_stackalloc 16
+; CHECK-EC-GI-NEXT:    .seh_endepilogue
+; CHECK-EC-GI-NEXT:    ret
+; CHECK-EC-GI-NEXT:    .seh_endfunclet
+; CHECK-EC-GI-NEXT:    .seh_endproc
+
   %x = call %struct.Pod @copy_pod(ptr @Pod)
   store %struct.Pod %x, ptr @Pod
   ret void
@@ -170,30 +412,145 @@ define void @call_copy_pod() {
 @NotCXX14Aggregate = external global %struct.NotCXX14Aggregate
 
 define void @call_copy_notcxx14aggregate() {
-; CHECK-LABEL: call_copy_notcxx14aggregate:
-; CHECK:       .seh_proc call_copy_notcxx14aggregate
-; CHECK-NEXT:  // %bb.0:
-; CHECK-NEXT:    sub sp, sp, #32
-; CHECK-NEXT:    .seh_stackalloc 32
-; CHECK-NEXT:    stp x19, x30, [sp, #16] // 16-byte Folded Spill
-; CHECK-NEXT:    .seh_save_lrpair x19, 16
-; CHECK-NEXT:    .seh_endprologue
-; CHECK-NEXT:    adrp x19, NotCXX14Aggregate
-; CHECK-NEXT:    add x19, x19, :lo12:NotCXX14Aggregate
-; CHECK-NEXT:    mov x0, sp
-; CHECK-NEXT:    mov x1, x19
-; CHECK-NEXT:    bl copy_notcxx14aggregate
-; CHECK-NEXT:    ldp d0, d1, [sp]
-; CHECK-NEXT:    stp d0, d1, [x19]
-; CHECK-NEXT:    .seh_startepilogue
-; CHECK-NEXT:    ldp x19, x30, [sp, #16] // 16-byte Folded Reload
-; CHECK-NEXT:    .seh_save_lrpair x19, 16
-; CHECK-NEXT:    add sp, sp, #32
-; CHECK-NEXT:    .seh_stackalloc 32
-; CHECK-NEXT:    .seh_endepilogue
-; CHECK-NEXT:    ret
-; CHECK-NEXT:    .seh_endfunclet
-; CHECK-NEXT:    .seh_endproc
+; CHECK-SD-LABEL: call_copy_notcxx14aggregate:
+; CHECK-SD:       .seh_proc call_copy_notcxx14aggregate
+; CHECK-SD-NEXT:  // %bb.0:
+; CHECK-SD-NEXT:    sub sp, sp, #32
+; CHECK-SD-NEXT:    .seh_stackalloc 32
+; CHECK-SD-NEXT:    stp x19, x30, [sp, #16] // 16-byte Folded Spill
+; CHECK-SD-NEXT:    .seh_save_lrpair x19, 16
+; CHECK-SD-NEXT:    .seh_endprologue
+; CHECK-SD-NEXT:    adrp x19, NotCXX14Aggregate
+; CHECK-SD-NEXT:    add x19, x19, :lo12:NotCXX14Aggregate
+; CHECK-SD-NEXT:    mov x0, sp
+; CHECK-SD-NEXT:    mov x1, x19
+; CHECK-SD-NEXT:    bl copy_notcxx14aggregate
+; CHECK-SD-NEXT:    ldp d0, d1, [sp]
+; CHECK-SD-NEXT:    stp d0, d1, [x19]
+; CHECK-SD-NEXT:    .seh_startepilogue
+; CHECK-SD-NEXT:    ldp x19, x30, [sp, #16] // 16-byte Folded Reload
+; CHECK-SD-NEXT:    .seh_save_lrpair x19, 16
+; CHECK-SD-NEXT:    add sp, sp, #32
+; CHECK-SD-NEXT:    .seh_stackalloc 32
+; CHECK-SD-NEXT:    .seh_endepilogue
+; CHECK-SD-NEXT:    ret
+; CHECK-SD-NEXT:    .seh_endfunclet
+; CHECK-SD-NEXT:    .seh_endproc
+;
+; CHECK-EC-SD-LABEL: call_copy_notcxx14aggregate:
+; CHECK-EC-SD:       .seh_proc call_copy_notcxx14aggregate
+; CHECK-EC-SD-NEXT:  // %bb.0:
+; CHECK-EC-SD-NEXT:    sub sp, sp, #32
+; CHECK-EC-SD-NEXT:    .seh_stackalloc 32
+; CHECK-EC-SD-NEXT:    stp x19, x30, [sp, #16] // 16-byte Folded Spill
+; CHECK-EC-SD-NEXT:    .seh_save_lrpair x19, 16
+; CHECK-EC-SD-NEXT:    .seh_endprologue
+; CHECK-EC-SD-NEXT:    adrp x19, NotCXX14Aggregate
+; CHECK-EC-SD-NEXT:    add x19, x19, :lo12:NotCXX14Aggregate
+; CHECK-EC-SD-NEXT:    mov x0, sp
+; CHECK-EC-SD-NEXT:    mov x1, x19
+; CHECK-EC-SD-NEXT:    .weak_anti_dep copy_notcxx14aggregate
+; CHECK-EC-SD-NEXT:  copy_notcxx14aggregate = "#copy_notcxx14aggregate"
+; CHECK-EC-SD-NEXT:    .weak_anti_dep "#copy_notcxx14aggregate"
+; CHECK-EC-SD-NEXT:  "#copy_notcxx14aggregate" = copy_notcxx14aggregate
+; CHECK-EC-SD-NEXT:    bl "#copy_notcxx14aggregate"
+; CHECK-EC-SD-NEXT:    ldp d0, d1, [sp]
+; CHECK-EC-SD-NEXT:    stp d0, d1, [x19]
+; CHECK-EC-SD-NEXT:    .seh_startepilogue
+; CHECK-EC-SD-NEXT:    ldp x19, x30, [sp, #16] // 16-byte Folded Reload
+; CHECK-EC-SD-NEXT:    .seh_save_lrpair x19, 16
+; CHECK-EC-SD-NEXT:    add sp, sp, #32
+; CHECK-EC-SD-NEXT:    .seh_stackalloc 32
+; CHECK-EC-SD-NEXT:    .seh_endepilogue
+; CHECK-EC-SD-NEXT:    ret
+; CHECK-EC-SD-NEXT:    .seh_endfunclet
+; CHECK-EC-SD-NEXT:    .seh_endproc
+;
+; CHECK-GI-LABEL: call_copy_notcxx14aggregate:
+; CHECK-GI:       .seh_proc call_copy_notcxx14aggregate
+; CHECK-GI-NEXT:  // %bb.0:
+; CHECK-GI-NEXT:    sub sp, sp, #48
+; CHECK-GI-NEXT:    .seh_stackalloc 48
+; CHECK-GI-NEXT:    stp x19, x20, [sp, #16] // 16-byte Folded Spill
+; CHECK-GI-NEXT:    .seh_save_regp x19, 16
+; CHECK-GI-NEXT:    str x30, [sp, #32] // 8-byte Spill
+; CHECK-GI-NEXT:    .seh_save_reg x30, 32
+; CHECK-GI-NEXT:    .seh_endprologue
+; CHECK-GI-NEXT:    adrp x19, NotCXX14Aggregate
+; CHECK-GI-NEXT:    add x19, x19, :lo12:NotCXX14Aggregate
+; CHECK-GI-NEXT:    mov x0, sp
+; CHECK-GI-NEXT:    mov x1, x19
+; CHECK-GI-NEXT:    adrp x20, NotCXX14Aggregate
+; CHECK-GI-NEXT:    bl copy_notcxx14aggregate
+; CHECK-GI-NEXT:    ldp x8, x9, [sp]
+; CHECK-GI-NEXT:    str x8, [x20, :lo12:NotCXX14Aggregate]
+; CHECK-GI-NEXT:    str x9, [x19, #8]
+; CHECK-GI-NEXT:    .seh_startepilogue
+; CHECK-GI-NEXT:    ldr x30, [sp, #32] // 8-byte Reload
+; CHECK-GI-NEXT:    .seh_save_reg x30, 32
+; CHECK-GI-NEXT:    ldp x19, x20, [sp, #16] // 16-byte Folded Reload
+; CHECK-GI-NEXT:    .seh_save_regp x19, 16
+; CHECK-GI-NEXT:    add sp, sp, #48
+; CHECK-GI-NEXT:    .seh_stackalloc 48
+; CHECK-GI-NEXT:    .seh_endepilogue
+; CHECK-GI-NEXT:    ret
+; CHECK-GI-NEXT:    .seh_endfunclet
+; CHECK-GI-NEXT:    .seh_endproc
+;
+; CHECK-FAST-LABEL: call_copy_notcxx14aggregate:
+; CHECK-FAST:       .seh_proc call_copy_notcxx14aggregate
+; CHECK-FAST-NEXT:  // %bb.0:
+; CHECK-FAST-NEXT:    sub sp, sp, #32
+; CHECK-FAST-NEXT:    .seh_stackalloc 32
+; CHECK-FAST-NEXT:    stp x19, x30, [sp, #16] // 16-byte Folded Spill
+; CHECK-FAST-NEXT:    .seh_save_lrpair x19, 16
+; CHECK-FAST-NEXT:    .seh_endprologue
+; CHECK-FAST-NEXT:    adrp x19, NotCXX14Aggregate
+; CHECK-FAST-NEXT:    add x19, x19, :lo12:NotCXX14Aggregate
+; CHECK-FAST-NEXT:    mov x0, sp
+; CHECK-FAST-NEXT:    mov x1, x19
+; CHECK-FAST-NEXT:    bl copy_notcxx14aggregate
+; CHECK-FAST-NEXT:    ldp d0, d1, [sp]
+; CHECK-FAST-NEXT:    stp d0, d1, [x19]
+; CHECK-FAST-NEXT:    .seh_startepilogue
+; CHECK-FAST-NEXT:    ldp x19, x30, [sp, #16] // 16-byte Folded Reload
+; CHECK-FAST-NEXT:    .seh_save_lrpair x19, 16
+; CHECK-FAST-NEXT:    add sp, sp, #32
+; CHECK-FAST-NEXT:    .seh_stackalloc 32
+; CHECK-FAST-NEXT:    .seh_endepilogue
+; CHECK-FAST-NEXT:    ret
+; CHECK-FAST-NEXT:    .seh_endfunclet
+; CHECK-FAST-NEXT:    .seh_endproc
+;
+; CHECK-EC-GI-LABEL: call_copy_notcxx14aggregate:
+; CHECK-EC-GI:       .seh_proc call_copy_notcxx14aggregate
+; CHECK-EC-GI-NEXT:  // %bb.0:
+; CHECK-EC-GI-NEXT:    sub sp, sp, #32
+; CHECK-EC-GI-NEXT:    .seh_stackalloc 32
+; CHECK-EC-GI-NEXT:    stp x19, x30, [sp, #16] // 16-byte Folded Spill
+; CHECK-EC-GI-NEXT:    .seh_save_lrpair x19, 16
+; CHECK-EC-GI-NEXT:    .seh_endprologue
+; CHECK-EC-GI-NEXT:    adrp x19, NotCXX14Aggregate
+; CHECK-EC-GI-NEXT:    add x19, x19, :lo12:NotCXX14Aggregate
+; CHECK-EC-GI-NEXT:    mov x0, sp
+; CHECK-EC-GI-NEXT:    mov x1, x19
+; CHECK-EC-GI-NEXT:    .weak_anti_dep copy_notcxx14aggregate
+; CHECK-EC-GI-NEXT:  copy_notcxx14aggregate = "#copy_notcxx14aggregate"
+; CHECK-EC-GI-NEXT:    .weak_anti_dep "#copy_notcxx14aggregate"
+; CHECK-EC-GI-NEXT:  "#copy_notcxx14aggregate" = copy_notcxx14aggregate
+; CHECK-EC-GI-NEXT:    bl "#copy_notcxx14aggregate"
+; CHECK-EC-GI-NEXT:    ldp d0, d1, [sp]
+; CHECK-EC-GI-NEXT:    stp d0, d1, [x19]
+; CHECK-EC-GI-NEXT:    .seh_startepilogue
+; CHECK-EC-GI-NEXT:    ldp x19, x30, [sp, #16] // 16-byte Folded Reload
+; CHECK-EC-GI-NEXT:    .seh_save_lrpair x19, 16
+; CHECK-EC-GI-NEXT:    add sp, sp, #32
+; CHECK-EC-GI-NEXT:    .seh_stackalloc 32
+; CHECK-EC-GI-NEXT:    .seh_endepilogue
+; CHECK-EC-GI-NEXT:    ret
+; CHECK-EC-GI-NEXT:    .seh_endfunclet
+; CHECK-EC-GI-NEXT:    .seh_endproc
+
   %x = alloca %struct.NotCXX14Aggregate
   call void @copy_notcxx14aggregate(ptr %x, ptr @NotCXX14Aggregate)
   %x1 = load %struct.NotCXX14Aggregate, ptr %x
@@ -204,28 +561,131 @@ define void @call_copy_notcxx14aggregate() {
 @NotPod = external global %struct.NotPod
 
 define void @call_copy_notpod() {
-; CHECK-LABEL: call_copy_notpod:
-; CHECK:       .seh_proc call_copy_notpod
-; CHECK-NEXT:  // %bb.0:
-; CHECK-NEXT:    sub sp, sp, #16
-; CHECK-NEXT:    .seh_stackalloc 16
-; CHECK-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
-; CHECK-NEXT:    .seh_save_lrpair x19, 0
-; CHECK-NEXT:    .seh_endprologue
-; CHECK-NEXT:    adrp x19, NotPod
-; CHECK-NEXT:    add x19, x19, :lo12:NotPod
-; CHECK-NEXT:    mov x0, x19
-; CHECK-NEXT:    bl copy_notpod
-; CHECK-NEXT:    stp x0, x1, [x19]
-; CHECK-NEXT:    .seh_startepilogue
-; CHECK-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
-; CHECK-NEXT:    .seh_save_lrpair x19, 0
-; CHECK-NEXT:    add sp, sp, #16
-; CHECK-NEXT:    .seh_stackalloc 16
-; CHECK-NEXT:    .seh_endepilogue
-; CHECK-NEXT:    ret
-; CHECK-NEXT:    .seh_endfunclet
-; CHECK-NEXT:    .seh_endproc
+; CHECK-SD-LABEL: call_copy_notpod:
+; CHECK-SD:       .seh_proc call_copy_notpod
+; CHECK-SD-NEXT:  // %bb.0:
+; CHECK-SD-NEXT:    sub sp, sp, #16
+; CHECK-SD-NEXT:    .seh_stackalloc 16
+; CHECK-SD-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
+; CHECK-SD-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-SD-NEXT:    .seh_endprologue
+; CHECK-SD-NEXT:    adrp x19, NotPod
+; CHECK-SD-NEXT:    add x19, x19, :lo12:NotPod
+; CHECK-SD-NEXT:    mov x0, x19
+; CHECK-SD-NEXT:    bl copy_notpod
+; CHECK-SD-NEXT:    stp x0, x1, [x19]
+; CHECK-SD-NEXT:    .seh_startepilogue
+; CHECK-SD-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
+; CHECK-SD-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-SD-NEXT:    add sp, sp, #16
+; CHECK-SD-NEXT:    .seh_stackalloc 16
+; CHECK-SD-NEXT:    .seh_endepilogue
+; CHECK-SD-NEXT:    ret
+; CHECK-SD-NEXT:    .seh_endfunclet
+; CHECK-SD-NEXT:    .seh_endproc
+;
+; CHECK-EC-SD-LABEL: call_copy_notpod:
+; CHECK-EC-SD:       .seh_proc call_copy_notpod
+; CHECK-EC-SD-NEXT:  // %bb.0:
+; CHECK-EC-SD-NEXT:    sub sp, sp, #16
+; CHECK-EC-SD-NEXT:    .seh_stackalloc 16
+; CHECK-EC-SD-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
+; CHECK-EC-SD-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-EC-SD-NEXT:    .seh_endprologue
+; CHECK-EC-SD-NEXT:    adrp x19, NotPod
+; CHECK-EC-SD-NEXT:    add x19, x19, :lo12:NotPod
+; CHECK-EC-SD-NEXT:    mov x0, x19
+; CHECK-EC-SD-NEXT:    .weak_anti_dep copy_notpod
+; CHECK-EC-SD-NEXT:  copy_notpod = "#copy_notpod"
+; CHECK-EC-SD-NEXT:    .weak_anti_dep "#copy_notpod"
+; CHECK-EC-SD-NEXT:  "#copy_notpod" = copy_notpod
+; CHECK-EC-SD-NEXT:    bl "#copy_notpod"
+; CHECK-EC-SD-NEXT:    stp x0, x1, [x19]
+; CHECK-EC-SD-NEXT:    .seh_startepilogue
+; CHECK-EC-SD-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
+; CHECK-EC-SD-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-EC-SD-NEXT:    add sp, sp, #16
+; CHECK-EC-SD-NEXT:    .seh_stackalloc 16
+; CHECK-EC-SD-NEXT:    .seh_endepilogue
+; CHECK-EC-SD-NEXT:    ret
+; CHECK-EC-SD-NEXT:    .seh_endfunclet
+; CHECK-EC-SD-NEXT:    .seh_endproc
+;
+; CHECK-GI-LABEL: call_copy_notpod:
+; CHECK-GI:       .seh_proc call_copy_notpod
+; CHECK-GI-NEXT:  // %bb.0:
+; CHECK-GI-NEXT:    stp x19, x20, [sp, #-32]! // 16-byte Folded Spill
+; CHECK-GI-NEXT:    .seh_save_regp_x x19, 32
+; CHECK-GI-NEXT:    str x30, [sp, #16] // 8-byte Spill
+; CHECK-GI-NEXT:    .seh_save_reg x30, 16
+; CHECK-GI-NEXT:    .seh_endprologue
+; CHECK-GI-NEXT:    adrp x19, NotPod
+; CHECK-GI-NEXT:    add x19, x19, :lo12:NotPod
+; CHECK-GI-NEXT:    adrp x20, NotPod
+; CHECK-GI-NEXT:    mov x0, x19
+; CHECK-GI-NEXT:    bl copy_notpod
+; CHECK-GI-NEXT:    str x0, [x20, :lo12:NotPod]
+; CHECK-GI-NEXT:    str x1, [x19, #8]
+; CHECK-GI-NEXT:    .seh_startepilogue
+; CHECK-GI-NEXT:    ldr x30, [sp, #16] // 8-byte Reload
+; CHECK-GI-NEXT:    .seh_save_reg x30, 16
+; CHECK-GI-NEXT:    ldp x19, x20, [sp], #32 // 16-byte Folded Reload
+; CHECK-GI-NEXT:    .seh_save_regp_x x19, 32
+; CHECK-GI-NEXT:    .seh_endepilogue
+; CHECK-GI-NEXT:    ret
+; CHECK-GI-NEXT:    .seh_endfunclet
+; CHECK-GI-NEXT:    .seh_endproc
+;
+; CHECK-FAST-LABEL: call_copy_notpod:
+; CHECK-FAST:       .seh_proc call_copy_notpod
+; CHECK-FAST-NEXT:  // %bb.0:
+; CHECK-FAST-NEXT:    sub sp, sp, #16
+; CHECK-FAST-NEXT:    .seh_stackalloc 16
+; CHECK-FAST-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
+; CHECK-FAST-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-FAST-NEXT:    .seh_endprologue
+; CHECK-FAST-NEXT:    adrp x19, NotPod
+; CHECK-FAST-NEXT:    add x19, x19, :lo12:NotPod
+; CHECK-FAST-NEXT:    mov x0, x19
+; CHECK-FAST-NEXT:    bl copy_notpod
+; CHECK-FAST-NEXT:    stp x0, x1, [x19]
+; CHECK-FAST-NEXT:    .seh_startepilogue
+; CHECK-FAST-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
+; CHECK-FAST-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-FAST-NEXT:    add sp, sp, #16
+; CHECK-FAST-NEXT:    .seh_stackalloc 16
+; CHECK-FAST-NEXT:    .seh_endepilogue
+; CHECK-FAST-NEXT:    ret
+; CHECK-FAST-NEXT:    .seh_endfunclet
+; CHECK-FAST-NEXT:    .seh_endproc
+;
+; CHECK-EC-GI-LABEL: call_copy_notpod:
+; CHECK-EC-GI:       .seh_proc call_copy_notpod
+; CHECK-EC-GI-NEXT:  // %bb.0:
+; CHECK-EC-GI-NEXT:    sub sp, sp, #16
+; CHECK-EC-GI-NEXT:    .seh_stackalloc 16
+; CHECK-EC-GI-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
+; CHECK-EC-GI-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-EC-GI-NEXT:    .seh_endprologue
+; CHECK-EC-GI-NEXT:    adrp x19, NotPod
+; CHECK-EC-GI-NEXT:    add x19, x19, :lo12:NotPod
+; CHECK-EC-GI-NEXT:    mov x0, x19
+; CHECK-EC-GI-NEXT:    .weak_anti_dep copy_notpod
+; CHECK-EC-GI-NEXT:  copy_notpod = "#copy_notpod"
+; CHECK-EC-GI-NEXT:    .weak_anti_dep "#copy_notpod"
+; CHECK-EC-GI-NEXT:  "#copy_notpod" = copy_notpod
+; CHECK-EC-GI-NEXT:    bl "#copy_notpod"
+; CHECK-EC-GI-NEXT:    stp x0, x1, [x19]
+; CHECK-EC-GI-NEXT:    .seh_startepilogue
+; CHECK-EC-GI-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
+; CHECK-EC-GI-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-EC-GI-NEXT:    add sp, sp, #16
+; CHECK-EC-GI-NEXT:    .seh_stackalloc 16
+; CHECK-EC-GI-NEXT:    .seh_endepilogue
+; CHECK-EC-GI-NEXT:    ret
+; CHECK-EC-GI-NEXT:    .seh_endfunclet
+; CHECK-EC-GI-NEXT:    .seh_endproc
+
   %x = call [2 x i64] @copy_notpod(ptr @NotPod)
   store [2 x i64] %x, ptr @NotPod
   ret void

diff  --git a/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll b/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll
index cd0a77a280aec..e81bcd07badc0 100644
--- a/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-windows-tailcall.ll
@@ -1,15 +1,32 @@
-; FIXME: Add tests for global-isel/fast-isel.
-
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc < %s -mtriple=arm64-windows | FileCheck %s
+; RUN: llc < %s -mtriple=arm64-windows -fast-isel=1 -global-isel=0 | FileCheck %s
+; RUN: llc < %s -mtriple=arm64-windows -fast-isel=0 -global-isel=1 -global-isel-abort=0 | FileCheck %s
 
 %class.C = type { [1 x i32] }
 
-define dso_local void @"?bar"(ptr inreg noalias sret(%class.C) %agg.result) {
+define dso_local void @bar(ptr inreg noalias sret(%class.C) %agg.result) {
+; CHECK-LABEL: bar:
+; CHECK:       .seh_proc bar
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    sub sp, sp, #16
+; CHECK-NEXT:    .seh_stackalloc 16
+; CHECK-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
+; CHECK-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-NEXT:    .seh_endprologue
+; CHECK-NEXT:    mov x19, x0
+; CHECK-NEXT:    bl "?foo"
+; CHECK-NEXT:    mov x0, x19
+; CHECK-NEXT:    .seh_startepilogue
+; CHECK-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
+; CHECK-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-NEXT:    add sp, sp, #16
+; CHECK-NEXT:    .seh_stackalloc 16
+; CHECK-NEXT:    .seh_endepilogue
+; CHECK-NEXT:    ret
+; CHECK-NEXT:    .seh_endfunclet
+; CHECK-NEXT:    .seh_endproc
 entry:
-; CHECK-LABEL: bar
-; CHECK: mov x19, x0
-; CHECK: bl "?foo"
-; CHECK: mov x0, x19
 
   tail call void @"?foo"(ptr dereferenceable(4) %agg.result)
   ret void
@@ -22,10 +39,28 @@ declare void @inreg_callee(ptr, ptr inreg sret(%class.C))
 
 define void @inreg_caller_1(ptr %a, ptr inreg sret(%class.C) %b) {
 ; A 
diff erent value is passed to the inreg parameter, so tail call is not possible.
-; CHECK-LABEL: inreg_caller_1
-; CHECK: mov x19, x1
-; CHECK: bl inreg_callee
-; CHECK: mov x0, x19
+; CHECK-LABEL: inreg_caller_1:
+; CHECK:       .seh_proc inreg_caller_1
+; CHECK-NEXT:  // %bb.0:
+; CHECK-NEXT:    sub sp, sp, #16
+; CHECK-NEXT:    .seh_stackalloc 16
+; CHECK-NEXT:    stp x19, x30, [sp] // 16-byte Folded Spill
+; CHECK-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-NEXT:    .seh_endprologue
+; CHECK-NEXT:    mov x19, x1
+; CHECK-NEXT:    mov x1, x0
+; CHECK-NEXT:    mov x0, x19
+; CHECK-NEXT:    bl inreg_callee
+; CHECK-NEXT:    mov x0, x19
+; CHECK-NEXT:    .seh_startepilogue
+; CHECK-NEXT:    ldp x19, x30, [sp] // 16-byte Folded Reload
+; CHECK-NEXT:    .seh_save_lrpair x19, 0
+; CHECK-NEXT:    add sp, sp, #16
+; CHECK-NEXT:    .seh_stackalloc 16
+; CHECK-NEXT:    .seh_endepilogue
+; CHECK-NEXT:    ret
+; CHECK-NEXT:    .seh_endfunclet
+; CHECK-NEXT:    .seh_endproc
 
   tail call void @inreg_callee(ptr %b, ptr inreg sret(%class.C) %a)
   ret void
@@ -34,8 +69,9 @@ define void @inreg_caller_1(ptr %a, ptr inreg sret(%class.C) %b) {
 define void @inreg_caller_2(ptr %a, ptr inreg sret(%class.C) %b) {
 ; The inreg attribute and value line up between caller and callee, so it can
 ; be tail called.
-; CHECK-LABEL: inreg_caller_2
-; CHECK: b inreg_callee
+; CHECK-LABEL: inreg_caller_2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    b inreg_callee
 
   tail call void @inreg_callee(ptr %a, ptr inreg sret(%class.C) %b)
   ret void


        


More information about the llvm-commits mailing list