Index: llvm/lib/Transforms/Coroutines/CoroSplit.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -1775,14 +1775,6 @@ Builder.CreateStore(RawFramePtr, Dest); } - // Map all uses of llvm.coro.begin to the allocated frame pointer. - { - // Make sure we don't invalidate Shape.FramePtr. - TrackingVH Handle(Shape.FramePtr); - Shape.CoroBegin->replaceAllUsesWith(RawFramePtr); - Shape.FramePtr = Handle.getValPtr(); - } - // Create a unique return block. BasicBlock *ReturnBB = nullptr; SmallVector ReturnPHIs; @@ -1867,6 +1859,14 @@ CoroCloner(F, "resume." + Twine(i), Shape, Clone, Suspend).create(); } + + // Map all uses of llvm.coro.begin to the allocated frame pointer. + { + // Make sure we don't invalidate Shape.FramePtr. + TrackingVH Handle(Shape.FramePtr); + Shape.CoroBegin->replaceAllUsesWith(RawFramePtr); + Shape.FramePtr = Handle.getValPtr(); + } } namespace { Index: llvm/test/Transforms/Coroutines/coro-retcon-alloca-opaque-ptr.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/Coroutines/coro-retcon-alloca-opaque-ptr.ll @@ -0,0 +1,90 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py + +; RUN: opt < %s -enable-coroutines -passes='default' -opaque-pointers=1 -S | FileCheck %s + +target datalayout = "p:64:64:64" + +declare {i8*, i8*, i32} @prototype_f(i8*, i1) +define {i8*, i8*, i32} @f(i8* %buffer, i32 %n) { +; CHECK-LABEL: @f( +; CHECK-NEXT: coro.return: +; CHECK-NEXT: [[N_VAL_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[BUFFER:%.*]], i64 0, i32 1 +; CHECK-NEXT: store i32 [[N:%.*]], ptr [[N_VAL_SPILL_ADDR]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = tail call ptr @allocate(i32 [[N]]) +; CHECK-NEXT: store ptr [[TMP0]], ptr [[BUFFER]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { ptr, ptr, i32 } { ptr @f.resume.0, ptr undef, i32 undef }, ptr [[TMP0]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { ptr, ptr, i32 } [[TMP1]], i32 [[N]], 2 +; CHECK-NEXT: ret { ptr, ptr, i32 } [[TMP2]] +; +entry: + %id = call token @llvm.coro.id.retcon(i32 1024, i32 8, i8* %buffer, i8* bitcast ({i8*, i8*, i32} (i8*, i1)* @prototype_f to i8*), i8* bitcast (i8* (i32)* @allocate to i8*), i8* bitcast (void (i8*)* @deallocate to i8*)) + %hdl = call i8* @llvm.coro.begin(token %id, i8* null) + br label %loop + +loop: + %n.val = phi i32 [ %n, %entry ], [ %inc, %resume ] + %alloca = call token @llvm.coro.alloca.alloc.i32(i32 %n.val, i32 8) + %ptr = call i8* @llvm.coro.alloca.get(token %alloca) + %unwind = call i1 (...) @llvm.coro.suspend.retcon.i1(i8* %ptr, i32 %n.val) + call void @llvm.coro.alloca.free(token %alloca) + br i1 %unwind, label %cleanup, label %resume + +resume: + %inc = add i32 %n.val, 1 + br label %loop + +cleanup: + call i1 @llvm.coro.end(i8* %hdl, i1 0) + unreachable +} + + +declare {i8*, i32} @prototype_g(i8*, i1) +define {i8*, i32} @g(i8* %buffer, i32 %n) { +; CHECK-LABEL: @g( +; CHECK-NEXT: coro.return: +; CHECK-NEXT: store i32 [[N:%.*]], ptr [[BUFFER:%.*]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[TMP0]], align 8 +; CHECK-NEXT: tail call void @use(ptr nonnull [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { ptr, i32 } { ptr @g.resume.0, i32 undef }, i32 [[N]], 1 +; CHECK-NEXT: ret { ptr, i32 } [[TMP2]] +; +entry: + %id = call token @llvm.coro.id.retcon(i32 1024, i32 8, i8* %buffer, i8* bitcast ({i8*, i32} (i8*, i1)* @prototype_g to i8*), i8* bitcast (i8* (i32)* @allocate to i8*), i8* bitcast (void (i8*)* @deallocate to i8*)) + %hdl = call i8* @llvm.coro.begin(token %id, i8* null) + br label %loop + +loop: + %n.val = phi i32 [ %n, %entry ], [ %inc, %resume ] + %alloca = call token @llvm.coro.alloca.alloc.i32(i32 %n.val, i32 8) + %ptr = call i8* @llvm.coro.alloca.get(token %alloca) + call void @use(i8* %ptr) + call void @llvm.coro.alloca.free(token %alloca) + %unwind = call i1 (...) @llvm.coro.suspend.retcon.i1(i32 %n.val) + br i1 %unwind, label %cleanup, label %resume + +resume: + %inc = add i32 %n.val, 1 + br label %loop + +cleanup: + call i1 @llvm.coro.end(i8* %hdl, i1 0) + unreachable +} + +declare token @llvm.coro.id.retcon(i32, i32, i8*, i8*, i8*, i8*) +declare i8* @llvm.coro.begin(token, i8*) +declare i1 @llvm.coro.suspend.retcon.i1(...) +declare void @llvm.coro.suspend.retcon.isVoid(...) +declare i1 @llvm.coro.end(i8*, i1) +declare i8* @llvm.coro.prepare.retcon(i8*) +declare token @llvm.coro.alloca.alloc.i32(i32, i32) +declare i8* @llvm.coro.alloca.get(token) +declare void @llvm.coro.alloca.free(token) + +declare noalias i8* @allocate(i32 %size) +declare void @deallocate(i8* %ptr) + +declare void @print(i32) +declare void @use(i8*) Index: llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll +++ llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll @@ -63,15 +63,15 @@ ; CHECK-NEXT: store i32 [[SUM8_I]], i32* [[N_VAL3_RELOAD_ADDR_I]], align 4, !noalias !3 ; CHECK-NEXT: store i32 4, i32* [[INPUT_RELOAD_ADDR_I]], align 4, !noalias !3 ; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]]) -; CHECK-NEXT: [[FRAMEPTR_I4:%.*]] = load %f.Frame*, %f.Frame** [[TMP2]], align 8, !alias.scope !6 -; CHECK-NEXT: [[INPUT_RELOAD_ADDR13_I:%.*]] = getelementptr inbounds [[F_FRAME]], %f.Frame* [[FRAMEPTR_I4]], i64 0, i32 2 +; CHECK-NEXT: [[FRAMEPTR_I2:%.*]] = load %f.Frame*, %f.Frame** [[TMP2]], align 8, !alias.scope !6 +; CHECK-NEXT: [[VFRAME_I:%.*]] = bitcast %f.Frame* [[FRAMEPTR_I2]] to i8* +; CHECK-NEXT: [[INPUT_RELOAD_ADDR13_I:%.*]] = getelementptr inbounds [[F_FRAME]], %f.Frame* [[FRAMEPTR_I2]], i64 0, i32 2 ; CHECK-NEXT: [[INPUT_RELOAD14_I:%.*]] = load i32, i32* [[INPUT_RELOAD_ADDR13_I]], align 4, !noalias !6 -; CHECK-NEXT: [[N_VAL3_RELOAD_ADDR11_I:%.*]] = getelementptr inbounds [[F_FRAME]], %f.Frame* [[FRAMEPTR_I4]], i64 0, i32 1 +; CHECK-NEXT: [[N_VAL3_RELOAD_ADDR11_I:%.*]] = getelementptr inbounds [[F_FRAME]], %f.Frame* [[FRAMEPTR_I2]], i64 0, i32 1 ; CHECK-NEXT: [[N_VAL3_RELOAD12_I:%.*]] = load i32, i32* [[N_VAL3_RELOAD_ADDR11_I]], align 4, !noalias !6 ; CHECK-NEXT: [[SUM7_I:%.*]] = add i32 [[N_VAL3_RELOAD12_I]], [[INPUT_RELOAD14_I]] ; CHECK-NEXT: call void @print(i32 [[SUM7_I]]), !noalias !6 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast %f.Frame* [[FRAMEPTR_I4]] to i8* -; CHECK-NEXT: call void @deallocate(i8* [[TMP3]]), !noalias !6 +; CHECK-NEXT: call void @deallocate(i8* [[VFRAME_I]]), !noalias !6 ; CHECK-NEXT: ret i32 0 ; entry: