-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Coroutines] Ignore instructions more aggressively in addMustTailToCo…
…roResumes() (#85271) The old code used isInstructionTriviallyDead() and removed instructions when walking the path from a resume call to function return to check if the call is in tail position. However, since the code was walking forwards it was not able to get past instructions such as: %gep = getelementptr inbounds i64, ptr %alloc.var, i32 0 %foo = ptrtoint ptr %gep to i64 This patch instead ignores such instructions as long as their values are not needed. This enables the code to emit tail calls in more situations.
- Loading branch information
Showing
3 changed files
with
104 additions
and
53 deletions.
There are no files selected for viewing
66 changes: 66 additions & 0 deletions
66
clang/test/CodeGenCoroutines/coro-symmetric-transfer-04.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// This tests that the symmetric transfer at the final suspend point could happen successfully. | ||
// Based on https://github.com/llvm/llvm-project/pull/85271#issuecomment-2007554532 | ||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O2 -emit-llvm %s -o - | FileCheck %s | ||
|
||
#include "Inputs/coroutine.h" | ||
|
||
struct Task { | ||
struct promise_type { | ||
struct FinalAwaiter { | ||
bool await_ready() const noexcept { return false; } | ||
template <typename PromiseType> | ||
std::coroutine_handle<> await_suspend(std::coroutine_handle<PromiseType> h) noexcept { | ||
return h.promise().continuation; | ||
} | ||
void await_resume() noexcept {} | ||
}; | ||
Task get_return_object() noexcept { | ||
return std::coroutine_handle<promise_type>::from_promise(*this); | ||
} | ||
std::suspend_always initial_suspend() noexcept { return {}; } | ||
FinalAwaiter final_suspend() noexcept { return {}; } | ||
void unhandled_exception() noexcept {} | ||
void return_value(int x) noexcept { | ||
_value = x; | ||
} | ||
std::coroutine_handle<> continuation; | ||
int _value; | ||
}; | ||
|
||
Task(std::coroutine_handle<promise_type> handle) : handle(handle), stuff(123) {} | ||
|
||
struct Awaiter { | ||
std::coroutine_handle<promise_type> handle; | ||
Awaiter(std::coroutine_handle<promise_type> handle) : handle(handle) {} | ||
bool await_ready() const noexcept { return false; } | ||
std::coroutine_handle<void> await_suspend(std::coroutine_handle<void> continuation) noexcept { | ||
handle.promise().continuation = continuation; | ||
return handle; | ||
} | ||
int await_resume() noexcept { | ||
int ret = handle.promise()._value; | ||
handle.destroy(); | ||
return ret; | ||
} | ||
}; | ||
|
||
auto operator co_await() { | ||
auto handle_ = handle; | ||
handle = nullptr; | ||
return Awaiter(handle_); | ||
} | ||
|
||
private: | ||
std::coroutine_handle<promise_type> handle; | ||
int stuff; | ||
}; | ||
|
||
Task task0() { | ||
co_return 43; | ||
} | ||
|
||
// CHECK-LABEL: define{{.*}} void @_Z5task0v.resume | ||
// This checks we are still in the scope of the current function. | ||
// CHECK-NOT: {{^}}} | ||
// CHECK: musttail call fastcc void | ||
// CHECK-NEXT: ret void |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters