https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/170518
>From 2513476f2f7ec5b611acdfc649c0d451e6030989 Mon Sep 17 00:00:00 2001 From: Paul Kirth <[email protected]> Date: Tue, 2 Dec 2025 15:14:32 -0800 Subject: [PATCH 1/6] [clang] Use tighter lifetime bounds for C temporary arguments In C, consecutive statements in the same scope are under CompoundStmt/CallExpr, while in C++ they typically fall under CompoundStmt/ExprWithCleanup. This leads to different behavior with respect to where pushFullExprCleanUp inserts the lifetime end markers (e.g., at the end of scope). For these cases, we can track and insert the lifetime end markers right after the call completes. Allowing the stack space to be reused immediately. This partially addresses #109204 and #43598 for improving stack usage. --- clang/lib/CodeGen/CGCall.cpp | 20 +++-- clang/lib/CodeGen/CGCall.h | 19 ++++ clang/test/CodeGen/stack-usage-lifetimes.c | 89 +++++++++++++++++++ .../CodeGenCXX/stack-reuse-miscompile.cpp | 2 +- 4 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGen/stack-usage-lifetimes.c diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 84d3229863fe9..1bb4ef1709d9d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4972,12 +4972,17 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, RawAddress ArgSlotAlloca = Address::invalid(); ArgSlot = CreateAggTemp(E->getType(), "agg.tmp", &ArgSlotAlloca); - // Emit a lifetime start/end for this temporary at the end of the full - // expression. + // Emit a lifetime start/end for this temporary. If the type has a + // destructor, then we need to keep it alive for the full expression. if (!CGM.getCodeGenOpts().NoLifetimeMarkersForTemporaries && - EmitLifetimeStart(ArgSlotAlloca.getPointer())) - pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, - ArgSlotAlloca); + EmitLifetimeStart(ArgSlotAlloca.getPointer())) { + if (E->getType().isDestructedType()) { + pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, + ArgSlotAlloca); + } else { + args.addLifetimeCleanup({ArgSlotAlloca.getPointer()}); + } + } } args.add(EmitAnyExpr(E, ArgSlot), type); @@ -6307,6 +6312,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, for (CallLifetimeEnd &LifetimeEnd : CallLifetimeEndAfterCall) LifetimeEnd.Emit(*this, /*Flags=*/{}); + if (!CGM.getCodeGenOpts().NoLifetimeMarkersForTemporaries) + for (const CallArgList::EndLifetimeInfo < : + CallArgs.getLifetimeCleanups()) + EmitLifetimeEnd(LT.Addr); + if (!ReturnValue.isExternallyDestructed() && RetTy.isDestructedType() == QualType::DK_nontrivial_c_struct) pushDestroy(QualType::DK_nontrivial_c_struct, Ret.getAggregateAddress(), diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 1ef8a3f114573..aab4b64d6a4a8 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -299,6 +299,10 @@ class CallArgList : public SmallVector<CallArg, 8> { llvm::Instruction *IsActiveIP; }; + struct EndLifetimeInfo { + llvm::Value *Addr; + }; + void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); } void addUncopiedAggregate(LValue LV, QualType type) { @@ -312,6 +316,9 @@ class CallArgList : public SmallVector<CallArg, 8> { llvm::append_range(*this, other); llvm::append_range(Writebacks, other.Writebacks); llvm::append_range(CleanupsToDeactivate, other.CleanupsToDeactivate); + LifetimeCleanups.insert(LifetimeCleanups.end(), + other.LifetimeCleanups.begin(), + other.LifetimeCleanups.end()); assert(!(StackBase && other.StackBase) && "can't merge stackbases"); if (!StackBase) StackBase = other.StackBase; @@ -352,6 +359,14 @@ class CallArgList : public SmallVector<CallArg, 8> { /// memory. bool isUsingInAlloca() const { return StackBase; } + void addLifetimeCleanup(EndLifetimeInfo Info) { + LifetimeCleanups.push_back(Info); + } + + ArrayRef<EndLifetimeInfo> getLifetimeCleanups() const { + return LifetimeCleanups; + } + // Support reversing writebacks for MSVC ABI. void reverseWritebacks() { std::reverse(Writebacks.begin(), Writebacks.end()); @@ -365,6 +380,10 @@ class CallArgList : public SmallVector<CallArg, 8> { /// occurs. SmallVector<CallArgCleanup, 1> CleanupsToDeactivate; + /// Lifetime information needed to call llvm.lifetime.end for any temporary + /// argument allocas. + SmallVector<EndLifetimeInfo, 2> LifetimeCleanups; + /// The stacksave call. It dominates all of the argument evaluation. llvm::CallInst *StackBase = nullptr; }; diff --git a/clang/test/CodeGen/stack-usage-lifetimes.c b/clang/test/CodeGen/stack-usage-lifetimes.c new file mode 100644 index 0000000000000..189bc9c229ca4 --- /dev/null +++ b/clang/test/CodeGen/stack-usage-lifetimes.c @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog %s -verify=x86-precise +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog -sloppy-temporary-lifetimes %s -verify=x86-sloppy + +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog %s -verify=aarch64-precise +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog -sloppy-temporary-lifetimes %s -verify=aarch64-sloppy + +// RUN: %clang_cc1 -triple riscv64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog %s -verify=riscv-precise +// RUN: %clang_cc1 -triple riscv64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog -sloppy-temporary-lifetimes %s -verify=riscv-sloppy + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog %s -verify=x86-precise -xc++ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog -sloppy-temporary-lifetimes %s -verify=x86-sloppy -xc++ + +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog %s -verify=aarch64-precise -xc++ +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog -sloppy-temporary-lifetimes %s -verify=aarch64-sloppy -xc++ + +// RUN: %clang_cc1 -triple riscv64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog %s -verify=riscv-precise -xc++ +// RUN: %clang_cc1 -triple riscv64-unknown-linux-gnu -O1 -emit-codegen-only -Rpass-analysis=prologepilog -sloppy-temporary-lifetimes %s -verify=riscv-sloppy -xc++ + + +typedef struct { char x[32]; } A; +typedef struct { char *w, *x, *y, *z; } B; + +void useA(A); +void useB(B); +A genA(void); +B genB(void); + +void t1(int c) { + // x86-precise-remark@-1 {{40 stack bytes}} + // x86-sloppy-remark@-2 {{72 stack bytes}} + // aarch64-precise-remark@-3 {{48 stack bytes}} + // aarch64-sloppy-remark@-4 {{80 stack bytes}} + // riscv-precise-remark@-5 {{48 stack bytes}} + // riscv-sloppy-remark@-6 {{80 stack bytes}} + + if (c) + useA(genA()); + else + useA(genA()); +} + +void t2(void) { + // x86-precise-remark@-1 {{40 stack bytes}} + // x86-sloppy-remark@-2 {{72 stack bytes}} + // aarch64-precise-remark@-3 {{48 stack bytes}} + // aarch64-sloppy-remark@-4 {{80 stack bytes}} + // riscv-precise-remark@-5 {{48 stack bytes}} + // riscv-sloppy-remark@-6 {{80 stack bytes}} + + useA(genA()); + useA(genA()); +} + +void t3(void) { + // x86-precise-remark@-1 {{40 stack bytes}} + // x86-sloppy-remark@-2 {{72 stack bytes}} + // aarch64-precise-remark@-3 {{48 stack bytes}} + // aarch64-sloppy-remark@-4 {{80 stack bytes}} + // riscv-precise-remark@-5 {{48 stack bytes}} + // riscv-sloppy-remark@-6 {{80 stack bytes}} + + useB(genB()); + useB(genB()); +} + +#ifdef __cplusplus +struct C { + char x[24]; + char *ptr; + ~C() {}; +}; + +void useC(C); +C genC(void); + +// This case works in C++, since its AST is structured slightly differently +// than it is in C (CompundStmt/ExprWithCleanup/CallExpr vs CompundStmt/CallExpr). +void t4() { + // x86-precise-remark@-1 {{40 stack bytes}} + // x86-sloppy-remark@-2 {{72 stack bytes}} + // aarch64-precise-remark@-3 {{48 stack bytes}} + // aarch64-sloppy-remark@-4 {{80 stack bytes}} + // riscv-precise-remark@-5 {{48 stack bytes}} + // riscv-sloppy-remark@-6 {{80 stack bytes}} + + useC(genC()); + useC(genC()); +} +#endif diff --git a/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp b/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp index 50c374d2710f4..4aef39119c94a 100644 --- a/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp +++ b/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp @@ -38,10 +38,10 @@ const char * f(S s) // CHECK: call void @llvm.lifetime.start.p0(ptr [[T3]]) // CHECK: call void @llvm.lifetime.start.p0(ptr [[AGG]]) // CHECK: [[T5:%.*]] = call noundef ptr @_ZN1TC1E1S(ptr {{[^,]*}} [[T3]], [2 x i32] %{{.*}}) +// CHECK: call void @llvm.lifetime.end.p0(ptr [[AGG]]) // // CHECK: call void @_ZNK1T6concatERKS_(ptr dead_on_unwind writable sret(%class.T) align 4 [[T1]], ptr {{[^,]*}} [[T2]], ptr noundef nonnull align 4 dereferenceable(16) [[T3]]) // CHECK: [[T6:%.*]] = call noundef ptr @_ZNK1T3strEv(ptr {{[^,]*}} [[T1]]) -// CHECK: call void @llvm.lifetime.end.p0(ptr [[AGG]]) // // CHECK: call void @llvm.lifetime.end.p0( // CHECK: call void @llvm.lifetime.end.p0( >From 8be2cad37bff33b82deee2e815696b52c2330944 Mon Sep 17 00:00:00 2001 From: Paul Kirth <[email protected]> Date: Wed, 3 Dec 2025 14:18:34 -0800 Subject: [PATCH 2/6] Update comment to be more accurate --- clang/lib/CodeGen/CGCall.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 1bb4ef1709d9d..607898c65f07c 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4962,12 +4962,10 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, AggValueSlot ArgSlot = AggValueSlot::ignored(); // For arguments with aggregate type, create an alloca to store - // the value. If the argument's type has a destructor, that destructor + // the value. If the argument's type has a destructor, that destructor // will run at the end of the full-expression; emit matching lifetime - // markers. - // - // FIXME: For types which don't have a destructor, consider using a - // narrower lifetime bound. + // markers. For types which don't have a destructor, we use a narrower + // lifetime bound. if (hasAggregateEvaluationKind(E->getType())) { RawAddress ArgSlotAlloca = Address::invalid(); ArgSlot = CreateAggTemp(E->getType(), "agg.tmp", &ArgSlotAlloca); >From 78523ec92fb2a96740f61a1fed8d68d778db2dec Mon Sep 17 00:00:00 2001 From: Paul Kirth <[email protected]> Date: Wed, 3 Dec 2025 16:37:11 -0800 Subject: [PATCH 3/6] Update invoke test for tighter lifetimes --- .../CodeGenCXX/aggregate-lifetime-invoke.cpp | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp b/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp index 32af6b51fe9c8..026f8cb97de2d 100644 --- a/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp +++ b/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp @@ -15,29 +15,27 @@ void test() { // CHECK: call void @llvm.lifetime.start.p0(ptr{{.*}} %[[AGG1]]) // CHECK: invoke void @func_that_throws(ptr{{.*}} %[[AGG1]]) - // CHECK-NEXT: to label %[[CONT1:.*]] unwind label %[[LPAD1:.*]] + // CHECK-NEXT: to label %[[CONT1:.*]] unwind label %[[LPAD:.*]] // CHECK: [[CONT1]]: + + // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG1]]) // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr{{.*}} %[[AGG2]]) - // CHECK: invoke void @func_that_throws(ptr{{.*}} %[[AGG2]]) - // CHECK-NEXT: to label %[[CONT2:.*]] unwind label %[[LPAD2:.*]] + // CHECK: invoke void @_func_that_throws(ptr{{.*}} %[[AGG2]]) + // CHECK-NEXT: to label %[[CONT2:.*]] unwind label %[[LPAD]] // CHECK: [[CONT2]]: - // CHECK-DAG: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG2]]) - // CHECK-DAG: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG1]]) + // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG2]]) // CHECK: br label %[[TRY_CONT:.*]] - // CHECK: [[LPAD1]]: - // CHECK: landingpad - // CHECK: br label %[[EHCLEANUP:.*]] - - // CHECK: [[LPAD2]]: + // CHECK: [[LPAD]]: // CHECK: landingpad - // CHECK: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG2]]) - // CHECK: br label %[[EHCLEANUP]] + // CHECK-NOT: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG1]]) + // CHECK-NOT: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG2]]) + // CHECK: br label %[[TRY_CONT]] - // CHECK: [[EHCLEANUP]]: - // CHECK: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG1]]) + // CHECK: [[TRY_CONT]]: + // CHECK-NEXT: ret void try { func_that_throws(Trivial{0}); func_that_throws(Trivial{0}); >From 5d714bdc2fc5a62a5e62159ed5559badcf5a6a56 Mon Sep 17 00:00:00 2001 From: Paul Kirth <[email protected]> Date: Thu, 4 Dec 2025 11:11:21 -0800 Subject: [PATCH 4/6] Add cleanups for the error path and add more tests --- clang/lib/CodeGen/CGCall.cpp | 3 +++ clang/test/CodeGen/lifetime-invoke-c.c | 12 ++++----- .../CodeGenCXX/aggregate-lifetime-invoke.cpp | 25 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 607898c65f07c..b9bc6ba25fa8e 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4979,6 +4979,9 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, ArgSlotAlloca); } else { args.addLifetimeCleanup({ArgSlotAlloca.getPointer()}); + if (getInvokeDest()) + pushFullExprCleanup<CallLifetimeEnd>(CleanupKind::EHCleanup, + ArgSlotAlloca); } } } diff --git a/clang/test/CodeGen/lifetime-invoke-c.c b/clang/test/CodeGen/lifetime-invoke-c.c index f3573f4b2ec17..95aadf9d2babf 100644 --- a/clang/test/CodeGen/lifetime-invoke-c.c +++ b/clang/test/CodeGen/lifetime-invoke-c.c @@ -22,16 +22,14 @@ void test() { // CHECK-NEXT: to label %[[CONT1:.*]] unwind label %[[LPAD1:.*]] // CHECK: [[CONT1]]: - // CHECK-NOT: call void @llvm.lifetime.end.p0(ptr %[[AGG1]]) - - // CHECK: call void @llvm.lifetime.start.p0(ptr %[[AGG2]]) - // CHECK: invoke void @gen(ptr{{.*}} sret(%struct.Trivial){{.*}} %[[AGG2]]) - // CHECK: invoke void @func(ptr{{.*}} %[[AGG2]]) + // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr %[[AGG1]]) + // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr %[[AGG2]]) + // CHECK: invoke void @gen(ptr{{.*}} sret(%struct.Trivial) align 4 %[[AGG2]]) + // CHECK: invoke void @func(ptr{{.*}} byval(%struct.Trivial) align 8 %[[AGG2]]) // CHECK-NEXT: to label %[[CONT2:.*]] unwind label %[[LPAD2:.*]] // CHECK: [[CONT2]]: - // CHECK-DAG: call void @llvm.lifetime.end.p0(ptr %[[AGG2]]) - // CHECK-DAG: call void @llvm.lifetime.end.p0(ptr %[[AGG1]]) + // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr %[[AGG2]]) // CHECK: [[LPAD1]]: // CHECK: landingpad diff --git a/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp b/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp index 026f8cb97de2d..adcc357cb2e45 100644 --- a/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp +++ b/clang/test/CodeGenCXX/aggregate-lifetime-invoke.cpp @@ -15,27 +15,26 @@ void test() { // CHECK: call void @llvm.lifetime.start.p0(ptr{{.*}} %[[AGG1]]) // CHECK: invoke void @func_that_throws(ptr{{.*}} %[[AGG1]]) - // CHECK-NEXT: to label %[[CONT1:.*]] unwind label %[[LPAD:.*]] - - // CHECK: [[CONT1]]: + // CHECK: [[CONT1:.*]]: // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG1]]) // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr{{.*}} %[[AGG2]]) - // CHECK: invoke void @_func_that_throws(ptr{{.*}} %[[AGG2]]) - // CHECK-NEXT: to label %[[CONT2:.*]] unwind label %[[LPAD]] + // CHECK: invoke void @func_that_throws(ptr{{.*}} %[[AGG2]]) - // CHECK: [[CONT2]]: + // CHECK: [[CONT2:.*]]: // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG2]]) - // CHECK: br label %[[TRY_CONT:.*]] - // CHECK: [[LPAD]]: + // CHECK: [[LPAD1:lpad.*]]: + // CHECK: landingpad + // CHECK: br label %[[EHCLEANUP:.*]] + + // CHECK: [[LPAD2:lpad.*]]: // CHECK: landingpad - // CHECK-NOT: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG1]]) - // CHECK-NOT: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG2]]) - // CHECK: br label %[[TRY_CONT]] + // CHECK: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG2]]) + // CHECK: br label %[[EHCLEANUP]] - // CHECK: [[TRY_CONT]]: - // CHECK-NEXT: ret void + // CHECK: [[EHCLEANUP]]: + // CHECK: call void @llvm.lifetime.end.p0(ptr{{.*}} %[[AGG1]]) try { func_that_throws(Trivial{0}); func_that_throws(Trivial{0}); >From aa32d945bd39935d14c731a2b24b51467dda9241 Mon Sep 17 00:00:00 2001 From: Paul Kirth <[email protected]> Date: Thu, 4 Dec 2025 13:55:05 -0800 Subject: [PATCH 5/6] Avoid checking NoLifetimeMarkersForTemporaries --- clang/lib/CodeGen/CGCall.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index b9bc6ba25fa8e..779c372613488 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -6313,10 +6313,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, for (CallLifetimeEnd &LifetimeEnd : CallLifetimeEndAfterCall) LifetimeEnd.Emit(*this, /*Flags=*/{}); - if (!CGM.getCodeGenOpts().NoLifetimeMarkersForTemporaries) - for (const CallArgList::EndLifetimeInfo < : - CallArgs.getLifetimeCleanups()) - EmitLifetimeEnd(LT.Addr); + // Add lifetime end markers for any temporary aggregates. Under + // NoLifetimeMarkersForTemporaries LifetimeCleanups will be empty, so this is + // still correct. + for (const CallArgList::EndLifetimeInfo < : CallArgs.getLifetimeCleanups()) + EmitLifetimeEnd(LT.Addr); if (!ReturnValue.isExternallyDestructed() && RetTy.isDestructedType() == QualType::DK_nontrivial_c_struct) >From 2560fa6b00c1776550c8f902b7f8b28f223c26b9 Mon Sep 17 00:00:00 2001 From: Paul Kirth <[email protected]> Date: Thu, 4 Dec 2025 14:35:38 -0800 Subject: [PATCH 6/6] Fix test checks --- clang/test/CodeGen/lifetime-invoke-c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/CodeGen/lifetime-invoke-c.c b/clang/test/CodeGen/lifetime-invoke-c.c index 95aadf9d2babf..5d38ad9e0c408 100644 --- a/clang/test/CodeGen/lifetime-invoke-c.c +++ b/clang/test/CodeGen/lifetime-invoke-c.c @@ -24,8 +24,8 @@ void test() { // CHECK: [[CONT1]]: // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr %[[AGG1]]) // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr %[[AGG2]]) - // CHECK: invoke void @gen(ptr{{.*}} sret(%struct.Trivial) align 4 %[[AGG2]]) - // CHECK: invoke void @func(ptr{{.*}} byval(%struct.Trivial) align 8 %[[AGG2]]) + // CHECK: invoke void @gen(ptr{{.*}} sret(%struct.Trivial){{.*}} %[[AGG2]]) + // CHECK: invoke void @func(ptr{{.*}} %[[AGG2]]) // CHECK-NEXT: to label %[[CONT2:.*]] unwind label %[[LPAD2:.*]] // CHECK: [[CONT2]]: _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
