[llvm-dev] Well-formed @llvm.lifetime.start and @llvm.lifetime.end intrinsics

Michael Kruse via llvm-dev llvm-dev at lists.llvm.org
Fri Mar 31 06:22:29 PDT 2017


2017-03-31 15:00 GMT+02:00 Than McIntosh <thanm at google.com>:
> Hi all,
>
> Just to clarify: the code I'm seeing in the stack coloring dumps is a little
> different from what is being discussed in previous spots in this thread. The
> example that Michael cited earlier on was
>
>     if (c) {
>       llvm.lifetime.start(&var)
>     }
>     [...]
>     llvm.lifetime.end(&var)
>
> however what I'm seeing is:
>
>     entry block:
>     [...]
>     if (c) {           // conditional branch terminating entry block
>       llvm.lifetime.start(&var)
>       [...]
>       exit(..);        // this is a no-return-call
>     }
>     [...]
>     llvm.lifetime.end(&var)
>
> In the first example there is a path from the lifetime start op to uses of
> the variable. In the second example (which is what I see when I look at the
> stack coloring dumps) there is no such path.
>
> Looking at the code in clang (e.g. CodeGenFunction::EmitAutoVarAlloca) it is
> pretty clear to me that when the lifetime marker is first manufactured, it
> is placed into the entry block. I don't know enough about how Polly operates
> to understand why it is migrating the lifetime in question down into the
> block containing the exit... but it seems to me that this is really the crux
> of the problem.

Thank you for the clarification. I indeed did not consider that the
exit/unreachable makes a difference.

This is what happens in Polly:

  llvm.lifetime.start(&var)
  if (c) {
    call void @_z10exit_usagepkc
    unreachable // because exit_usage is no-return
  }

- Optimistically assume that no functions are executed or control flow
ends in an unreachable. It can determine the condition c1 for when no
such thing ever appears (in which case c1 is just "true")
- Version the old code and the new code:

if (c1) {
  // optimized code without lifetime markers
  ...
} else {
 // Orginal code, not modified by Polly
  llvm.lifetime.start(&var);
  if (c) {
    call void @_z10exit_usagepkc
    unreachable // because exit_usage is no-return
  }
}

In this case c happens to be equal to c1, in which case I guess some
pass removes the inner inner conditional because it is always true.

How do you think code versioning in general should handle this? I
looked into LoopVersioning.cpp (used by LLVM's vectorizer), but could
not see how it handles this situation. Maybe it is not affected
because lifetime markers usually do not cross loop bounds.

Michael


More information about the llvm-dev mailing list