lxfind created this revision. Herald added subscribers: ChuanqiXu, hoy, modimo, wenlei, hiraditya. lxfind requested review of this revision. Herald added subscribers: llvm-commits, cfe-commits, jdoerfert. Herald added projects: clang, LLVM.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D102465 Files: clang/lib/CodeGen/CGCoroutine.cpp clang/test/CodeGenCoroutines/Inputs/coroutine.h clang/test/CodeGenCoroutines/coro-param-memcpy.cpp llvm/include/llvm/IR/Intrinsics.td llvm/lib/Transforms/Coroutines/CoroSplit.cpp
Index: llvm/lib/Transforms/Coroutines/CoroSplit.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -1766,6 +1766,11 @@ bool ReuseFrameSlot) { PrettyStackTraceFunction prettyStackTrace(F); + for (Instruction &I : make_early_inc_range(instructions(F))) + if (auto *II = dyn_cast<IntrinsicInst>(&I)) + if (II->getIntrinsicID() == Intrinsic::coro_mark_param) + II->eraseFromParent(); + // The suspend-crossing algorithm in buildCoroutineFrame get tripped // up by uses in unreachable blocks, so remove them as a first pass. removeUnreachableBlocks(F); Index: llvm/include/llvm/IR/Intrinsics.td =================================================================== --- llvm/include/llvm/IR/Intrinsics.td +++ llvm/include/llvm/IR/Intrinsics.td @@ -1274,6 +1274,8 @@ ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>]>; +def int_coro_mark_param : Intrinsic<[], [llvm_ptr_ty], []>; + ///===-------------------------- Other Intrinsics --------------------------===// // def int_trap : Intrinsic<[], [], [IntrNoReturn, IntrCold]>, @@ -1305,8 +1307,8 @@ def int_sideeffect : DefaultAttrsIntrinsic<[], [], [IntrInaccessibleMemOnly, IntrWillReturn]>; // The pseudoprobe intrinsic works as a place holder to the block it probes. -// Like the sideeffect intrinsic defined above, this intrinsic is treated by the -// optimizer as having opaque side effects so that it won't be get rid of or moved +// Like the sideeffect intrinsic defined above, this intrinsic is treated by the +// optimizer as having opaque side effects so that it won't be get rid of or moved // out of the block it probes. def int_pseudoprobe : Intrinsic<[], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [IntrInaccessibleMemOnly, IntrWillReturn]>; Index: clang/test/CodeGenCoroutines/coro-param-memcpy.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCoroutines/coro-param-memcpy.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++17 -O1 -fno-inline -emit-llvm %s -o - | FileCheck %s + +#include "Inputs/coroutine.h" + +struct task { + struct promise_type { + task get_return_object() { return {this}; } + std::experimental::suspend_always initial_suspend() { return {}; } + std::experimental::suspend_always final_suspend() noexcept { return {}; } + void return_void() {} + void unhandled_exception() {} + }; + promise_type *promise; +}; + +namespace std::experimental { +template <typename... Args> +struct coroutine_traits<task, Args...> { + using promise_type = typename task::promise_type; +}; +} // namespace std::experimental + +void *g = nullptr; + +struct A { + unsigned long long a = 1; + unsigned long long b; + unsigned int c; +}; + +task foo(A a1) { + A a2 = a1; // Necessary. + g = &a2; // So the address isn't optimized out. + co_return; +} + +// verify that the entire struct param is in the frame. +// CHECK: %_Z3foo1A.Frame = type { void (%_Z3foo1A.Frame*)*, void (%_Z3foo1A.Frame*)*, %"struct.task::promise_type", i1, %"struct.std::experimental::coroutines_v1::suspend_always", [5 x i8], [24 x i8] } + +// CHECK-LABEL: define dso_local %"struct.task::promise_type"* @_Z3foo1A( +// CHECK: %[[FRAME:.+]] = call noalias nonnull i8* @_Znwm( +// CHECK: %[[PTR:.+]] = getelementptr inbounds i8, i8* %[[FRAME]], i64 24 +// CHECK: %[[PARAM:.+]] = bitcast %struct.A* %a1 to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(24) %[[PTR]], i8* noundef nonnull align 8 dereferenceable(24) %[[PARAM]], i64 24, i1 false) Index: clang/test/CodeGenCoroutines/Inputs/coroutine.h =================================================================== --- clang/test/CodeGenCoroutines/Inputs/coroutine.h +++ clang/test/CodeGenCoroutines/Inputs/coroutine.h @@ -67,9 +67,9 @@ } struct suspend_always { - bool await_ready() { return false; } - void await_suspend(coroutine_handle<>) {} - void await_resume() {} + bool await_ready() noexcept { return false; } + void await_suspend(coroutine_handle<>) noexcept {} + void await_resume() noexcept {} }; struct suspend_never { bool await_ready() noexcept { return true; } Index: clang/lib/CodeGen/CGCoroutine.cpp =================================================================== --- clang/lib/CodeGen/CGCoroutine.cpp +++ clang/lib/CodeGen/CGCoroutine.cpp @@ -623,6 +623,13 @@ for (auto *PM : S.getParamMoves()) { EmitStmt(PM); ParamReplacer.addCopy(cast<DeclStmt>(PM)); + auto *Alloca = cast<llvm::AllocaInst>( + GetAddrOfLocalVar(cast<VarDecl>(cast<DeclStmt>(PM)->getSingleDecl())) + .getPointer()); + auto *Cast = new llvm::BitCastInst(Alloca, VoidPtrTy, "", + Builder.GetInsertBlock()); + Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::coro_mark_param), + {Cast}); // TODO: if(CoroParam(...)) need to surround ctor and dtor // for the copy, so that llvm can elide it if the copy is // not needed.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits