[llvm] [NFC] Update coroutine intrinsics documentation and few remaining tests to opaque pointers (PR #65698)
Anton Korobeynikov via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 7 16:29:59 PDT 2023
https://github.com/asl created https://github.com/llvm/llvm-project/pull/65698:
None
>From d6c12968a8cb16235a2511b9af5cb09499a0b65e Mon Sep 17 00:00:00 2001
From: Anton Korobeynikov <anton at korobeynikov.info>
Date: Thu, 7 Sep 2023 16:20:19 -0700
Subject: [PATCH] [NFC] Update coroutine intrinsics documentation and few
remaining tests to opaque pointers
---
llvm/docs/Coroutines.rst | 284 +++++++++---------
.../Transforms/Coroutines/coro-async-remat.ll | 38 +--
.../Coroutines/coro-retcon-opaque-ptr.ll | 16 +-
.../Coroutines/coro-retcon-remat.ll | 22 +-
.../Coroutines/coro-spill-corobegin.ll | 2 +-
.../Coroutines/coro-spill-promise-02.ll | 10 +-
6 files changed, 183 insertions(+), 189 deletions(-)
diff --git a/llvm/docs/Coroutines.rst b/llvm/docs/Coroutines.rst
index 37c0614b3985db6..0a65a39119fd83c 100644
--- a/llvm/docs/Coroutines.rst
+++ b/llvm/docs/Coroutines.rst
@@ -28,10 +28,10 @@ then destroy it:
define i32 @main() {
entry:
- %hdl = call i8* @f(i32 4)
- call void @llvm.coro.resume(i8* %hdl)
- call void @llvm.coro.resume(i8* %hdl)
- call void @llvm.coro.destroy(i8* %hdl)
+ %hdl = call ptr @f(i32 4)
+ call void @llvm.coro.resume(ptr %hdl)
+ call void @llvm.coro.resume(ptr %hdl)
+ call void @llvm.coro.destroy(ptr %hdl)
ret i32 0
}
@@ -186,7 +186,7 @@ coroutine. Therefore an async coroutine returns `void`.
.. code-block:: llvm
- define swiftcc void @async_coroutine(i8* %async.ctxt, i8*, i8*) {
+ define swiftcc void @async_coroutine(ptr %async.ctxt, ptr, ptr) {
}
Values live across a suspend point need to be stored in the coroutine frame to
@@ -216,10 +216,10 @@ a parameter to the `llvm.coro.suspend.async` intrinsic.
.. code-block:: llvm
- %resume_func_ptr = call i8* @llvm.coro.async.resume()
- call {i8*, i8*, i8*} (i8*, i8*, ...) @llvm.coro.suspend.async(
- i8* %resume_func_ptr,
- i8* %context_projection_function
+ %resume_func_ptr = call ptr @llvm.coro.async.resume()
+ call {ptr, ptr, ptr} (ptr, ptr, ...) @llvm.coro.suspend.async(
+ ptr %resume_func_ptr,
+ ptr %context_projection_function
The frontend should provide a `async function pointer` struct associated with
each async coroutine by `llvm.coro.id.async`'s argument. The initial size and
@@ -249,11 +249,11 @@ the async coroutine.
.. code-block:: llvm
- call {i8*, i8*, i8*} (i8*, i8*, ...) @llvm.coro.suspend.async(
- i8* %resume_func_ptr,
- i8* %context_projection_function,
- i8* (bitcast void (i8*, i8*, i8*)* to i8*) %suspend_function,
- i8* %arg1, i8* %arg2, i8 %arg3)
+ call {ptr, ptr, ptr} (ptr, ptr, ...) @llvm.coro.suspend.async(
+ ptr %resume_func_ptr,
+ ptr %context_projection_function,
+ ptr %suspend_function,
+ ptr %arg1, ptr %arg2, i8 %arg3)
Coroutines by Example
=====================
@@ -284,12 +284,12 @@ The LLVM IR for this coroutine looks like this:
.. code-block:: llvm
- define i8* @f(i32 %n) presplitcoroutine {
+ define ptr @f(i32 %n) presplitcoroutine {
entry:
- %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
+ %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
- %alloc = call i8* @malloc(i32 %size)
- %hdl = call noalias i8* @llvm.coro.begin(token %id, i8* %alloc)
+ %alloc = call ptr @malloc(i32 %size)
+ %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %alloc)
br label %loop
loop:
%n.val = phi i32 [ %n, %entry ], [ %inc, %loop ]
@@ -299,12 +299,12 @@ The LLVM IR for this coroutine looks like this:
switch i8 %0, label %suspend [i8 0, label %loop
i8 1, label %cleanup]
cleanup:
- %mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
- call void @free(i8* %mem)
+ %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
+ call void @free(ptr %mem)
br label %suspend
suspend:
- %unused = call i1 @llvm.coro.end(i8* %hdl, i1 false)
- ret i8* %hdl
+ %unused = call i1 @llvm.coro.end(ptr %hdl, i1 false)
+ ret ptr %hdl
}
The `entry` block establishes the coroutine frame. The `coro.size`_ intrinsic is
@@ -351,7 +351,7 @@ example, the coroutine frame will be:
.. code-block:: llvm
- %f.frame = type { void (%f.frame*)*, void (%f.frame*)*, i32 }
+ %f.frame = type { ptr, ptr, i32 }
After resume and destroy parts are outlined, function `f` will contain only the
code responsible for creation and initialization of the coroutine frame and
@@ -359,35 +359,34 @@ execution of the coroutine until a suspend point is reached:
.. code-block:: llvm
- define i8* @f(i32 %n) {
+ define ptr @f(i32 %n) {
entry:
- %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
- %alloc = call noalias i8* @malloc(i32 24)
- %0 = call noalias i8* @llvm.coro.begin(token %id, i8* %alloc)
- %frame = bitcast i8* %0 to %f.frame*
- %1 = getelementptr %f.frame, %f.frame* %frame, i32 0, i32 0
- store void (%f.frame*)* @f.resume, void (%f.frame*)** %1
- %2 = getelementptr %f.frame, %f.frame* %frame, i32 0, i32 1
- store void (%f.frame*)* @f.destroy, void (%f.frame*)** %2
+ %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
+ %alloc = call noalias ptr @malloc(i32 24)
+ %frame = call noalias ptr @llvm.coro.begin(token %id, ptr %alloc)
+ %1 = getelementptr %f.frame, ptr %frame, i32 0, i32 0
+ store ptr @f.resume, ptr %1
+ %2 = getelementptr %f.frame, ptr %frame, i32 0, i32 1
+ store ptr @f.destroy, ptr %2
%inc = add nsw i32 %n, 1
- %inc.spill.addr = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 0, i32 2
- store i32 %inc, i32* %inc.spill.addr
+ %inc.spill.addr = getelementptr inbounds %f.Frame, ptr %FramePtr, i32 0, i32 2
+ store i32 %inc, ptr %inc.spill.addr
call void @print(i32 %n)
- ret i8* %frame
+ ret ptr %frame
}
Outlined resume part of the coroutine will reside in function `f.resume`:
.. code-block:: llvm
- define internal fastcc void @f.resume(%f.frame* %frame.ptr.resume) {
+ define internal fastcc void @f.resume(ptr %frame.ptr.resume) {
entry:
- %inc.spill.addr = getelementptr %f.frame, %f.frame* %frame.ptr.resume, i64 0, i32 2
- %inc.spill = load i32, i32* %inc.spill.addr, align 4
+ %inc.spill.addr = getelementptr %f.frame, ptr %frame.ptr.resume, i64 0, i32 2
+ %inc.spill = load i32, ptr %inc.spill.addr, align 4
%inc = add i32 %n.val, 1
- store i32 %inc, i32* %inc.spill.addr, align 4
+ store i32 %inc, ptr %inc.spill.addr, align 4
tail call void @print(i32 %inc)
ret void
}
@@ -396,10 +395,9 @@ Whereas function `f.destroy` will contain the cleanup code for the coroutine:
.. code-block:: llvm
- define internal fastcc void @f.destroy(%f.frame* %frame.ptr.destroy) {
+ define internal fastcc void @f.destroy(ptr %frame.ptr.destroy) {
entry:
- %0 = bitcast %f.frame* %frame.ptr.destroy to i8*
- tail call void @free(i8* %0)
+ tail call void @free(ptr %frame.ptr.destroy)
ret void
}
@@ -420,16 +418,16 @@ elided.
.. code-block:: llvm
entry:
- %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
+ %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)
br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin
dyn.alloc:
%size = call i32 @llvm.coro.size.i32()
- %alloc = call i8* @CustomAlloc(i32 %size)
+ %alloc = call ptr @CustomAlloc(i32 %size)
br label %coro.begin
coro.begin:
- %phi = phi i8* [ null, %entry ], [ %alloc, %dyn.alloc ]
- %hdl = call noalias i8* @llvm.coro.begin(token %id, i8* %phi)
+ %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]
+ %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %phi)
In the cleanup block, we will make freeing the coroutine frame conditional on
`coro.free`_ intrinsic. If allocation is elided, `coro.free`_ returns `null`
@@ -438,11 +436,11 @@ thus skipping the deallocation code:
.. code-block:: llvm
cleanup:
- %mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
- %need.dyn.free = icmp ne i8* %mem, null
+ %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
+ %need.dyn.free = icmp ne ptr %mem, null
br i1 %need.dyn.free, label %dyn.free, label %if.end
dyn.free:
- call void @CustomFree(i8* %mem)
+ call void @CustomFree(ptr %mem)
br label %if.end
if.end:
...
@@ -502,13 +500,13 @@ as follows:
.. code-block:: llvm
- define internal fastcc void @f.Resume(%f.Frame* %FramePtr) {
+ define internal fastcc void @f.Resume(ptr %FramePtr) {
entry.Resume:
- %index.addr = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i64 0, i32 2
- %index = load i8, i8* %index.addr, align 1
+ %index.addr = getelementptr inbounds %f.Frame, ptr %FramePtr, i64 0, i32 2
+ %index = load i8, ptr %index.addr, align 1
%switch = icmp eq i8 %index, 0
- %n.addr = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i64 0, i32 3
- %n = load i32, i32* %n.addr, align 4
+ %n.addr = getelementptr inbounds %f.Frame, ptr %FramePtr, i64 0, i32 3
+ %n = load i32, ptr %n.addr, align 4
br i1 %switch, label %loop.resume, label %loop
loop.resume:
@@ -517,13 +515,13 @@ as follows:
br label %suspend
loop:
%inc = add nsw i32 %n, 1
- store i32 %inc, i32* %n.addr, align 4
+ store i32 %inc, ptr %n.addr, align 4
tail call void @print(i32 %inc)
br label %suspend
suspend:
%storemerge = phi i8 [ 0, %loop ], [ 1, %loop.resume ]
- store i8 %storemerge, i8* %index.addr, align 1
+ store i8 %storemerge, ptr %index.addr, align 1
ret void
}
@@ -579,14 +577,14 @@ correct resume point):
.. code-block:: llvm
if.true:
- %save1 = call token @llvm.coro.save(i8* %hdl)
- call void @async_op1(i8* %hdl)
+ %save1 = call token @llvm.coro.save(ptr %hdl)
+ call void @async_op1(ptr %hdl)
%suspend1 = call i1 @llvm.coro.suspend(token %save1, i1 false)
switch i8 %suspend1, label %suspend [i8 0, label %resume1
i8 1, label %cleanup]
if.false:
- %save2 = call token @llvm.coro.save(i8* %hdl)
- call void @async_op2(i8* %hdl)
+ %save2 = call token @llvm.coro.save(ptr %hdl)
+ call void @async_op2(ptr %hdl)
%suspend2 = call i1 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend1, label %suspend [i8 0, label %resume2
i8 1, label %cleanup]
@@ -606,35 +604,34 @@ store the current value produced by a coroutine.
.. code-block:: llvm
- define i8* @f(i32 %n) {
+ define ptr @f(i32 %n) {
entry:
%promise = alloca i32
- %pv = bitcast i32* %promise to i8*
- %id = call token @llvm.coro.id(i32 0, i8* %pv, i8* null, i8* null)
+ %id = call token @llvm.coro.id(i32 0, ptr %promise, ptr null, ptr null)
%need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)
br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin
dyn.alloc:
%size = call i32 @llvm.coro.size.i32()
- %alloc = call i8* @malloc(i32 %size)
+ %alloc = call ptr @malloc(i32 %size)
br label %coro.begin
coro.begin:
- %phi = phi i8* [ null, %entry ], [ %alloc, %dyn.alloc ]
- %hdl = call noalias i8* @llvm.coro.begin(token %id, i8* %phi)
+ %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]
+ %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %phi)
br label %loop
loop:
%n.val = phi i32 [ %n, %coro.begin ], [ %inc, %loop ]
%inc = add nsw i32 %n.val, 1
- store i32 %n.val, i32* %promise
+ store i32 %n.val, ptr %promise
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %loop
i8 1, label %cleanup]
cleanup:
- %mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
- call void @free(i8* %mem)
+ %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
+ call void @free(ptr %mem)
br label %suspend
suspend:
- %unused = call i1 @llvm.coro.end(i8* %hdl, i1 false)
- ret i8* %hdl
+ %unused = call i1 @llvm.coro.end(ptr %hdl, i1 false)
+ ret ptr %hdl
}
A coroutine consumer can rely on the `coro.promise`_ intrinsic to access the
@@ -644,18 +641,17 @@ coroutine promise.
define i32 @main() {
entry:
- %hdl = call i8* @f(i32 4)
- %promise.addr.raw = call i8* @llvm.coro.promise(i8* %hdl, i32 4, i1 false)
- %promise.addr = bitcast i8* %promise.addr.raw to i32*
- %val0 = load i32, i32* %promise.addr
+ %hdl = call ptr @f(i32 4)
+ %promise.addr = call ptr @llvm.coro.promise(ptr %hdl, i32 4, i1 false)
+ %val0 = load i32, ptr %promise.addr
call void @print(i32 %val0)
- call void @llvm.coro.resume(i8* %hdl)
- %val1 = load i32, i32* %promise.addr
+ call void @llvm.coro.resume(ptr %hdl)
+ %val1 = load i32, ptr %promise.addr
call void @print(i32 %val1)
- call void @llvm.coro.resume(i8* %hdl)
- %val2 = load i32, i32* %promise.addr
+ call void @llvm.coro.resume(ptr %hdl)
+ %val2 = load i32, ptr %promise.addr
call void @print(i32 %val2)
- call void @llvm.coro.destroy(i8* %hdl)
+ call void @llvm.coro.destroy(ptr %hdl)
ret i32 0
}
@@ -701,14 +697,14 @@ destroyed:
define i32 @main() {
entry:
- %hdl = call i8* @f(i32 4)
+ %hdl = call ptr @f(i32 4)
br label %while
while:
- call void @llvm.coro.resume(i8* %hdl)
- %done = call i1 @llvm.coro.done(i8* %hdl)
+ call void @llvm.coro.resume(ptr %hdl)
+ %done = call i1 @llvm.coro.done(ptr %hdl)
br i1 %done, label %end, label %while
end:
- call void @llvm.coro.destroy(i8* %hdl)
+ call void @llvm.coro.destroy(ptr %hdl)
ret i32 0
}
@@ -768,7 +764,7 @@ Syntax:
::
- declare void @llvm.coro.destroy(i8* <handle>)
+ declare void @llvm.coro.destroy(ptr <handle>)
Overview:
"""""""""
@@ -796,7 +792,7 @@ frame. Destroying a coroutine that is not suspended leads to undefined behavior.
::
- declare void @llvm.coro.resume(i8* <handle>)
+ declare void @llvm.coro.resume(ptr <handle>)
Overview:
"""""""""
@@ -823,7 +819,7 @@ Resuming a coroutine that is not suspended leads to undefined behavior.
::
- declare i1 @llvm.coro.done(i8* <handle>)
+ declare i1 @llvm.coro.done(ptr <handle>)
Overview:
"""""""""
@@ -849,7 +845,7 @@ or on a coroutine that is not suspended leads to undefined behavior.
::
- declare i8* @llvm.coro.promise(i8* <ptr>, i32 <alignment>, i1 <from>)
+ declare ptr @llvm.coro.promise(ptr <ptr>, i32 <alignment>, i1 <from>)
Overview:
"""""""""
@@ -888,28 +884,26 @@ Example:
.. code-block:: llvm
- define i8* @f(i32 %n) {
+ define ptr @f(i32 %n) {
entry:
%promise = alloca i32
- %pv = bitcast i32* %promise to i8*
; the second argument to coro.id points to the coroutine promise.
- %id = call token @llvm.coro.id(i32 0, i8* %pv, i8* null, i8* null)
+ %id = call token @llvm.coro.id(i32 0, ptr %promise, ptr null, ptr null)
...
- %hdl = call noalias i8* @llvm.coro.begin(token %id, i8* %alloc)
+ %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %alloc)
...
- store i32 42, i32* %promise ; store something into the promise
+ store i32 42, ptr %promise ; store something into the promise
...
- ret i8* %hdl
+ ret ptr %hdl
}
define i32 @main() {
entry:
- %hdl = call i8* @f(i32 4) ; starts the coroutine and returns its handle
- %promise.addr.raw = call i8* @llvm.coro.promise(i8* %hdl, i32 4, i1 false)
- %promise.addr = bitcast i8* %promise.addr.raw to i32*
- %val = load i32, i32* %promise.addr ; load a value from the promise
+ %hdl = call ptr @f(i32 4) ; starts the coroutine and returns its handle
+ %promise.addr = call ptr @llvm.coro.promise(ptr %hdl, i32 4, i1 false)
+ %val = load i32, ptr %promise.addr ; load a value from the promise
call void @print(i32 %val)
- call void @llvm.coro.destroy(i8* %hdl)
+ call void @llvm.coro.destroy(ptr %hdl)
ret i32 0
}
@@ -979,7 +973,7 @@ the coroutine frame.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare i8* @llvm.coro.begin(token <id>, i8* <mem>)
+ declare ptr @llvm.coro.begin(token <id>, ptr <mem>)
Overview:
"""""""""
@@ -1013,7 +1007,7 @@ A frontend should emit exactly one `coro.begin` intrinsic per coroutine.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare i8* @llvm.coro.free(token %id, i8* <frame>)
+ declare ptr @llvm.coro.free(token %id, ptr <frame>)
Overview:
"""""""""
@@ -1038,11 +1032,11 @@ Example (custom deallocation function):
.. code-block:: llvm
cleanup:
- %mem = call i8* @llvm.coro.free(token %id, i8* %frame)
- %mem_not_null = icmp ne i8* %mem, null
+ %mem = call ptr @llvm.coro.free(token %id, ptr %frame)
+ %mem_not_null = icmp ne ptr %mem, null
br i1 %mem_not_null, label %if.then, label %if.end
if.then:
- call void @CustomFree(i8* %mem)
+ call void @CustomFree(ptr %mem)
br label %if.end
if.end:
ret void
@@ -1053,8 +1047,8 @@ Example (standard deallocation functions):
.. code-block:: llvm
cleanup:
- %mem = call i8* @llvm.coro.free(token %id, i8* %frame)
- call void @free(i8* %mem)
+ %mem = call ptr @llvm.coro.free(token %id, ptr %frame)
+ call void @free(ptr %mem)
ret void
.. _coro.alloc:
@@ -1091,18 +1085,18 @@ Example:
.. code-block:: llvm
entry:
- %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
+ %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%dyn.alloc.required = call i1 @llvm.coro.alloc(token %id)
br i1 %dyn.alloc.required, label %coro.alloc, label %coro.begin
coro.alloc:
%frame.size = call i32 @llvm.coro.size()
- %alloc = call i8* @MyAlloc(i32 %frame.size)
+ %alloc = call ptr @MyAlloc(i32 %frame.size)
br label %coro.begin
coro.begin:
- %phi = phi i8* [ null, %entry ], [ %alloc, %coro.alloc ]
- %frame = call i8* @llvm.coro.begin(token %id, i8* %phi)
+ %phi = phi ptr [ null, %entry ], [ %alloc, %coro.alloc ]
+ %frame = call ptr @llvm.coro.begin(token %id, ptr %phi)
.. _coro.noop:
@@ -1110,7 +1104,7 @@ Example:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare i8* @llvm.coro.noop()
+ declare ptr @llvm.coro.noop()
Overview:
"""""""""
@@ -1136,7 +1130,7 @@ Note that in different translation units llvm.coro.noop may return different poi
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare i8* @llvm.coro.frame()
+ declare ptr @llvm.coro.frame()
Overview:
"""""""""
@@ -1162,8 +1156,8 @@ coroutine frame.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare token @llvm.coro.id(i32 <align>, i8* <promise>, i8* <coroaddr>,
- i8* <fnaddrs>)
+ declare token @llvm.coro.id(i32 <align>, ptr <promise>, ptr <coroaddr>,
+ ptr <fnaddrs>)
Overview:
"""""""""
@@ -1176,7 +1170,7 @@ Arguments:
The first argument provides information on the alignment of the memory returned
by the allocation function and given to `coro.begin` by the first argument. If
-this argument is 0, the memory is assumed to be aligned to 2 * sizeof(i8*).
+this argument is 0, the memory is assumed to be aligned to 2 * sizeof(ptr).
This argument only accepts constants.
The second argument, if not `null`, designates a particular alloca instruction
@@ -1209,8 +1203,8 @@ A frontend should emit function attribute `presplitcoroutine` for the coroutine.
::
declare token @llvm.coro.id.async(i32 <context size>, i32 <align>,
- i8* <context arg>,
- i8* <async function pointer>)
+ ptr <context arg>,
+ ptr <async function pointer>)
Overview:
"""""""""
@@ -1249,9 +1243,9 @@ A frontend should emit function attribute `presplitcoroutine` for the coroutine.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare token @llvm.coro.id.retcon(i32 <size>, i32 <align>, i8* <buffer>,
- i8* <continuation prototype>,
- i8* <alloc>, i8* <dealloc>)
+ declare token @llvm.coro.id.retcon(i32 <size>, i32 <align>, ptr <buffer>,
+ ptr <continuation prototype>,
+ ptr <alloc>, ptr <dealloc>)
Overview:
"""""""""
@@ -1304,9 +1298,9 @@ A frontend should emit function attribute `presplitcoroutine` for the coroutine.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare token @llvm.coro.id.retcon.once(i32 <size>, i32 <align>, i8* <buffer>,
- i8* <prototype>,
- i8* <alloc>, i8* <dealloc>)
+ declare token @llvm.coro.id.retcon.once(i32 <size>, i32 <align>, ptr <buffer>,
+ ptr <prototype>,
+ ptr <alloc>, ptr <dealloc>)
Overview:
"""""""""
@@ -1332,7 +1326,7 @@ A frontend should emit function attribute `presplitcoroutine` for the coroutine.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare i1 @llvm.coro.end(i8* <handle>, i1 <unwind>)
+ declare i1 @llvm.coro.end(ptr <handle>, i1 <unwind>)
Overview:
"""""""""
@@ -1384,18 +1378,18 @@ For landingpad based exception model, it is expected that frontend uses the
.. code-block:: llvm
ehcleanup:
- %InResumePart = call i1 @llvm.coro.end(i8* null, i1 true)
+ %InResumePart = call i1 @llvm.coro.end(ptr null, i1 true)
br i1 %InResumePart, label %eh.resume, label %cleanup.cont
cleanup.cont:
; rest of the cleanup
eh.resume:
- %exn = load i8*, i8** %exn.slot, align 8
- %sel = load i32, i32* %ehselector.slot, align 4
- %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn, 0
- %lpad.val29 = insertvalue { i8*, i32 } %lpad.val, i32 %sel, 1
- resume { i8*, i32 } %lpad.val29
+ %exn = load ptr, ptr %exn.slot, align 8
+ %sel = load i32, ptr %ehselector.slot, align 4
+ %lpad.val = insertvalue { ptr, i32 } undef, ptr %exn, 0
+ %lpad.val29 = insertvalue { ptr, i32 } %lpad.val, i32 %sel, 1
+ resume { ptr, i32 } %lpad.val29
The `CoroSpit` pass replaces `coro.end` with ``True`` in the resume functions,
thus leading to immediate unwind to the caller, whereas in start function it
@@ -1409,7 +1403,7 @@ referring to an enclosing cleanuppad as follows:
ehcleanup:
%tok = cleanuppad within none []
- %unused = call i1 @llvm.coro.end(i8* null, i1 true) [ "funclet"(token %tok) ]
+ %unused = call i1 @llvm.coro.end(ptr null, i1 true) [ "funclet"(token %tok) ]
cleanupret from %tok unwind label %RestOfTheCleanup
The `CoroSplit` pass, if the funclet bundle is present, will insert
@@ -1439,7 +1433,7 @@ The following table summarizes the handling of `coro.end`_ intrinsic.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare i1 @llvm.coro.end.async(i8* <handle>, i1 <unwind>, ...)
+ declare i1 @llvm.coro.end.async(ptr <handle>, i1 <unwind>, ...)
Overview:
"""""""""
@@ -1470,10 +1464,10 @@ the function call.
.. code-block:: llvm
- call i1 (i8*, i1, ...) @llvm.coro.end.async(
- i8* %hdl, i1 0,
- void (i8*, %async.task*, %async.actor*)* @must_tail_call_return,
- i8* %ctxt, %async.task* %task, %async.actor* %actor)
+ call i1 (ptr, i1, ...) @llvm.coro.end.async(
+ ptr %hdl, i1 0,
+ ptr @must_tail_call_return,
+ ptr %ctxt, ptr %task, ptr %actor)
unreachable
.. _coro.suspend:
@@ -1547,7 +1541,7 @@ unreachable and can perform optimizations that can take advantage of that fact.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare token @llvm.coro.save(i8* <handle>)
+ declare token @llvm.coro.save(ptr <handle>)
Overview:
"""""""""
@@ -1584,8 +1578,8 @@ to the coroutine:
.. code-block:: llvm
- %save1 = call token @llvm.coro.save(i8* %hdl)
- call void @async_op1(i8* %hdl)
+ %save1 = call token @llvm.coro.save(ptr %hdl)
+ call void @async_op1(ptr %hdl)
%suspend1 = call i1 @llvm.coro.suspend(token %save1, i1 false)
switch i8 %suspend1, label %suspend [i8 0, label %resume1
i8 1, label %cleanup]
@@ -1596,9 +1590,9 @@ to the coroutine:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare {i8*, i8*, i8*} @llvm.coro.suspend.async(
- i8* <resume function>,
- i8* <context projection function>,
+ declare {ptr, ptr, ptr} @llvm.coro.suspend.async(
+ ptr <resume function>,
+ ptr <context projection function>,
... <function to call>
... <arguments to function>)
@@ -1617,7 +1611,7 @@ point.
The second argument is the `context projection function`. It should describe
how-to restore the `async context` in the continuation function from the first
-argument of the continuation function. Its type is `i8* (i8*)`.
+argument of the continuation function. Its type is `ptr (ptr)`.
The third argument is the function that models transfer to the callee at the
suspend point. It should take 3 arguments. Lowering will `musttail` call this
@@ -1638,7 +1632,7 @@ called.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare i8* @llvm.coro.prepare.async(i8* <coroutine function>)
+ declare ptr @llvm.coro.prepare.async(ptr <coroutine function>)
Overview:
"""""""""
@@ -1649,7 +1643,7 @@ async coroutine until after coroutine splitting.
Arguments:
""""""""""
-The first argument should be an async coroutine of type `void (i8*, i8*, i8*)`.
+The first argument should be an async coroutine of type `void (ptr, ptr, ptr)`.
Lowering will replace this intrinsic with its coroutine function argument.
.. _coro.suspend.retcon:
diff --git a/llvm/test/Transforms/Coroutines/coro-async-remat.ll b/llvm/test/Transforms/Coroutines/coro-async-remat.ll
index 60c045464093a57..fd2a35c0c7f8819 100644
--- a/llvm/test/Transforms/Coroutines/coro-async-remat.ll
+++ b/llvm/test/Transforms/Coroutines/coro-async-remat.ll
@@ -2,34 +2,34 @@
%async_func_ptr = type <{ i32, i32 }>
%Tsq = type <{}>
-%swift.context = type { %swift.context*, void (%swift.context*)*, i64 }
+%swift.context = type { ptr, ptr, i64 }
%swift.type = type { i64 }
%FlatMapSeq = type <{}>
%swift.error = type opaque
%swift.opaque = type opaque
- at repoTU = global %async_func_ptr <{ i32 trunc (i64 sub (i64 ptrtoint (void (%Tsq*, %swift.context*, %swift.type*, %FlatMapSeq*)* @repo to i64), i64 ptrtoint (%async_func_ptr* @repoTU to i64)) to i32), i32 20 }>, section "__TEXT,__const", align 8
+ at repoTU = global %async_func_ptr <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @repo to i64), i64 ptrtoint (ptr @repoTU to i64)) to i32), i32 20 }>, section "__TEXT,__const", align 8
; Function Attrs: nounwind
-declare token @llvm.coro.id.async(i32, i32, i32, i8*) #0
+declare token @llvm.coro.id.async(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
-declare i8* @llvm.coro.begin(token, i8* writeonly) #0
+declare ptr @llvm.coro.begin(token, ptr writeonly) #0
; Function Attrs: nounwind
-declare i8* @llvm.coro.async.resume() #0
+declare ptr @llvm.coro.async.resume() #0
-define hidden i8* @__swift_async_resume_project_context(i8* %0) {
+define hidden ptr @__swift_async_resume_project_context(ptr %0) {
entry:
- ret i8* undef
+ ret ptr undef
}
-define swifttailcc void @repo(%Tsq* %0, %swift.context* %1, %swift.type* %arg, %FlatMapSeq* %2) #1 {
+define swifttailcc void @repo(ptr %0, ptr %1, ptr %arg, ptr %2) #1 {
entry:
- %swifterror = alloca swifterror %swift.error*, align 8
- %3 = call token @llvm.coro.id.async(i32 20, i32 16, i32 1, i8* bitcast (%async_func_ptr* @repoTU to i8*))
- %4 = call i8* @llvm.coro.begin(token %3, i8* null)
- %5 = bitcast i8* undef to %swift.opaque*
+ %swifterror = alloca swifterror ptr, align 8
+ %3 = call token @llvm.coro.id.async(i32 20, i32 16, i32 1, ptr @repoTU)
+ %4 = call ptr @llvm.coro.begin(token %3, ptr null)
+ %5 = bitcast ptr undef to ptr
br label %6
6: ; preds = %21, %15, %entry
@@ -39,11 +39,11 @@ entry:
br i1 undef, label %8, label %16
8: ; preds = %7
- %initializeWithTake35 = bitcast i8* undef to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)*
- %9 = call %swift.opaque* %initializeWithTake35(%swift.opaque* noalias %5, %swift.opaque* noalias undef, %swift.type* undef) #0
- %10 = call i8* @llvm.coro.async.resume()
- %11 = bitcast i8* %10 to void (%swift.context*)*
- %12 = call { i8*, %swift.error* } (i32, i8*, i8*, ...) @llvm.coro.suspend.async.sl_p0i8p0s_swift.error.4.220.413.429.445.461.672.683ss(i32 256, i8* %10, i8* bitcast (i8* (i8*)* @__swift_async_resume_project_context to i8*), i8* bitcast (void (i8*, %Tsq*, %swift.context*, %swift.opaque*, %swift.type*, i8**)* @__swift_suspend_dispatch_5.23 to i8*), i8* undef, %Tsq* undef, %swift.context* undef, %swift.opaque* %5, %swift.type* undef, i8** undef)
+ %initializeWithTake35 = bitcast ptr undef to ptr
+ %9 = call ptr %initializeWithTake35(ptr noalias %5, ptr noalias undef, ptr undef) #0
+ %10 = call ptr @llvm.coro.async.resume()
+ %11 = bitcast ptr %10 to ptr
+ %12 = call { ptr, ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0i8p0s_swift.error.4.220.413.429.445.461.672.683ss(i32 256, ptr %10, ptr @__swift_async_resume_project_context, ptr @__swift_suspend_dispatch_5.23, ptr undef, ptr undef, ptr undef, ptr %5, ptr undef, ptr undef)
br i1 undef, label %25, label %13
13: ; preds = %8
@@ -120,13 +120,13 @@ entry:
ret void
}
-define dso_local swifttailcc void @__swift_suspend_dispatch_5.23(i8* %0, %Tsq* %1, %swift.context* %2, %swift.opaque* %3, %swift.type* %4, i8** %5) {
+define dso_local swifttailcc void @__swift_suspend_dispatch_5.23(ptr %0, ptr %1, ptr %2, ptr %3, ptr %4, ptr %5) {
entry:
ret void
}
; Function Attrs: nounwind
-declare { i8*, %swift.error* } @llvm.coro.suspend.async.sl_p0i8p0s_swift.error.4.220.413.429.445.461.672.683ss(i32, i8*, i8*, ...) #0
+declare { ptr, ptr } @llvm.coro.suspend.async.sl_p0i8p0s_swift.error.4.220.413.429.445.461.672.683ss(i32, ptr, ptr, ...) #0
attributes #0 = { nounwind }
attributes #1 = { "tune-cpu"="generic" }
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll b/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll
index 868a9c4966756a5..559d3af0246941d 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll
@@ -74,16 +74,16 @@ cleanup: ; preds = %loop
unreachable
}
-declare token @llvm.coro.id.retcon(i32, i32, i8*, i8*, i8*, i8*)
-declare i8* @llvm.coro.begin(token, i8*)
+declare token @llvm.coro.id.retcon(i32, i32, ptr, ptr, ptr, ptr)
+declare ptr @llvm.coro.begin(token, ptr)
declare i1 @llvm.coro.suspend.retcon.i1(...)
-declare i1 @llvm.coro.end(i8*, i1)
-declare i8* @llvm.coro.prepare.retcon(i8*)
+declare i1 @llvm.coro.end(ptr, i1)
+declare ptr @llvm.coro.prepare.retcon(ptr)
-declare i8* @prototype(i8*, i1 zeroext)
-declare {i8*,i8*} @g_prototype(i8*, i1 zeroext)
+declare ptr @prototype(ptr, i1 zeroext)
+declare {ptr,ptr} @g_prototype(ptr, i1 zeroext)
-declare noalias i8* @allocate(i32 %size)
-declare void @deallocate(i8* %ptr)
+declare noalias ptr @allocate(i32 %size)
+declare void @deallocate(ptr %ptr)
declare void @print(i32)
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll b/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll
index 584c4e0da87b720..70de163caff5d91 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll
@@ -4,10 +4,10 @@
; CHECK: %f.Frame = type { i32 }
-define { i8*, i32 } @f(i8* %buffer, i32 %n) {
+define { ptr, i32 } @f(ptr %buffer, i32 %n) {
entry:
- %id = call token @llvm.coro.id.retcon(i32 8, i32 4, i8* %buffer, i8* bitcast ({ i8*, i32 } (i8*, i1)* @f_prototype 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)
+ %id = call token @llvm.coro.id.retcon(i32 8, i32 4, ptr %buffer, ptr @f_prototype, ptr @allocate, ptr @deallocate)
+ %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
br label %loop
loop:
@@ -31,19 +31,19 @@ resume1:
br label %loop
cleanup:
- call i1 @llvm.coro.end(i8* %hdl, i1 0)
+ call i1 @llvm.coro.end(ptr %hdl, i1 0)
unreachable
}
-declare token @llvm.coro.id.retcon(i32, i32, i8*, i8*, i8*, i8*)
-declare i8* @llvm.coro.begin(token, i8*)
+declare token @llvm.coro.id.retcon(i32, i32, ptr, ptr, ptr, ptr)
+declare ptr @llvm.coro.begin(token, ptr)
declare i1 @llvm.coro.suspend.retcon.i1(...)
-declare i1 @llvm.coro.end(i8*, i1)
-declare i8* @llvm.coro.prepare.retcon(i8*)
+declare i1 @llvm.coro.end(ptr, i1)
+declare ptr @llvm.coro.prepare.retcon(ptr)
-declare { i8*, i32 } @f_prototype(i8*, i1 zeroext)
+declare { ptr, i32 } @f_prototype(ptr, i1 zeroext)
-declare noalias i8* @allocate(i32 %size)
-declare void @deallocate(i8* %ptr)
+declare noalias ptr @allocate(i32 %size)
+declare void @deallocate(ptr %ptr)
declare void @print(i32)
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
index 7e19fd6b76d10ce..9653bd5b28eeae0 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
@@ -37,7 +37,7 @@ suspend:
ret ptr %hdl
}
-; See if the i8* for coro.begin was added to f.Frame
+; See if the ptr for coro.begin was added to f.Frame
; CHECK-LABEL: %f.Frame = type { ptr, ptr, ptr, i1 }
; See if the g's coro.begin was spilled into the frame
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll b/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
index 5ea90d79ebc2485..0ea6a9dd00a96e0 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
@@ -3,7 +3,7 @@
%"class.task::promise_type" = type { [64 x i8] }
-declare void @consume(i32*)
+declare void @consume(ptr)
declare void @consume2(%"class.task::promise_type"*)
define ptr @f() presplitcoroutine {
@@ -11,17 +11,17 @@ entry:
%data = alloca i32, align 4
%__promise = alloca %"class.task::promise_type", align 64
%id = call token @llvm.coro.id(i32 0, ptr %__promise, ptr null, ptr null)
- call void @consume2(%"class.task::promise_type"* %__promise)
+ call void @consume2(ptr %__promise)
%size = call i32 @llvm.coro.size.i32()
%alloc = call ptr @malloc(i32 %size)
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
- call void @consume(i32* %data)
+ call void @consume(ptr %data)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
i8 1, label %cleanup]
resume:
- call void @consume(i32* %data)
- call void @consume2(%"class.task::promise_type"* %__promise)
+ call void @consume(ptr %data)
+ call void @consume2(ptr %__promise)
br label %cleanup
cleanup:
More information about the llvm-commits
mailing list