Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane

From: Arnaud A. de Grandmaison <arnaud.degrandmaison <at> arm.com>
Subject: lifetime.start/end clarification
Newsgroups: gmane.comp.compilers.llvm.devel
Date: Tuesday 4th November 2014 11:59:28 UTC (over 3 years ago)
The LRM (http://llvm.org/docs/LangRef.html#llvm-lifetime-start-intrinsic)
essentially  states that:

- ptr is dead before a call to "lifetime.start size, ptr"

- ptr is dead after a call to "lifetime.end size, ptr"

 

This is all good and fine, and the expected use case is that all
"lifetime.end size, ptr" markers are matched with a preceding
"lifetime.start size, ptr" in the CFG.

 

What is supposed to happen when a "lifetime.end size, ptr" is not matched
with a "lifetime.start size, ptr" ? I think there are a few possible
answers:

- the memory area pointed to by ptr is assumed to be alive since function
entry

- the memory area pointed to by ptr is assumed to be dead since function
entry, as it has not been marked alive

- this is an unexpected situation

 

I think this ambiguity should be cleared in the LRM, because today's
implicit assumption may be broken at any time.

 

This is not a theoretical question: clang can generate such cases. For
example, the following testcase:

struct X {

  void doSomething();

  char b[33];

};

 

void bar(X &);

void baz();

 

void test(int i) {

  if (i==9) {

    X x;

    x.doSomething();

label:

    bar(x);

  } else {

    baz();

    if (i==0)

      goto label;

  }

}

 

Produces:

 

%struct.X = type { [33 x i8] }

 

define void @_Z4testi(i32 %i) {

entry:

  %x = alloca %struct.X, align 1

  %cmp = icmp eq i32 %i, 9

  br i1 %cmp, label %if.then, label %if.else

 

if.then:                                          ; preds = %entry

  %0 = getelementptr inbounds %struct.X* %x, i64 0, i32 0, i64 0

  call void @llvm.lifetime.start(i64 33, i8* %0)

  call void @_ZN1X11doSomethingEv(%struct.X* %x)

  br label %label

 

label:                                            ; preds =
%if.else.label_crit_edge, %if.then

  %.pre-phi = phi i8* [ %.pre, %if.else.label_crit_edge ], [ %0, %if.then ]

  call void @_Z3barR1X(%struct.X* dereferenceable(33) %x)

  call void @llvm.lifetime.end(i64 33, i8* %.pre-phi)

  br label %if.end3

 

if.else:                                          ; preds = %entry

  tail call void @_Z3bazv()

  %cmp1 = icmp eq i32 %i, 0

  br i1 %cmp1, label %if.else.label_crit_edge, label %if.end3

 

if.else.label_crit_edge:                          ; preds = %if.else

  %.pre = getelementptr inbounds %struct.X* %x, i64 0, i32 0, i64 0

  br label %label

 

if.end3:                                          ; preds = %if.else,
%label

  ret void

}

 

Note that the path thru if.else.label_crit_edge has no lifetime start.

 

Cheers,

--

Arnaud
 
CD: 4ms