[PATCH] D108122: FunctionAttrs: do not mark coroutines with odd return path `noreturn`

Tim Northover via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 16 04:59:12 PDT 2021


t.p.northover created this revision.
t.p.northover added a reviewer: aschwaighofer.
Herald added subscribers: ormris, ChuanqiXu, lxfind, hiraditya, mcrosier.
t.p.northover requested review of this revision.
Herald added a project: LLVM.

Under one of the ABIs we support for coroutines, a call to `@llvm.coro.end` may actually (despite not being a BB terminator) return from the function. This is weird, but documented in https://llvm.org/docs/Coroutines.html#llvm-coro-end-intrinsic:

> In returned-continuation lowering, llvm.coro.end fully destroys the coroutine frame. If the second argument is false, it also returns from the coroutine with a null continuation pointer, and the next instruction will be unreachable.

In this case, because of the `unreachable` at the end we'd normally decide the block cannot return (and if it's the only return block in the function, that the function itself is `noreturn), but this logic needs revising.


https://reviews.llvm.org/D108122

Files:
  llvm/lib/Transforms/IPO/FunctionAttrs.cpp
  llvm/test/Transforms/FunctionAttrs/noreturn.ll


Index: llvm/test/Transforms/FunctionAttrs/noreturn.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/noreturn.ll
+++ llvm/test/Transforms/FunctionAttrs/noreturn.ll
@@ -71,3 +71,20 @@
   call i32 @f() noreturn
   ret void
 }
+
+; CHECK: Function Attrs: {{.*}}noreturn
+; CHECK-NEXT: @unreachable
+define void @unreachable() {
+  unreachable
+}
+
+; CHECK-NOT: Function Attrs: {{.*}}noreturn
+; CHECK: @coro
+define void @coro() {
+  call token @llvm.coro.id.retcon.once(i32 0, i32 0, i8* null, i8* bitcast(void() *@coro to i8*), i8* null, i8* null)
+  call i1 @llvm.coro.end(i8* null, i1 false)
+  unreachable
+}
+
+declare token @llvm.coro.id.retcon.once(i32 %size, i32 %align, i8* %buffer, i8* %prototype, i8* %alloc, i8* %free)
+declare i1 @llvm.coro.end(i8*, i1)
Index: llvm/lib/Transforms/IPO/FunctionAttrs.cpp
===================================================================
--- llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -1404,9 +1404,25 @@
 // A basic block can only return if it terminates with a ReturnInst and does not
 // contain calls to noreturn functions.
 static bool basicBlockCanReturn(BasicBlock &BB) {
-  if (!isa<ReturnInst>(BB.getTerminator()))
+  if (!isa<ReturnInst>(BB.getTerminator()) &&
+      !isa<UnreachableInst>(BB.getTerminator()))
     return false;
-  return none_of(BB, instructionDoesNotReturn);
+
+  for (auto &I : BB) {
+    if (instructionDoesNotReturn(I))
+      return false;
+
+    // Calls to @llvm.coro.end(..., i1 false) are themselves a return operation
+    // if the coroutine is retcon, so conservatively assume all are.
+    if (auto *CB = dyn_cast<CallBase>(&I)) {
+      if (CB->getCalledFunction() &&
+          CB->getCalledFunction()->getIntrinsicID() == Intrinsic::coro_end &&
+          cast<ConstantInt>(CB->getOperand(1))->isZero())
+        return true;
+    }
+  }
+
+  return isa<ReturnInst>(BB.getTerminator());
 }
 
 // Set the noreturn function attribute if possible.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D108122.366593.patch
Type: text/x-patch
Size: 2043 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210816/44a7eebc/attachment.bin>


More information about the llvm-commits mailing list