[llvm] [coro][pgp] Do not insert counters in the `suspend` block (PR #71262)

Mircea Trofin via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 13 13:10:56 PST 2023


mtrofin wrote:

> Still trying to understand the details here. Is the problem here that new instructions are inserted between a `llvm.coro.suspend` call and the corresponding `switch` of the results? If so wouldn't it be easier to just move the instrumentation upwards in the basic block?

No, it's inserted in the `suspend` block. Let's use `llvm/test/Transforms/Coroutines/coro-split-musttail.ll` as an example.

Without pgo instrumentation, the end of the `opt` mini-pipeline looks like this:

```
entry.resume:
  %index.addr = getelementptr inbounds %f.Frame, ptr %vFrame, i32 0, i32 2
  %index = load i1, ptr %index.addr, align 1
  switch i1 %index, label %unreachable [
    i1 false, label %AfterCoroSuspend
    i1 true, label %CoroEnd
  ]

AfterCoroSuspend:                                 ; preds = %entry.resume
  br i1 true, label %CoroSave1, label %CoroEnd

CoroSave1:                                        ; preds = %AfterCoroSuspend
  store i1 true, ptr %index.addr, align 1
  %addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
  musttail call fastcc void %addr2(ptr null)
  ret void
```

Note how the call to `%addr2` is a tail call.

OK, now with pgo instrumentation. First, right after `pgo-instr-gen`, without this PR, it'd look like this:

```
entry:
  ...
  %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
  switch i8 %suspend, label %entry.exit_crit_edge [
    i8 0, label %await.ready
    i8 1, label %exit
  ]

entry.exit_crit_edge:                             ; preds = %entry
  call void @llvm.instrprof.increment(ptr @__profn_f, i64 1063614631108132880, i32 5, i32 0)
  br label %exit
```

The effect after `coro-split` is that, in `f.resume`, we'd end up with this:

```
entry.resume:
  %index.addr = getelementptr inbounds %f.Frame, ptr %vFrame, i32 0, i32 2
  %index = load i1, ptr %index.addr, align 1
  switch i1 %index, label %unreachable [
    i1 false, label %await.ready
    i1 true, label %AfterCoroSuspend5
  ]

await.ready:                                      ; preds = %entry.resume
  ...
  %addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
  ...
  call fastcc void %addr2(ptr null)
  br label %AfterCoroSuspend5
```

so the call to `%addr2` is a regular call instead of a tail call. With the fix:

```
entry.resume:
  %index.addr = getelementptr inbounds %f.Frame, ptr %vFrame, i32 0, i32 2
  %index = load i1, ptr %index.addr, align 1
  switch i1 %index, label %unreachable [
    i1 false, label %AfterCoroSuspend
    i1 true, label %CoroEnd
  ]

AfterCoroSuspend:                                 ; preds = %entry.resume
  br i1 true, label %CoroSave1, label %CoroEnd

CoroSave1:                                        ; preds = %AfterCoroSuspend
  ...
  %addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
  ...
  musttail call fastcc void %addr2(ptr null)
  ret void

```

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


More information about the llvm-commits mailing list