https://github.com/NewSigma updated 
https://github.com/llvm/llvm-project/pull/151067

>From 335a1884354b77afc4b4cdacc88956c55eb0191e Mon Sep 17 00:00:00 2001
From: NewSigma <[email protected]>
Date: Thu, 30 Oct 2025 09:15:32 +0800
Subject: [PATCH 1/2] Promote point of GRO

---
 clang/lib/CodeGen/CGCoroutine.cpp             | 120 +++++++++++++++---
 .../test/CodeGenCoroutines/coro-dest-slot.cpp |   2 +-
 clang/test/CodeGenCoroutines/coro-gro.cpp     |  75 +++++++----
 .../coro-symmetric-transfer-02.cpp            |   4 +-
 4 files changed, 160 insertions(+), 41 deletions(-)

diff --git a/clang/lib/CodeGen/CGCoroutine.cpp 
b/clang/lib/CodeGen/CGCoroutine.cpp
index b76450152203d..a805a4d536616 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -53,6 +53,10 @@ struct clang::CodeGen::CGCoroData {
   // handler, this is null.
   llvm::Value *ResumeEHVar = nullptr;
 
+  // Stores the i1 that identify if control flows off the end of the coroutine
+  // body
+  llvm::PHINode *BodyDone = nullptr;
+
   // Stores the jump destination just before the coroutine memory is freed.
   // This is the destination that every suspend point jumps to for the cleanup
   // branch.
@@ -599,14 +603,18 @@ namespace {
 struct CallCoroDelete final : public EHScopeStack::Cleanup {
   Stmt *Deallocate;
 
-  // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;"
+  void Emit(CodeGenFunction &CGF, Flags F) override {
+    // Cleanup always happens on unwind. No need for pre-cleanup block.
+    if (F.isForNormalCleanup())
+      EmitPreCleanupBB(CGF);
+    // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;"
+
+    // Note: That deallocation will be emitted twice: once for a normal exit 
and
+    // once for exceptional exit. This usage is safe because Deallocate does 
not
+    // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
+    // builds a single call to a deallocation function which is safe to emit
+    // multiple times.
 
-  // Note: That deallocation will be emitted twice: once for a normal exit and
-  // once for exceptional exit. This usage is safe because Deallocate does not
-  // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
-  // builds a single call to a deallocation function which is safe to emit
-  // multiple times.
-  void Emit(CodeGenFunction &CGF, Flags) override {
     // Remember the current point, as we are going to emit deallocation code
     // first to get to coro.free instruction that is an argument to a delete
     // call.
@@ -642,6 +650,37 @@ struct CallCoroDelete final : public EHScopeStack::Cleanup 
{
     CGF.Builder.SetInsertPoint(AfterFreeBB);
   }
   explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
+
+private:
+  // [dcl.fct.def.coroutine]: The coroutine state is destroyed when control
+  // flows off the end of the coroutine or the destroy member function of a
+  // coroutine handle that refers to the coroutine is invoked.
+  void EmitPreCleanupBB(CodeGenFunction &CGF) {
+    auto &Builder = CGF.Builder;
+    auto &Data = *CGF.CurCoro.Data;
+    auto *BodyDone = Data.BodyDone;
+    BasicBlock *SaveInsertBlock = Builder.GetInsertBlock();
+    BasicBlock *PreConvBB = BodyDone->getParent();
+    BasicBlock *AfterConvBB =
+        cast<llvm::BranchInst>(PreConvBB->getTerminator())->getSuccessor(1);
+    BasicBlock *CleanupBB = AfterConvBB->getSingleSuccessor();
+    BasicBlock *PreCleanupBB = CleanupBB->splitBasicBlock(
+        CleanupBB->getFirstNonPHIIt(), "pre.coro.cleanup", true);
+    Builder.SetInsertPoint(PreCleanupBB);
+    PreCleanupBB->getTerminator()->eraseFromParent();
+
+    auto *NeedCleanup = Builder.CreatePHI(
+        Builder.getInt1Ty(), llvm::pred_size(PreCleanupBB), "is.completed");
+    for (auto *Pred : llvm::predecessors(PreCleanupBB)) {
+      auto *V = (Pred == AfterConvBB) ? cast<Value>(BodyDone)
+                                      : cast<Value>(Builder.getTrue());
+      NeedCleanup->addIncoming(V, Pred);
+    }
+
+    auto *RetBB = Data.CleanupJD.getBlock();
+    Builder.CreateCondBr(NeedCleanup, CleanupBB, RetBB);
+    Builder.SetInsertPoint(SaveInsertBlock);
+  }
 };
 }
 
@@ -691,7 +730,7 @@ struct GetReturnObjectManager {
   // split its emission in two parts. EmitGroAlloca emits an alloca and sets up
   // cleanups. Later when coroutine promise is available we initialize the gro
   // and sets the flag that the cleanup is now active.
-  void EmitGroAlloca() {
+  void EmitGroActive() {
     if (DirectEmit)
       return;
 
@@ -701,12 +740,23 @@ struct GetReturnObjectManager {
       return;
     }
 
-    auto *GroVarDecl = cast<VarDecl>(GroDeclStmt->getSingleDecl());
-
     // Set GRO flag that it is not initialized yet
     GroActiveFlag = CGF.CreateTempAlloca(Builder.getInt1Ty(), CharUnits::One(),
                                          "gro.active");
     Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
+  }
+
+  void EmitGroAlloca() {
+    if (DirectEmit)
+      return;
+
+    auto *GroDeclStmt = dyn_cast_or_null<DeclStmt>(S.getResultDecl());
+    if (!GroDeclStmt) {
+      // If get_return_object returns void, no need to do an alloca.
+      return;
+    }
+
+    auto *GroVarDecl = cast<VarDecl>(GroDeclStmt->getSingleDecl());
 
     GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl);
 
@@ -768,6 +818,38 @@ struct GetReturnObjectManager {
     CGF.EmitAutoVarInit(GroEmission);
     Builder.CreateStore(Builder.getTrue(), GroActiveFlag);
   }
+
+  void EmitGroConv() {
+    auto *InsertPt = Builder.GetInsertBlock();
+    auto *PreConvBB = CGF.CurCoro.Data->SuspendBB;
+    auto *AfterConvBB = CGF.createBasicBlock("after.gro.conv", CGF.CurFn, 
InsertPt);
+    Builder.SetInsertPoint(AfterConvBB);
+    BasicBlock *AfterFinalBB = nullptr;
+    if (InsertPt) {
+      AfterFinalBB = InsertPt->getSinglePredecessor();
+      InsertPt->replaceAllUsesWith(PreConvBB);
+      Builder.CreateBr(InsertPt);
+    }
+
+    auto *ConvBB = CGF.createBasicBlock("gro.conv", CGF.CurFn, AfterConvBB);
+    Builder.SetInsertPoint(ConvBB);
+    Builder.CreateBr(AfterConvBB);
+
+    CGF.EmitBlock(PreConvBB);
+    PreConvBB->moveBefore(ConvBB);
+    auto *BodyDone =
+        Builder.CreatePHI(Builder.getInt1Ty(), llvm::pred_size(PreConvBB));
+    for (auto *Pred : llvm::predecessors(PreConvBB)) {
+      auto *V = (Pred == AfterFinalBB) ? Builder.getTrue() : 
Builder.getFalse();
+      BodyDone->addIncoming(V, Pred);
+    }
+    CGF.CurCoro.Data->BodyDone = BodyDone;
+    auto *InRampFn = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_is_in_ramp);
+    auto *InRamp = Builder.CreateCall(InRampFn, {}, "InRamp");
+    Builder.CreateCondBr(InRamp, ConvBB, AfterConvBB);
+
+    Builder.SetInsertPoint(InsertPt == nullptr ? AfterConvBB : InsertPt);
+  }
 };
 } // namespace
 
@@ -790,12 +872,13 @@ void CodeGenFunction::EmitCoroutineBody(const 
CoroutineBodyStmt &S) {
   auto *InitBB = createBasicBlock("coro.init");
   auto *FinalBB = createBasicBlock("coro.final");
   auto *RetBB = createBasicBlock("coro.ret");
+  auto *PreConvBB = createBasicBlock("pre.gvo.conv");
 
   auto *CoroId = Builder.CreateCall(
       CGM.getIntrinsic(llvm::Intrinsic::coro_id),
       {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});
   createCoroData(*this, CurCoro, CoroId);
-  CurCoro.Data->SuspendBB = RetBB;
+  CurCoro.Data->SuspendBB = PreConvBB;
   assert(ShouldEmitLifetimeMarkers &&
          "Must emit lifetime intrinsics for coroutines");
 
@@ -840,7 +923,6 @@ void CodeGenFunction::EmitCoroutineBody(const 
CoroutineBodyStmt &S) {
   CurCoro.Data->CoroBegin = CoroBegin;
 
   GetReturnObjectManager GroManager(*this, S);
-  GroManager.EmitGroAlloca();
 
   CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB);
   {
@@ -884,6 +966,7 @@ void CodeGenFunction::EmitCoroutineBody(const 
CoroutineBodyStmt &S) {
       // not needed.
     }
 
+    GroManager.EmitGroActive();
     EmitStmt(S.getPromiseDeclStmt());
 
     Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl());
@@ -895,6 +978,7 @@ void CodeGenFunction::EmitCoroutineBody(const 
CoroutineBodyStmt &S) {
     CoroId->setArgOperand(1, PromiseAddrVoidPtr);
 
     // Now we have the promise, initialize the GRO
+    GroManager.EmitGroAlloca();
     GroManager.EmitGroInit();
 
     EHStack.pushCleanup<CallCoroEnd>(EHCleanup);
@@ -950,11 +1034,12 @@ void CodeGenFunction::EmitCoroutineBody(const 
CoroutineBodyStmt &S) {
       // We don't need FinalBB. Emit it to make sure the block is deleted.
       EmitBlock(FinalBB, /*IsFinished=*/true);
     }
+    GroManager.EmitGroConv();
   }
 
   EmitBlock(RetBB);
-  // Emit coro.end before getReturnStmt (and parameter destructors), since
-  // resume and destroy parts of the coroutine should not include them.
+  // Emit coro.end before ret instruction, since resume and destroy parts of 
the
+  // coroutine should return void.
   llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
   Builder.CreateCall(CoroEnd,
                      {NullPtr, Builder.getFalse(),
@@ -973,8 +1058,13 @@ void CodeGenFunction::EmitCoroutineBody(const 
CoroutineBodyStmt &S) {
     // shouldn't change the AST.
     if (PreviousRetValue)
       cast<ReturnStmt>(Ret)->setRetValue(PreviousRetValue);
+    // Send GRO conversion to ConvBB
+    auto *ConvBB =
+        cast<llvm::BranchInst>(PreConvBB->getTerminator())->getSuccessor(0);
+    auto FromIt = ++RetBB->getFirstInsertionPt();
+    auto ToIt = RetBB->getTerminator()->getIterator();
+    ConvBB->splice(ConvBB->getFirstNonPHIIt(), RetBB, FromIt, ToIt);
   }
-
   // LLVM require the frontend to mark the coroutine.
   CurFn->setPresplitCoroutine();
 
diff --git a/clang/test/CodeGenCoroutines/coro-dest-slot.cpp 
b/clang/test/CodeGenCoroutines/coro-dest-slot.cpp
index d794c74cd52d6..a770da4d7e321 100644
--- a/clang/test/CodeGenCoroutines/coro-dest-slot.cpp
+++ b/clang/test/CodeGenCoroutines/coro-dest-slot.cpp
@@ -25,7 +25,7 @@ extern "C" coro f(int) { co_return; }
 // CHECK: %[[CLEANUP_DEST0:.+]] = phi i32 [ 0, %[[INIT_READY]] ], [ 2, 
%[[INIT_CLEANUP]] ]
 
 // CHECK: %[[FINAL_SUSPEND:.+]] = call i8 @llvm.coro.suspend(
-// CHECK-NEXT: switch i8 %{{.*}}, label %coro.ret [
+// CHECK-NEXT: switch i8 %{{.*}}, label %pre.gvo.conv [
 // CHECK-NEXT:   i8 0, label %[[FINAL_READY:.+]]
 // CHECK-NEXT:   i8 1, label %[[FINAL_CLEANUP:.+]]
 // CHECK-NEXT: ]
diff --git a/clang/test/CodeGenCoroutines/coro-gro.cpp 
b/clang/test/CodeGenCoroutines/coro-gro.cpp
index 037fd03349e76..826d22a5584e2 100644
--- a/clang/test/CodeGenCoroutines/coro-gro.cpp
+++ b/clang/test/CodeGenCoroutines/coro-gro.cpp
@@ -29,47 +29,76 @@ void doSomething() noexcept;
 // CHECK: define{{.*}} i32 @_Z1fv(
 int f() {
   // CHECK: %[[RetVal:.+]] = alloca i32
-  // CHECK: %[[GroActive:.+]] = alloca i1
-  // CHECK: %[[CoroGro:.+]] = alloca %struct.GroType, {{.*}} 
!coro.outside.frame ![[OutFrameMetadata:.+]]
+  // CHECK-NEXT: %[[GroActive:.+]] = alloca i1
+  // CHECK-NEXT: %[[Promise:.+]] = alloca 
%"struct.std::coroutine_traits<int>::promise_type", align 1
+  // CHECK-NEXT: %[[CoroGro:.+]] = alloca %struct.GroType, {{.*}} 
!coro.outside.frame ![[OutFrameMetadata:.+]]
 
   // CHECK: %[[Size:.+]] = call i64 @llvm.coro.size.i64()
-  // CHECK: call noalias noundef nonnull ptr @_Znwm(i64 noundef %[[Size]])
+  // CHECK-NEXT: call noalias noundef nonnull ptr @_Znwm(i64 noundef %[[Size]])
+
   // CHECK: store i1 false, ptr %[[GroActive]]
-  // CHECK: call void @_ZNSt16coroutine_traitsIiJEE12promise_typeC1Ev(
-  // CHECK: call void 
@_ZNSt16coroutine_traitsIiJEE12promise_type17get_return_objectEv({{.*}} 
%[[CoroGro]]
-  // CHECK: store i1 true, ptr %[[GroActive]]
+  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr %[[Promise]])
+  // CHECK-NEXT: call void @_ZNSt16coroutine_traitsIiJEE12promise_typeC1Ev(
+  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr %[[CoroGro]])
+  // CHECK-NEXT: call void 
@_ZNSt16coroutine_traitsIiJEE12promise_type17get_return_objectEv({{.*}} 
%[[CoroGro]]
+  // CHECK-NEXT: store i1 true, ptr %[[GroActive]]
 
   Cleanup cleanup;
   doSomething();
   co_return;
 
   // CHECK: call void @_Z11doSomethingv(
-  // CHECK: call void 
@_ZNSt16coroutine_traitsIiJEE12promise_type11return_voidEv(
-  // CHECK: call void @_ZN7CleanupD1Ev(
-
-  // Destroy promise and free the memory.
-
-  // CHECK: call void @_ZNSt16coroutine_traitsIiJEE12promise_typeD1Ev(
-  // CHECK: %[[Mem:.+]] = call ptr @llvm.coro.free(
-  // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
-  // CHECK: call void @_ZdlPvm(ptr noundef %[[Mem]], i64 noundef %[[SIZE]])
+  // CHECK-NEXT: call void 
@_ZNSt16coroutine_traitsIiJEE12promise_type11return_voidEv(
+  // CHECK-NEXT: call void @_ZN7CleanupD1Ev(
 
   // Initialize retval from Gro and destroy Gro
   // Note this also tests delaying initialization when Gro and function return
   // types mismatch (see cwg2563).
 
-  // CHECK: %[[Conv:.+]] = call noundef i32 @_ZN7GroTypecviEv(
-  // CHECK: store i32 %[[Conv]], ptr %[[RetVal]]
-  // CHECK: %[[IsActive:.+]] = load i1, ptr %[[GroActive]]
-  // CHECK: br i1 %[[IsActive]], label %[[CleanupGro:.+]], label %[[Done:.+]]
+  // CHECK: pre.gvo.conv:
+  // CHECK-NEXT: %10 = phi i1 [ true, %cleanup8 ], [ false, %final.suspend ], 
[ false, %init.suspend ]
+  // CHECK-NEXT: %InRamp = call i1 @llvm.coro.is_in_ramp()
+  // CHECK-NEXT: br i1 %InRamp, label %[[GroConv:.+]], label 
%[[AfterGroConv:.+]]
+
+  // CHECK: [[GroConv]]:
+  // CHECK-NEXT: %[[Conv:.+]] = call noundef i32 @_ZN7GroTypecviEv(
+  // CHECK-NEXT: store i32 %[[Conv]], ptr %[[RetVal]]
+  // CHECK-NEXT: br label %[[AfterGroConv]]
+
+  // CHECK: [[AfterGroConv]]:
+  // CHECK-NEXT: br label %[[PreCleanup:.+]]
+
+  // CHECK: [[PreCleanup]]:
+  // CHECK-NEXT: %[[NeedCleanup:.+]] = phi i1 [ %10, %after.gro.conv ]
+  // CHECK-NEXT: br i1 %[[NeedCleanup]], label %cleanup.cont10, label 
%[[CoroRet:.+]]
+
+  // CHECK: cleanup.cont10:
+  // CHECK-NEXT: br label %[[Cleanup:.+]]
+
+  // CHECK: [[Cleanup]]:
+  // CHECK-NEXT: %{{.*}} = phi i32
+  // CHECK-NEXT: %[[IsActive:.+]] = load i1, ptr %[[GroActive]]
+  // CHECK-NEXT: br i1 %[[IsActive]], label %[[CleanupGro:.+]], label 
%[[Done:.+]]
 
   // CHECK: [[CleanupGro]]:
-  // CHECK:   call void @_ZN7GroTypeD1Ev(
-  // CHECK:   br label %[[Done]]
+  // CHECK-NEXT: call void @_ZN7GroTypeD1Ev(
+  // CHECK-NEXT: br label %[[Done]]
+
+  // Destroy promise and free the memory.
 
   // CHECK: [[Done]]:
-  // CHECK:   %[[LoadRet:.+]] = load i32, ptr %[[RetVal]]
-  // CHECK:   ret i32 %[[LoadRet]]
+  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr %[[CoroGro]])
+  // CHECK-NEXT: call void @_ZNSt16coroutine_traitsIiJEE12promise_typeD1Ev(
+  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr %[[Promise]])
+  // CHECK-NEXT: %[[Mem:.+]] = call ptr @llvm.coro.free(
+
+  // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
+  // CHECK-NEXT: call void @_ZdlPvm(ptr noundef %[[Mem]], i64 noundef 
%[[SIZE]])
+
+  // CHECK: [[CoroRet]]:
+  // CHECK-NEXT: call void @llvm.coro.end(
+  // CHECK-NEXT: %[[LoadRet:.+]] = load i32, ptr %[[RetVal]]
+  // CHECK-NEXT: ret i32 %[[LoadRet]]
 }
 
 class invoker {
diff --git a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp 
b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp
index f36f89926505f..bfed718016b83 100644
--- a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp
+++ b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp
@@ -91,7 +91,7 @@ Task bar() {
 // CHECK-NEXT:    %{{.+}} = call token @llvm.coro.save(ptr null)
 // CHECK-NEXT:    call void @llvm.coro.await.suspend.handle
 // CHECK-NEXT:    %{{.+}} = call i8 @llvm.coro.suspend
-// CHECK-NEXT:    switch i8 %{{.+}}, label %coro.ret [
+// CHECK-NEXT:    switch i8 %{{.+}}, label %pre.gvo.conv [
 // CHECK-NEXT:      i8 0, label %[[CASE1_AWAIT_READY]]
 // CHECK-NEXT:      i8 1, label %[[CASE1_AWAIT_CLEANUP:.+]]
 // CHECK-NEXT:    ]
@@ -105,7 +105,7 @@ Task bar() {
 // CHECK-NEXT:    %{{.+}} = call token @llvm.coro.save(ptr null)
 // CHECK-NEXT:    call void @llvm.coro.await.suspend.handle
 // CHECK-NEXT:    %{{.+}} = call i8 @llvm.coro.suspend
-// CHECK-NEXT:    switch i8 %{{.+}}, label %coro.ret [
+// CHECK-NEXT:    switch i8 %{{.+}}, label %pre.gvo.conv [
 // CHECK-NEXT:      i8 0, label %[[CASE2_AWAIT_READY]]
 // CHECK-NEXT:      i8 1, label %[[CASE2_AWAIT_CLEANUP:.+]]
 // CHECK-NEXT:    ]

>From c515650ffe8d21a9fd907eda7856927e47560f0b Mon Sep 17 00:00:00 2001
From: NewSigma <[email protected]>
Date: Thu, 30 Oct 2025 15:41:48 +0800
Subject: [PATCH 2/2] Simplify pre-cleanup check

---
 clang/lib/CodeGen/CGCoroutine.cpp         | 38 ++++++++---------------
 clang/test/CodeGenCoroutines/coro-gro.cpp |  6 +---
 2 files changed, 14 insertions(+), 30 deletions(-)

diff --git a/clang/lib/CodeGen/CGCoroutine.cpp 
b/clang/lib/CodeGen/CGCoroutine.cpp
index a805a4d536616..569070123e368 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -604,9 +604,9 @@ struct CallCoroDelete final : public EHScopeStack::Cleanup {
   Stmt *Deallocate;
 
   void Emit(CodeGenFunction &CGF, Flags F) override {
-    // Cleanup always happens on unwind. No need for pre-cleanup block.
+    // Cleanup always happens on unwind. No need for pre-cleanup check.
     if (F.isForNormalCleanup())
-      EmitPreCleanupBB(CGF);
+      EmitPreCleanup(CGF);
     // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;"
 
     // Note: That deallocation will be emitted twice: once for a normal exit 
and
@@ -652,10 +652,7 @@ struct CallCoroDelete final : public EHScopeStack::Cleanup 
{
   explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
 
 private:
-  // [dcl.fct.def.coroutine]: The coroutine state is destroyed when control
-  // flows off the end of the coroutine or the destroy member function of a
-  // coroutine handle that refers to the coroutine is invoked.
-  void EmitPreCleanupBB(CodeGenFunction &CGF) {
+  void EmitPreCleanup(CodeGenFunction &CGF) {
     auto &Builder = CGF.Builder;
     auto &Data = *CGF.CurCoro.Data;
     auto *BodyDone = Data.BodyDone;
@@ -664,21 +661,11 @@ struct CallCoroDelete final : public 
EHScopeStack::Cleanup {
     BasicBlock *AfterConvBB =
         cast<llvm::BranchInst>(PreConvBB->getTerminator())->getSuccessor(1);
     BasicBlock *CleanupBB = AfterConvBB->getSingleSuccessor();
-    BasicBlock *PreCleanupBB = CleanupBB->splitBasicBlock(
-        CleanupBB->getFirstNonPHIIt(), "pre.coro.cleanup", true);
-    Builder.SetInsertPoint(PreCleanupBB);
-    PreCleanupBB->getTerminator()->eraseFromParent();
-
-    auto *NeedCleanup = Builder.CreatePHI(
-        Builder.getInt1Ty(), llvm::pred_size(PreCleanupBB), "is.completed");
-    for (auto *Pred : llvm::predecessors(PreCleanupBB)) {
-      auto *V = (Pred == AfterConvBB) ? cast<Value>(BodyDone)
-                                      : cast<Value>(Builder.getTrue());
-      NeedCleanup->addIncoming(V, Pred);
-    }
+    BasicBlock *RetBB = Data.CleanupJD.getBlock();
 
-    auto *RetBB = Data.CleanupJD.getBlock();
-    Builder.CreateCondBr(NeedCleanup, CleanupBB, RetBB);
+    AfterConvBB->getTerminator()->eraseFromParent();
+    Builder.SetInsertPoint(AfterConvBB);
+    Builder.CreateCondBr(BodyDone, CleanupBB, RetBB);
     Builder.SetInsertPoint(SaveInsertBlock);
   }
 };
@@ -726,10 +713,10 @@ struct GetReturnObjectManager {
   }
 
   // The gro variable has to outlive coroutine frame and coroutine promise, 
but,
-  // it can only be initialized after coroutine promise was created, thus, we
-  // split its emission in two parts. EmitGroAlloca emits an alloca and sets up
-  // cleanups. Later when coroutine promise is available we initialize the gro
-  // and sets the flag that the cleanup is now active.
+  // it can only be initialized after coroutine promise was created. Thus,
+  // EmitGroActive emits a flag and sets it to false. Later when coroutine
+  // promise is available we initialize the gro and set the flag indicating 
that
+  // the cleanup is now active.
   void EmitGroActive() {
     if (DirectEmit)
       return;
@@ -822,7 +809,8 @@ struct GetReturnObjectManager {
   void EmitGroConv() {
     auto *InsertPt = Builder.GetInsertBlock();
     auto *PreConvBB = CGF.CurCoro.Data->SuspendBB;
-    auto *AfterConvBB = CGF.createBasicBlock("after.gro.conv", CGF.CurFn, 
InsertPt);
+    auto *AfterConvBB =
+        CGF.createBasicBlock("after.gro.conv", CGF.CurFn, InsertPt);
     Builder.SetInsertPoint(AfterConvBB);
     BasicBlock *AfterFinalBB = nullptr;
     if (InsertPt) {
diff --git a/clang/test/CodeGenCoroutines/coro-gro.cpp 
b/clang/test/CodeGenCoroutines/coro-gro.cpp
index 826d22a5584e2..fb9d0a6d85377 100644
--- a/clang/test/CodeGenCoroutines/coro-gro.cpp
+++ b/clang/test/CodeGenCoroutines/coro-gro.cpp
@@ -66,11 +66,7 @@ int f() {
   // CHECK-NEXT: br label %[[AfterGroConv]]
 
   // CHECK: [[AfterGroConv]]:
-  // CHECK-NEXT: br label %[[PreCleanup:.+]]
-
-  // CHECK: [[PreCleanup]]:
-  // CHECK-NEXT: %[[NeedCleanup:.+]] = phi i1 [ %10, %after.gro.conv ]
-  // CHECK-NEXT: br i1 %[[NeedCleanup]], label %cleanup.cont10, label 
%[[CoroRet:.+]]
+  // CHECK-NEXT: br i1 %10, label %cleanup.cont10, label %[[CoroRet:.+]]
 
   // CHECK: cleanup.cont10:
   // CHECK-NEXT: br label %[[Cleanup:.+]]

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to