-O0 inlining lost an alloca under subtle circumstances

Hi Chandler,

In reducing a debug info test case I came across what looks like an
odd variation in inlining output.

Compiling the attached example produces the following IR for 'f7':

  define void @_Z2f7v() #0 {
  entry:
    %i.addr.i.i = alloca i32, align 4
    %agg.tmp.i = alloca %struct.A, align 1
    call void @llvm.dbg.declare(metadata !{null}, metadata !47) #3, !dbg !48
    store i32 0, i32* %i.addr.i.i, align 4
    call void @llvm.dbg.declare(metadata !{i32* %i.addr.i.i}, metadata
!34) #3, !dbg !51
    call void @_Z2f3v() #3, !dbg !51
    ret void, !dbg !50
  }

If you comment out 'f3', you get this instead:

  define void @_Z2f7v() #0 {
  entry:
    %i.addr.i.i.i = alloca i32, align 4
    %a.i.i = alloca %struct.A, align 1
    %agg.tmp.i = alloca %struct.A, align 1
    call void @llvm.dbg.declare(metadata !{%struct.A* %a.i.i},
metadata !45) #3, !dbg !46
    store i32 0, i32* %i.addr.i.i.i, align 4
    call void @llvm.dbg.declare(metadata !{i32* %i.addr.i.i.i},
metadata !33) #3, !dbg !49
    call void @_Z2f3v() #3, !dbg !49
    ret void, !dbg !48
  }

While debug info should cope with the dbg.declare with a null value in
the first example, it... doesn't. (debug info is still /very/ much
attached to those allocas). But in the second example, the alloca
remains and the world is a happy place*.

Any idea why this is happening? Should it be considered a bug in the
inliner? (I haven't actually done all the IR pass-by-pass examination,
but this is coming out of Clang -O0 with a few always_inline
attributes, so I'm not sure there's much else at work here, especially
given how this is affected by other functions that are never inlined
anywhere - all that talk of strongly connected components in the call
graph is starting to feel vaguely familiar here)

- David

* the specific description of how this affects debug info is this: The
first time we see the inlined function, we create the abstract
definition but since the alloca was dropped, we don't include that
variable in the abstract definition (above -O0, the frontend emits a
list of all the variables in the function, and we use that to recover
from cases where variables are optimized away - at -O0, this doesn't
happen because we assume the allocas are preserved, etc). Later on,
another function gets this inlined and /does/ have the variable, it
assumes that since the abstract definition has been constructed, so
have all the abstract variables... but that's evidently not the case
and it fires the assert I've been trying to enable for the last couple
of weeks. (though even if it weren't for the assert, it'd still cause
incorrect debug info, because we're missing some of the abstract
variables)

missing_abstract.cpp (393 Bytes)

Ping