Revert "[Coroutines] Set presplit attribute in Clang instead of CoroEarly pass"

This reverts commit fa6b54c44a.
The commited patch broke mlir tests. It seems that mlir tests depend on coroutine function properties set in CoroEarly pass.
This commit is contained in:
Xun Li
2021-04-18 17:20:02 -07:00
parent 5e7367d3e4
commit 5faba87938
16 changed files with 58 additions and 127 deletions

View File

@@ -558,8 +558,6 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
CurCoro.Data->SuspendBB = RetBB;
assert(ShouldEmitLifetimeMarkers &&
"Must emit lifetime intrinsics for coroutines");
// CORO_PRESPLIT_ATTR = UNPREPARED_FOR_SPLIT
CurFn->addFnAttr("coroutine.presplit", "0");
// Backend is allowed to elide memory allocations, to help it, emit
// auto mem = coro.alloc() ? 0 : ... allocation code ...;

View File

@@ -1,54 +0,0 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fcoroutines-ts \
// RUN: -fexperimental-new-pass-manager -O0 %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fcoroutines-ts \
// RUN: -fexperimental-new-pass-manager -fno-inline -O0 %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fcoroutines-ts \
// RUN: -O0 %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fcoroutines-ts \
// RUN: -fno-inline -O0 %s -o - | FileCheck %s
namespace std {
namespace experimental {
struct handle {};
struct awaitable {
bool await_ready() noexcept { return true; }
// CHECK-NOT: await_suspend
inline void __attribute__((__always_inline__)) await_suspend(handle) noexcept {}
bool await_resume() noexcept { return true; }
};
template <typename T>
struct coroutine_handle {
static handle from_address(void *address) noexcept { return {}; }
};
template <typename T = void>
struct coroutine_traits {
struct promise_type {
awaitable initial_suspend() { return {}; }
awaitable final_suspend() noexcept { return {}; }
void return_void() {}
T get_return_object() { return T(); }
void unhandled_exception() {}
};
};
} // namespace experimental
} // namespace std
// CHECK-LABEL: @_Z3foov
// CHECK-LABEL: entry:
// CHECK-NEXT: %this.addr.i{{[0-9]*}} = alloca %"struct.std::experimental::awaitable"*, align 8
// CHECK-NEXT: %this.addr.i{{[0-9]*}} = alloca %"struct.std::experimental::awaitable"*, align 8
// CHECK: [[CAST0:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CAST0]])
// CHECK: [[CAST1:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CAST1]])
// CHECK: [[CAST2:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CAST2]])
// CHECK: [[CAST3:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CAST3]])
void foo() { co_return; }

View File

