Generating assumption loads of vptr after ctor call (fixed)

Generating call assume(icmp %vtable, %global_vtable) after constructor
call for devirtualization purposes.

For more info go to:
http://lists.llvm.org/pipermail/cfe-dev/2015-July/044227.html

Edit:
Fixed version because of PR24479.

http://reviews.llvm.org/D11859

llvm-svn: 245721
diff --git a/clang/test/CodeGen/available-externally-hidden.cpp b/clang/test/CodeGen/available-externally-hidden.cpp
index dc13f26..88ebfa9 100644
--- a/clang/test/CodeGen/available-externally-hidden.cpp
+++ b/clang/test/CodeGen/available-externally-hidden.cpp
@@ -27,6 +27,6 @@
 };
 
 int main() {
-TestSyncMessageFilter*  f = new TestSyncMessageFilter;
+  TestSyncMessageFilter *f = new TestSyncMessageFilter;
   f->Send(new Message);
 }
diff --git a/clang/test/CodeGenCXX/ctor-globalopt.cpp b/clang/test/CodeGenCXX/ctor-globalopt.cpp
index bcab609..6fd2118 100644
--- a/clang/test/CodeGenCXX/ctor-globalopt.cpp
+++ b/clang/test/CodeGenCXX/ctor-globalopt.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O1 | FileCheck %s --check-prefix=O1
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O2 | opt - -S -globalopt -o - | FileCheck %s --check-prefix=O1
 // RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O1 | FileCheck %s --check-prefix=O1
+// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O2 | opt - -S -globalopt -o - | FileCheck %s --check-prefix=O1
 
 // Check that GlobalOpt can eliminate static constructors for simple implicit
 // constructors. This is a targetted integration test to make sure that LLVM's
diff --git a/clang/test/CodeGenCXX/template-instantiation.cpp b/clang/test/CodeGenCXX/template-instantiation.cpp
index 90b8099..0eab85a 100644
--- a/clang/test/CodeGenCXX/template-instantiation.cpp
+++ b/clang/test/CodeGenCXX/template-instantiation.cpp
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 %s -O1 -disable-llvm-optzns -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
 
+// CHECK:     @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant
+
 // CHECK: @_ZN7PR100011xE = global
 // CHECK-NOT: @_ZN7PR100014kBarE = external global i32
 //
@@ -12,7 +14,6 @@
 // CHECK: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32]
 // CHECK-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A
 
-// CHECK:     @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant
 
 // CHECK-NOT: _ZTVN5test31SIiEE
 // CHECK-NOT: _ZTSN5test31SIiEE
