@@ -30,6 +30,7 @@ class Lowerer : public coro::LowererBase {
3030 void lowerCoroPromise (CoroPromiseInst *Intrin);
3131 void lowerCoroDone (IntrinsicInst *II);
3232 void lowerCoroNoop (IntrinsicInst *II);
33+ void hidePromiseAlloca (CoroIdInst *CoroId, CoroBeginInst *CoroBegin);
3334
3435public:
3536 Lowerer (Module &M)
@@ -153,6 +154,27 @@ void Lowerer::lowerCoroNoop(IntrinsicInst *II) {
153154 II->eraseFromParent ();
154155}
155156
157+ // Later middle-end passes will assume promise alloca dead after coroutine
158+ // suspend, leading to misoptimizations. We hide promise alloca using
159+ // coro.promise and will lower it back to alloca at CoroSplit.
160+ void Lowerer::hidePromiseAlloca (CoroIdInst *CoroId, CoroBeginInst *CoroBegin) {
161+ auto *PA = CoroId->getPromise ();
162+ if (!PA || !CoroBegin)
163+ return ;
164+ Builder.SetInsertPoint (*CoroBegin->getInsertionPointAfterDef ());
165+
166+ auto *Alignment = Builder.getInt32 (PA->getAlign ().value ());
167+ auto *FromPromise = Builder.getInt1 (false );
168+ SmallVector<Value *, 3 > Arg{CoroBegin, Alignment, FromPromise};
169+ auto *PI = Builder.CreateIntrinsic (
170+ Builder.getPtrTy (), Intrinsic::coro_promise, Arg, {}, " promise.addr" );
171+ PA->replaceUsesWithIf (PI, [CoroId](Use &U) {
172+ bool IsBitcast = U == U.getUser ()->stripPointerCasts ();
173+ bool IsCoroId = U.getUser () == CoroId;
174+ return !IsBitcast && !IsCoroId;
175+ });
176+ }
177+
156178// Prior to CoroSplit, calls to coro.begin needs to be marked as NoDuplicate,
157179// as CoroSplit assumes there is exactly one coro.begin. After CoroSplit,
158180// NoDuplicate attribute will be removed from coro.begin otherwise, it will
@@ -252,22 +274,7 @@ void Lowerer::lowerEarlyIntrinsics(Function &F) {
252274 for (CoroFreeInst *CF : CoroFrees)
253275 CF->setArgOperand (0 , CoroId);
254276
255- auto *PA = CoroId->getPromise ();
256- if (PA && CoroBegin) {
257- assert (isa<AllocaInst>(PA) && " Must pass alloca to coro.id" );
258- Builder.SetInsertPoint (*CoroBegin->getInsertionPointAfterDef ());
259-
260- auto *Alignment = Builder.getInt32 (PA->getAlign ().value ());
261- auto *FromPromise = Builder.getInt1 (false );
262- SmallVector<Value *, 3 > Arg{CoroBegin, Alignment, FromPromise};
263- auto *PI = Builder.CreateIntrinsic (
264- Builder.getPtrTy (), Intrinsic::coro_promise, Arg, {}, " promise.addr" );
265- PA->replaceUsesWithIf (PI, [CoroId](Use &U) {
266- bool IsBitcast = U == U.getUser ()->stripPointerCasts ();
267- bool IsCoroId = U.getUser () == CoroId;
268- return !IsBitcast && !IsCoroId;
269- });
270- }
277+ hidePromiseAlloca (CoroId, CoroBegin);
271278 }
272279
273280 // Coroutine suspention could potentially lead to any argument modified
0 commit comments