@@ -1,68 +1,54 @@
// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -std=c++2a %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s
// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -std=c++2a %s -emit-llvm -disable-llvm-passes -o - | opt -always-inline -S | FileCheck --check-prefix=INLINE %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fcoroutines-ts \
// RUN: -fexperimental-new-pass-manager -O0 %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fcoroutines-ts \
// RUN: -fexperimental-new-pass-manager -fno-inline -O0 %s -o - | FileCheck %s
#include "Inputs/coroutine.h"
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fcoroutines-ts \
// RUN: -O0 %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fcoroutines-ts \
// RUN: -fno-inline -O0 %s -o - | FileCheck %s
namespace coro = std::experimental::coroutines_v1;
namespace std {
namespace experimental {
class task {
public:
class promise_type {
public:
task get_return_object() noexcept;
coro::suspend_always initial_suspend() noexcept;
void return_void() noexcept;
void unhandled_exception() noexcept;
struct handle {};
struct final_awaiter {
bool await_ready() noexcept;
void await_suspend(coro::coroutine_handle<promise_type> h) noexcept;
void await_resume() noexcept;
};
final_awaiter final_suspend() noexcept;
coro::coroutine_handle<> continuation;
};
task(task &&t) noexcept;
~task();
class awaiter {
public:
bool await_ready() noexcept;
void await_suspend(coro::coroutine_handle<> continuation) noexcept;
void await_resume() noexcept;
private:
friend task;
explicit awaiter(coro::coroutine_handle<promise_type> h) noexcept;
coro::coroutine_handle<promise_type> coro_;
};
awaiter operator co_await() &&noexcept;
private:
explicit task(coro::coroutine_handle<promise_type> h) noexcept;
coro::coroutine_handle<promise_type> coro_;
struct awaitable {
bool await_ready() noexcept { return true; }
// CHECK-NOT: await_suspend
inline void __attribute__((__always_inline__)) await_suspend(handle) noexcept {}
bool await_resume() noexcept { return true; }
};
task cee();
template <typename T>
struct coroutine_handle {
static handle from_address(void *address) noexcept { return {}; }
};
__attribute__((always_inline)) inline task bar() {
co_await cee();
co_return;
}
template <typename T = void>
struct coroutine_traits {
struct promise_type {
awaitable initial_suspend() { return {}; }
awaitable final_suspend() noexcept { return {}; }
void return_void() {}
T get_return_object() { return T(); }
void unhandled_exception() {}
};
};
} // namespace experimental
} // namespace std
task foo() {
co_await bar();
co_return;
}
// CHECK-LABEL: @_Z3foov
// CHECK-LABEL: entry:
// CHECK-NEXT: %this.addr.i{{[0-9]*}} = alloca %"struct.std::experimental::awaitable"*, align 8
// CHECK-NEXT: %this.addr.i{{[0-9]*}} = alloca %"struct.std::experimental::awaitable"*, align 8
// CHECK: [[CAST0:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CAST0]])
// CHECK: [[CAST1:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CAST1]])
// check that Clang front-end will tag bar with both alwaysinline and coroutine presplit
// CHECK: define linkonce_odr void @_Z3barv({{.*}}) #[[ATTR:[0-9]+]] {{.*}}
// CHECK: attributes #[[ATTR]] = { alwaysinline {{.*}} "coroutine.presplit"="0" {{.*}}}
// check that bar is not inlined even it's marked as always_inline
// INLINE-LABEL: define dso_local void @_Z3foov(
// INLINE: call void @_Z3barv(
// CHECK: [[CAST2:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CAST2]])
// CHECK: [[CAST3:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CAST3]])
void foo() { co_return; }

View File

@@ -179,6 +179,7 @@ bool Lowerer::lowerEarlyIntrinsics(Function &F) {
// with a coroutine attribute.
if (auto *CII = cast<CoroIdInst>(&I)) {
if (CII->getInfo().isPreSplit()) {
F.addFnAttr(CORO_PRESPLIT_ATTR, UNPREPARED_FOR_SPLIT);
setCannotDuplicate(CII);
CII->setCoroutineSelf();
CoroId = cast<CoroIdInst>(&I);

View File

@@ -9,7 +9,7 @@
; CHECK: ![[PROMISEVAR_RESUME]] = !DILocalVariable(name: "__promise"
%promise_type = type { i32, i32, double }
define void @f() "coroutine.presplit"="0" !dbg !8 {
define void @f() !dbg !8 {
entry:
%__promise = alloca %promise_type, align 8
%0 = bitcast %promise_type* %__promise to i8*

View File

@@ -63,7 +63,7 @@
; CHECK: ![[IVAR_RESUME]] = !DILocalVariable(name: "i"
; CHECK: ![[JVAR_RESUME]] = !DILocalVariable(name: "j"
; CHECK: ![[JDBGLOC_RESUME]] = !DILocation(line: 32, column: 7, scope: ![[RESUME_SCOPE]])
define void @f() "coroutine.presplit"="0" {
define void @f() {
entry:
%__promise = alloca i8, align 8
%i = alloca i32, align 4

View File

@@ -2,7 +2,7 @@
; RUN: opt < %s -S -enable-coroutines -O2 | FileCheck %s
; RUN: opt < %s -S -enable-coroutines -passes='default<O2>' | FileCheck %s
define i8* @f() "coroutine.presplit"="0" {
define i8* @f() {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)

View File

@@ -13,7 +13,7 @@ declare i8 @llvm.coro.suspend(token, i1)
; CHECK: call void @foo()
; CHECK-LABEL: define {{.*}}void @foo.destroy(
define void @foo() "coroutine.presplit"="0" {
define void @foo() {
entry:
%__promise = alloca i32, align 8
%0 = bitcast i32* %__promise to i8*

View File

@@ -2,7 +2,7 @@
; RUN: opt < %s -enable-coroutines -O2 -preserve-alignment-assumptions-during-inlining=false -S | FileCheck %s
; RUN: opt < %s -enable-coroutines -aa-pipeline=basic-aa -passes='default<O2>' -preserve-alignment-assumptions-during-inlining=false -S | FileCheck %s
define i8* @f(i32 %n) "coroutine.presplit"="0" {
define i8* @f(i32 %n) {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%size = call i32 @llvm.coro.size.i32()

View File

@@ -2,7 +2,7 @@
; RUN: opt < %s -O2 -enable-coroutines -preserve-alignment-assumptions-during-inlining=false -S | FileCheck %s
; RUN: opt < %s -aa-pipeline=basic-aa -passes='default<O2>' -enable-coroutines -preserve-alignment-assumptions-during-inlining=false -S | FileCheck %s
define i8* @f(i32 %n) "coroutine.presplit"="0" {
define i8* @f(i32 %n) {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%size = call i32 @llvm.coro.size.i32()

View File

@@ -2,7 +2,7 @@
; RUN: opt < %s -O2 -enable-coroutines -S | FileCheck %s
; RUN: opt < %s -passes='default<O2>' -enable-coroutines -S | FileCheck %s
define i8* @f(i32 %n) "coroutine.presplit"="0" {
define i8* @f(i32 %n) {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)

View File

@@ -2,7 +2,7 @@
; RUN: opt < %s -O2 -enable-coroutines -S | FileCheck %s
; RUN: opt < %s -aa-pipeline=basic-aa -passes='default<O2>' -enable-coroutines -S | FileCheck %s
define i8* @f(i32 %n) "coroutine.presplit"="0" {
define i8* @f(i32 %n) {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%size = call i32 @llvm.coro.size.i32()

View File

@@ -2,7 +2,7 @@
; RUN: opt < %s -O2 -enable-coroutines -S | FileCheck %s
; RUN: opt < %s -passes='default<O2>' -enable-coroutines -S | FileCheck %s
define i8* @f(i32 %n) "coroutine.presplit"="0" {
define i8* @f(i32 %n) {
entry:
%promise = alloca i32
%pv = bitcast i32* %promise to i8*

View File

@@ -2,7 +2,7 @@
; RUN: opt < %s -O2 -enable-coroutines -preserve-alignment-assumptions-during-inlining=false -S | FileCheck %s
; RUN: opt < %s -aa-pipeline=basic-aa -passes='default<O2>' -enable-coroutines -preserve-alignment-assumptions-during-inlining=false -S | FileCheck %s
define i8* @f(i32 %n) "coroutine.presplit"="0" {
define i8* @f(i32 %n) {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%size = call i32 @llvm.coro.size.i32()

View File

@@ -2,7 +2,7 @@
; RUN: opt < %s -O2 -enable-coroutines -S | FileCheck %s
; RUN: opt < %s -aa-pipeline=basic-aa -passes='default<O2>' -enable-coroutines -S | FileCheck %s
define i8* @f(i32 %n) "coroutine.presplit"="0" {
define i8* @f(i32 %n) {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%size = call i32 @llvm.coro.size.i32()

View File

@@ -12,7 +12,7 @@
; CHECK: CoroSplit: Processing coroutine 'f' state: 0
; CHECK-NEXT: CoroSplit: Processing coroutine 'f' state: 1
define void @f() "coroutine.presplit"="0" {
define void @f() {
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call i8* @malloc(i32 %size)