[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
Fri Sep 8 09:26:36 PDT 2023


https://github.com/asl updated https://github.com/llvm/llvm-project/pull/65698:

>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 1/2] [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:

>From dc9a9b86a0ead7d58346d2adbe095eb633a50072 Mon Sep 17 00:00:00 2001
From: Anton Korobeynikov <anton at korobeynikov.info>
Date: Fri, 8 Sep 2023 09:26:15 -0700
Subject: [PATCH 2/2] Add one more missed cases

---
 llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll b/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
index 0ea6a9dd00a96e0..411067362825efa 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
@@ -4,7 +4,7 @@
 %"class.task::promise_type" = type { [64 x i8] }
 
 declare void @consume(ptr)
-declare void @consume2(%"class.task::promise_type"*)
+declare void @consume2(ptr)
 
 define ptr @f() presplitcoroutine {
 entry:



More information about the llvm-commits mailing list