Home | History | Annotate | Download | only in Inline
      1 ; RUN: opt -always-inline -S < %s | FileCheck %s
      2 ; RUN: opt -passes=always-inline -S < %s | FileCheck %s
      3 
      4 ; We used to misclassify inalloca as a static alloca in the inliner. This only
      5 ; arose with for alwaysinline functions, because the normal inliner refuses to
      6 ; inline such things.
      7 
      8 ; Generated using this C++ source:
      9 ; struct Foo {
     10 ;   Foo();
     11 ;   Foo(const Foo &o);
     12 ;   ~Foo();
     13 ;   int a;
     14 ; };
     15 ; __forceinline void h(Foo o) {}
     16 ; __forceinline void g() { h(Foo()); }
     17 ; void f() { g(); }
     18 
     19 ; ModuleID = 't.cpp'
     20 source_filename = "t.cpp"
     21 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
     22 target triple = "i386-pc-windows-msvc19.0.24210"
     23 
     24 %struct.Foo = type { i32 }
     25 
     26 declare i8* @llvm.stacksave()
     27 declare void @llvm.stackrestore(i8*)
     28 
     29 declare x86_thiscallcc %struct.Foo* @"\01??0Foo@@QAE@XZ"(%struct.Foo* returned) unnamed_addr
     30 declare x86_thiscallcc void @"\01??1Foo@@QAE@XZ"(%struct.Foo*) unnamed_addr
     31 
     32 define void @f() {
     33 entry:
     34   call void @g()
     35   ret void
     36 }
     37 
     38 define internal void @g() alwaysinline {
     39 entry:
     40   %inalloca.save = call i8* @llvm.stacksave()
     41   %argmem = alloca inalloca <{ %struct.Foo }>, align 4
     42   %0 = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %argmem, i32 0, i32 0
     43   %call = call x86_thiscallcc %struct.Foo* @"\01??0Foo@@QAE@XZ"(%struct.Foo* %0)
     44   call void @h(<{ %struct.Foo }>* inalloca %argmem)
     45   call void @llvm.stackrestore(i8* %inalloca.save)
     46   ret void
     47 }
     48 
     49 ; Function Attrs: alwaysinline inlinehint nounwind
     50 define internal void @h(<{ %struct.Foo }>* inalloca) alwaysinline {
     51 entry:
     52   %o = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0
     53   call x86_thiscallcc void @"\01??1Foo@@QAE@XZ"(%struct.Foo* %o)
     54   ret void
     55 }
     56 
     57 ; CHECK: define void @f()
     58 ; CHECK:   %[[STACKSAVE:.*]] = call i8* @llvm.stacksave()
     59 ; CHECK:   %[[ARGMEM:.*]] = alloca inalloca <{ %struct.Foo }>, align 4
     60 ; CHECK:   %[[GEP1:.*]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %[[ARGMEM]], i32 0, i32 0
     61 ; CHECK:   %[[CALL:.*]] = call x86_thiscallcc %struct.Foo* @"\01??0Foo@@QAE@XZ"(%struct.Foo* %[[GEP1]])
     62 ; CHECK:   %[[GEP2:.*]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %[[ARGMEM]], i32 0, i32 0
     63 ; CHECK:   call x86_thiscallcc void @"\01??1Foo@@QAE@XZ"(%struct.Foo* %[[GEP2]])
     64 ; CHECK:   call void @llvm.stackrestore(i8* %[[STACKSAVE]])
     65 ; CHECK:   ret void
     66