On Thu, Jun 9, 2016 at 1:49 PM, Eli Friedman <eli.friedman at gmail.com> wrote:>> Right... but that doesn't mean the call to the suspend intrinsic has to be >> the last non-terminator instruction in the basic block before you run >> CoroSplit. You can split the basic block in CoroSplit so any instructions >> after the suspend call are part of a different basic block. Then resume and >> destroy both branch to the continuation of the basic block (and run different >> codepaths based on the boolean).I love it!!! it is so much simpler. Indeed, we absolutely don't need to care about the resume and cleanup branches. Let me restate the model as I understand it. Lowering of coro.suspend number X: 1) split block at coro.suspend, new block becomes jump point for resumption X 2) RAUW coro.suspend with i1 true in resume clone i1 false in destroy clone 3) replace coro.suspend with br %return.block in 'f', 'ret void' in clones Scratch the proposed corosuspend instruction. I think the intrinsic will work just fine! Gor
On Thu, Jun 9, 2016 at 2:33 PM, Gor Nishanov <gornishanov at gmail.com> wrote:> Lowering of coro.suspend number X: > > 1) split block at coro.suspend, new block becomes jump point for > resumption X > 2) RAUW coro.suspend with i1 true in resume clone i1 false in destroy clone > 3) replace coro.suspend with br %return.block in 'f', 'ret void' in clones > > Scratch the proposed corosuspend instruction. I think the intrinsic will > work > just fine! >That sounds right. If you're going down that route, that still leaves the question of the semantics of the fork intrinsic... thinking about it a bit more, I think you're going to run into problems with trying to keep around a return block through optimizations: [...] %first.return = call i1 @llvm.experimental.coro.fork() %cmp = icmp eq i32 %x, 0 br i1 %cmp, label %block1, label %block2 block1: [...] br i1 %first.return, label %coro.return, label %coro.start block2: [...] br i1 %first.return, label %coro.return, label %coro.start coro.return: %xxx = phi i32 [ %a, %block1 ], [ %b, %block2 ] call void @f(i32 %xxx) ret i8* %frame (Now you can't trivially insert branches to the return block because of the PHI node.) -Eli -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160609/520ee160/attachment.html>
Hi Eli:>> semantics of the fork intrinsic... thinking about it a bit more, I think >> you're going to run into problems with trying to keep around a return block >> through optimizations:How about this? Make all control flow explicit (duh). declare i8 coro.suspend([...]) returns: 0 - resume 1 - cleanup anything else - suspend Now we can get rid of the coro.fork altogether. [...] %0 = call i8 @llvm.coro.suspend([...]) switch i8 %0, label %suspend [ i32 0, label %resume, i32 1, label %cleanup] suspend: call void @llvm.coro.end() br %return.block We no longer have to do any special handling of return block as coro.end takes care of it. Lowering of coro.suspend X 1. Split block at coro.suspend, new block becomes the resume label X 2. RAUW coro.suspend with 0 in f.resume and 1 in f.destroy 3. Replace coro.suspend with 'br %suspend' coro.end expands as before: in f => no-op in f.resume/f.destroy => ret void (+ fancy things in landing pads) Gor On Thu, Jun 9, 2016 at 4:50 PM, Eli Friedman <eli.friedman at gmail.com> wrote:> On Thu, Jun 9, 2016 at 2:33 PM, Gor Nishanov <gornishanov at gmail.com> wrote: >> >> Lowering of coro.suspend number X: >> >> 1) split block at coro.suspend, new block becomes jump point for >> resumption X >> 2) RAUW coro.suspend with i1 true in resume clone i1 false in destroy >> clone >> 3) replace coro.suspend with br %return.block in 'f', 'ret void' in clones >> >> Scratch the proposed corosuspend instruction. I think the intrinsic will >> work >> just fine! > > > That sounds right. > > > If you're going down that route, that still leaves the question of the > semantics of the fork intrinsic... thinking about it a bit more, I think > you're going to run into problems with trying to keep around a return block > through optimizations: > > [...] > %first.return = call i1 @llvm.experimental.coro.fork() > %cmp = icmp eq i32 %x, 0 > br i1 %cmp, label %block1, label %block2 > > block1: > [...] > br i1 %first.return, label %coro.return, label %coro.start > > block2: > [...] > br i1 %first.return, label %coro.return, label %coro.start > > coro.return: > %xxx = phi i32 [ %a, %block1 ], [ %b, %block2 ] > call void @f(i32 %xxx) > ret i8* %frame > > (Now you can't trivially insert branches to the return block because of the > PHI node.) > > -Eli