[llvm] Fix stack temporary leaks for indirect arguments (PR #213134)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 30 13:46:19 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: AZero13 (AZero13)
<details>
<summary>Changes</summary>
When passing arguments indirectly (like byval structs or x87 floats), LLVM creates temporary stack slots in the backend.
Right now, these temporary stack slots leak memory across function calls.
To fix:
Add LIFETIME_START / LIFETIME_END markers around temporary argument slots in LowerCall.
Allow StackColoring to safely merge stack slots even if they don't have a matching IR AllocaInst.
Parallelize indirect argument setup in LowerCall using MemOpChains so the instruction scheduler isn't artificially constrained.
---
Patch is 20.95 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/213134.diff
9 Files Affected:
- (modified) llvm/lib/CodeGen/StackColoring.cpp (+41-39)
- (modified) llvm/lib/Target/X86/X86ISelLoweringCall.cpp (+19-8)
- (modified) llvm/test/CodeGen/X86/avx512-regcall-Mask.ll (+9-9)
- (modified) llvm/test/CodeGen/X86/dag-stlf-mismatch.ll (+2-1)
- (modified) llvm/test/CodeGen/X86/fp128-libcalls-strict.ll (+3-3)
- (modified) llvm/test/CodeGen/X86/fp128-libcalls.ll (+8-8)
- (modified) llvm/test/CodeGen/X86/sse-intel-ocl.ll (+10-10)
- (added) llvm/test/CodeGen/X86/stack-coloring-x87.ll (+98)
- (modified) llvm/test/CodeGen/X86/win64-byval.ll (+3-3)
``````````diff
diff --git a/llvm/lib/CodeGen/StackColoring.cpp b/llvm/lib/CodeGen/StackColoring.cpp
index ea1f33f791765..8902f560d47e8 100644
--- a/llvm/lib/CodeGen/StackColoring.cpp
+++ b/llvm/lib/CodeGen/StackColoring.cpp
@@ -928,31 +928,6 @@ void StackColoring::remapInstructions(DenseMap<int, int> &SlotRemap) {
for (const std::pair<int, int> &SI : SlotRemap) {
const AllocaInst *From = MFI->getObjectAllocation(SI.first);
const AllocaInst *To = MFI->getObjectAllocation(SI.second);
- assert(To && From && "Invalid allocation object");
- Allocas[From] = To;
-
- // If From is before wo, its possible that there is a use of From between
- // them.
- if (From->comesBefore(To))
- const_cast<AllocaInst *>(To)->moveBefore(
- const_cast<AllocaInst *>(From)->getIterator());
-
- // AA might be used later for instruction scheduling, and we need it to be
- // able to deduce the correct aliasing releationships between pointers
- // derived from the alloca being remapped and the target of that remapping.
- // The only safe way, without directly informing AA about the remapping
- // somehow, is to directly update the IR to reflect the change being made
- // here.
- Instruction *Inst = const_cast<AllocaInst *>(To);
- if (From->getType() != To->getType()) {
- BitCastInst *Cast = new BitCastInst(Inst, From->getType());
- Cast->insertAfter(Inst->getIterator());
- Inst = Cast;
- }
-
- // We keep both slots to maintain AliasAnalysis metadata later.
- MergedAllocas.insert(From);
- MergedAllocas.insert(To);
// Transfer the stack protector layout tag, but make sure that SSPLK_AddrOf
// does not overwrite SSPLK_SmallArray or SSPLK_LargeArray, and make sure
@@ -966,21 +941,48 @@ void StackColoring::remapInstructions(DenseMap<int, int> &SlotRemap) {
FromKind != MachineFrameInfo::SSPLK_AddrOf)))
MFI->setObjectSSPLayout(SI.second, FromKind);
- // The new alloca might not be valid in a llvm.dbg.declare for this
- // variable, so poison out the use to make the verifier happy.
- AllocaInst *FromAI = const_cast<AllocaInst *>(From);
- if (FromAI->isUsedByMetadata())
- ValueAsMetadata::handleRAUW(FromAI, PoisonValue::get(FromAI->getType()));
- for (auto &Use : FromAI->uses()) {
- if (BitCastInst *BCI = dyn_cast<BitCastInst>(Use.get()))
- if (BCI->isUsedByMetadata())
- ValueAsMetadata::handleRAUW(BCI, PoisonValue::get(BCI->getType()));
- }
+ if (From && To) {
+ Allocas[From] = To;
+
+ // If From is before wo, its possible that there is a use of From between
+ // them.
+ if (From->comesBefore(To))
+ const_cast<AllocaInst *>(To)->moveBefore(
+ const_cast<AllocaInst *>(From)->getIterator());
+
+ // AA might be used later for instruction scheduling, and we need it to be
+ // able to deduce the correct aliasing releationships between pointers
+ // derived from the alloca being remapped and the target of that remapping.
+ // The only safe way, without directly informing AA about the remapping
+ // somehow, is to directly update the IR to reflect the change being made
+ // here.
+ Instruction *Inst = const_cast<AllocaInst *>(To);
+ if (From->getType() != To->getType()) {
+ BitCastInst *Cast = new BitCastInst(Inst, From->getType());
+ Cast->insertAfter(Inst->getIterator());
+ Inst = Cast;
+ }
- // Note that this will not replace uses in MMOs (which we'll update below),
- // or anywhere else (which is why we won't delete the original
- // instruction).
- FromAI->replaceAllUsesWith(Inst);
+ // We keep both slots to maintain AliasAnalysis metadata later.
+ MergedAllocas.insert(From);
+ MergedAllocas.insert(To);
+
+ // The new alloca might not be valid in a llvm.dbg.declare for this
+ // variable, so poison out the use to make the verifier happy.
+ AllocaInst *FromAI = const_cast<AllocaInst *>(From);
+ if (FromAI->isUsedByMetadata())
+ ValueAsMetadata::handleRAUW(FromAI, PoisonValue::get(FromAI->getType()));
+ for (auto &Use : FromAI->uses()) {
+ if (BitCastInst *BCI = dyn_cast<BitCastInst>(Use.get()))
+ if (BCI->isUsedByMetadata())
+ ValueAsMetadata::handleRAUW(BCI, PoisonValue::get(BCI->getType()));
+ }
+
+ // Note that this will not replace uses in MMOs (which we'll update below),
+ // or anywhere else (which is why we won't delete the original
+ // instruction).
+ FromAI->replaceAllUsesWith(Inst);
+ }
}
// Remap all instructions to the new stack slots.
diff --git a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
index 8f14198cf268b..bf6daa03d9992 100644
--- a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
+++ b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
@@ -2318,7 +2318,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
SmallVector<SDValue, 8> MemOpChains;
-
+ SmallVector<int, 8> CallTemporaries;
// The next loop assumes that the locations are in the same order of the
// input arguments.
assert(isSortedByValueNo(ArgLocs) &&
@@ -2365,17 +2365,21 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
Arg = DAG.getBitcast(RegVT, Arg);
break;
case CCValAssign::Indirect: {
+ SDValue SetupChain;
if (isByVal) {
// Memcpy the argument to a temporary stack slot to prevent
// the caller from seeing any modifications the callee may make
// as guaranteed by the `byval` attribute.
+ uint64_t Size = Flags.getByValSize();
int FrameIdx = MF.getFrameInfo().CreateStackObject(
- Flags.getByValSize(),
+ Size,
std::max(Align(16), Flags.getNonZeroByValAlign()), false);
+ CallTemporaries.push_back(FrameIdx);
+ SetupChain = DAG.getLifetimeNode(true, dl, Chain, FrameIdx);
SDValue StackSlot =
DAG.getFrameIndex(FrameIdx, getPointerTy(DAG.getDataLayout()));
- Chain =
- CreateCopyOfByValArgument(Arg, StackSlot, Chain, Flags, DAG, dl);
+ SetupChain =
+ CreateCopyOfByValArgument(Arg, StackSlot, SetupChain, Flags, DAG, dl);
// From now on treat this as a regular pointer
Arg = StackSlot;
isByVal = false;
@@ -2383,11 +2387,14 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// Store the argument.
SDValue SpillSlot = DAG.CreateStackTemporary(VA.getValVT());
int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
- Chain = DAG.getStore(
- Chain, dl, Arg, SpillSlot,
+ CallTemporaries.push_back(FI);
+ SetupChain = DAG.getLifetimeNode(true, dl, Chain, FI);
+ SetupChain = DAG.getStore(
+ SetupChain, dl, Arg, SpillSlot,
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI));
Arg = SpillSlot;
}
+ MemOpChains.push_back(SetupChain);
break;
}
}
@@ -2790,8 +2797,12 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// Handle result values, copying them out of physregs into vregs that we
// return.
- return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
- InVals, RegMask);
+ SDValue ResChain = LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
+ InVals, RegMask);
+ for (int FI : CallTemporaries) {
+ ResChain = DAG.getLifetimeNode(false, dl, ResChain, FI);
+ }
+ return ResChain;
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/X86/avx512-regcall-Mask.ll b/llvm/test/CodeGen/X86/avx512-regcall-Mask.ll
index 162f5efd78f6d..e772e1bf3fcf5 100644
--- a/llvm/test/CodeGen/X86/avx512-regcall-Mask.ll
+++ b/llvm/test/CodeGen/X86/avx512-regcall-Mask.ll
@@ -323,9 +323,9 @@ define dso_local x86_regcallcc i32 @test_argv32i1(<32 x i1> %x0, <32 x i1> %x1,
; WIN64-NEXT: .seh_setframe %rbp, 128
; WIN64-NEXT: .seh_endprologue
; WIN64-NEXT: andq $-32, %rsp
-; WIN64-NEXT: kmovd %edx, %k0
-; WIN64-NEXT: kmovd %eax, %k1
-; WIN64-NEXT: kmovd %ecx, %k2
+; WIN64-NEXT: kmovd %eax, %k0
+; WIN64-NEXT: kmovd %ecx, %k1
+; WIN64-NEXT: kmovd %edx, %k2
; WIN64-NEXT: vpmovm2b %k2, %zmm0
; WIN64-NEXT: vmovdqa %ymm0, {{[0-9]+}}(%rsp)
; WIN64-NEXT: vpmovm2b %k1, %zmm0
@@ -549,9 +549,9 @@ define dso_local x86_regcallcc i16 @test_argv16i1(<16 x i1> %x0, <16 x i1> %x1,
; WIN64-NEXT: subq $88, %rsp
; WIN64-NEXT: .seh_stackalloc 88
; WIN64-NEXT: .seh_endprologue
-; WIN64-NEXT: kmovd %edx, %k0
-; WIN64-NEXT: kmovd %eax, %k1
-; WIN64-NEXT: kmovd %ecx, %k2
+; WIN64-NEXT: kmovd %eax, %k0
+; WIN64-NEXT: kmovd %ecx, %k1
+; WIN64-NEXT: kmovd %edx, %k2
; WIN64-NEXT: vpmovm2b %k2, %zmm0
; WIN64-NEXT: vmovdqa %xmm0, {{[0-9]+}}(%rsp)
; WIN64-NEXT: vpmovm2b %k1, %zmm0
@@ -779,9 +779,9 @@ define dso_local x86_regcallcc i8 @test_argv8i1(<8 x i1> %x0, <8 x i1> %x1, <8 x
; WIN64-NEXT: subq $88, %rsp
; WIN64-NEXT: .seh_stackalloc 88
; WIN64-NEXT: .seh_endprologue
-; WIN64-NEXT: kmovd %edx, %k0
-; WIN64-NEXT: kmovd %eax, %k1
-; WIN64-NEXT: kmovd %ecx, %k2
+; WIN64-NEXT: kmovd %eax, %k0
+; WIN64-NEXT: kmovd %ecx, %k1
+; WIN64-NEXT: kmovd %edx, %k2
; WIN64-NEXT: vpmovm2w %k2, %zmm0
; WIN64-NEXT: vmovdqa %xmm0, {{[0-9]+}}(%rsp)
; WIN64-NEXT: vpmovm2w %k1, %zmm0
diff --git a/llvm/test/CodeGen/X86/dag-stlf-mismatch.ll b/llvm/test/CodeGen/X86/dag-stlf-mismatch.ll
index 309df51e303d8..b94e8f9c8b448 100644
--- a/llvm/test/CodeGen/X86/dag-stlf-mismatch.ll
+++ b/llvm/test/CodeGen/X86/dag-stlf-mismatch.ll
@@ -79,7 +79,8 @@ define void @test_stlf_late_byval(ptr %ptr) nounwind {
; AVX512: # %bb.0:
; AVX512-NEXT: subq $40, %rsp
; AVX512-NEXT: movl $0, (%rcx)
-; AVX512-NEXT: movl $0, {{[0-9]+}}(%rsp)
+; AVX512-NEXT: movl (%rcx), %eax
+; AVX512-NEXT: movl %eax, {{[0-9]+}}(%rsp)
; AVX512-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; AVX512-NEXT: callq ext_func
; AVX512-NEXT: addq $40, %rsp
diff --git a/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll b/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll
index cae271f7a2ed4..9c80bdab640b6 100644
--- a/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll
+++ b/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll
@@ -599,9 +599,9 @@ define fp128 @fma(fp128 %x, fp128 %y, fp128 %z) nounwind strictfp {
; WIN-NEXT: pushq %rsi
; WIN-NEXT: subq $96, %rsp
; WIN-NEXT: movq %rcx, %rsi
-; WIN-NEXT: movaps (%r9), %xmm0
-; WIN-NEXT: movaps (%rdx), %xmm1
-; WIN-NEXT: movaps (%r8), %xmm2
+; WIN-NEXT: movaps (%rdx), %xmm0
+; WIN-NEXT: movaps (%r8), %xmm1
+; WIN-NEXT: movaps (%r9), %xmm2
; WIN-NEXT: movaps %xmm2, {{[0-9]+}}(%rsp)
; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
diff --git a/llvm/test/CodeGen/X86/fp128-libcalls.ll b/llvm/test/CodeGen/X86/fp128-libcalls.ll
index c594b15ef1cbe..4c71a44e95757 100644
--- a/llvm/test/CodeGen/X86/fp128-libcalls.ll
+++ b/llvm/test/CodeGen/X86/fp128-libcalls.ll
@@ -212,8 +212,8 @@ define dso_local void @Test128_1Add(fp128 %d1) nounwind {
; WIN-NEXT: subq $88, %rsp
; WIN-NEXT: movaps (%rcx), %xmm0
; WIN-NEXT: movaps vf128(%rip), %xmm1
-; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
+; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %r8
@@ -469,8 +469,8 @@ define dso_local void @Test128_1Sub(fp128 %d1) nounwind {
; WIN-NEXT: subq $88, %rsp
; WIN-NEXT: movaps (%rcx), %xmm0
; WIN-NEXT: movaps vf128(%rip), %xmm1
-; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
+; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %r8
@@ -726,8 +726,8 @@ define dso_local void @Test128_1Mul(fp128 %d1) nounwind {
; WIN-NEXT: subq $88, %rsp
; WIN-NEXT: movaps (%rcx), %xmm0
; WIN-NEXT: movaps vf128(%rip), %xmm1
-; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
+; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %r8
@@ -983,8 +983,8 @@ define dso_local void @Test128_1Div(fp128 %d1) nounwind {
; WIN-NEXT: subq $88, %rsp
; WIN-NEXT: movaps (%rcx), %xmm0
; WIN-NEXT: movaps vf128(%rip), %xmm1
-; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
+; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %r8
@@ -1222,8 +1222,8 @@ define dso_local void @Test128_1Rem(fp128 %d1) nounwind {
; WIN-NEXT: subq $88, %rsp
; WIN-NEXT: movaps (%rcx), %xmm0
; WIN-NEXT: movaps vf128(%rip), %xmm1
-; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
+; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %r8
@@ -2143,9 +2143,9 @@ define fp128 @Test128FMA(fp128 %a, fp128 %b, fp128 %c) nounwind {
; WIN-NEXT: pushq %rsi
; WIN-NEXT: subq $96, %rsp
; WIN-NEXT: movq %rcx, %rsi
-; WIN-NEXT: movaps (%r9), %xmm0
-; WIN-NEXT: movaps (%rdx), %xmm1
-; WIN-NEXT: movaps (%r8), %xmm2
+; WIN-NEXT: movaps (%rdx), %xmm0
+; WIN-NEXT: movaps (%r8), %xmm1
+; WIN-NEXT: movaps (%r9), %xmm2
; WIN-NEXT: movaps %xmm2, {{[0-9]+}}(%rsp)
; WIN-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
; WIN-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
diff --git a/llvm/test/CodeGen/X86/sse-intel-ocl.ll b/llvm/test/CodeGen/X86/sse-intel-ocl.ll
index b2de7545ff5f5..001f3ff66de37 100644
--- a/llvm/test/CodeGen/X86/sse-intel-ocl.ll
+++ b/llvm/test/CodeGen/X86/sse-intel-ocl.ll
@@ -220,26 +220,26 @@ define intel_ocl_bicc <16 x float> @test_prolog_epilog(<16 x float> %a, <16 x fl
; WIN64-NEXT: subq $232, %rsp
; WIN64-NEXT: movaps %xmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
; WIN64-NEXT: movaps %xmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
-; WIN64-NEXT: movaps (%r9), %xmm4
+; WIN64-NEXT: movaps (%rcx), %xmm4
; WIN64-NEXT: movaps (%rdx), %xmm5
; WIN64-NEXT: movaps (%r8), %xmm6
-; WIN64-NEXT: movaps (%rcx), %xmm7
-; WIN64-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
-; WIN64-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
-; WIN64-NEXT: movaps %xmm2, {{[0-9]+}}(%rsp)
-; WIN64-NEXT: movaps %xmm3, {{[0-9]+}}(%rsp)
-; WIN64-NEXT: movaps %xmm7, {{[0-9]+}}(%rsp)
-; WIN64-NEXT: movaps %xmm6, {{[0-9]+}}(%rsp)
-; WIN64-NEXT: movaps %xmm5, {{[0-9]+}}(%rsp)
+; WIN64-NEXT: movaps (%r9), %xmm7
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rax
; WIN64-NEXT: movq %rax, {{[0-9]+}}(%rsp)
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rax
; WIN64-NEXT: movq %rax, {{[0-9]+}}(%rsp)
-; WIN64-NEXT: movaps %xmm4, {{[0-9]+}}(%rsp)
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rax
; WIN64-NEXT: movq %rax, {{[0-9]+}}(%rsp)
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rax
; WIN64-NEXT: movq %rax, {{[0-9]+}}(%rsp)
+; WIN64-NEXT: movaps %xmm7, {{[0-9]+}}(%rsp)
+; WIN64-NEXT: movaps %xmm6, {{[0-9]+}}(%rsp)
+; WIN64-NEXT: movaps %xmm5, {{[0-9]+}}(%rsp)
+; WIN64-NEXT: movaps %xmm4, {{[0-9]+}}(%rsp)
+; WIN64-NEXT: movaps %xmm3, {{[0-9]+}}(%rsp)
+; WIN64-NEXT: movaps %xmm2, {{[0-9]+}}(%rsp)
+; WIN64-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp)
+; WIN64-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
; WIN64-NEXT: leaq {{[0-9]+}}(%rsp), %r8
diff --git a/llvm/test/CodeGen/X86/stack-coloring-x87.ll b/llvm/test/CodeGen/X86/stack-coloring-x87.ll
new file mode 100644
index 0000000000000..53dd483d3d5be
--- /dev/null
+++ b/llvm/test/CodeGen/X86/stack-coloring-x87.ll
@@ -0,0 +1,98 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc -O2 | FileCheck %s
+
+%struct.ByValStruct = type { [4 x i64] }
+declare void @use_byval(ptr byval(%struct.ByValStruct) %a)
+
+define void @test_byval(ptr %p1, ptr %p2, ptr %p3) {
+; CHECK-LABEL: test_byval:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: pushq %rsi
+; CHECK-NEXT: .seh_pushreg %rsi
+; CHECK-NEXT: pushq %rdi
+; CHECK-NEXT: .seh_pushreg %rdi
+; CHECK-NEXT: subq $72, %rsp
+; CHECK-NEXT: .seh_stackalloc 72
+; CHECK-NEXT: .seh_endprologue
+; CHECK-NEXT: movq %r8, %rsi
+; CHECK-NEXT: movq %rdx, %rdi
+; CHECK-NEXT: movq 24(%rcx), %rax
+; CHECK-NEXT: movq %rax, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: movq 16(%rcx), %rax
+; CHECK-NEXT: movq %rax, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: movq (%rcx), %rax
+; CHECK-NEXT: movq 8(%rcx), %rcx
+; CHECK-NEXT: movq %rcx, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: movq %rax, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
+; CHECK-NEXT: callq use_byval
+; CHECK-NEXT: movq 24(%rdi), %rax
+; CHECK-NEXT: movq %rax, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: movq 16(%rdi), %rax
+; CHECK-NEXT: movq %rax, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: movq (%rdi), %rax
+; CHECK-NEXT: movq 8(%rdi), %rcx
+; CHECK-NEXT: movq %rcx, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: movq %rax, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
+; CHECK-NEXT: callq use_byval
+; CHECK-NEXT: movq 24(%rsi), %rax
+; CHECK-NEXT: movq %rax, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: movq 16(%rsi), %rax
+; CHECK-NEXT: movq %rax, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: movq (%rsi), %rax
+; CHECK-NEXT: movq 8(%rsi), %rcx
+; CHECK-NEXT: movq %rcx, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: movq %rax, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
+; CHECK-NEXT: callq use_byval
+; CHECK-NEXT: nop
+; CHECK-NEXT: .seh_startepilogue
+; CHECK-NEXT: addq $72, %rsp
+; CHECK-NEXT: popq %rdi
+; CHECK-NEXT: popq %rsi
+; CHECK-NEXT: .seh_endepilogue
+; CHECK-NEXT: retq
+; CHECK-NEXT: .seh_endproc
+entry:
+ call void @use_byval(ptr byval(%struct.ByValStruct) %p1)
+ call void @use_byval(ptr byval(%struct.ByValStruct) %p2)
+ call void @use_byval(ptr byval(%struct.ByValStruct) %p3)
+ ret void
+}
+
+declare void @use_f80(x86_fp80)
+define void @test_f80(x86_fp80 %p1, x86_fp80 %p2, x86_fp80 %p3) {
+; CHECK-LABEL: test_f80:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: subq $72, %rsp
+; CHECK-NEXT: .seh_stackalloc 72
+; CHECK-NEXT: .seh_endprologue
+; CHECK-NEXT: fldt (%r8)
+; CHECK-NEXT: fstpt {{[-0-9]+}}(%r{{[sb]}}p) # 10-byte Folded Spill
+; CHECK-NEXT: fldt (%rdx)
+; CHECK-NEXT: fstpt {{[-0-9]+}}(%r{{[sb]}}p) # 10-byte Folded Spill
+; CHECK-NEXT: fldt (%rcx)
+; CHECK-NEXT: fstpt {{[0-9]+}}(%rsp)
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
+; CHECK-NEXT: callq use_f80
+; CHECK-NEXT: fldt {{[-0-9]+}}(%r{{[sb]}}p) # 10-byte Folded Reload
+; CHECK-NEXT: fstpt {{[0-9]+}}(%rsp)
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
+; CHECK-NEXT: callq use_f80
+; CHECK-NEXT: fldt {{[-0-9]+}}(%r{{[sb]}}p) # 10-byte Folded Reload
+; CHECK-NEXT: fstpt {{[0-9]+}}(%rsp)
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
+; CHECK-NEXT: callq use_f80
+; CHECK-NEXT: nop
+; CHECK-NEXT: .seh_startepilogue
+; CHECK-NEXT: addq $72, %rsp
+; CHECK-NEXT: .seh_endepilogue
+; CHECK-NEXT: retq
+; CHECK-NEXT: .seh_endproc
+entry:
+ call void @use_f80(x86_fp80 %p1)
+ call void @use_f80(x86_fp80 %p2)
+ call void @use_f80(x86_fp80 %p3)
+ ret void
+}
diff --git a/llvm/test/CodeGen/X86/win64-byval.ll b/llvm/test/CodeGen/X86/win64-byval.ll
index 573a0016e8772..a4ed85cad6078 100644
--- a/llvm/test/CodeGen/X86/win64-byval.ll
+++ b/llvm/test/CodeGen/X86/win64-byval.ll
@@ -63,21 +63,21 @@ define void @test() {
; CHECK-NEXT: subq $136, %rsp
; CHECK-NEXT: .seh_stackalloc 136
; CHEC...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/213134
More information about the llvm-commits
mailing list