[clang] [Clang][CodeGen] Do not emit lifetime intrinsics for coro promise alloca (PR #140548)
NewSigma wrote: After further consideration, I think this is not a satisfactory solution to the issue. I may revisit it if I develop a concrete plan. Apologies for any inconvenience. https://github.com/llvm/llvm-project/pull/140548 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CodeGen] Do not emit lifetime intrinsics for coro promise alloca (PR #140548)
https://github.com/NewSigma closed https://github.com/llvm/llvm-project/pull/140548 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CodeGen] Do not emit lifetime intrinsics for coro promise alloca (PR #140548)
https://github.com/NewSigma created https://github.com/llvm/llvm-project/pull/140548 Coro promise has same lifetime as coro frame. It do not need explicit lifetime guarding. If we add lifetimes to it, middle end passes may assume promise dead after lifetime.end, leading to mis-optimizations. Fix #120200 >From d2e1a8d8a650f2a38387c500f942a0c6722c8a84 Mon Sep 17 00:00:00 2001 From: NewSigma Date: Mon, 19 May 2025 22:12:45 +0800 Subject: [PATCH] Do not emit lifetime intrinsics for coro promise alloca --- clang/lib/CodeGen/CGDecl.cpp | 5 + clang/test/CodeGenCoroutines/coro-params.cpp | 3 --- clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 4a8f7f6a42ecb..556adebc6fa39 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1343,6 +1343,11 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size, if (!ShouldEmitLifetimeMarkers) return nullptr; + // No lifetimes on promise alloca, or middle end passes will assume promise + // dead after lifetime.end, leading to mis-optimization + if (Addr->getName() == "__promise") +return nullptr; + assert(Addr->getType()->getPointerAddressSpace() == CGM.getDataLayout().getAllocaAddrSpace() && "Pointer should be in alloca address space"); diff --git a/clang/test/CodeGenCoroutines/coro-params.cpp b/clang/test/CodeGenCoroutines/coro-params.cpp index 719726cca29c5..4f13e093197ff 100644 --- a/clang/test/CodeGenCoroutines/coro-params.cpp +++ b/clang/test/CodeGenCoroutines/coro-params.cpp @@ -84,7 +84,6 @@ void f(int val, MoveOnly moParam, MoveAndCopy mcParam, TrivialABI trivialParam) // CHECK-NEXT: call void @_ZN11MoveAndCopyC1EOS_(ptr {{[^,]*}} %[[McCopy]], ptr noundef nonnull align 4 dereferenceable(4) %[[McParam]]) # // CHECK-NEXT: call void @llvm.lifetime.start.p0( // CHECK-NEXT: call void @_ZN10TrivialABIC1EOS_(ptr {{[^,]*}} %[[TrivialCopy]], ptr {{[^,]*}} %[[TrivialAlloca]]) - // CHECK-NEXT: call void @llvm.lifetime.start.p0( // CHECK-NEXT: invoke void @_ZNSt16coroutine_traitsIJvi8MoveOnly11MoveAndCopy10TrivialABIEE12promise_typeC1Ev( // CHECK: call void @_ZN14suspend_always12await_resumeEv( @@ -106,7 +105,6 @@ void f(int val, MoveOnly moParam, MoveAndCopy mcParam, TrivialABI trivialParam) // Destroy promise, then parameter copies: // CHECK: call void @_ZNSt16coroutine_traitsIJvi8MoveOnly11MoveAndCopy10TrivialABIEE12promise_typeD1Ev(ptr {{[^,]*}} %__promise) - // CHECK-NEXT: call void @llvm.lifetime.end.p0( // CHECK-NEXT: call void @_ZN10TrivialABID1Ev(ptr {{[^,]*}} %[[TrivialCopy]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0( // CHECK-NEXT: call void @_ZN11MoveAndCopyD1Ev(ptr {{[^,]*}} %[[McCopy]]) @@ -135,7 +133,6 @@ void dependent_params(T x, U, U y) { // CHECK-NEXT: call void @_ZN1BC1EOS_(ptr {{[^,]*}} %[[unnamed_copy]], ptr noundef nonnull align 4 dereferenceable(512) %0) // CHECK-NEXT: call void @llvm.lifetime.start.p0( // CHECK-NEXT: call void @_ZN1BC1EOS_(ptr {{[^,]*}} %[[y_copy]], ptr noundef nonnull align 4 dereferenceable(512) %y) - // CHECK-NEXT: call void @llvm.lifetime.start.p0( // CHECK-NEXT: invoke void @_ZNSt16coroutine_traitsIJv1A1BS1_EE12promise_typeC1Ev( co_return; diff --git a/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp b/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp index d71c2c558996a..d028c127e1e21 100644 --- a/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp +++ b/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp @@ -52,7 +52,7 @@ coroutine ArrayInitCoro() { // CHECK-NEXT: store ptr %arrayinit.element, ptr %arrayinit.endOfInit.reload.addr, align 8 co_await Awaiter{} // CHECK-NEXT: @_ZNSt14suspend_always11await_readyEv -// CHECK-NEXT: br i1 %{{.+}}, label %await.ready, label %CoroSave30 +// CHECK-NEXT: br i1 %{{.+}}, label %await.ready, label %CoroSave29 }; // CHECK: await.cleanup:; preds = %AfterCoroSuspend{{.*}} // CHECK-NEXT:br label %cleanup{{.*}}.from.await.cleanup ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CodeGen] Do not emit lifetime intrinsics for coro promise alloca (PR #140548)
NewSigma wrote: Here is a example ``` LLVM define i32 @fn() { entry: %__promise = alloca i32, align 4 %id = call token @llvm.coro.id(i32 16, ptr nonnull %__promise, ptr nonnull @fn, ptr null) %hdl = call ptr @llvm.coro.begin(token %id, ptr null) #14 %promise.addr = call ptr @llvm.coro.promise(ptr %hdl, i32 4, i1 false) #14 call void @llvm.lifetime.start.p0(i64 4, ptr %promise.addr) #2 store i32 5, ptr %promise.addr, align 4 ; DSE eliminates call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %promise.addr) #2 %0 = call i1 @llvm.coro.end(ptr null, i1 false, token none) #14 %value = load i32, ptr %promise.addr, align 4 ret i32 %value } ``` https://github.com/llvm/llvm-project/pull/140548 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CodeGen] Do not emit lifetime intrinsics for coro promise alloca (PR #140548)
https://github.com/NewSigma updated https://github.com/llvm/llvm-project/pull/140548 >From d2e1a8d8a650f2a38387c500f942a0c6722c8a84 Mon Sep 17 00:00:00 2001 From: NewSigma Date: Mon, 19 May 2025 22:12:45 +0800 Subject: [PATCH 1/2] Do not emit lifetime intrinsics for coro promise alloca --- clang/lib/CodeGen/CGDecl.cpp | 5 + clang/test/CodeGenCoroutines/coro-params.cpp | 3 --- clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 4a8f7f6a42ecb..556adebc6fa39 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1343,6 +1343,11 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size, if (!ShouldEmitLifetimeMarkers) return nullptr; + // No lifetimes on promise alloca, or middle end passes will assume promise + // dead after lifetime.end, leading to mis-optimization + if (Addr->getName() == "__promise") +return nullptr; + assert(Addr->getType()->getPointerAddressSpace() == CGM.getDataLayout().getAllocaAddrSpace() && "Pointer should be in alloca address space"); diff --git a/clang/test/CodeGenCoroutines/coro-params.cpp b/clang/test/CodeGenCoroutines/coro-params.cpp index 719726cca29c5..4f13e093197ff 100644 --- a/clang/test/CodeGenCoroutines/coro-params.cpp +++ b/clang/test/CodeGenCoroutines/coro-params.cpp @@ -84,7 +84,6 @@ void f(int val, MoveOnly moParam, MoveAndCopy mcParam, TrivialABI trivialParam) // CHECK-NEXT: call void @_ZN11MoveAndCopyC1EOS_(ptr {{[^,]*}} %[[McCopy]], ptr noundef nonnull align 4 dereferenceable(4) %[[McParam]]) # // CHECK-NEXT: call void @llvm.lifetime.start.p0( // CHECK-NEXT: call void @_ZN10TrivialABIC1EOS_(ptr {{[^,]*}} %[[TrivialCopy]], ptr {{[^,]*}} %[[TrivialAlloca]]) - // CHECK-NEXT: call void @llvm.lifetime.start.p0( // CHECK-NEXT: invoke void @_ZNSt16coroutine_traitsIJvi8MoveOnly11MoveAndCopy10TrivialABIEE12promise_typeC1Ev( // CHECK: call void @_ZN14suspend_always12await_resumeEv( @@ -106,7 +105,6 @@ void f(int val, MoveOnly moParam, MoveAndCopy mcParam, TrivialABI trivialParam) // Destroy promise, then parameter copies: // CHECK: call void @_ZNSt16coroutine_traitsIJvi8MoveOnly11MoveAndCopy10TrivialABIEE12promise_typeD1Ev(ptr {{[^,]*}} %__promise) - // CHECK-NEXT: call void @llvm.lifetime.end.p0( // CHECK-NEXT: call void @_ZN10TrivialABID1Ev(ptr {{[^,]*}} %[[TrivialCopy]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0( // CHECK-NEXT: call void @_ZN11MoveAndCopyD1Ev(ptr {{[^,]*}} %[[McCopy]]) @@ -135,7 +133,6 @@ void dependent_params(T x, U, U y) { // CHECK-NEXT: call void @_ZN1BC1EOS_(ptr {{[^,]*}} %[[unnamed_copy]], ptr noundef nonnull align 4 dereferenceable(512) %0) // CHECK-NEXT: call void @llvm.lifetime.start.p0( // CHECK-NEXT: call void @_ZN1BC1EOS_(ptr {{[^,]*}} %[[y_copy]], ptr noundef nonnull align 4 dereferenceable(512) %y) - // CHECK-NEXT: call void @llvm.lifetime.start.p0( // CHECK-NEXT: invoke void @_ZNSt16coroutine_traitsIJv1A1BS1_EE12promise_typeC1Ev( co_return; diff --git a/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp b/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp index d71c2c558996a..d028c127e1e21 100644 --- a/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp +++ b/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp @@ -52,7 +52,7 @@ coroutine ArrayInitCoro() { // CHECK-NEXT: store ptr %arrayinit.element, ptr %arrayinit.endOfInit.reload.addr, align 8 co_await Awaiter{} // CHECK-NEXT: @_ZNSt14suspend_always11await_readyEv -// CHECK-NEXT: br i1 %{{.+}}, label %await.ready, label %CoroSave30 +// CHECK-NEXT: br i1 %{{.+}}, label %await.ready, label %CoroSave29 }; // CHECK: await.cleanup:; preds = %AfterCoroSuspend{{.*}} // CHECK-NEXT:br label %cleanup{{.*}}.from.await.cleanup >From 8f3a3bdc40d418d1b9325c63236b5d5741d0d760 Mon Sep 17 00:00:00 2001 From: NewSigma Date: Tue, 20 May 2025 08:03:02 +0800 Subject: [PATCH 2/2] Use VarDecl::getName instead of Value::getName --- clang/lib/CodeGen/CGDecl.cpp | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 556adebc6fa39..a308b8bf2c387 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1343,11 +1343,6 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size, if (!ShouldEmitLifetimeMarkers) return nullptr; - // No lifetimes on promise alloca, or middle end passes will assume promise - // dead after lifetime.end, leading to mis-optimization - if (Addr->getName() == "__promise") -return nullptr; - assert(Addr->getType()->getPointerAddressSpace() == CGM.getDataLayout().getAllocaAddrSpace() && "Poin
[clang] [Clang][CodeGen] Do not emit lifetime intrinsics for coro promise alloca (PR #140548)
@@ -1343,6 +1343,11 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size, if (!ShouldEmitLifetimeMarkers) return nullptr; + // No lifetimes on promise alloca, or middle end passes will assume promise + // dead after lifetime.end, leading to mis-optimization + if (Addr->getName() == "__promise") NewSigma wrote: Thank you for catching that. I've now used VarDecl::getName and tested it on non-assert builds. https://github.com/llvm/llvm-project/pull/140548 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits