https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/225548
Backport 8890be35705834c5af8e21424d7900639be03180 Requested by: @efriedma-quic >From 6dd1f43032d3bfe880b4ea96c49dc4bcb1d1dde8 Mon Sep 17 00:00:00 2001 From: Eli Friedman <[email protected]> Date: Tue, 22 Sep 2026 15:45:53 -0700 Subject: [PATCH] [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 (cherry picked from commit 8890be35705834c5af8e21424d7900639be03180) --- llvm/lib/Target/AArch64/AArch64FastISel.cpp | 3 + .../AArch64/GISel/AArch64CallLowering.cpp | 11 +- .../CodeGen/AArch64/arm64-windows-calls.ll | 652 +++++++++++++++--- .../CodeGen/AArch64/arm64-windows-tailcall.ll | 62 +- 4 files changed, 616 insertions(+), 112 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index b6deb703893fdb..caa0983ca5fb15 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 b0a409d153fd21..76439176474749 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp @@ -715,9 +715,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 41f00a6c41b3b9..3305a6dce3029e 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@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@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 cd0a77a280aec2..e81bcd07badc09 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 different 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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
