ldc icon indicating copy to clipboard operation
ldc copied to clipboard

Annotate variables with `llvm.lifetime.start` `end`

Open JohanEngelen opened this issue 8 years ago • 1 comments
trafficstars

For optimization, we should mark our variables with llvm.lifetime.start and llvm.lifetime.end, but we only have to do that when O-level > 0. For ASan, these lifetime annotations are used for use-after-scope checking, and should be enabled at -O0 already. So enable when Olevel > 0 || ASan_enabled; that's what Clang does.

For optimization, this allows stack reuse. For ASan, it is needed for use-after-scope checking which catches bugs like this:

void useAfterScope() {
  int* p;
  {
    int x = 0;
    p = &x;  // cannot statically disallow this because
    *p = 1;  // this is a valid use of things
  }
  *p = 5;  // but then this can happen... bug!
}

JohanEngelen avatar Jul 21 '17 19:07 JohanEngelen

I'll start working on this.

Another testcase:

void opaque(int* i);

void foo() {
    {
        int[100] arr = void;
        opaque(&arr[0]);
    }
    {
        int[100] arr = void;
        opaque(&arr[0]);
    }
}

Currently gives this IR (i.e. without lifetime annotation):

eclare void @_D7example6opaqueFPiZv(i32*)

define void @_D7example3fooFZv() {
  %arr = alloca [100 x i32], align 4
  %arr1 = alloca [100 x i32], align 4
  %1 = bitcast [100 x i32]* %arr to i32*
  call void @_D7example6opaqueFPiZv(i32* %1)
  %2 = bitcast [100 x i32]* %arr1 to i32*
  call void @_D7example6opaqueFPiZv(i32* %2)
  ret void
}

with asm:

_D7example3fooFZv:                      # @_D7example3fooFZv
        sub     rsp, 808. # 808 bytes stack allocation
    ...

With lifetime annotation, codegen is better:

declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)

define void @with_lifetime() {
  %arr = alloca [100 x i32], align 4
  %arr1 = alloca [100 x i32], align 4
  call void @llvm.lifetime.start.p0(i64 400, ptr nonnull %arr)
  %1 = bitcast [100 x i32]* %arr to i32*
  call void @_D7example6opaqueFPiZv(i32* %1)
  call void @llvm.lifetime.end.p0(i64 400, ptr nonnull %arr)
  call void @llvm.lifetime.start.p0(i64 400, ptr nonnull %arr1)
  %2 = bitcast [100 x i32]* %arr1 to i32*
  call void @_D7example6opaqueFPiZv(i32* %2)
  call void @llvm.lifetime.end.p0(i64 400, ptr nonnull %arr1)
  ret void
}

asm:

with_lifetime:                          # @with_lifetime
        sub     rsp, 408.  # 408 bytes stack
        ....

JohanEngelen avatar May 07 '23 20:05 JohanEngelen

#4395

JohanEngelen avatar Mar 17 '24 15:03 JohanEngelen