diff --git a/clang/test/CodeGenCXX/thunks.cpp b/clang/test/CodeGenCXX/thunks.cpp
index 38afb9d..3e5f005 100644
--- a/clang/test/CodeGenCXX/thunks.cpp
+++ b/clang/test/CodeGenCXX/thunks.cpp
@@ -1,5 +1,9 @@
-// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t.opt -O1 -disable-llvm-optzns
+// RUN: FileCheck %s < %t
+// RUN: FileCheck %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t
+// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
 
 namespace Test1 {
 
@@ -380,13 +384,25 @@
 
 /**** The following has to go at the end of the file ****/
 
+// checking without opt
+// CHECK-NONOPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
+// CHECK-NONOPT-NOT: comdat
+
 // This is from Test5:
-// CHECK-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
-// CHECK-NOT: comdat
-// CHECK-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
+// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
 
 // This is from Test10:
-// CHECK-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
-// CHECK-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
+// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
+// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
+
+// Checking with opt
+// CHECK-OPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous namespace)::C"* %this) unnamed_addr #0 align 2
+
+// This is from Test10:
+// CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
+// CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
+
+// This is from Test5:
+// CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
 
 // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }
diff --git a/clang/test/CodeGenCXX/virtual-base-ctor.cpp b/clang/test/CodeGenCXX/virtual-base-ctor.cpp
index 8c28965..20a88cd 100644
--- a/clang/test/CodeGenCXX/virtual-base-ctor.cpp
+++ b/clang/test/CodeGenCXX/virtual-base-ctor.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | opt - -S -globalopt -o - | FileCheck %s
 
 struct B;
 extern B x;
diff --git a/clang/test/CodeGenCXX/vtable-assume-load.cpp b/clang/test/CodeGenCXX/vtable-assume-load.cpp
new file mode 100644
index 0000000..5ea9e75
--- /dev/null
+++ b/clang/test/CodeGenCXX/vtable-assume-load.cpp
@@ -0,0 +1,172 @@
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions
+
+// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s
+// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s
+// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s
+// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s
+// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s
+
+namespace test1 {
+
+struct A {
+  A();
+  virtual void foo();
+};
+
+struct B : A {
+  virtual void foo();
+};
+
+void g(A *a) { a->foo(); }
+
+// CHECK1-LABEL: define void @_ZN5test14fooAEv()
+// CHECK1: call void @_ZN5test11AC1Ev(%"struct.test1::A"*
+// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
+// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2)
+// CHECK1: call void @llvm.assume(i1 %[[CMP]])
+// CHECK1-LABEL: }
+
+void fooA() {
+  A a;
+  g(&a);
+}
+
+// CHECK1-LABEL: define void @_ZN5test14fooBEv()
+// CHECK1: call void @_ZN5test11BC1Ev(%"struct.test1::B"* %{{.*}})
+// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
+// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2)
+// CHECK1: call void @llvm.assume(i1 %[[CMP]])
+// CHECK1-LABEL: }
+
+void fooB() {
+  B b;
+  g(&b);
+}
+// there should not be any assumes in the ctor that calls base ctor
+// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%"struct.test1::B"*
+// CHECK1-NOT: @llvm.assume(
+// CHECK1-LABEL: }
+}
+namespace test2 {
+struct A {
+  A();
+  virtual void foo();
+};
+
+struct B {
+  B();
+  virtual void bar();
+};
+
+struct C : A, B {
+  C();
+  virtual void foo();
+};
+void g(A *a) { a->foo(); }
+void h(B *b) { b->bar(); }
+
+// CHECK2-LABEL: define void @_ZN5test24testEv()
+// CHECK2: call void @_ZN5test21CC1Ev(%"struct.test2::C"*
+// CHECK2: %[[VTABLE:.*]] = load i8**, i8*** {{.*}}
+// CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 2)
+// CHECK2: call void @llvm.assume(i1 %[[CMP]])
+
+// CHECK2: %[[V2:.*]] = bitcast %"struct.test2::C"* %{{.*}} to i8*
+// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 8
+// CHECK2: %[[V3:.*]] = bitcast i8* %[[ADD_PTR]] to i8***
+// CHECK2: %[[VTABLE2:.*]] = load i8**, i8*** %[[V3]]
+// CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 5)
+// CHECK2: call void @llvm.assume(i1 %[[CMP2]])
+
+// CHECK2: call void @_ZN5test21gEPNS_1AE(
+// CHECK2-LABEL: }
+
+void test() {
+  C c;
+  g(&c);
+  h(&c);
+}
+}
+
+namespace test3 {
+struct A {
+  A();
+};
+
+struct B : A {
+  B();
+  virtual void foo();
+};
+
+struct C : virtual A, B {
+  C();
+  virtual void foo();
+};
+void g(B *a) { a->foo(); }
+
+// CHECK3-LABEL: define void @_ZN5test34testEv()
+// CHECK3: call void @_ZN5test31CC1Ev(%"struct.test3::C"*
+// CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5test31CE, i64 0, i64 3)
+// CHECK3: call void @llvm.assume(i1 %[[CMP]])
+// CHECK3-LABLEL: }
+void test() {
+  C c;
+  g(&c);
+}
+} // test3
+
+namespace test4 {
+struct A {
+  A();
+  virtual void foo();
+};
+
+struct B : virtual A {
+  B();
+  virtual void foo();
+};
+struct C : B {
+  C();
+  virtual void foo();
+};
+
+void g(C *c) { c->foo(); }
+
+// CHECK4-LABEL: define void @_ZN5test44testEv()
+// CHECK4: call void @_ZN5test41CC1Ev(%"struct.test4::C"*
+// CHECK4: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
+// CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4)
+// CHECK4: call void @llvm.assume(i1 %[[CMP]]
+
+// CHECK4: %[[VTABLE2:.*]] = load i8**, i8*** %{{.*}}
+// CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4)
+// CHECK4: call void @llvm.assume(i1 %[[CMP2]])
+// CHECK4-LABEL: }
+
+void test() {
+  C c;
+  g(&c);
+}
+} // test4
+
+namespace test5 {
+
+struct __declspec(novtable) S {
+  virtual void foo();
+};
+
+void g(S &s) { s.foo(); }
+
+// if struct has novtable specifier, then we can't generate assumes
+// CHECK-MS-LABEL: define void @"\01?test@test5@@YAXXZ"()
+// CHECK-MS: call x86_thiscallcc %"struct.test5::S"* @"\01??0S@test5@@QAE@XZ"(
+// CHECK-MS-NOT: @llvm.assume
+// CHECK-MS-LABEL: }
+
+void test() {
+  S s;
+  g(s);
+}
+
+} // test5
diff --git a/clang/test/CodeGenCXX/vtable-available-externally.cpp b/clang/test/CodeGenCXX/vtable-available-externally.cpp
index 4527efc..8134047 100644
--- a/clang/test/CodeGenCXX/vtable-available-externally.cpp
+++ b/clang/test/CodeGenCXX/vtable-available-externally.cpp
@@ -186,8 +186,8 @@
 namespace Test9 {
 // all virtual functions are outline, so we can assume that it will
 // be generated in translation unit where foo is defined
-// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant
-// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant
+// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant
+// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
@@ -210,7 +210,7 @@
 namespace Test10 {
 
 // because A's key function is defined here, vtable is generated in this TU
-// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
@@ -218,14 +218,14 @@
 void A::foo() {}
 
 // Because key function is inline we will generate vtable as linkonce_odr
-// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 struct D : A {
   void bar();
 };
 inline void D::bar() {}
 
 // because B has outline key function then we can refer to
-// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant
+// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant
 struct B : A {
   void foo();
   void bar();
@@ -234,7 +234,7 @@
 // C's key function (car) is outline, but C has inline virtual function so we
 // can't guarantee that we will be able to refer to bar from name
 // so (at the moment) we can't emit vtable available_externally
-// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
 struct C : A {
   void bar() {}               // defined in body - not key function
   virtual inline void gar();  // inline in body - not key function
@@ -242,7 +242,7 @@
 };
 
 // no key function, vtable will be generated everywhere it will be used
-// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
 struct E : A {};
 
 void g(A& a) {