[clang] Extend `retcon.once` coroutines lowering to optionally produce a normal result (PR #66333)

Anton Korobeynikov via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 14 19:17:01 PDT 2023


asl wrote:

> > > Out of curiousity, why don't we have the problem in the normal return continuation ABI?
> > 
> > 
> > The problem happens when the value is directly used in `coro.end` intrinsic. For example, when we're forwarding coroutine argument as a result. Or, when the value itself is computed before the suspend. Everything else is correctly handled by the present code due to BB split (the corresponding instructions appear in `Cleanup` block for example and correctly spilled).
> 
> I still don't understand the motivation fully. Do you say we don't have the problem naturally? Or could you show some motivation examples? (In LLVM IR?)

This one is problematic:
```llvm
define {ptr, ptr} @g(ptr %buffer, ptr %ptr, i8 %val) presplitcoroutine {
entry:
  %temp = alloca i32, align 4
  %id = call token @llvm.coro.id.retcon.once(i32 8, i32 8, ptr %buffer, ptr @prototype2, ptr @allocate, ptr @deallocate)
  %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
  %oldvalue = load i32, ptr %ptr
  store i32 %oldvalue, ptr %temp
  %unwind = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr %temp)
  br i1 %unwind, label %cleanup, label %cont

cont:
  %newvalue = load i32, ptr %temp
  store i32 %newvalue, ptr %ptr
  br label %cleanup

cleanup:
  call i1 (ptr, i1, ...) @llvm.coro.end(ptr %hdl, i1 0, i8 %val)
  unreachable
}
```

but this one is not:
```llvm
define {ptr, ptr} @g(ptr %buffer, ptr %ptr, i8 %val) presplitcoroutine {
entry:
  %temp = alloca i32, align 4
  %id = call token @llvm.coro.id.retcon.once(i32 8, i32 8, ptr %buffer, ptr @prototype2, ptr @allocate, ptr @deallocate)
  %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
  %oldvalue = load i32, ptr %ptr
  store i32 %oldvalue, ptr %temp
  %unwind = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr %temp)
  br i1 %unwind, label %cleanup, label %cont

cont:
  %newvalue = load i32, ptr %temp
  store i32 %newvalue, ptr %ptr
  br label %cleanup

cleanup:
  %newval = add i8 %val, 42
  call i1 (ptr, i1, ...) @llvm.coro.end(ptr %hdl, i1 0, i8 %newval)
  unreachable
}
```

This one is problematic as well:
```llvm
define {ptr, ptr} @g(ptr %buffer, ptr %ptr, i8 %val) presplitcoroutine {
entry:
  %temp = alloca i32, align 4
  %id = call token @llvm.coro.id.retcon.once(i32 8, i32 8, ptr %buffer, ptr @prototype2, ptr @allocate, ptr @deallocate)
  %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
  %oldvalue = load i32, ptr %ptr
  store i32 %oldvalue, ptr %temp
  %newval = add i8 %val, 42
  %unwind = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr %temp)
  br i1 %unwind, label %cleanup, label %cont

cont:
  %newvalue = load i32, ptr %temp
  store i32 %newvalue, ptr %ptr
  br label %cleanup

cleanup:
  call i1 (ptr, i1, ...) @llvm.coro.end(ptr %hdl, i1 0, i8 %newval)
  unreachable
}
```

All these are "new" cases I would say, everything else is handled via current split approach.

https://github.com/llvm/llvm-project/pull/66333


More information about the cfe-commits mailing list