[clang] c2985a3 - [Clang] Convert some tests to opaque pointers (NFC)

Nikita Popov via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 8 01:38:17 PDT 2023


Author: Nikita Popov
Date: 2023-06-08T10:38:08+02:00
New Revision: c2985a330cd5c418488cbd87bd7a2922d6a8f7da

URL: https://github.com/llvm/llvm-project/commit/c2985a330cd5c418488cbd87bd7a2922d6a8f7da
DIFF: https://github.com/llvm/llvm-project/commit/c2985a330cd5c418488cbd87bd7a2922d6a8f7da.diff

LOG: [Clang] Convert some tests to opaque pointers (NFC)

Added: 
    

Modified: 
    clang/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
    clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
    clang/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
    clang/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
    clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
    clang/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
    clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
    clang/test/CodeGenCXX/microsoft-abi-structors.cpp
    clang/test/CodeGenCXX/microsoft-abi-this-nullable.cpp
    clang/test/CodeGenCXX/microsoft-abi-thunks.cpp
    clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
    clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp

Removed: 
    


################################################################################
diff  --git a/clang/test/CodeGenCXX/microsoft-abi-array-cookies.cpp b/clang/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
index 28cf226450da5..1cc0e9af571c3 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -no-opaque-pointers -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
 
 struct ClassWithoutDtor {
   char x;
@@ -7,7 +7,7 @@ struct ClassWithoutDtor {
 void check_array_no_cookies() {
 // CHECK: define dso_local void @"?check_array_no_cookies@@YAXXZ"() [[NUW:#[0-9]+]]
 
-// CHECK: call noalias noundef nonnull i8* @"??_U at YAPAXI@Z"(i32 noundef 42)
+// CHECK: call noalias noundef nonnull ptr @"??_U at YAPAXI@Z"(i32 noundef 42)
   ClassWithoutDtor *array = new ClassWithoutDtor[42];
 
 // CHECK: call void @"??_V at YAXPAX@Z"(
@@ -24,16 +24,13 @@ void check_array_cookies_simple() {
 // CHECK: define {{.*}} @"?check_array_cookies_simple@@YAXXZ"()
 
   ClassWithDtor *array = new ClassWithDtor[42];
-// CHECK: [[ALLOCATED:%.*]] = call noalias noundef nonnull i8* @"??_U at YAPAXI@Z"(i32 noundef 46)
+// CHECK: [[ALLOCATED:%.*]] = call noalias noundef nonnull ptr @"??_U at YAPAXI@Z"(i32 noundef 46)
 // 46 = 42 + size of cookie (4)
-// CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32*
-// CHECK: store i32 42, i32* [[COOKIE]]
-// CHECK: [[ARRAY:%.*]] = getelementptr inbounds i8, i8* [[ALLOCATED]], i32 4
-// CHECK: bitcast i8* [[ARRAY]] to [[CLASS:%.*]]*
+// CHECK: store i32 42, ptr [[ALLOCATED]]
+// CHECK: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[ALLOCATED]], i32 4
 
   delete [] array;
-// CHECK: [[ARRAY_AS_CHAR:%.*]] = bitcast [[CLASS]]* {{%.*}} to i8*
-// CHECK: getelementptr inbounds i8, i8* [[ARRAY_AS_CHAR]], i32 -4
+// CHECK: getelementptr inbounds i8, ptr {{%.*}}, i32 -4
 }
 
 struct __attribute__((aligned(8))) ClassWithAlignment {
@@ -46,16 +43,13 @@ struct __attribute__((aligned(8))) ClassWithAlignment {
 void check_array_cookies_aligned() {
 // CHECK: define {{.*}} @"?check_array_cookies_aligned@@YAXXZ"()
   ClassWithAlignment *array = new ClassWithAlignment[42];
-// CHECK: [[ALLOCATED:%.*]] = call noalias noundef nonnull i8* @"??_U at YAPAXI@Z"(i32 noundef 344)
+// CHECK: [[ALLOCATED:%.*]] = call noalias noundef nonnull ptr @"??_U at YAPAXI@Z"(i32 noundef 344)
 //   344 = 42*8 + size of cookie (8, due to alignment)
-// CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32*
-// CHECK: store i32 42, i32* [[COOKIE]]
-// CHECK: [[ARRAY:%.*]] = getelementptr inbounds i8, i8* [[ALLOCATED]], i32 8
-// CHECK: bitcast i8* [[ARRAY]] to [[CLASS:%.*]]*
+// CHECK: store i32 42, ptr [[ALLOCATED]]
+// CHECK: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[ALLOCATED]], i32 8
 
   delete [] array;
-// CHECK: [[ARRAY_AS_CHAR:%.*]] = bitcast [[CLASS]]*
-// CHECK: getelementptr inbounds i8, i8* [[ARRAY_AS_CHAR]], i32 -8
+// CHECK: getelementptr inbounds i8, ptr {{.*}}, i32 -8
 }
 
 namespace PR23990 {
@@ -63,7 +57,7 @@ struct S {
   char x[42];
   void operator delete[](void *p, __SIZE_TYPE__);
   // CHECK-LABEL: define dso_local void @"?delete_s at PR23990@@YAXPAUS at 1@@Z"(
-  // CHECK: call void @"??_VS at PR23990@@SAXPAXI at Z"(i8* noundef {{.*}}, i32 noundef 42)
+  // CHECK: call void @"??_VS at PR23990@@SAXPAXI at Z"(ptr noundef {{.*}}, i32 noundef 42)
 };
 void delete_s(S *s) { delete[] s; }
 }

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp b/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
index 89944053c6816..80ea63e2a1e10 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -no-opaque-pointers -Wno-non-pod-varargs -emit-llvm %s -o - -triple=i686-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck %s
+// RUN: %clang_cc1 -Wno-non-pod-varargs -emit-llvm %s -o - -triple=i686-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck %s
 
 #include <stdarg.h>
 
@@ -19,14 +19,14 @@ int foo(A a, ...) {
   return sum;
 }
 
-// CHECK-LABEL: define dso_local noundef i32 @"?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca(<{ %struct.A }>) %0, ...)
+// CHECK-LABEL: define dso_local noundef i32 @"?foo@@YAHUA@@ZZ"(ptr inalloca(<{ %struct.A }>) %0, ...)
 
 int main() {
   return foo(A(3), 1, 2, 3);
 }
 // CHECK-LABEL: define dso_local noundef i32 @main()
 // CHECK: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.A, i32, i32, i32 }>
-// CHECK: call noundef i32 {{.*bitcast.*}}@"?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca(<{ %struct.A, i32, i32, i32 }>) %[[argmem]])
+// CHECK: call noundef i32 (ptr, ...) @"?foo@@YAHUA@@ZZ"{{.*}}(ptr inalloca(<{ %struct.A, i32, i32, i32 }>) %[[argmem]])
 
 void varargs_zero(...);
 void varargs_one(int, ...);
@@ -41,10 +41,10 @@ void call_var_args() {
 }
 
 // CHECK-LABEL: define dso_local void @"?call_var_args@@YAXXZ"()
-// CHECK: call void {{.*bitcast.*varargs_zero.*}}(<{ %struct.A }>* inalloca(<{ %struct.A }>) %{{.*}})
-// CHECK: call void {{.*bitcast.*varargs_one.*}}(<{ i32, %struct.A }>* inalloca(<{ i32, %struct.A }>) %{{.*}})
-// CHECK: call void {{.*bitcast.*varargs_two.*}}(<{ i32, i32, %struct.A }>* inalloca(<{ i32, i32, %struct.A }>) %{{.*}})
-// CHECK: call void {{.*bitcast.*varargs_three.*}}(<{ i32, i32, i32, %struct.A }>* inalloca(<{ i32, i32, i32, %struct.A }>) %{{.*}})
+// CHECK: call void {{.*varargs_zero.*}}(ptr inalloca(<{ %struct.A }>) %{{.*}})
+// CHECK: call void {{.*varargs_one.*}}(ptr inalloca(<{ i32, %struct.A }>) %{{.*}})
+// CHECK: call void {{.*varargs_two.*}}(ptr inalloca(<{ i32, i32, %struct.A }>) %{{.*}})
+// CHECK: call void {{.*varargs_three.*}}(ptr inalloca(<{ i32, i32, i32, %struct.A }>) %{{.*}})
 
 // CHECK-LABEL: declare dso_local void @"?varargs_zero@@YAXZZ"(...)
 // CHECK-LABEL: declare dso_local void @"?varargs_one@@YAXHZZ"(i32 noundef, ...)

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
index 7601e6293ec90..3a82c76b4c145 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
 
 struct A {
   constexpr A(int x) : x(x) {}
@@ -7,7 +7,7 @@ struct A {
 };
 
 A a(42);
-// CHECK: @"?a@@3UA@@A" = dso_local global { { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"??_7A@@6B@", i32 42 }, align 4
+// CHECK: @"?a@@3UA@@A" = dso_local global %struct.A { ptr @"??_7A@@6B@", i32 42 }, align 4
 
 struct B {
   constexpr B(int y) : y(y) {}
@@ -20,4 +20,4 @@ struct C : A, B {
 };
 
 C c;
-// CHECK: @"?c@@3UC@@A" = dso_local global { { [1 x i8*] }*, i32, { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"??_7C@@6BA@@@", i32 777, { [1 x i8*] }* @"??_7C@@6BB@@@", i32 13 }
+// CHECK: @"?c@@3UC@@A" = dso_local global { ptr, i32, ptr, i32 } { ptr @"??_7C@@6BA@@@", i32 777, ptr @"??_7C@@6BB@@@", i32 13 }

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-eh-catch.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
index ed2c257bac494..2a5aef6e19da4 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc \
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc \
 // RUN:     -mconstructor-aliases -fexceptions -fcxx-exceptions \
 // RUN:     -O1 -disable-llvm-passes \
 // RUN:     | FileCheck -check-prefix WIN64 %s
@@ -25,7 +25,7 @@ extern "C" void catch_all() {
 // WIN64: %[[catchswitch:[^ ]*]] = catchswitch within none [label %[[catchpad_lpad:[^ ]*]]] unwind to caller
 //
 // WIN64: [[catchpad_lpad]]
-// WIN64: catchpad within %[[catchswitch]] [i8* null, i32 64, i8* null]
+// WIN64: catchpad within %[[catchswitch]] [ptr null, i32 64, ptr null]
 // WIN64: call void @recover()
 // WIN64: catchret from %{{.*}} to label %[[catchret:[^ ]*]]
 //
@@ -47,17 +47,16 @@ extern "C" void catch_int() {
 }
 
 // WIN64-LABEL: define dso_local void @catch_int()
-// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor2* @"??_R0H at 8", i32 0, i32* %[[e_addr:[^\]]*]]]
+// WIN64: catchpad within %{{[^ ]*}} [ptr @"??_R0H at 8", i32 0, ptr %[[e_addr:.*]]]
 //
 // The catchpad instruction starts the lifetime of 'e'. Unfortunately, that
 // leaves us with nowhere to put lifetime.start, so we don't emit lifetime
 // markers for now.
 // WIN64-NOT: lifetime.start
 //
-// WIN64: %[[e_i8:[^ ]*]] = bitcast i32* %[[e_addr]] to i8*
 // WIN64-NOT: lifetime.start
 // WIN64: call void @handle_exception
-// WIN64-SAME: (i8* noundef %[[e_i8]])
+// WIN64-SAME: (ptr noundef %[[e_addr]])
 // WIN64-NOT: lifetime.end
 // WIN64: catchret
 
@@ -69,7 +68,7 @@ extern "C" void catch_int_unnamed() {
 }
 
 // WIN64-LABEL: define dso_local void @catch_int_unnamed()
-// WIN64: catchpad within %{{.*}} [%rtti.TypeDescriptor2* @"??_R0H at 8", i32 0, i8* null]
+// WIN64: catchpad within %{{.*}} [ptr @"??_R0H at 8", i32 0, ptr null]
 // WIN64: catchret
 
 struct A {
@@ -96,9 +95,8 @@ extern "C" void catch_a_byval() {
 
 // WIN64-LABEL: define dso_local void @catch_a_byval()
 // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A
-// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]]
-// WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
-// WIN64: call void @handle_exception(i8* noundef %[[e_i8]])
+// WIN64: catchpad within %{{[^ ]*}} [ptr @"??_R0?AUA@@@8", i32 0, ptr %[[e_addr]]]
+// WIN64: call void @handle_exception(ptr noundef %[[e_addr]])
 // WIN64: catchret
 
 extern "C" void catch_a_ref() {
@@ -110,11 +108,10 @@ extern "C" void catch_a_ref() {
 }
 
 // WIN64-LABEL: define dso_local void @catch_a_ref()
-// WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A*
-// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]]
-// WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]]
-// WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8*
-// WIN64: call void @handle_exception(i8* noundef %[[eptr_i8]])
+// WIN64: %[[e_addr:[^ ]*]] = alloca ptr
+// WIN64: catchpad within %{{[^ ]*}} [ptr @"??_R0?AUA@@@8", i32 8, ptr %[[e_addr]]]
+// WIN64: %[[eptr:[^ ]*]] = load ptr, ptr %[[e_addr]]
+// WIN64: call void @handle_exception(ptr noundef %[[eptr]])
 // WIN64: catchret
 
 extern "C" void fn_with_exc_spec() throw(int) {
@@ -145,7 +142,7 @@ extern "C" void catch_nested() {
 // WIN64: %[[catchswitch_outer_scope:[^ ]*]] = catchswitch within none [label %[[catch_int_outer:[^ ]*]]] unwind to caller
 //
 // WIN64: [[catch_int_outer]]
-// WIN64: %[[catchpad:[^ ]*]] = catchpad within %[[catchswitch_outer_scope]] [%rtti.TypeDescriptor2* @"??_R0H at 8", i32 0, i8* null]
+// WIN64: %[[catchpad:[^ ]*]] = catchpad within %[[catchswitch_outer_scope]] [ptr @"??_R0H at 8", i32 0, ptr null]
 // WIN64: invoke void @might_throw()
 // WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[catchswitch_inner:[^ ]*]]
 //
@@ -153,7 +150,7 @@ extern "C" void catch_nested() {
 // WIN64: %[[catchswitch_inner_scope:[^ ]*]] = catchswitch within %[[catchpad]] [label %[[catch_int_inner:[^ ]*]]] unwind to caller
 //
 // WIN64: [[catch_int_inner]]
-// WIN64: catchpad within %[[catchswitch_inner_scope]] [%rtti.TypeDescriptor2* @"??_R0H at 8", i32 0, i8* null]
+// WIN64: catchpad within %[[catchswitch_inner_scope]] [ptr @"??_R0H at 8", i32 0, ptr null]
 // WIN64-NEXT: call void @might_throw()
 // WIN64: catchret {{.*}} to label %[[catchret2:[^ ]*]]
 //

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
index c464c1c7071ea..6e4b7f259727b 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -1,14 +1,14 @@
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck -allow-deprecated-dag-overlap %s
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify
+// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck -allow-deprecated-dag-overlap %s
+// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64
+// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify
+// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify
 
 namespace pr37399 {
 template <typename T>
 struct Functor {
   void (T::*PtrToMemberFunction)();
 };
-// CHECK-DAG: %"struct.pr37399::Functor" = type { i8* }
+// CHECK-DAG: %"struct.pr37399::Functor" = type { ptr }
 
 template <typename SomeType>
 class SimpleDerivedFunctor;
@@ -77,20 +77,20 @@ class VirtuallyDerivedFunctor
 pr37399::DerivedFunctor<int>           BFunctor;
 // CHECK-DAG: @"?BFunctor@@3V?$DerivedFunctor at H@pr37399@@A" = dso_local global %"[[BFUNCTOR:class.pr37399::DerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
 // CHECK-DAG: %"[[BFUNCTOR]]" = type { %"[[BFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]" }
-// CHECK-DAG: %"[[BFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } }
+// CHECK-DAG: %"[[BFUNCTORBASE]]" = type { { ptr, i32, i32, i32 } }
 pr37399::DerivedFunctor<void>          AFunctor;
 // CHECK-DAG: @"?AFunctor@@3V?$DerivedFunctor at X@pr37399@@A" = dso_local global %"[[AFUNCTOR:class.pr37399::DerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
 // CHECK-DAG: %"[[AFUNCTOR]]" = type { %"[[AFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]" }
-// CHECK-DAG: %"[[AFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } }
+// CHECK-DAG: %"[[AFUNCTORBASE]]" = type { { ptr, i32, i32, i32 } }
 
 pr37399::MultiplyDerivedFunctor<int>   DFunctor;
 // CHECK-DAG: @"?DFunctor@@3V?$MultiplyDerivedFunctor at H@pr37399@@A" = dso_local global %"[[DFUNCTOR:class.pr37399::MultiplyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
 // CHECK-DAG: %"[[DFUNCTOR]]" = type { %"[[DFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]", %"class.pr37399::MultipleBase", [6 x i8] }
-// CHECK-DAG: %"[[DFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } }
+// CHECK-DAG: %"[[DFUNCTORBASE]]" = type { { ptr, i32, i32, i32 } }
 pr37399::MultiplyDerivedFunctor<void>  CFunctor;
 // CHECK-DAG: @"?CFunctor@@3V?$MultiplyDerivedFunctor at X@pr37399@@A" = dso_local global %"[[CFUNCTOR:class.pr37399::MultiplyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
 // CHECK-DAG: %"[[CFUNCTOR]]" = type { %"[[CFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]", %"class.pr37399::MultipleBase", [6 x i8] }
-// CHECK-DAG: %"[[CFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } }
+// CHECK-DAG: %"[[CFUNCTORBASE]]" = type { { ptr, i32, i32, i32 } }
 
 pr37399::VirtuallyDerivedFunctor<int>  FFunctor;
 // CHECK-DAG: @"?FFunctor@@3V?$VirtuallyDerivedFunctor at H@pr37399@@A" = dso_local global %"[[FFUNCTOR:class.pr37399::VirtuallyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
@@ -99,8 +99,8 @@ pr37399::VirtuallyDerivedFunctor<void> EFunctor;
 // CHECK-DAG: @"?EFunctor@@3V?$VirtuallyDerivedFunctor at X@pr37399@@A" = dso_local global %"[[EFUNCTOR:class.pr37399::VirtuallyDerivedFunctor(\.[0-9]+)?]]" zeroinitializer, align 8
 // CHECK-DAG: %"[[EFUNCTOR]]" = type { %"class.pr37399::VirtBaseFunctor.base", %"class.pr37399::VirtualBase" }
 
-// CHECK-DAG: %"class.pr37399::VirtBaseFunctor.base" = type <{ %"[[VFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]", i32*, [4 x i8] }>
-// CHECK-DAG: %"[[VFUNCTORBASE]]" = type { { i8*, i32, i32, i32 } }
+// CHECK-DAG: %"class.pr37399::VirtBaseFunctor.base" = type <{ %"[[VFUNCTORBASE:struct.pr37399::Functor(\.[0-9]+)?]]", ptr, [4 x i8] }>
+// CHECK-DAG: %"[[VFUNCTORBASE]]" = type { { ptr, i32, i32, i32 } }
 
 namespace pr37399 {
 void SingleInheritanceFnPtrCall() {
@@ -170,17 +170,17 @@ void PR26313_f(PR26313_FUNC *p) { delete p; }
 struct PR26313_Z;
 int PR26313_Z::**a = nullptr;
 int PR26313_Z::*b = *a;
-// CHECK-DAG: @"?a@@3PAPQPR26313_Z@@HA" = dso_local global %0* null, align 4
+// CHECK-DAG: @"?a@@3PAPQPR26313_Z@@HA" = dso_local global ptr null, align 4
 // CHECK-DAG: @"?b@@3PQPR26313_Z@@HQ1@" = dso_local global { i32, i32, i32 } { i32 0, i32 0, i32 -1 }, align 4
 
 namespace PR20947 {
 struct A;
 int A::**a = nullptr;
-// CHECK-DAG: @"?a at PR20947@@3PAPQA at 1@HA" = dso_local global %{{.*}}* null, align 4
+// CHECK-DAG: @"?a at PR20947@@3PAPQA at 1@HA" = dso_local global ptr null, align 4
 
 struct B;
 int B::*&b = b;
-// CHECK-DAG: @"?b at PR20947@@3AAPQB at 1@HA" = dso_local global %{{.*}}* null, align 4
+// CHECK-DAG: @"?b at PR20947@@3AAPQB at 1@HA" = dso_local global ptr null, align 4
 }
 
 namespace PR20017 {
@@ -190,7 +190,7 @@ struct A {
 };
 struct B;
 auto a = &A<B>::m_fn1;
-// CHECK-DAG: @"?a at PR20017@@3P8?$A at UB@PR20017@@@1 at AEPQB@1 at HXZQ21@" = dso_local global i8* bitcast ({ i32, i32, i32 } ({{.*}}*)* @"?m_fn1@?$A at UB@PR20017@@@PR20017@@QAEPQB at 2@HXZ" to i8*), align 4
+// CHECK-DAG: @"?a at PR20017@@3P8?$A at UB@PR20017@@@1 at AEPQB@1 at HXZQ21@" = dso_local global ptr @"?m_fn1@?$A at UB@PR20017@@@PR20017@@QAEPQB at 2@HXZ", align 4
 }
 
 #ifndef INCOMPLETE_VIRTUAL
@@ -259,9 +259,9 @@ int UnspecSingle::*us_d_memptr;
 void (Single  ::*s_f_memptr)();
 void (Multiple::*m_f_memptr)();
 void (Virtual ::*v_f_memptr)();
-// CHECK: @"?s_f_memptr@@3P8Single@@AEXXZQ1@" = dso_local global i8* null, align 4
-// CHECK: @"?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = dso_local global { i8*, i32 } zeroinitializer, align 4
-// CHECK: @"?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = dso_local global { i8*, i32, i32 } zeroinitializer, align 4
+// CHECK: @"?s_f_memptr@@3P8Single@@AEXXZQ1@" = dso_local global ptr null, align 4
+// CHECK: @"?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = dso_local global { ptr, i32 } zeroinitializer, align 4
+// CHECK: @"?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = dso_local global { ptr, i32, i32 } zeroinitializer, align 4
 
 // We can define Unspecified after locking in the inheritance model.
 struct Unspecified : Multiple, Virtual {
@@ -281,15 +281,15 @@ void (Virtual    ::*v_f_mp)() = &Virtual::foo;
 void (Unspecified::*u_f_mp)() = &Unspecified::foo;
 void (UnspecSingle::*us_f_mp)() = &UnspecSingle::foo;
 // CHECK: @"?s_f_mp at Const@@3P8Single@@AEXXZQ2@" =
-// CHECK:   global i8* bitcast ({{.*}} @"?foo at Single@@QAEXXZ" to i8*), align 4
+// CHECK:   global ptr @"?foo at Single@@QAEXXZ", align 4
 // CHECK: @"?m_f_mp at Const@@3P8Multiple@@AEXXZQ2@" =
-// CHECK:   global { i8*, i32 } { i8* bitcast ({{.*}} @"?foo at B2@@QAEXXZ" to i8*), i32 4 }, align 4
+// CHECK:   global { ptr, i32 } { ptr @"?foo at B2@@QAEXXZ", i32 4 }, align 4
 // CHECK: @"?v_f_mp at Const@@3P8Virtual@@AEXXZQ2@" =
-// CHECK:   global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"?foo at Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4
+// CHECK:   global { ptr, i32, i32 } { ptr @"?foo at Virtual@@QAEXXZ", i32 0, i32 0 }, align 4
 // CHECK: @"?u_f_mp at Const@@3P8Unspecified@@AEXXZQ2@" =
-// CHECK:   global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"?foo at Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
+// CHECK:   global { ptr, i32, i32, i32 } { ptr @"?foo at Unspecified@@QAEXXZ", i32 0, i32 0, i32 0 }, align 4
 // CHECK: @"?us_f_mp at Const@@3P8UnspecSingle@@AEXXZQ2@" =
-// CHECK:   global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"?foo at UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
+// CHECK:   global { ptr, i32, i32, i32 } { ptr @"?foo at UnspecSingle@@QAEXXZ", i32 0, i32 0, i32 0 }, align 4
 }
 
 namespace CastParam {
@@ -306,16 +306,16 @@ struct C : B, A { int c; };
 
 void (A::*ptr1)(void *) = (void (A::*)(void *)) &A::foo;
 // CHECK: @"?ptr1 at CastParam@@3P8A at 1@AEXPAX at ZQ21@" =
-// CHECK:   global i8* bitcast (void ({{.*}})* @"?foo at A@CastParam@@QAEXPAU12@@Z" to i8*), align 4
+// CHECK:   global ptr @"?foo at A@CastParam@@QAEXPAU12@@Z", align 4
 
 // Try a reinterpret_cast followed by a memptr conversion.
 void (C::*ptr2)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) &A::foo;
 // CHECK: @"?ptr2 at CastParam@@3P8C at 1@AEXPAX at ZQ21@" =
-// CHECK:   global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"?foo at A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 4
+// CHECK:   global { ptr, i32 } { ptr @"?foo at A@CastParam@@QAEXPAU12@@Z", i32 4 }, align 4
 
 void (C::*ptr3)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) (void (A::*)(A *)) 0;
 // CHECK: @"?ptr3 at CastParam@@3P8C at 1@AEXPAX at ZQ21@" =
-// CHECK:   global { i8*, i32 } zeroinitializer, align 4
+// CHECK:   global { ptr, i32 } zeroinitializer, align 4
 
 struct D : C {
   virtual void isPolymorphic();
@@ -347,24 +347,24 @@ void EmitNonVirtualMemberPointers() {
   void (Unspecified::*u_f_memptr)() = &Unspecified::foo;
   void (UnspecWithVBPtr::*u2_f_memptr)() = &UnspecWithVBPtr::foo;
 // CHECK: define dso_local void @"?EmitNonVirtualMemberPointers@@YAXXZ"() {{.*}} {
-// CHECK:   alloca i8*, align 4
-// CHECK:   alloca { i8*, i32 }, align 4
-// CHECK:   alloca { i8*, i32, i32 }, align 4
-// CHECK:   alloca { i8*, i32, i32, i32 }, align 4
-// CHECK:   store i8* bitcast (void (%{{.*}}*)* @"?foo at Single@@QAEXXZ" to i8*), i8** %{{.*}}, align 4
-// CHECK:   store { i8*, i32 }
-// CHECK:     { i8* bitcast (void (%{{.*}}*)* @"?foo at Multiple@@QAEXXZ" to i8*), i32 0 },
-// CHECK:     { i8*, i32 }* %{{.*}}, align 4
-// CHECK:   store { i8*, i32, i32 }
-// CHECK:     { i8* bitcast (void (%{{.*}}*)* @"?foo at Virtual@@QAEXXZ" to i8*), i32 0, i32 0 },
-// CHECK:     { i8*, i32, i32 }* %{{.*}}, align 4
-// CHECK:   store { i8*, i32, i32, i32 }
-// CHECK:     { i8* bitcast (void (%{{.*}}*)* @"?foo at Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 },
-// CHECK:     { i8*, i32, i32, i32 }* %{{.*}}, align 4
-// CHECK:   store { i8*, i32, i32, i32 }
-// CHECK:     { i8* bitcast (void (%{{.*}}*)* @"?foo at UnspecWithVBPtr@@QAEXXZ" to i8*),
+// CHECK:   alloca ptr, align 4
+// CHECK:   alloca { ptr, i32 }, align 4
+// CHECK:   alloca { ptr, i32, i32 }, align 4
+// CHECK:   alloca { ptr, i32, i32, i32 }, align 4
+// CHECK:   store ptr @"?foo at Single@@QAEXXZ", ptr %{{.*}}, align 4
+// CHECK:   store { ptr, i32 }
+// CHECK:     { ptr @"?foo at Multiple@@QAEXXZ", i32 0 },
+// CHECK:     ptr %{{.*}}, align 4
+// CHECK:   store { ptr, i32, i32 }
+// CHECK:     { ptr @"?foo at Virtual@@QAEXXZ", i32 0, i32 0 },
+// CHECK:     ptr %{{.*}}, align 4
+// CHECK:   store { ptr, i32, i32, i32 }
+// CHECK:     { ptr @"?foo at Unspecified@@QAEXXZ", i32 0, i32 0, i32 0 },
+// CHECK:     ptr %{{.*}}, align 4
+// CHECK:   store { ptr, i32, i32, i32 }
+// CHECK:     { ptr @"?foo at UnspecWithVBPtr@@QAEXXZ",
 // CHECK:       i32 0, i32 0, i32 0 },
-// CHECK:     { i8*, i32, i32, i32 }* %{{.*}}, align 4
+// CHECK:     ptr %{{.*}}, align 4
 // CHECK:   ret void
 // CHECK: }
 }
@@ -378,12 +378,12 @@ void podMemPtrs() {
 // Check that member pointers use the right offsets and that null is -1.
 // CHECK:      define dso_local void @"?podMemPtrs@@YAXXZ"() {{.*}} {
 // CHECK:        %[[memptr:.*]] = alloca i32, align 4
-// CHECK-NEXT:   store i32 0, i32* %[[memptr]], align 4
-// CHECK-NEXT:   store i32 4, i32* %[[memptr]], align 4
-// CHECK-NEXT:   %[[memptr_val:.*]] = load i32, i32* %[[memptr]], align 4
+// CHECK-NEXT:   store i32 0, ptr %[[memptr]], align 4
+// CHECK-NEXT:   store i32 4, ptr %[[memptr]], align 4
+// CHECK-NEXT:   %[[memptr_val:.*]] = load i32, ptr %[[memptr]], align 4
 // CHECK-NEXT:   %{{.*}} = icmp ne i32 %[[memptr_val]], -1
 // CHECK-NEXT:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
-// CHECK:        store i32 -1, i32* %[[memptr]], align 4
+// CHECK:        store i32 -1, ptr %[[memptr]], align 4
 // CHECK:        ret void
 // CHECK:      }
 }
@@ -398,12 +398,12 @@ void polymorphicMemPtrs() {
 // offset and use 0 to represent null.
 // CHECK:      define dso_local void @"?polymorphicMemPtrs@@YAXXZ"() {{.*}} {
 // CHECK:        %[[memptr:.*]] = alloca i32, align 4
-// CHECK-NEXT:   store i32 4, i32* %[[memptr]], align 4
-// CHECK-NEXT:   store i32 8, i32* %[[memptr]], align 4
-// CHECK-NEXT:   %[[memptr_val:.*]] = load i32, i32* %[[memptr]], align 4
+// CHECK-NEXT:   store i32 4, ptr %[[memptr]], align 4
+// CHECK-NEXT:   store i32 8, ptr %[[memptr]], align 4
+// CHECK-NEXT:   %[[memptr_val:.*]] = load i32, ptr %[[memptr]], align 4
 // CHECK-NEXT:   %{{.*}} = icmp ne i32 %[[memptr_val]], 0
 // CHECK-NEXT:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
-// CHECK:        store i32 0, i32* %[[memptr]], align 4
+// CHECK:        store i32 0, ptr %[[memptr]], align 4
 // CHECK:        ret void
 // CHECK:      }
 }
@@ -411,9 +411,9 @@ void polymorphicMemPtrs() {
 bool nullTestDataUnspecified(int Unspecified::*mp) {
   return mp;
 // CHECK: define dso_local noundef zeroext i1 @"?nullTestDataUnspecified@@YA_NPQUnspecified@@H at Z"{{.*}} {
-// CHECK:   %{{.*}} = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
+// CHECK:   %{{.*}} = load { i32, i32, i32 }, ptr %{{.*}}, align 4
 // CHECK:   store { i32, i32, i32 } {{.*}} align 4
-// CHECK:   %[[mp:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
+// CHECK:   %[[mp:.*]] = load { i32, i32, i32 }, ptr %{{.*}}, align 4
 // CHECK:   %[[mp0:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 0
 // CHECK:   %[[cmp0:.*]] = icmp ne i32 %[[mp0]], 0
 // CHECK:   %[[mp1:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 1
@@ -427,17 +427,17 @@ bool nullTestDataUnspecified(int Unspecified::*mp) {
 
 // Pass this large type indirectly.
 // X64-LABEL: define dso_local noundef zeroext i1 @"?nullTestDataUnspecified@@
-// X64:             ({ i32, i32, i32 }* noundef %0)
+// X64:             (ptr noundef %0)
 }
 
 bool nullTestFunctionUnspecified(void (Unspecified::*mp)()) {
   return mp;
 // CHECK: define dso_local noundef zeroext i1 @"?nullTestFunctionUnspecified@@YA_NP8Unspecified@@AEXXZ at Z"{{.*}} {
-// CHECK:   %{{.*}} = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 4
-// CHECK:   store { i8*, i32, i32, i32 } {{.*}} align 4
-// CHECK:   %[[mp:.*]] = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 4
-// CHECK:   %[[mp0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[mp]], 0
-// CHECK:   %[[cmp0:.*]] = icmp ne i8* %[[mp0]], null
+// CHECK:   %{{.*}} = load { ptr, i32, i32, i32 }, ptr %{{.*}}, align 4
+// CHECK:   store { ptr, i32, i32, i32 } {{.*}} align 4
+// CHECK:   %[[mp:.*]] = load { ptr, i32, i32, i32 }, ptr %{{.*}}, align 4
+// CHECK:   %[[mp0:.*]] = extractvalue { ptr, i32, i32, i32 } %[[mp]], 0
+// CHECK:   %[[cmp0:.*]] = icmp ne ptr %[[mp0]], null
 // CHECK:   ret i1 %[[cmp0]]
 // CHECK: }
 }
@@ -447,28 +447,25 @@ int loadDataMemberPointerVirtual(Virtual *o, int Virtual::*memptr) {
 // Test that we can unpack this aggregate member pointer and load the member
 // data pointer.
 // CHECK: define dso_local noundef i32 @"?loadDataMemberPointerVirtual@@YAHPAUVirtual@@PQ1 at H@Z"{{.*}} {
-// CHECK:   %[[o:.*]] = load %{{.*}}*, %{{.*}}** %{{.*}}, align 4
-// CHECK:   %[[memptr:.*]] = load { i32, i32 }, { i32, i32 }* %{{.*}}, align 4
+// CHECK:   %[[o:.*]] = load ptr, ptr %{{.*}}, align 4
+// CHECK:   %[[memptr:.*]] = load { i32, i32 }, ptr %{{.*}}, align 4
 // CHECK:   %[[memptr0:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 0
 // CHECK:   %[[memptr1:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 1
-// CHECK:   %[[v6:.*]] = bitcast %{{.*}}* %[[o]] to i8*
-// CHECK:   %[[vbptr:.*]] = getelementptr inbounds i8, i8* %[[v6]], i32 0
-// CHECK:   %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32**
-// CHECK:   %[[vbtable:.*]] = load i32*, i32** %[[vbptr_a:.*]]
+// CHECK:   %[[vbptr:.*]] = getelementptr inbounds i8, ptr %[[o]], i32 0
+// CHECK:   %[[vbtable:.*]] = load ptr, ptr %[[vbptr_a:.*]]
 // CHECK:   %[[memptr1_shr:.*]] = ashr exact i32 %[[memptr1]], 2
-// CHECK:   %[[v7:.*]] = getelementptr inbounds i32, i32* %[[vbtable]], i32 %[[memptr1_shr]]
-// CHECK:   %[[vbase_offs:.*]] = load i32, i32* %[[v7]]
-// CHECK:   %[[v10:.*]] = getelementptr inbounds i8, i8* %[[vbptr]], i32 %[[vbase_offs]]
-// CHECK:   %[[offset:.*]] = getelementptr inbounds i8, i8* %[[v10]], i32 %[[memptr0]]
-// CHECK:   %[[v11:.*]] = bitcast i8* %[[offset]] to i32*
-// CHECK:   %[[v12:.*]] = load i32, i32* %[[v11]]
+// CHECK:   %[[v7:.*]] = getelementptr inbounds i32, ptr %[[vbtable]], i32 %[[memptr1_shr]]
+// CHECK:   %[[vbase_offs:.*]] = load i32, ptr %[[v7]]
+// CHECK:   %[[v10:.*]] = getelementptr inbounds i8, ptr %[[vbptr]], i32 %[[vbase_offs]]
+// CHECK:   %[[offset:.*]] = getelementptr inbounds i8, ptr %[[v10]], i32 %[[memptr0]]
+// CHECK:   %[[v12:.*]] = load i32, ptr %[[offset]]
 // CHECK:   ret i32 %[[v12]]
 // CHECK: }
 
 // A two-field data memptr on x64 gets coerced to i64 and is passed in a
 // register or memory.
 // X64-LABEL: define dso_local noundef i32 @"?loadDataMemberPointerVirtual@@YAHPEAUVirtual@@PEQ1 at H@Z"
-// X64:             (%struct.Virtual* noundef %o, i64 %memptr.coerce)
+// X64:             (ptr noundef %o, i64 %memptr.coerce)
 }
 
 int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) {
@@ -476,29 +473,26 @@ int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) {
 // Test that we can unpack this aggregate member pointer and load the member
 // data pointer.
 // CHECK: define dso_local noundef i32 @"?loadDataMemberPointerUnspecified@@YAHPAUUnspecified@@PQ1 at H@Z"{{.*}} {
-// CHECK:   %[[o:.*]] = load %{{.*}}*, %{{.*}}** %{{.*}}, align 4
-// CHECK:   %[[memptr:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
+// CHECK:   %[[o:.*]] = load ptr, ptr %{{.*}}, align 4
+// CHECK:   %[[memptr:.*]] = load { i32, i32, i32 }, ptr %{{.*}}, align 4
 // CHECK:   %[[memptr0:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 0
 // CHECK:   %[[memptr1:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 1
 // CHECK:   %[[memptr2:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 2
-// CHECK:   %[[base:.*]] = bitcast %{{.*}}* %[[o]] to i8*
 // CHECK:   %[[is_vbase:.*]] = icmp ne i32 %[[memptr2]], 0
 // CHECK:   br i1 %[[is_vbase]], label %[[vadjust:.*]], label %[[skip:.*]]
 //
 // CHECK: [[vadjust]]
-// CHECK:   %[[vbptr:.*]] = getelementptr inbounds i8, i8* %[[base]], i32 %[[memptr1]]
-// CHECK:   %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32**
-// CHECK:   %[[vbtable:.*]] = load i32*, i32** %[[vbptr_a:.*]]
+// CHECK:   %[[vbptr:.*]] = getelementptr inbounds i8, ptr %[[o]], i32 %[[memptr1]]
+// CHECK:   %[[vbtable:.*]] = load ptr, ptr %[[vbptr_a:.*]]
 // CHECK:   %[[memptr2_shr:.*]] = ashr exact i32 %[[memptr2]], 2
-// CHECK:   %[[v7:.*]] = getelementptr inbounds i32, i32* %[[vbtable]], i32 %[[memptr2_shr]]
-// CHECK:   %[[vbase_offs:.*]] = load i32, i32* %[[v7]]
-// CHECK:   %[[base_adj:.*]] = getelementptr inbounds i8, i8* %[[vbptr]], i32 %[[vbase_offs]]
+// CHECK:   %[[v7:.*]] = getelementptr inbounds i32, ptr %[[vbtable]], i32 %[[memptr2_shr]]
+// CHECK:   %[[vbase_offs:.*]] = load i32, ptr %[[v7]]
+// CHECK:   %[[base_adj:.*]] = getelementptr inbounds i8, ptr %[[vbptr]], i32 %[[vbase_offs]]
 //
 // CHECK: [[skip]]
-// CHECK:   %[[new_base:.*]] = phi i8* [ %[[base]], %{{.*}} ], [ %[[base_adj]], %[[vadjust]] ]
-// CHECK:   %[[offset:.*]] = getelementptr inbounds i8, i8* %[[new_base]], i32 %[[memptr0]]
-// CHECK:   %[[v11:.*]] = bitcast i8* %[[offset]] to i32*
-// CHECK:   %[[v12:.*]] = load i32, i32* %[[v11]]
+// CHECK:   %[[new_base:.*]] = phi ptr [ %[[o]], %{{.*}} ], [ %[[base_adj]], %[[vadjust]] ]
+// CHECK:   %[[offset:.*]] = getelementptr inbounds i8, ptr %[[new_base]], i32 %[[memptr0]]
+// CHECK:   %[[v12:.*]] = load i32, ptr %[[offset]]
 // CHECK:   ret i32 %[[v12]]
 // CHECK: }
 }
@@ -507,25 +501,22 @@ void callMemberPointerSingle(Single *o, void (Single::*memptr)()) {
   (o->*memptr)();
 // Just look for an indirect thiscall.
 // CHECK: define dso_local void @"?callMemberPointerSingle@@{{.*}} {{.*}} {
-// CHECK:   call x86_thiscallcc void %{{.*}}(%{{.*}} %{{.*}})
+// CHECK:   call x86_thiscallcc void %{{.*}}({{.*}} %{{.*}})
 // CHECK:   ret void
 // CHECK: }
 
 // X64-LABEL: define dso_local void @"?callMemberPointerSingle@@
-// X64:           (%struct.Single* noundef %o, i8* %memptr)
-// X64:   bitcast i8* %{{[^ ]*}} to void (%struct.Single*)*
+// X64:           (ptr noundef %o, ptr %memptr)
 // X64:   ret void
 }
 
 void callMemberPointerMultiple(Multiple *o, void (Multiple::*memptr)()) {
   (o->*memptr)();
 // CHECK: define dso_local void @"?callMemberPointerMultiple@@{{.*}} {
-// CHECK:   %[[memptr0:.*]] = extractvalue { i8*, i32 } %{{.*}}, 0
-// CHECK:   %[[memptr1:.*]] = extractvalue { i8*, i32 } %{{.*}}, 1
-// CHECK:   %[[this_adjusted:.*]] = getelementptr inbounds i8, i8* %{{.*}}, i32 %[[memptr1]]
-// CHECK:   %[[this:.*]] = bitcast i8* %[[this_adjusted]] to {{.*}}
-// CHECK:   %[[fptr:.*]] = bitcast i8* %[[memptr0]] to {{.*}}
-// CHECK:   call x86_thiscallcc void %[[fptr]](%{{.*}} %[[this]])
+// CHECK:   %[[memptr0:.*]] = extractvalue { ptr, i32 } %{{.*}}, 0
+// CHECK:   %[[memptr1:.*]] = extractvalue { ptr, i32 } %{{.*}}, 1
+// CHECK:   %[[this_adjusted:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 %[[memptr1]]
+// CHECK:   call x86_thiscallcc void %[[memptr0]]({{.*}} %[[this_adjusted]])
 // CHECK:   ret void
 // CHECK: }
 }
@@ -534,20 +525,17 @@ void callMemberPointerVirtualBase(Virtual *o, void (Virtual::*memptr)()) {
   (o->*memptr)();
 // This shares a lot with virtual data member pointers.
 // CHECK: define dso_local void @"?callMemberPointerVirtualBase@@{{.*}} {
-// CHECK:   %[[memptr0:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 0
-// CHECK:   %[[memptr1:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 1
-// CHECK:   %[[memptr2:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 2
-// CHECK:   %[[vbptr:.*]] = getelementptr inbounds i8, i8* %{{.*}}, i32 0
-// CHECK:   %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32**
-// CHECK:   %[[vbtable:.*]] = load i32*, i32** %[[vbptr_a:.*]]
+// CHECK:   %[[memptr0:.*]] = extractvalue { ptr, i32, i32 } %{{.*}}, 0
+// CHECK:   %[[memptr1:.*]] = extractvalue { ptr, i32, i32 } %{{.*}}, 1
+// CHECK:   %[[memptr2:.*]] = extractvalue { ptr, i32, i32 } %{{.*}}, 2
+// CHECK:   %[[vbptr:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 0
+// CHECK:   %[[vbtable:.*]] = load ptr, ptr %[[vbptr_a:.*]]
 // CHECK:   %[[memptr2_shr:.*]] = ashr exact i32 %[[memptr2]], 2
-// CHECK:   %[[v7:.*]] = getelementptr inbounds i32, i32* %[[vbtable]], i32 %[[memptr2_shr]]
-// CHECK:   %[[vbase_offs:.*]] = load i32, i32* %[[v7]]
-// CHECK:   %[[v10:.*]] = getelementptr inbounds i8, i8* %[[vbptr]], i32 %[[vbase_offs]]
-// CHECK:   %[[this_adjusted:.*]] = getelementptr inbounds i8, i8* %[[v10]], i32 %[[memptr1]]
-// CHECK:   %[[fptr:.*]] = bitcast i8* %[[memptr0]] to void ({{.*}})
-// CHECK:   %[[this:.*]] = bitcast i8* %[[this_adjusted]] to {{.*}}
-// CHECK:   call x86_thiscallcc void %[[fptr]](%{{.*}} %[[this]])
+// CHECK:   %[[v7:.*]] = getelementptr inbounds i32, ptr %[[vbtable]], i32 %[[memptr2_shr]]
+// CHECK:   %[[vbase_offs:.*]] = load i32, ptr %[[v7]]
+// CHECK:   %[[v10:.*]] = getelementptr inbounds i8, ptr %[[vbptr]], i32 %[[vbase_offs]]
+// CHECK:   %[[this_adjusted:.*]] = getelementptr inbounds i8, ptr %[[v10]], i32 %[[memptr1]]
+// CHECK:   call x86_thiscallcc void %[[memptr0]]({{.*}} %[[this_adjusted]])
 // CHECK:   ret void
 // CHECK: }
 }
@@ -563,7 +551,7 @@ bool compareSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
 // CHECK: }
 
 // X64-LABEL: define dso_local noundef zeroext i1 @"?compareSingleFunctionMemptr@@
-// X64:             (i8* %{{[^,]*}}, i8* %{{[^)]*}})
+// X64:             (ptr %{{[^,]*}}, ptr %{{[^)]*}})
 }
 
 bool compareNeqSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
@@ -580,48 +568,48 @@ bool compareNeqSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
 bool unspecFuncMemptrEq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
   return l == r;
 // CHECK: define dso_local noundef zeroext i1 @"?unspecFuncMemptrEq@@YA_NP8Unspecified@@AEXXZ0 at Z"{{.*}} {
-// CHECK:   %[[lhs0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[l:.*]], 0
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r:.*]], 0
-// CHECK:   %[[cmp0:.*]] = icmp eq i8* %[[lhs0]], %{{.*}}
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 1
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 1
+// CHECK:   %[[lhs0:.*]] = extractvalue { ptr, i32, i32, i32 } %[[l:.*]], 0
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[r:.*]], 0
+// CHECK:   %[[cmp0:.*]] = icmp eq ptr %[[lhs0]], %{{.*}}
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[l]], 1
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[r]], 1
 // CHECK:   %[[cmp1:.*]] = icmp eq i32
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 2
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 2
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[l]], 2
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[r]], 2
 // CHECK:   %[[cmp2:.*]] = icmp eq i32
 // CHECK:   %[[res12:.*]] = and i1 %[[cmp1]], %[[cmp2]]
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 3
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 3
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[l]], 3
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[r]], 3
 // CHECK:   %[[cmp3:.*]] = icmp eq i32
 // CHECK:   %[[res123:.*]] = and i1 %[[res12]], %[[cmp3]]
-// CHECK:   %[[iszero:.*]] = icmp eq i8* %[[lhs0]], null
+// CHECK:   %[[iszero:.*]] = icmp eq ptr %[[lhs0]], null
 // CHECK:   %[[bits_or_null:.*]] = or i1 %[[res123]], %[[iszero]]
 // CHECK:   %{{.*}} = and i1 %[[bits_or_null]], %[[cmp0]]
 // CHECK:   ret i1 %{{.*}}
 // CHECK: }
 
 // X64-LABEL: define dso_local noundef zeroext i1 @"?unspecFuncMemptrEq@@
-// X64:             ({ i8*, i32, i32, i32 }* noundef %0, { i8*, i32, i32, i32 }* noundef %1)
+// X64:             (ptr noundef %0, ptr noundef %1)
 }
 
 bool unspecFuncMemptrNeq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
   return l != r;
 // CHECK: define dso_local noundef zeroext i1 @"?unspecFuncMemptrNeq@@YA_NP8Unspecified@@AEXXZ0 at Z"{{.*}} {
-// CHECK:   %[[lhs0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[l:.*]], 0
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r:.*]], 0
-// CHECK:   %[[cmp0:.*]] = icmp ne i8* %[[lhs0]], %{{.*}}
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 1
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 1
+// CHECK:   %[[lhs0:.*]] = extractvalue { ptr, i32, i32, i32 } %[[l:.*]], 0
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[r:.*]], 0
+// CHECK:   %[[cmp0:.*]] = icmp ne ptr %[[lhs0]], %{{.*}}
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[l]], 1
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[r]], 1
 // CHECK:   %[[cmp1:.*]] = icmp ne i32
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 2
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 2
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[l]], 2
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[r]], 2
 // CHECK:   %[[cmp2:.*]] = icmp ne i32
 // CHECK:   %[[res12:.*]] = or i1 %[[cmp1]], %[[cmp2]]
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 3
-// CHECK:   %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 3
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[l]], 3
+// CHECK:   %{{.*}} = extractvalue { ptr, i32, i32, i32 } %[[r]], 3
 // CHECK:   %[[cmp3:.*]] = icmp ne i32
 // CHECK:   %[[res123:.*]] = or i1 %[[res12]], %[[cmp3]]
-// CHECK:   %[[iszero:.*]] = icmp ne i8* %[[lhs0]], null
+// CHECK:   %[[iszero:.*]] = icmp ne ptr %[[lhs0]], null
 // CHECK:   %[[bits_or_null:.*]] = and i1 %[[res123]], %[[iszero]]
 // CHECK:   %{{.*}} = or i1 %[[bits_or_null]], %[[cmp0]]
 // CHECK:   ret i1 %{{.*}}
@@ -646,24 +634,24 @@ bool unspecDataMemptrEq(int Unspecified::*l, int Unspecified::*r) {
 // CHECK: }
 
 // X64-LABEL: define dso_local noundef zeroext i1 @"?unspecDataMemptrEq@@
-// X64:             ({ i32, i32, i32 }* noundef %0, { i32, i32, i32 }* noundef %1)
+// X64:             (ptr noundef %0, ptr noundef %1)
 }
 
 void (Multiple::*convertB2FuncToMultiple(void (B2::*mp)()))() {
   return mp;
 // CHECK: define dso_local i64 @"?convertB2FuncToMultiple@@YAP8Multiple@@AEXXZP8B2@@AEXXZ at Z"{{.*}} {
 // CHECK:   store
-// CHECK:   %[[mp:.*]] = load i8*, i8** %{{.*}}, align 4
-// CHECK:   icmp ne i8* %[[mp]], null
+// CHECK:   %[[mp:.*]] = load ptr, ptr %{{.*}}, align 4
+// CHECK:   icmp ne ptr %[[mp]], null
 // CHECK:   br i1 %{{.*}} label %{{.*}}, label %{{.*}}
 //
 //        memptr.convert:                                   ; preds = %entry
-// CHECK:   insertvalue { i8*, i32 } undef, i8* %[[mp]], 0
-// CHECK:   insertvalue { i8*, i32 } %{{.*}}, i32 4, 1
+// CHECK:   insertvalue { ptr, i32 } undef, ptr %[[mp]], 0
+// CHECK:   insertvalue { ptr, i32 } %{{.*}}, i32 4, 1
 // CHECK:   br label
 //
 //        memptr.converted:                                 ; preds = %memptr.convert, %entry
-// CHECK:   phi { i8*, i32 } [ zeroinitializer, %{{.*}} ], [ {{.*}} ]
+// CHECK:   phi { ptr, i32 } [ zeroinitializer, %{{.*}} ], [ {{.*}} ]
 // CHECK: }
 }
 
@@ -671,23 +659,23 @@ void (B2::*convertMultipleFuncToB2(void (Multiple::*mp)()))() {
 // FIXME: cl emits warning C4407 on this code because of the representation
 // change.  We might want to do the same.
   return static_cast<void (B2::*)()>(mp);
-// FIXME: We should return i8* instead of i32 here.  The ptrtoint cast prevents
+// FIXME: We should return ptr instead of i32 here.  The ptrtoint cast prevents
 // LLVM from optimizing away the branch.  This is likely a bug in
 // lib/CodeGen/TargetInfo.cpp with how we classify memptr types for returns.
 //
 // CHECK: define dso_local i32 @"?convertMultipleFuncToB2@@YAP8B2@@AEXXZP8Multiple@@AEXXZ at Z"{{.*}} {
 // CHECK:   store
-// CHECK:   %[[src:.*]] = load { i8*, i32 }, { i8*, i32 }* %{{.*}}, align 4
-// CHECK:   extractvalue { i8*, i32 } %[[src]], 0
-// CHECK:   icmp ne i8* %{{.*}}, null
+// CHECK:   %[[src:.*]] = load { ptr, i32 }, ptr %{{.*}}, align 4
+// CHECK:   extractvalue { ptr, i32 } %[[src]], 0
+// CHECK:   icmp ne ptr %{{.*}}, null
 // CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
 //
 //        memptr.convert:                                   ; preds = %entry
-// CHECK:   %[[fp:.*]] = extractvalue { i8*, i32 } %[[src]], 0
+// CHECK:   %[[fp:.*]] = extractvalue { ptr, i32 } %[[src]], 0
 // CHECK:   br label
 //
 //        memptr.converted:                                 ; preds = %memptr.convert, %entry
-// CHECK:   phi i8* [ null, %{{.*}} ], [ %[[fp]], %{{.*}} ]
+// CHECK:   phi ptr [ null, %{{.*}} ], [ %[[fp]], %{{.*}} ]
 // CHECK: }
 }
 
@@ -702,27 +690,27 @@ void (D::*convertCToD(void (C::*mp)()))() {
   return mp;
 // CHECK: define dso_local void @"?convertCToD at Test1@@YAP8D at 1@AEXXZP8C at 1@AEXXZ at Z"{{.*}} {
 // CHECK:   store
-// CHECK:   load { i8*, i32, i32 }, { i8*, i32, i32 }* %{{.*}}, align 4
-// CHECK:   extractvalue { i8*, i32, i32 } %{{.*}}, 0
-// CHECK:   icmp ne i8* %{{.*}}, null
+// CHECK:   load { ptr, i32, i32 }, ptr %{{.*}}, align 4
+// CHECK:   extractvalue { ptr, i32, i32 } %{{.*}}, 0
+// CHECK:   icmp ne ptr %{{.*}}, null
 // CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
 //
 //        memptr.convert:                                   ; preds = %entry
-// CHECK:   extractvalue { i8*, i32, i32 } %{{.*}}, 0
-// CHECK:   %[[nvoff:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 1
-// CHECK:   %[[vbidx:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 2
+// CHECK:   extractvalue { ptr, i32, i32 } %{{.*}}, 0
+// CHECK:   %[[nvoff:.*]] = extractvalue { ptr, i32, i32 } %{{.*}}, 1
+// CHECK:   %[[vbidx:.*]] = extractvalue { ptr, i32, i32 } %{{.*}}, 2
 // CHECK:   %[[is_nvbase:.*]] = icmp eq i32 %[[vbidx]], 0
 // CHECK:   %[[nv_disp:.*]] = add nsw i32 %[[nvoff]], 4
 // CHECK:   %[[nv_adj:.*]] = select i1 %[[is_nvbase]], i32 %[[nv_disp]], i32 0
 // CHECK:   %[[dst_adj:.*]] = select i1 %[[is_nvbase]], i32 4, i32 0
 // CHECK:   %[[adj:.*]] = sub nsw i32 %[[nv_adj]], %[[dst_adj]]
-// CHECK:   insertvalue { i8*, i32, i32 } undef, i8* {{.*}}, 0
-// CHECK:   insertvalue { i8*, i32, i32 } {{.*}}, i32 %[[adj]], 1
-// CHECK:   insertvalue { i8*, i32, i32 } {{.*}}, i32 {{.*}}, 2
+// CHECK:   insertvalue { ptr, i32, i32 } undef, ptr {{.*}}, 0
+// CHECK:   insertvalue { ptr, i32, i32 } {{.*}}, i32 %[[adj]], 1
+// CHECK:   insertvalue { ptr, i32, i32 } {{.*}}, i32 {{.*}}, 2
 // CHECK:   br label
 //
 //        memptr.converted:                                 ; preds = %memptr.convert, %entry
-// CHECK:   phi { i8*, i32, i32 } [ { i8* null, i32 0, i32 -1 }, {{.*}} ], [ {{.*}} ]
+// CHECK:   phi { ptr, i32, i32 } [ { ptr null, i32 0, i32 -1 }, {{.*}} ], [ {{.*}} ]
 // CHECK: }
 }
 
@@ -749,7 +737,7 @@ int A::*reinterpret(int B::*mp) {
 int A::*reinterpret(int C::*mp) {
   return reinterpret_cast<int A::*>(mp);
 // CHECK: define dso_local i32 @"?reinterpret at Test2@@YAPQA at 1@HPQC at 1@H at Z"{{.*}}  {
-// CHECK:   %[[mp:.*]] = load i32, i32*
+// CHECK:   %[[mp:.*]] = load i32, ptr
 // CHECK:   %[[cmp:.*]] = icmp ne i32 %[[mp]], 0
 // CHECK:   select i1 %[[cmp]], i32 %[[mp]], i32 -1
 // CHECK: }
@@ -758,7 +746,7 @@ int A::*reinterpret(int C::*mp) {
 }
 
 namespace Test3 {
-// Make sure we cast 'this' to i8* before using GEP.
+// Make sure we cast 'this' to ptr before using GEP.
 
 struct A {
   int a;
@@ -767,11 +755,10 @@ struct A {
 
 int *load_data(A *a, int A::*mp) {
   return &(a->*mp);
-// CHECK-LABEL: define dso_local noundef i32* @"?load_data at Test3@@YAPAHPAUA at 1@PQ21 at H@Z"{{.*}}  {
-// CHECK:    %[[a:.*]] = load %"struct.Test3::A"*, %"struct.Test3::A"** %{{.*}}, align 4
-// CHECK:    %[[mp:.*]] = load i32, i32* %{{.*}}, align 4
-// CHECK:    %[[a_i8:.*]] = bitcast %"struct.Test3::A"* %[[a]] to i8*
-// CHECK:    getelementptr inbounds i8, i8* %[[a_i8]], i32 %[[mp]]
+// CHECK-LABEL: define dso_local noundef ptr @"?load_data at Test3@@YAPAHPAUA at 1@PQ21 at H@Z"{{.*}}  {
+// CHECK:    %[[a:.*]] = load ptr, ptr %{{.*}}, align 4
+// CHECK:    %[[mp:.*]] = load i32, ptr %{{.*}}, align 4
+// CHECK:    getelementptr inbounds i8, ptr %[[a]], i32 %[[mp]]
 // CHECK: }
 }
 
@@ -787,15 +774,15 @@ void (C::*getmp())() {
   return &C::g;
 }
 // CHECK-LABEL: define dso_local i64 @"?getmp at Test4@@YAP8C at 1@AEXXZXZ"()
-// CHECK: store { i8*, i32 } { i8* bitcast (void (%"struct.Test4::C"*, ...)* @"??_9C at Test4@@$BA at AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}}
+// CHECK: store { ptr, i32 } { ptr @"??_9C at Test4@@$BA at AE", i32 4 }, ptr %{{.*}}
 //
 
-// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C at Test4@@$BA at AE"(%"struct.Test4::C"* noundef %this, ...) {{.*}} comdat
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C at Test4@@$BA at AE"(ptr noundef %this, ...) {{.*}} comdat
 // CHECK-NOT:  getelementptr
-// CHECK:  load void (%"struct.Test4::C"*, ...)**, void (%"struct.Test4::C"*, ...)*** %{{.*}}
-// CHECK:  getelementptr inbounds void (%"struct.Test4::C"*, ...)*, void (%"struct.Test4::C"*, ...)** %{{.*}}, i64 0
+// CHECK:  load ptr, ptr %{{.*}}
+// CHECK:  getelementptr inbounds ptr, ptr %{{.*}}, i64 0
 // CHECK-NOT:  getelementptr
-// CHECK:  musttail call x86_thiscallcc void (%"struct.Test4::C"*, ...) %
+// CHECK:  musttail call x86_thiscallcc void (ptr, ...) %
 
 }
 
@@ -807,7 +794,7 @@ struct A {
 struct B : public A {};
 void test() { void (B::*a)() = &B::f; }
 // CHECK-LABEL: define dso_local void @"?test at pr20007@@YAXXZ"
-// CHECK: store i8* bitcast (void (%"struct.pr20007::A"*)* @"?f at A@pr20007@@QAEXXZ" to i8*)
+// CHECK: store ptr @"?f at A@pr20007@@QAEXXZ"
 }
 
 namespace pr20007_kw {
@@ -819,7 +806,7 @@ struct __single_inheritance B;
 struct B : public A {};
 void test() { void (B::*a)() = &B::f; }
 // CHECK-LABEL: define dso_local void @"?test at pr20007_kw@@YAXXZ"
-// CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"?f at A@pr20007_kw@@QAEXXZ" to i8*)
+// CHECK: store ptr @"?f at A@pr20007_kw@@QAEXXZ"
 }
 
 namespace pr20007_pragma {
@@ -894,7 +881,7 @@ struct D : A, C {};
 typedef void (D::*DMemPtrTy)();
 
 // CHECK-LABEL: define dso_local void @"?get_memptr at pr23878@@YAP8D at 1@AEXXZXZ"
-// CHECK: @"??_9C at pr23878@@$BA at AE" to i8*), i32 0, i32 4
+// CHECK: @"??_9C at pr23878@@$BA at AE", i32 0, i32 4
 DMemPtrTy get_memptr() { return &D::f; }
 }
 
@@ -910,7 +897,7 @@ class CA : public C {
 
 // CHECK-LABEL: foo_fun
 void foo_fun() {
-  // CHECK: store i8* bitcast (void (%class.CA*)* @"?OnHelp at CA@@QAEXXZ" to i8*), i8**
+  // CHECK: store ptr @"?OnHelp at CA@@QAEXXZ", ptr
   f func = (f)&CA::OnHelp;
 }
 namespace PR24703 {

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
index c3a9743dbe804..f9d6473cb6c62 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -no-opaque-pointers -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
 
 struct Left {
   virtual void left();
@@ -20,110 +20,93 @@ extern "C" void foo(void *);
 
 void call_left_no_override(ChildNoOverride *child) {
 // CHECK-LABEL: define dso_local void @"?call_left_no_override
-// CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
+// CHECK: %[[CHILD:.*]] = load ptr
 
   child->left();
 // Only need to cast 'this' to Left*.
-// CHECK: %[[LEFT:.*]] = bitcast %struct.ChildNoOverride* %[[CHILD]] to %struct.Left*
-// CHECK: %[[VFPTR:.*]] = bitcast %struct.Left* %[[LEFT]] to void (%struct.Left*)***
-// CHECK: %[[VFTABLE:.*]] = load void (%struct.Left*)**, void (%struct.Left*)*** %[[VFPTR]]
-// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.Left*)*, void (%struct.Left*)** %[[VFTABLE]], i64 0
-// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.Left*)*, void (%struct.Left*)** %[[VFUN]]
-// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.Left* {{[^,]*}} %[[LEFT]])
+// CHECK: %[[VFTABLE:.*]] = load ptr, ptr %[[CHILD]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds ptr, ptr %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load ptr, ptr %[[VFUN]]
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](ptr {{[^,]*}} %[[CHILD]])
 // CHECK: ret
 }
 
 void ChildOverride::left() {
 // CHECK-LABEL: define dso_local x86_thiscallcc void @"?left at ChildOverride@@UAEXXZ"
-// CHECK-SAME: (%struct.ChildOverride* {{[^,]*}} %[[THIS:.*]])
+// CHECK-SAME: (ptr {{[^,]*}} %[[THIS:.*]])
 //
 // No need to adjust 'this' as the ChildOverride's layout begins with Left.
-// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.ChildOverride*, align 4
-// CHECK: store %struct.ChildOverride* %[[THIS]], %struct.ChildOverride** %[[THIS_ADDR]], align 4
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 4
+// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 4
 
   foo(this);
-// CHECK: %[[THIS:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_ADDR]]
-// CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
-// CHECK: call void @foo(i8* noundef %[[THIS_i8]])
+// CHECK: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: call void @foo(ptr noundef %[[THIS]])
 // CHECK: ret
 }
 
 void call_left_override(ChildOverride *child) {
 // CHECK-LABEL: define dso_local void @"?call_left_override
-// CHECK: %[[CHILD:.*]] = load %struct.ChildOverride
+// CHECK: %[[CHILD:.*]] = load ptr
 
   child->left();
-// CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to void (%struct.ChildOverride*)***
-// CHECK: %[[VFTABLE:.*]] = load void (%struct.ChildOverride*)**, void (%struct.ChildOverride*)*** %[[VFPTR]]
-// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.ChildOverride*)*, void (%struct.ChildOverride*)** %[[VFTABLE]], i64 0
-// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.ChildOverride*)*, void (%struct.ChildOverride*)** %[[VFUN]]
+// CHECK: %[[VFTABLE:.*]] = load ptr, ptr %[[CHILD]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds ptr, ptr %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load ptr, ptr %[[VFUN]]
 //
-// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.ChildOverride* {{[^,]*}} %[[CHILD]])
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](ptr {{[^,]*}} %[[CHILD]])
 // CHECK: ret
 }
 
 void call_right_no_override(ChildNoOverride *child) {
 // CHECK-LABEL: define dso_local void @"?call_right_no_override
-// CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
+// CHECK: %[[CHILD:.*]] = load ptr
 
   child->right();
 // When calling a right base's virtual method, one needs to adjust 'this' at
 // the caller site.
 //
-// CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildNoOverride* %[[CHILD]] to i8*
-// CHECK: %[[RIGHT_i8:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
-// CHECK: %[[RIGHT:.*]] = bitcast i8* %[[RIGHT_i8]] to %struct.Right*
+// CHECK: %[[RIGHT_i8:.*]] = getelementptr inbounds i8, ptr %[[CHILD]], i32 4
 //
-// CHECK: %[[VFPTR:.*]] = bitcast %struct.Right* %[[RIGHT]] to void (%struct.Right*)***
-// CHECK: %[[VFTABLE:.*]] = load void (%struct.Right*)**, void (%struct.Right*)*** %[[VFPTR]]
-// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.Right*)*, void (%struct.Right*)** %[[VFTABLE]], i64 0
-// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.Right*)*, void (%struct.Right*)** %[[VFUN]]
-// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.Right* {{[^,]*}} %[[RIGHT]])
+// CHECK: %[[VFTABLE:.*]] = load ptr, ptr %[[RIGHT_i8]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds ptr, ptr %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load ptr, ptr %[[VFUN]]
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](ptr {{[^,]*}} %[[RIGHT_i8]])
 // CHECK: ret
 }
 
 void ChildOverride::right() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"?right at ChildOverride@@UAEXXZ"(i8*
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?right at ChildOverride@@UAEXXZ"(ptr
 //
 // ChildOverride::right gets 'this' cast to Right* in ECX (i.e. this+4) so we
 // need to adjust 'this' before use.
 //
-// CHECK: %[[THIS_STORE:.*]] = alloca %struct.ChildOverride*, align 4
-// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.ChildOverride*, align 4
-// CHECK: %[[COERCE_VAL:.*]] = bitcast i8* %[[ECX:.*]] to %struct.ChildOverride*
-// CHECK: store %struct.ChildOverride* %[[COERCE_VAL]], %struct.ChildOverride** %[[THIS_STORE]], align 4
-// CHECK: %[[THIS_INIT:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_STORE]], align 4
-// CHECK: store %struct.ChildOverride* %[[THIS_INIT]], %struct.ChildOverride** %[[THIS_ADDR]], align 4
-// CHECK: %[[THIS_RELOAD:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_ADDR]]
-// CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS_RELOAD]] to i8*
-// CHECK: %[[THIS_ADJUSTED:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 -4
-// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJUSTED]] to %struct.ChildOverride*
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 4
+// CHECK: store ptr %[[ECX:.*]], ptr %[[THIS_ADDR]], align 4
+// CHECK: %[[THIS_RELOAD:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[THIS_ADJUSTED:.*]] = getelementptr inbounds i8, ptr %[[THIS_RELOAD]], i32 -4
 
   foo(this);
-// CHECK: %[[THIS_PARAM:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
-// CHECK: call void @foo(i8* noundef %[[THIS_PARAM]])
+// CHECK: call void @foo(ptr noundef %[[THIS_ADJUSTED]])
 // CHECK: ret
 }
 
 void call_right_override(ChildOverride *child) {
 // CHECK-LABEL: define dso_local void @"?call_right_override
-// CHECK: %[[CHILD:.*]] = load %struct.ChildOverride
+// CHECK: %[[CHILD:.*]] = load ptr
 
   child->right();
 // When calling a right child's virtual method, one needs to adjust 'this' at
 // the caller site.
 //
-// CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to i8*
-// CHECK: %[[RIGHT:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
+// CHECK: %[[RIGHT:.*]] = getelementptr inbounds i8, ptr %[[CHILD]], i32 4
 //
-// CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to i8*
-// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
-// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to void (i8*)***
-// CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]]
-// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 0
-// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
+// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, ptr %[[CHILD]], i32 4
+// CHECK: %[[VFTABLE:.*]] = load ptr, ptr %[[VFPTR_i8]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds ptr, ptr %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load ptr, ptr %[[VFUN]]
 //
-// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* noundef %[[RIGHT]])
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](ptr noundef %[[RIGHT]])
 // CHECK: ret
 }
 
@@ -132,22 +115,15 @@ struct GrandchildOverride : ChildOverride {
 };
 
 void GrandchildOverride::right() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"?right at GrandchildOverride@@UAEXXZ"(i8*
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?right at GrandchildOverride@@UAEXXZ"(ptr
 //
-// CHECK: %[[THIS_STORE:.*]] = alloca %struct.GrandchildOverride*, align 4
-// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.GrandchildOverride*, align 4
-// CHECK: %[[COERCE_VAL:.*]] = bitcast i8* %[[ECX:.*]] to %struct.GrandchildOverride*
-// CHECK: store %struct.GrandchildOverride* %[[COERCE_VAL]], %struct.GrandchildOverride** %[[THIS_STORE]], align 4
-// CHECK: %[[THIS_INIT:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** %[[THIS_STORE]], align 4
-// CHECK: store %struct.GrandchildOverride* %[[THIS_INIT]], %struct.GrandchildOverride** %[[THIS_ADDR]], align 4
-// CHECK: %[[THIS_RELOAD:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** %[[THIS_ADDR]]
-// CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS_RELOAD]] to i8*
-// CHECK: %[[THIS_ADJUSTED:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 -4
-// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJUSTED]] to %struct.GrandchildOverride*
+// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 4
+// CHECK: store ptr %[[ECX:.*]], ptr %[[THIS_ADDR]], align 4
+// CHECK: %[[THIS_RELOAD:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK: %[[THIS_ADJUSTED:.*]] = getelementptr inbounds i8, ptr %[[THIS_RELOAD]], i32 -4
 
   foo(this);
-// CHECK: %[[THIS_PARAM:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8*
-// CHECK: call void @foo(i8* noundef %[[THIS_PARAM]])
+// CHECK: call void @foo(ptr noundef %[[THIS_ADJUSTED]])
 // CHECK: ret
 }
 
@@ -160,35 +136,29 @@ void emit_ctors() {
   Left l;
   // CHECK-LABEL: define {{.*}} @"??0Left@@QAE at XZ"
   // CHECK-NOT: getelementptr
-  // CHECK:   store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7Left@@6B@" to i32 (...)**)
+  // CHECK:   store ptr @"??_7Left@@6B@"
   // CHECK: ret
 
   Right r;
   // CHECK-LABEL: define {{.*}} @"??0Right@@QAE at XZ"
   // CHECK-NOT: getelementptr
-  // CHECK:   store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7Right@@6B@" to i32 (...)**)
+  // CHECK:   store ptr @"??_7Right@@6B@"
   // CHECK: ret
 
   ChildOverride co;
   // CHECK-LABEL: define {{.*}} @"??0ChildOverride@@QAE at XZ"
-  // CHECK:   %[[THIS:.*]] = load %struct.ChildOverride*, %struct.ChildOverride**
-  // CHECK:   %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i32 (...)***
-  // CHECK:   store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
-  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
-  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 4
-  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
-  // CHECK:   store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+  // CHECK:   %[[THIS:.*]] = load ptr, ptr
+  // CHECK:   store ptr @"??_7ChildOverride@@6BLeft@@@", ptr %[[THIS]]
+  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i32 4
+  // CHECK:   store ptr @"??_7ChildOverride@@6BRight@@@", ptr %[[VFPTR_i8]]
   // CHECK: ret
 
   GrandchildOverride gc;
   // CHECK-LABEL: define {{.*}} @"??0GrandchildOverride@@QAE at XZ"
-  // CHECK:   %[[THIS:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride**
-  // CHECK:   %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i32 (...)***
-  // CHECK:   store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
-  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8*
-  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 4
-  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
-  // CHECK:   store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+  // CHECK:   %[[THIS:.*]] = load ptr, ptr
+  // CHECK:   store ptr @"??_7GrandchildOverride@@6BLeft@@@", ptr %[[THIS]]
+  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i32 4
+  // CHECK:   store ptr @"??_7GrandchildOverride@@6BRight@@@", ptr %[[VFPTR_i8]]
   // CHECK: ret
 }
 
@@ -204,8 +174,8 @@ struct AsymmetricChild : LeftWithNonVirtualDtor, Right {
 void call_asymmetric_child_complete_dtor() {
   // CHECK-LABEL: define dso_local void @"?call_asymmetric_child_complete_dtor@@YAXXZ"
   AsymmetricChild obj;
-  // CHECK: call x86_thiscallcc noundef %struct.AsymmetricChild* @"??0AsymmetricChild@@QAE at XZ"(%struct.AsymmetricChild* {{[^,]*}} %[[OBJ:.*]])
+  // CHECK: call x86_thiscallcc noundef ptr @"??0AsymmetricChild@@QAE at XZ"(ptr {{[^,]*}} %[[OBJ:.*]])
   // CHECK-NOT: getelementptr
-  // CHECK: call x86_thiscallcc void @"??1AsymmetricChild@@UAE at XZ"(%struct.AsymmetricChild* {{[^,]*}} %[[OBJ]])
+  // CHECK: call x86_thiscallcc void @"??1AsymmetricChild@@UAE at XZ"(ptr {{[^,]*}} %[[OBJ]])
   // CHECK: ret
 }

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index 08c9faf6fd774..9d737e3979ddd 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -1,8 +1,8 @@
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 --check-prefix WIN %s
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=thumb-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA --check-prefix WIN %s
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 --check-prefix WIN %s
-// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=aarch64-windows-msvc -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA64 --check-prefix WIN %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 --check-prefix WIN %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=thumb-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA --check-prefix WIN %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 --check-prefix WIN %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=aarch64-windows-msvc -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA64 --check-prefix WIN %s
 
 struct Empty {};
 
@@ -79,8 +79,7 @@ struct SmallWithSmallWithPrivate {
 };
 
 // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
-// WIN32:       (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
-// WIN32:           i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca(<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor, i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>)
+// WIN32:       (ptr inalloca(<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor, i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>)
 void take_bools_and_chars(char a, char b, SmallWithDtor c, char d, bool e, int f, bool g);
 void call_bools_and_chars() {
   take_bools_and_chars('A', 'B', SmallWithDtor(), 'D', true, 13, false);
@@ -88,58 +87,58 @@ void call_bools_and_chars() {
 
 // Returning structs that fit into a register.
 Small small_return() { return Small(); }
-// LINUX-LABEL: define{{.*}} void @_Z12small_returnv(%struct.Small* noalias sret(%struct.Small) align 4 %agg.result)
+// LINUX-LABEL: define{{.*}} void @_Z12small_returnv(ptr noalias sret(%struct.Small) align 4 %agg.result)
 // WIN32: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
 // WIN64: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
 // WOA64: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
 
 Medium medium_return() { return Medium(); }
-// LINUX-LABEL: define{{.*}} void @_Z13medium_returnv(%struct.Medium* noalias sret(%struct.Medium) align 4 %agg.result)
+// LINUX-LABEL: define{{.*}} void @_Z13medium_returnv(ptr noalias sret(%struct.Medium) align 4 %agg.result)
 // WIN32: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"()
 // WIN64: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"()
 // WOA64: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"()
 
 // Returning structs that fit into a register but are not POD.
 SmallCpp11NotCpp03Pod small_non_pod_return() { return SmallCpp11NotCpp03Pod(); }
-// LINUX-LABEL: define{{.*}} void @_Z20small_non_pod_returnv(%struct.SmallCpp11NotCpp03Pod* noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)
-// WIN32: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)
-// WIN64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)
-// WOA64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* inreg noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)
+// LINUX-LABEL: define{{.*}} void @_Z20small_non_pod_returnv(ptr noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)
+// WIN32: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(ptr noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)
+// WIN64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(ptr noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)
+// WOA64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(ptr inreg noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)
 
 SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); }
-// LINUX-LABEL: define{{.*}} void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
-// WIN32: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
-// WIN64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
+// LINUX-LABEL: define{{.*}} void @_Z22small_with_ctor_returnv(ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
+// WIN32: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
+// WIN64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
 // FIXME: The 'sret' mark here doesn't seem to be enough to convince LLVM to
 // preserve the hidden sret pointer in R0 across the function.
-// WOA: define dso_local arm_aapcs_vfpcc void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
-// WOA64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* inreg noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
+// WOA64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr inreg noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
 
 SmallWithDtor small_with_dtor_return() { return SmallWithDtor(); }
-// LINUX-LABEL: define{{.*}} void @_Z22small_with_dtor_returnv(%struct.SmallWithDtor* noalias sret(%struct.SmallWithDtor) align 4 %agg.result)
-// WIN32: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(%struct.SmallWithDtor* noalias sret(%struct.SmallWithDtor) align 4 %agg.result)
-// WIN64: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(%struct.SmallWithDtor* noalias sret(%struct.SmallWithDtor) align 4 %agg.result)
-// WOA64: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(%struct.SmallWithDtor* inreg noalias sret(%struct.SmallWithDtor) align 4 %agg.result)
+// LINUX-LABEL: define{{.*}} void @_Z22small_with_dtor_returnv(ptr noalias sret(%struct.SmallWithDtor) align 4 %agg.result)
+// WIN32: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(ptr noalias sret(%struct.SmallWithDtor) align 4 %agg.result)
+// WIN64: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(ptr noalias sret(%struct.SmallWithDtor) align 4 %agg.result)
+// WOA64: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(ptr inreg noalias sret(%struct.SmallWithDtor) align 4 %agg.result)
 
 SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); }
-// LINUX-LABEL: define{{.*}} void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret(%struct.SmallWithVftable) align 4 %agg.result)
-// WIN32: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret(%struct.SmallWithVftable) align 4 %agg.result)
-// WIN64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret(%struct.SmallWithVftable) align 8 %agg.result)
-// WOA64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* inreg noalias sret(%struct.SmallWithVftable) align 8 %agg.result)
+// LINUX-LABEL: define{{.*}} void @_Z25small_with_vftable_returnv(ptr noalias sret(%struct.SmallWithVftable) align 4 %agg.result)
+// WIN32: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(ptr noalias sret(%struct.SmallWithVftable) align 4 %agg.result)
+// WIN64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(ptr noalias sret(%struct.SmallWithVftable) align 8 %agg.result)
+// WOA64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(ptr inreg noalias sret(%struct.SmallWithVftable) align 8 %agg.result)
 
 MediumWithCopyCtor medium_with_copy_ctor_return() { return MediumWithCopyCtor(); }
-// LINUX-LABEL: define{{.*}} void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
-// WIN32: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
-// WIN64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
-// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
-// WOA64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* inreg noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
+// LINUX-LABEL: define{{.*}} void @_Z28medium_with_copy_ctor_returnv(ptr noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
+// WIN32: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
+// WIN64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
+// WOA64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr inreg noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
 
 // Returning a large struct that doesn't fit into a register.
 Big big_return() { return Big(); }
-// LINUX-LABEL: define{{.*}} void @_Z10big_returnv(%struct.Big* noalias sret(%struct.Big) align 4 %agg.result)
-// WIN32: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret(%struct.Big) align 4 %agg.result)
-// WIN64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret(%struct.Big) align 4 %agg.result)
-// WOA64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret(%struct.Big) align 4 %agg.result)
+// LINUX-LABEL: define{{.*}} void @_Z10big_returnv(ptr noalias sret(%struct.Big) align 4 %agg.result)
+// WIN32: define dso_local void @"?big_return@@YA?AUBig@@XZ"(ptr noalias sret(%struct.Big) align 4 %agg.result)
+// WIN64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(ptr noalias sret(%struct.Big) align 4 %agg.result)
+// WOA64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(ptr noalias sret(%struct.Big) align 4 %agg.result)
 
 
 void small_arg(Small s) {}
@@ -155,50 +154,50 @@ void medium_arg(Medium s) {}
 // WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg@@YAXUMedium@@@Z"([2 x i32] %s.coerce)
 
 void base_no_byval_arg(BaseNoByval s) {}
-// LINUX-LABEL: define{{.*}} void @_Z17base_no_byval_arg11BaseNoByval(%struct.BaseNoByval* noundef byval(%struct.BaseNoByval) align 4 %s)
+// LINUX-LABEL: define{{.*}} void @_Z17base_no_byval_arg11BaseNoByval(ptr noundef byval(%struct.BaseNoByval) align 4 %s)
 // WIN32: define dso_local void @"?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i32 %s.0, i32 %s.1)
 // WIN64: define dso_local void @"?base_no_byval_arg@@YAXUBaseNoByval@@@Z"(i64 %s.coerce)
 // WOA: define dso_local arm_aapcs_vfpcc void @"?base_no_byval_arg@@YAXUBaseNoByval@@@Z"([2 x i32] %s.coerce)
 
 void small_arg_with_ctor(SmallWithCtor s) {}
-// LINUX-LABEL: define{{.*}} void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* noundef byval(%struct.SmallWithCtor) align 4 %s)
+// LINUX-LABEL: define{{.*}} void @_Z19small_arg_with_ctor13SmallWithCtor(ptr noundef byval(%struct.SmallWithCtor) align 4 %s)
 // WIN32: define dso_local void @"?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.0)
 // WIN64: define dso_local void @"?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce)
 // WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"([1 x i32] %s.coerce)
 
 // FIXME: We could coerce to a series of i32s here if we wanted to.
 void multibyte_arg(Multibyte s) {}
-// LINUX-LABEL: define{{.*}} void @_Z13multibyte_arg9Multibyte(%struct.Multibyte* noundef byval(%struct.Multibyte) align 4 %s)
-// WIN32: define dso_local void @"?multibyte_arg@@YAXUMultibyte@@@Z"(%struct.Multibyte* noundef byval(%struct.Multibyte) align 4 %s)
+// LINUX-LABEL: define{{.*}} void @_Z13multibyte_arg9Multibyte(ptr noundef byval(%struct.Multibyte) align 4 %s)
+// WIN32: define dso_local void @"?multibyte_arg@@YAXUMultibyte@@@Z"(ptr noundef byval(%struct.Multibyte) align 4 %s)
 // WIN64: define dso_local void @"?multibyte_arg@@YAXUMultibyte@@@Z"(i32 %s.coerce)
 // WOA: define dso_local arm_aapcs_vfpcc void @"?multibyte_arg@@YAXUMultibyte@@@Z"([1 x i32] %s.coerce)
 
 void packed_arg(Packed s) {}
-// LINUX-LABEL: define{{.*}} void @_Z10packed_arg6Packed(%struct.Packed* noundef byval(%struct.Packed) align 4 %s)
-// WIN32: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* noundef byval(%struct.Packed) align 4 %s)
-// WIN64: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* noundef %s)
+// LINUX-LABEL: define{{.*}} void @_Z10packed_arg6Packed(ptr noundef byval(%struct.Packed) align 4 %s)
+// WIN32: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(ptr noundef byval(%struct.Packed) align 4 %s)
+// WIN64: define dso_local void @"?packed_arg@@YAXUPacked@@@Z"(ptr noundef %s)
 
 // Test that dtors are invoked in the callee.
 void small_arg_with_dtor(SmallWithDtor s) {}
-// WIN32: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca(<{ %struct.SmallWithDtor }>) %0) {{.*}} {
+// WIN32: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(ptr inalloca(<{ %struct.SmallWithDtor }>) %0) {{.*}} {
 // WIN32:   call x86_thiscallcc void @"??1SmallWithDtor@@QAE at XZ"
 // WIN32: }
 // WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
 // WIN64:   call void @"??1SmallWithDtor@@QEAA at XZ"
 // WIN64: }
 // WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA at XZ"(%struct.SmallWithDtor* {{[^,]*}} %s)
+// WOA64:   call void @"??1SmallWithDtor@@QEAA at XZ"(ptr {{[^,]*}} %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
-// WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* noundef %s) {{.*}} {
-// WOA:   call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA at XZ"(%struct.SmallWithDtor* {{[^,]*}} %s)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(ptr noundef %s) {{.*}} {
+// WOA:   call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA at XZ"(ptr {{[^,]*}} %s)
 // WOA: }
 
 
 // Test that the eligible non-aggregate is passed directly, but returned
 // indirectly on ARM64 Windows.
-// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret(%struct.SmallWithPrivate) align 4 %agg.result, i64 %s.coerce) {{.*}} {
+// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(ptr inreg noalias sret(%struct.SmallWithPrivate) align 4 %agg.result, i64 %s.coerce) {{.*}} {
 SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }
 
 // WOA64: define dso_local i32 @"?small_arg_with_small_struct_with_private_member@@YA?AUSmallWithSmallWithPrivate@@U1@@Z"(i64 %s.coerce) {{.*}} {
@@ -209,19 +208,19 @@ void call_small_arg_with_dtor() {
   small_arg_with_dtor(SmallWithDtor());
 }
 // WIN64-LABEL: define dso_local void @"?call_small_arg_with_dtor@@YAXXZ"()
-// WIN64:   call noundef %struct.SmallWithDtor* @"??0SmallWithDtor@@QEAA at XZ"
+// WIN64:   call noundef ptr @"??0SmallWithDtor@@QEAA at XZ"
 // WIN64:   call void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %{{.*}})
 // WIN64:   ret void
 
 // Test that references aren't destroyed in the callee.
 void ref_small_arg_with_dtor(const SmallWithDtor &s) { }
-// WIN32: define dso_local void @"?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %s) {{.*}} {
+// WIN32: define dso_local void @"?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %s) {{.*}} {
 // WIN32-NOT:   call x86_thiscallcc void @"??1SmallWithDtor@@QAE at XZ"
 // WIN32: }
-// WIN64-LABEL: define dso_local void @"?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(%struct.SmallWithDtor* noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %s)
+// WIN64-LABEL: define dso_local void @"?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %s)
 
 void big_arg_with_dtor(BigWithDtor s) {}
-// WIN64-LABEL: define dso_local void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* noundef %s)
+// WIN64-LABEL: define dso_local void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(ptr noundef %s)
 // WIN64:   call void @"??1BigWithDtor@@QEAA at XZ"
 // WIN64: }
 
@@ -231,8 +230,8 @@ void call_big_arg_with_dtor() {
 // We can elide the copy of the temporary in the caller, because this object is
 // larger than 8 bytes and is passed indirectly.
 // WIN64-LABEL: define dso_local void @"?call_big_arg_with_dtor@@YAXXZ"()
-// WIN64:   call noundef %struct.BigWithDtor* @"??0BigWithDtor@@QEAA at XZ"
-// WIN64:   call void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* noundef %{{.*}})
+// WIN64:   call noundef ptr @"??0BigWithDtor@@QEAA at XZ"
+// WIN64:   call void @"?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(ptr noundef %{{.*}})
 // WIN64-NOT: call void @"??1BigWithDtor@@QEAA at XZ"
 // WIN64:   ret void
 
@@ -241,7 +240,7 @@ void temporary_ref_with_dtor() {
   ref_small_arg_with_dtor(SmallWithDtor());
 }
 // WIN32: define dso_local void @"?temporary_ref_with_dtor@@YAXXZ"() {{.*}} {
-// WIN32:   call x86_thiscallcc noundef %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE at XZ"
+// WIN32:   call x86_thiscallcc noundef ptr @"??0SmallWithDtor@@QAE at XZ"
 // WIN32:   call void @"?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"
 // WIN32:   call x86_thiscallcc void @"??1SmallWithDtor@@QAE at XZ"
 // WIN32: }
@@ -253,29 +252,29 @@ void eh_cleanup_arg_with_dtor() {
 //   When exceptions are off, we don't have any cleanups.  See
 //   microsoft-abi-exceptions.cpp for these cleanups.
 // WIN32: define dso_local void @"?eh_cleanup_arg_with_dtor@@YAXXZ"() {{.*}} {
-// WIN32:   call x86_thiscallcc noundef %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE at XZ"
-// WIN32:   call x86_thiscallcc noundef %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE at XZ"
+// WIN32:   call x86_thiscallcc noundef ptr @"??0SmallWithDtor@@QAE at XZ"
+// WIN32:   call x86_thiscallcc noundef ptr @"??0SmallWithDtor@@QAE at XZ"
 // WIN32:   call void @"?takes_two_by_val_with_dtor@@YAXUSmallWithDtor@@0 at Z"
 // WIN32-NOT: call x86_thiscallcc void @"??1SmallWithDtor@@QAE at XZ"
 // WIN32: }
 
 void small_arg_with_vftable(SmallWithVftable s) {}
-// LINUX-LABEL: define{{.*}} void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* noundef %s)
-// WIN32: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca(<{ %struct.SmallWithVftable }>) %0)
-// WIN64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* noundef %s)
-// WOA64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* noundef %s)
+// LINUX-LABEL: define{{.*}} void @_Z22small_arg_with_vftable16SmallWithVftable(ptr noundef %s)
+// WIN32: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(ptr inalloca(<{ %struct.SmallWithVftable }>) %0)
+// WIN64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(ptr noundef %s)
+// WOA64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(ptr noundef %s)
 
 void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {}
-// LINUX-LABEL: define{{.*}} void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* noundef %s)
-// WIN32: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca(<{ %struct.MediumWithCopyCtor }>) %0)
-// WIN64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* noundef %s)
-// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* noundef %s)
-// WOA64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* noundef %s)
+// LINUX-LABEL: define{{.*}} void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(ptr noundef %s)
+// WIN32: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr inalloca(<{ %struct.MediumWithCopyCtor }>) %0)
+// WIN64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr noundef %s)
+// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr noundef %s)
+// WOA64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(ptr noundef %s)
 
 void big_arg(Big s) {}
-// LINUX-LABEL: define{{.*}} void @_Z7big_arg3Big(%struct.Big* noundef byval(%struct.Big) align 4 %s)
-// WIN32: define dso_local void @"?big_arg@@YAXUBig@@@Z"(%struct.Big* noundef byval(%struct.Big) align 4 %s)
-// WIN64: define dso_local void @"?big_arg@@YAXUBig@@@Z"(%struct.Big* noundef %s)
+// LINUX-LABEL: define{{.*}} void @_Z7big_arg3Big(ptr noundef byval(%struct.Big) align 4 %s)
+// WIN32: define dso_local void @"?big_arg@@YAXUBig@@@Z"(ptr noundef byval(%struct.Big) align 4 %s)
+// WIN64: define dso_local void @"?big_arg@@YAXUBig@@@Z"(ptr noundef %s)
 
 // PR27607: We would attempt to load i32 value out of the reference instead of
 // just loading the pointer from the struct during argument expansion.
@@ -284,8 +283,8 @@ struct RefField {
   int &x;
 };
 void takes_ref_field(RefField s) {}
-// LINUX-LABEL: define{{.*}} void @_Z15takes_ref_field8RefField(%struct.RefField* noundef byval(%struct.RefField) align 4 %s)
-// WIN32: define dso_local void @"?takes_ref_field@@YAXURefField@@@Z"(i32* %s.0)
+// LINUX-LABEL: define{{.*}} void @_Z15takes_ref_field8RefField(ptr noundef byval(%struct.RefField) align 4 %s)
+// WIN32: define dso_local void @"?takes_ref_field@@YAXURefField@@@Z"(ptr %s.0)
 // WIN64: define dso_local void @"?takes_ref_field@@YAXURefField@@@Z"(i64 %s.coerce)
 
 void pass_ref_field() {
@@ -293,61 +292,61 @@ void pass_ref_field() {
   takes_ref_field(RefField(x));
 }
 // LINUX-LABEL: define{{.*}} void @_Z14pass_ref_fieldv()
-// LINUX: call void @_Z15takes_ref_field8RefField(%struct.RefField* noundef byval(%struct.RefField) align 4 %{{.*}})
+// LINUX: call void @_Z15takes_ref_field8RefField(ptr noundef byval(%struct.RefField) align 4 %{{.*}})
 // WIN32-LABEL: define dso_local void @"?pass_ref_field@@YAXXZ"()
-// WIN32: call void @"?takes_ref_field@@YAXURefField@@@Z"(i32* %{{.*}})
+// WIN32: call void @"?takes_ref_field@@YAXURefField@@@Z"(ptr %{{.*}})
 // WIN64-LABEL: define dso_local void @"?pass_ref_field@@YAXXZ"()
 // WIN64: call void @"?takes_ref_field@@YAXURefField@@@Z"(i64 %{{.*}})
 
 class Class {
  public:
   Small thiscall_method_small() { return Small(); }
-  // LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret(%struct.Small) align 4 %agg.result, %class.Class* {{[^,]*}} %this)
-  // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small at Class@@QAE?AUSmall@@XZ"(%class.Class* {{[^,]*}} %this, %struct.Small* noalias sret(%struct.Small) align 4 %agg.result)
-  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small at Class@@QEAA?AUSmall@@XZ"(%class.Class* {{[^,]*}} %this, %struct.Small* noalias sret(%struct.Small) align 4 %agg.result)
-  // WOA64: define linkonce_odr dso_local void @"?thiscall_method_small at Class@@QEAA?AUSmall@@XZ"(%class.Class* {{[^,]*}} %this, %struct.Small* inreg noalias sret(%struct.Small) align 4 %agg.result)
+  // LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(ptr noalias sret(%struct.Small) align 4 %agg.result, ptr {{[^,]*}} %this)
+  // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small at Class@@QAE?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Small) align 4 %agg.result)
+  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small at Class@@QEAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Small) align 4 %agg.result)
+  // WOA64: define linkonce_odr dso_local void @"?thiscall_method_small at Class@@QEAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr inreg noalias sret(%struct.Small) align 4 %agg.result)
 
   SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); }
-  // LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result, %class.Class* {{[^,]*}} %this)
-  // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small_with_ctor at Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* {{[^,]*}} %this, %struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
-  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor at Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* {{[^,]*}} %this, %struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
-  // WOA64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor at Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* {{[^,]*}} %this, %struct.SmallWithCtor* inreg noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
+  // LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result, ptr {{[^,]*}} %this)
+  // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small_with_ctor at Class@@QAE?AUSmallWithCtor@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
+  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor at Class@@QEAA?AUSmallWithCtor@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
+  // WOA64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor at Class@@QEAA?AUSmallWithCtor@@XZ"(ptr {{[^,]*}} %this, ptr inreg noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
 
   Small __cdecl cdecl_method_small() { return Small(); }
-  // LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret(%struct.Small) align 4 %agg.result, %class.Class* {{[^,]*}} %this)
-  // WIN32: define {{.*}} void @"?cdecl_method_small at Class@@QAA?AUSmall@@XZ"(%class.Class* {{[^,]*}} %this, %struct.Small* noalias sret(%struct.Small) align 4 %agg.result)
-  // WIN64: define linkonce_odr dso_local void @"?cdecl_method_small at Class@@QEAA?AUSmall@@XZ"(%class.Class* {{[^,]*}} %this, %struct.Small* noalias sret(%struct.Small) align 4 %agg.result)
+  // LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(ptr noalias sret(%struct.Small) align 4 %agg.result, ptr {{[^,]*}} %this)
+  // WIN32: define {{.*}} void @"?cdecl_method_small at Class@@QAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Small) align 4 %agg.result)
+  // WIN64: define linkonce_odr dso_local void @"?cdecl_method_small at Class@@QEAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Small) align 4 %agg.result)
 
   Big __cdecl cdecl_method_big() { return Big(); }
-  // LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret(%struct.Big) align 4 %agg.result, %class.Class* {{[^,]*}} %this)
-  // WIN32: define {{.*}} void @"?cdecl_method_big at Class@@QAA?AUBig@@XZ"(%class.Class* {{[^,]*}} %this, %struct.Big* noalias sret(%struct.Big) align 4 %agg.result)
-  // WIN64: define linkonce_odr dso_local void @"?cdecl_method_big at Class@@QEAA?AUBig@@XZ"(%class.Class* {{[^,]*}} %this, %struct.Big* noalias sret(%struct.Big) align 4 %agg.result)
-  // WOA64: define linkonce_odr dso_local void @"?cdecl_method_big at Class@@QEAA?AUBig@@XZ"(%class.Class* {{[^,]*}} %this, %struct.Big* inreg noalias sret(%struct.Big) align 4 %agg.result)
+  // LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(ptr noalias sret(%struct.Big) align 4 %agg.result, ptr {{[^,]*}} %this)
+  // WIN32: define {{.*}} void @"?cdecl_method_big at Class@@QAA?AUBig@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Big) align 4 %agg.result)
+  // WIN64: define linkonce_odr dso_local void @"?cdecl_method_big at Class@@QEAA?AUBig@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Big) align 4 %agg.result)
+  // WOA64: define linkonce_odr dso_local void @"?cdecl_method_big at Class@@QEAA?AUBig@@XZ"(ptr {{[^,]*}} %this, ptr inreg noalias sret(%struct.Big) align 4 %agg.result)
 
   void thiscall_method_arg(Empty s) {}
-  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(%class.Class* {{[^,]*}} %this)
-  // WIN32: define {{.*}} void @"?thiscall_method_arg at Class@@QAEXUEmpty@@@Z"(%class.Class* {{[^,]*}} %this, %struct.Empty* noundef byval(%struct.Empty) align 4 %s)
-  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg at Class@@QEAAXUEmpty@@@Z"(%class.Class* {{[^,]*}} %this, i8 %s.coerce)
+  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(ptr {{[^,]*}} %this)
+  // WIN32: define {{.*}} void @"?thiscall_method_arg at Class@@QAEXUEmpty@@@Z"(ptr {{[^,]*}} %this, ptr noundef byval(%struct.Empty) align 4 %s)
+  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg at Class@@QEAAXUEmpty@@@Z"(ptr {{[^,]*}} %this, i8 %s.coerce)
 
   void thiscall_method_arg(EmptyWithCtor s) {}
-  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13EmptyWithCtor(%class.Class* {{[^,]*}} %this)
-  // WIN32: define {{.*}} void @"?thiscall_method_arg at Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* {{[^,]*}} %this, %struct.EmptyWithCtor* noundef byval(%struct.EmptyWithCtor) align 4 %s)
-  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg at Class@@QEAAXUEmptyWithCtor@@@Z"(%class.Class* {{[^,]*}} %this, i8 %s.coerce)
+  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13EmptyWithCtor(ptr {{[^,]*}} %this)
+  // WIN32: define {{.*}} void @"?thiscall_method_arg at Class@@QAEXUEmptyWithCtor@@@Z"(ptr {{[^,]*}} %this, ptr noundef byval(%struct.EmptyWithCtor) align 4 %s)
+  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg at Class@@QEAAXUEmptyWithCtor@@@Z"(ptr {{[^,]*}} %this, i8 %s.coerce)
 
   void thiscall_method_arg(Small s) {}
-  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(%class.Class* {{[^,]*}} %this, i32 %s.0)
-  // WIN32: define {{.*}} void @"?thiscall_method_arg at Class@@QAEXUSmall@@@Z"(%class.Class* {{[^,]*}} %this, i32 %s.0)
-  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg at Class@@QEAAXUSmall@@@Z"(%class.Class* {{[^,]*}} %this, i32 %s.coerce)
+  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(ptr {{[^,]*}} %this, i32 %s.0)
+  // WIN32: define {{.*}} void @"?thiscall_method_arg at Class@@QAEXUSmall@@@Z"(ptr {{[^,]*}} %this, i32 %s.0)
+  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg at Class@@QEAAXUSmall@@@Z"(ptr {{[^,]*}} %this, i32 %s.coerce)
 
   void thiscall_method_arg(SmallWithCtor s) {}
-  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(%class.Class* {{[^,]*}} %this, %struct.SmallWithCtor* noundef byval(%struct.SmallWithCtor) align 4 %s)
-  // WIN32: define {{.*}} void @"?thiscall_method_arg at Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* {{[^,]*}} %this, i32 %s.0)
-  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg at Class@@QEAAXUSmallWithCtor@@@Z"(%class.Class* {{[^,]*}} %this, i32 %s.coerce)
+  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(ptr {{[^,]*}} %this, ptr noundef byval(%struct.SmallWithCtor) align 4 %s)
+  // WIN32: define {{.*}} void @"?thiscall_method_arg at Class@@QAEXUSmallWithCtor@@@Z"(ptr {{[^,]*}} %this, i32 %s.0)
+  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg at Class@@QEAAXUSmallWithCtor@@@Z"(ptr {{[^,]*}} %this, i32 %s.coerce)
 
   void thiscall_method_arg(Big s) {}
-  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(%class.Class* {{[^,]*}} %this, %struct.Big* noundef byval(%struct.Big) align 4 %s)
-  // WIN32: define {{.*}} void @"?thiscall_method_arg at Class@@QAEXUBig@@@Z"(%class.Class* {{[^,]*}} %this, %struct.Big* noundef byval(%struct.Big) align 4 %s)
-  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg at Class@@QEAAXUBig@@@Z"(%class.Class* {{[^,]*}} %this, %struct.Big* noundef %s)
+  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(ptr {{[^,]*}} %this, ptr noundef byval(%struct.Big) align 4 %s)
+  // WIN32: define {{.*}} void @"?thiscall_method_arg at Class@@QAEXUBig@@@Z"(ptr {{[^,]*}} %this, ptr noundef byval(%struct.Big) align 4 %s)
+  // WIN64: define linkonce_odr dso_local void @"?thiscall_method_arg at Class@@QEAAXUBig@@@Z"(ptr {{[^,]*}} %this, ptr noundef %s)
 };
 
 void use_class() {
@@ -371,8 +370,8 @@ struct X {
 };
 void g(X) {
 }
-// WIN32: define dso_local void @"?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca(<{ %struct.X, [3 x i8] }>) %0) {{.*}} {
-// WIN32:   call x86_thiscallcc void @"??1X@@QAE at XZ"(%struct.X* {{.*}})
+// WIN32: define dso_local void @"?g@@YAXUX@@@Z"(ptr inalloca(<{ %struct.X, [3 x i8] }>) %0) {{.*}} {
+// WIN32:   call x86_thiscallcc void @"??1X@@QAE at XZ"(ptr {{.*}})
 // WIN32: }
 void f() {
   g(X());
@@ -402,11 +401,11 @@ void bar() {
 }
 // WIN32-LABEL: define dso_local void @"?bar at test2@@YAXXZ"() {{.*}} {
 // WIN32:   %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty:<{ %"struct.test2::NonTrivial", %"struct.test2::POD" }>]]
-// WIN32:   getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
+// WIN32:   getelementptr inbounds [[argmem_ty]], ptr %[[argmem]], i32 0, i32 1
 // WIN32:   call void @llvm.memcpy
-// WIN32:   getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
-// WIN32:   call x86_thiscallcc noundef %"struct.test2::NonTrivial"* @"??0NonTrivial at test2@@QAE at XZ"
-// WIN32:   call noundef i32 @"?foo at test2@@YAHUNonTrivial at 1@UPOD at 1@@Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %argmem)
+// WIN32:   getelementptr inbounds [[argmem_ty]], ptr %[[argmem]], i32 0, i32 0
+// WIN32:   call x86_thiscallcc noundef ptr @"??0NonTrivial at test2@@QAE at XZ"
+// WIN32:   call noundef i32 @"?foo at test2@@YAHUNonTrivial at 1@UPOD at 1@@Z"(ptr inalloca([[argmem_ty]]) %argmem)
 // WIN32:   ret void
 // WIN32: }
 
@@ -422,7 +421,7 @@ struct NonTrivial {
   int a;
 };
 void foo(NonTrivial a, bool b) { }
-// WIN32-LABEL: define dso_local void @"?foo at test3@@YAXUNonTrivial at 1@_N at Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>) %0)
+// WIN32-LABEL: define dso_local void @"?foo at test3@@YAXUNonTrivial at 1@_N at Z"(ptr inalloca(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>) %0)
 
 }
 
@@ -438,20 +437,17 @@ struct ForwardDeclare1 {};
 
 void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); };
 // WIN32-LABEL: define dso_local void @"?fn2@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"
-// WIN32:   %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]], [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]]* %{{.*}}, i32 0, i32 0
-// WIN32:   %[[a1:[^ ]*]] = bitcast {}** %[[a]] to void [[dst_ty:\(%struct.ForwardDeclare1\*\)\*]]*
-// WIN32:   %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
-// WIN32:   %[[gep1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
-// WIN32:   %[[bc1:[^ ]*]] = bitcast %struct.SmallWithDtor* %[[gep1]] to i8*
-// WIN32:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %[[bc1]], i8* align 4 {{.*}}, i32 4, i1 false)
-// WIN32:   %[[a2:[^ ]*]] = load void [[dst_ty]], void [[dst_ty]]* %[[a1]], align 4
-// WIN32:   %[[gep2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
-// WIN32:   %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]*
-// WIN32:   store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4
-// WIN32:   call void @"?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %[[argmem]])
+// WIN32:   %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty:<{ ptr, %struct.SmallWithDtor }>]], ptr %{{.*}}, i32 0, i32 0
+// WIN32:   %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty:<{ ptr, %struct.SmallWithDtor }>]]
+// WIN32:   %[[gep1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], ptr %[[argmem]], i32 0, i32 1
+// WIN32:   call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[gep1]], ptr align 4 {{.*}}, i32 4, i1 false)
+// WIN32:   %[[a2:[^ ]*]] = load ptr, ptr %[[a]], align 4
+// WIN32:   %[[gep2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], ptr %[[argmem]], i32 0, i32 0
+// WIN32:   store ptr %[[a2]], ptr %[[gep2]], align 4
+// WIN32:   call void @"?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"(ptr inalloca([[argmem_ty]]) %[[argmem]])
 
 namespace pr30293 {
-// Virtual methods living in a secondary vtable take i8* as their 'this'
+// Virtual methods living in a secondary vtable take ptr as their 'this'
 // parameter because the 'this' parameter on entry points to the secondary
 // vptr. We used to have a bug where we didn't apply this rule consistently,
 // and it would cause assertion failures when used with inalloca.
@@ -468,13 +464,13 @@ struct C final : A, B {
 };
 void C::g() { return h(SmallWithDtor()); }
 
-// WIN32-LABEL: define dso_local x86_thiscallcc void @"?g at C@pr30293@@QAEXXZ"(%"struct.pr30293::C"* {{[^,]*}} %this)
-// WIN32: call x86_thiscallcc noundef %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE at XZ"
-// WIN32: call void @"?h at C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca(<{ i8*, %struct.SmallWithDtor }>) %{{[^,)]*}})
-// WIN32: declare dso_local void @"?h at C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca(<{ i8*, %struct.SmallWithDtor }>))
+// WIN32-LABEL: define dso_local x86_thiscallcc void @"?g at C@pr30293@@QAEXXZ"(ptr {{[^,]*}} %this)
+// WIN32: call x86_thiscallcc noundef ptr @"??0SmallWithDtor@@QAE at XZ"
+// WIN32: call void @"?h at C@pr30293@@UAAXUSmallWithDtor@@@Z"(ptr inalloca(<{ ptr, %struct.SmallWithDtor }>) %{{[^,)]*}})
+// WIN32: declare dso_local void @"?h at C@pr30293@@UAAXUSmallWithDtor@@@Z"(ptr inalloca(<{ ptr, %struct.SmallWithDtor }>))
 
-// WIN64-LABEL: define dso_local void @"?g at C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* {{[^,]*}} %this)
-// WIN64: declare dso_local void @"?h at C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8* noundef, i32)
+// WIN64-LABEL: define dso_local void @"?g at C@pr30293@@QEAAXXZ"(ptr {{[^,]*}} %this)
+// WIN64: declare dso_local void @"?h at C@pr30293@@UEAAXUSmallWithDtor@@@Z"(ptr noundef, i32)
 }
 
 namespace protected_member_of_member {

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
index 676d345da1f22..07abc3d065e5e 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -no-opaque-pointers -no-enable-noundef-analysis -emit-llvm -fno-rtti %s -std=c++11 -o - -mconstructor-aliases -triple=i386-pc-win32 -fno-rtti > %t
+// RUN: %clang_cc1 -no-enable-noundef-analysis -emit-llvm -fno-rtti %s -std=c++11 -o - -mconstructor-aliases -triple=i386-pc-win32 -fno-rtti > %t
 // RUN: FileCheck %s < %t
 // vftables are emitted very late, so do another pass to try to keep the checks
 // in source order.
@@ -7,7 +7,7 @@
 // RUN: FileCheck --check-prefix DTORS3 %s < %t
 // RUN: FileCheck --check-prefix DTORS4 %s < %t
 //
-// RUN: %clang_cc1 -no-opaque-pointers -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti -std=c++11 | FileCheck --check-prefix DTORS-X64 %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti -std=c++11 | FileCheck --check-prefix DTORS-X64 %s
 
 namespace basic {
 
@@ -20,11 +20,11 @@ class A {
 void no_constructor_destructor_infinite_recursion() {
   A a;
 
-// CHECK:      define linkonce_odr dso_local x86_thiscallcc %"class.basic::A"* @"??0A at basic@@QAE at XZ"(%"class.basic::A"* {{[^,]*}} returned {{[^,]*}} %this) {{.*}} comdat {{.*}} {
-// CHECK:        [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca %"class.basic::A"*, align 4
-// CHECK-NEXT:   store %"class.basic::A"* %this, %"class.basic::A"** [[THIS_ADDR]], align 4
-// CHECK-NEXT:   [[T1:%[.0-9A-Z_a-z]+]] = load %"class.basic::A"*, %"class.basic::A"** [[THIS_ADDR]]
-// CHECK-NEXT:   ret %"class.basic::A"* [[T1]]
+// CHECK:      define linkonce_odr dso_local x86_thiscallcc ptr @"??0A at basic@@QAE at XZ"(ptr {{[^,]*}} returned {{[^,]*}} %this) {{.*}} comdat {{.*}} {
+// CHECK:        [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca ptr, align 4
+// CHECK-NEXT:   store ptr %this, ptr [[THIS_ADDR]], align 4
+// CHECK-NEXT:   [[T1:%[.0-9A-Z_a-z]+]] = load ptr, ptr [[THIS_ADDR]]
+// CHECK-NEXT:   ret ptr [[T1]]
 // CHECK-NEXT: }
 }
 
@@ -41,28 +41,27 @@ struct B {
 
 // Tests that we can define constructors outside the class (PR12784).
 B::B() {
-  // CHECK: define dso_local x86_thiscallcc %"struct.basic::B"* @"??0B at basic@@QAE at XZ"(%"struct.basic::B"* {{[^,]*}} returned {{[^,]*}} %this)
+  // CHECK: define dso_local x86_thiscallcc ptr @"??0B at basic@@QAE at XZ"(ptr {{[^,]*}} returned {{[^,]*}} %this)
   // CHECK: ret
 }
 
 struct C {
   virtual ~C() {
-// DTORS:      define linkonce_odr dso_local x86_thiscallcc i8* @"??_GC at basic@@UAEPAXI at Z"(%"struct.basic::C"* {{[^,]*}} %this, i32 %should_call_delete) {{.*}} comdat {{.*}} {
-// DTORS:        store i32 %should_call_delete, i32* %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 4
-// DTORS:        store i8* %{{.*}}, i8** %[[RETVAL:[0-9a-z._]+]]
-// DTORS:        %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32, i32* %[[SHOULD_DELETE_VAR]]
-// DTORS:        call x86_thiscallcc void @"??1C at basic@@UAE at XZ"(%"struct.basic::C"* {{[^,]*}} %[[THIS:[0-9a-z]+]])
+// DTORS:      define linkonce_odr dso_local x86_thiscallcc ptr @"??_GC at basic@@UAEPAXI at Z"(ptr {{[^,]*}} %this, i32 %should_call_delete) {{.*}} comdat {{.*}} {
+// DTORS:        store i32 %should_call_delete, ptr %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 4
+// DTORS:        store ptr %{{.*}}, ptr %[[RETVAL:retval]]
+// DTORS:        %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32, ptr %[[SHOULD_DELETE_VAR]]
+// DTORS:        call x86_thiscallcc void @"??1C at basic@@UAE at XZ"(ptr {{[^,]*}} %[[THIS:[0-9a-z]+]])
 // DTORS-NEXT:   %[[CONDITION:[0-9]+]] = icmp eq i32 %[[SHOULD_DELETE_VALUE]], 0
 // DTORS-NEXT:   br i1 %[[CONDITION]], label %[[CONTINUE_LABEL:[0-9a-z._]+]], label %[[CALL_DELETE_LABEL:[0-9a-z._]+]]
 //
 // DTORS:      [[CALL_DELETE_LABEL]]
-// DTORS-NEXT:   %[[THIS_AS_VOID:[0-9a-z]+]] = bitcast %"struct.basic::C"* %[[THIS]] to i8*
-// DTORS-NEXT:   call void @"??3 at YAXPAX@Z"(i8* %[[THIS_AS_VOID]])
+// DTORS-NEXT:   call void @"??3 at YAXPAX@Z"(ptr %[[THIS]])
 // DTORS-NEXT:   br label %[[CONTINUE_LABEL]]
 //
 // DTORS:      [[CONTINUE_LABEL]]
-// DTORS-NEXT:   %[[RET:.*]] = load i8*, i8** %[[RETVAL]]
-// DTORS-NEXT:   ret i8* %[[RET]]
+// DTORS-NEXT:   %[[RET:.*]] = load ptr, ptr %[[RETVAL]]
+// DTORS-NEXT:   ret ptr %[[RET]]
 
 // Check that we do the mangling correctly on x64.
 // DTORS-X64:  @"??_GC at basic@@UEAAPEAXI at Z"
@@ -76,50 +75,46 @@ void C::foo() {}
 void check_vftable_offset() {
   C c;
 // The vftable pointer should point at the beginning of the vftable.
-// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to i32 (...)***
-// CHECK: store i32 (...)** bitcast ({ [2 x i8*] }* @"??_7C at basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]]
+// CHECK: store ptr @"??_7C at basic@@6B@", ptr {{.*}}
 }
 
 void call_complete_dtor(C *obj_ptr) {
-// CHECK: define dso_local void @"?call_complete_dtor at basic@@YAXPAUC at 1@@Z"(%"struct.basic::C"* %obj_ptr)
+// CHECK: define dso_local void @"?call_complete_dtor at basic@@YAXPAUC at 1@@Z"(ptr %obj_ptr)
   obj_ptr->~C();
-// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
-// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
-// CHECK-NEXT: %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)**, i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
-// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
-// CHECK-NEXT: %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
-// CHECK-NEXT: call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* {{[^,]*}} %[[OBJ_PTR_VALUE]], i32 0)
+// CHECK: %[[OBJ_PTR_VALUE:.*]] = load ptr, ptr %{{.*}}, align 4
+// CHECK-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[OBJ_PTR_VALUE]]
+// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i64 0
+// CHECK-NEXT: %[[VDTOR:.*]] = load ptr, ptr %[[PVDTOR]]
+// CHECK-NEXT: call x86_thiscallcc ptr %[[VDTOR]](ptr {{[^,]*}} %[[OBJ_PTR_VALUE]], i32 0)
 // CHECK-NEXT: ret void
 }
 
 void call_deleting_dtor(C *obj_ptr) {
-// CHECK: define dso_local void @"?call_deleting_dtor at basic@@YAXPAUC at 1@@Z"(%"struct.basic::C"* %obj_ptr)
+// CHECK: define dso_local void @"?call_deleting_dtor at basic@@YAXPAUC at 1@@Z"(ptr %obj_ptr)
   delete obj_ptr;
-// CHECK:      %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
+// CHECK:      %[[OBJ_PTR_VALUE:.*]] = load ptr, ptr %{{.*}}, align 4
 // CHECK:      br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
 
 // CHECK:      [[DELETE_NOTNULL]]
-// CHECK-NEXT:   %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
-// CHECK-NEXT:   %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)**, i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
-// CHECK-NEXT:   %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
-// CHECK-NEXT:   %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
-// CHECK-NEXT:   call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* {{[^,]*}} %[[OBJ_PTR_VALUE]], i32 1)
+// CHECK-NEXT:   %[[VTABLE:.*]] = load ptr, ptr %[[OBJ_PTR_VALUE]]
+// CHECK-NEXT:   %[[PVDTOR:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i64 0
+// CHECK-NEXT:   %[[VDTOR:.*]] = load ptr, ptr %[[PVDTOR]]
+// CHECK-NEXT:   call x86_thiscallcc ptr %[[VDTOR]](ptr {{[^,]*}} %[[OBJ_PTR_VALUE]], i32 1)
 // CHECK:      ret void
 }
 
 void call_deleting_dtor_and_global_delete(C *obj_ptr) {
-// CHECK: define dso_local void @"?call_deleting_dtor_and_global_delete at basic@@YAXPAUC at 1@@Z"(%"struct.basic::C"* %obj_ptr)
+// CHECK: define dso_local void @"?call_deleting_dtor_and_global_delete at basic@@YAXPAUC at 1@@Z"(ptr %obj_ptr)
   ::delete obj_ptr;
-// CHECK:      %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"*, %"struct.basic::C"** %{{.*}}, align 4
+// CHECK:      %[[OBJ_PTR_VALUE:.*]] = load ptr, ptr %{{.*}}, align 4
 // CHECK:      br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
 
 // CHECK:      [[DELETE_NOTNULL]]
-// CHECK-NEXT:   %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to i8* (%"struct.basic::C"*, i32)***
-// CHECK-NEXT:   %[[VTABLE:.*]] = load i8* (%"struct.basic::C"*, i32)**, i8* (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
-// CHECK-NEXT:   %[[PVDTOR:.*]] = getelementptr inbounds i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
-// CHECK-NEXT:   %[[VDTOR:.*]] = load i8* (%"struct.basic::C"*, i32)*, i8* (%"struct.basic::C"*, i32)** %[[PVDTOR]]
-// CHECK-NEXT:   %[[CALL:.*]] = call x86_thiscallcc i8* %[[VDTOR]](%"struct.basic::C"* {{[^,]*}} %[[OBJ_PTR_VALUE]], i32 0)
-// CHECK-NEXT:   call void @"??3 at YAXPAX@Z"(i8* %[[CALL]])
+// CHECK-NEXT:   %[[VTABLE:.*]] = load ptr, ptr %[[OBJ_PTR_VALUE]]
+// CHECK-NEXT:   %[[PVDTOR:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i64 0
+// CHECK-NEXT:   %[[VDTOR:.*]] = load ptr, ptr %[[PVDTOR]]
+// CHECK-NEXT:   %[[CALL:.*]] = call x86_thiscallcc ptr %[[VDTOR]](ptr {{[^,]*}} %[[OBJ_PTR_VALUE]], i32 0)
+// CHECK-NEXT:   call void @"??3 at YAXPAX@Z"(ptr %[[CALL]])
 // CHECK:      ret void
 }
 
@@ -155,26 +150,24 @@ struct C : A, B {
 };
 
 C::~C() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1C at dtor_in_second_nvbase@@UAE at XZ"(i8*{{[^,]*}} %this.coerce)
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1C at dtor_in_second_nvbase@@UAE at XZ"(ptr{{[^,]*}} %this)
 //      No this adjustment!
 // CHECK-NOT: getelementptr
-// CHECK:   load %"struct.dtor_in_second_nvbase::C"*, %"struct.dtor_in_second_nvbase::C"** %{{.*}}
+// CHECK:   load ptr, ptr %{{.*}}
 //      Now we this-adjust before calling ~B.
-// CHECK:   bitcast %"struct.dtor_in_second_nvbase::C"* %{{.*}} to i8*
-// CHECK:   getelementptr inbounds i8, i8* %{{.*}}, i32 4
-// CHECK:   bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::B"*
-// CHECK:   call x86_thiscallcc void @"??1B at dtor_in_second_nvbase@@UAE at XZ"(%"struct.dtor_in_second_nvbase::B"*{{[^,]*}} %{{.*}})
+// CHECK:   getelementptr inbounds i8, ptr %{{.*}}, i32 4
+// CHECK:   call x86_thiscallcc void @"??1B at dtor_in_second_nvbase@@UAE at XZ"(ptr{{[^,]*}} %{{.*}})
 // CHECK:   ret void
 }
 
 void foo() {
   C c;
 }
-// DTORS2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_EC at dtor_in_second_nvbase@@W3AEPAXI at Z"(i8* %this.coerce, i32 %should_call_delete)
+// DTORS2-LABEL: define linkonce_odr dso_local x86_thiscallcc ptr @"??_EC at dtor_in_second_nvbase@@W3AEPAXI at Z"(ptr %this, i32 %should_call_delete)
 //      Do an adjustment from B* to C*.
-// DTORS2:   getelementptr i8, i8* %{{.*}}, i32 -4
-// DTORS2:   %[[CALL:.*]] = tail call x86_thiscallcc i8* @"??_GC at dtor_in_second_nvbase@@UAEPAXI at Z"
-// DTORS2:   ret i8* %[[CALL]]
+// DTORS2:   getelementptr i8, ptr %{{.*}}, i32 -4
+// DTORS2:   %[[CALL:.*]] = tail call x86_thiscallcc ptr @"??_GC at dtor_in_second_nvbase@@UAEPAXI at Z"
+// DTORS2:   ret ptr %[[CALL]]
 }
 
 namespace test2 {
@@ -191,12 +184,11 @@ struct E : virtual C { int e; };
 struct F : D, E { ~F(); int f; };
 
 F::~F() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1F at test2@@UAE at XZ"(i8*{{[^,]*}})
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1F at test2@@UAE at XZ"(ptr{{[^,]*}})
 //      Do an adjustment from C vbase subobject to F as though F was the
 //      complete type.
-// CHECK:   getelementptr inbounds i8, i8* %{{.*}}, i32 -20
-// CHECK:   bitcast i8* %{{.*}} to %"struct.test2::F"*
-// CHECK:   store %"struct.test2::F"*
+// CHECK:   getelementptr inbounds i8, ptr %{{.*}}, i32 -20
+// CHECK:   store ptr
 }
 
 void foo() {
@@ -204,7 +196,7 @@ void foo() {
 }
 // DTORS3-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??_DF at test2@@QAEXXZ"({{.*}} {{.*}} comdat
 //      Do an adjustment from C* to F*.
-// DTORS3:   getelementptr i8, i8* %{{.*}}, i32 20
+// DTORS3:   getelementptr i8, ptr %{{.*}}, i32 20
 // DTORS3:   call x86_thiscallcc void @"??1F at test2@@UAE at XZ"
 // DTORS3:   ret void
 
@@ -222,8 +214,8 @@ struct B : A {
 };
 
 B::B() {
-  // CHECK: define dso_local x86_thiscallcc %"struct.constructors::B"* @"??0B at constructors@@QAE at XZ"(%"struct.constructors::B"* {{[^,]*}} returned {{[^,]*}} %this)
-  // CHECK: call x86_thiscallcc %"struct.constructors::A"* @"??0A at constructors@@QAE at XZ"(%"struct.constructors::A"* {{[^,]*}} %{{.*}})
+  // CHECK: define dso_local x86_thiscallcc ptr @"??0B at constructors@@QAE at XZ"(ptr {{[^,]*}} returned {{[^,]*}} %this)
+  // CHECK: call x86_thiscallcc ptr @"??0A at constructors@@QAE at XZ"(ptr {{[^,]*}} %{{.*}})
   // CHECK: ret
 }
 
@@ -232,22 +224,18 @@ struct C : virtual A {
 };
 
 C::C() {
-  // CHECK: define dso_local x86_thiscallcc %"struct.constructors::C"* @"??0C at constructors@@QAE at XZ"(%"struct.constructors::C"* {{[^,]*}} returned {{[^,]*}} %this, i32 %is_most_derived)
+  // CHECK: define dso_local x86_thiscallcc ptr @"??0C at constructors@@QAE at XZ"(ptr {{[^,]*}} returned {{[^,]*}} %this, i32 %is_most_derived)
   // TODO: make sure this works in the Release build too;
-  // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
-  // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
+  // CHECK: store i32 %is_most_derived, ptr %[[IS_MOST_DERIVED_VAR:.*]], align 4
+  // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, ptr %[[IS_MOST_DERIVED_VAR]]
   // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
   // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
   //
   // CHECK: [[INIT_VBASES]]
-  // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::C"* %{{.*}} to i8*
-  // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
-  // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
-  // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"??_8C at constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
-  // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8*
-  // CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
-  // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
-  // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"??0A at constructors@@QAE at XZ"(%"struct.constructors::A"* {{[^,]*}} %{{.*}})
+  // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 0
+  // CHECK-NEXT: store ptr @"??_8C at constructors@@7B@", ptr %[[vbptr_off]]
+  // CHECK-NEXT: getelementptr inbounds i8, ptr %{{.*}}, i32 4
+  // CHECK-NEXT: call x86_thiscallcc ptr @"??0A at constructors@@QAE at XZ"(ptr {{[^,]*}} %{{.*}})
   // CHECK-NEXT: br label %[[SKIP_VBASES]]
   //
   // CHECK: [[SKIP_VBASES]]
@@ -259,7 +247,7 @@ C::C() {
 void create_C() {
   C c;
   // CHECK: define dso_local void @"?create_C at constructors@@YAXXZ"()
-  // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"??0C at constructors@@QAE at XZ"(%"struct.constructors::C"* {{[^,]*}} %c, i32 1)
+  // CHECK: call x86_thiscallcc ptr @"??0C at constructors@@QAE at XZ"(ptr {{[^,]*}} %c, i32 1)
   // CHECK: ret
 }
 
@@ -268,25 +256,21 @@ struct D : C {
 };
 
 D::D() {
-  // CHECK: define dso_local x86_thiscallcc %"struct.constructors::D"* @"??0D at constructors@@QAE at XZ"(%"struct.constructors::D"* {{[^,]*}} returned {{[^,]*}} %this, i32 %is_most_derived) unnamed_addr
-  // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
-  // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
+  // CHECK: define dso_local x86_thiscallcc ptr @"??0D at constructors@@QAE at XZ"(ptr {{[^,]*}} returned {{[^,]*}} %this, i32 %is_most_derived) unnamed_addr
+  // CHECK: store i32 %is_most_derived, ptr %[[IS_MOST_DERIVED_VAR:.*]], align 4
+  // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, ptr %[[IS_MOST_DERIVED_VAR]]
   // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
   // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
   //
   // CHECK: [[INIT_VBASES]]
-  // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::D"* %{{.*}} to i8*
-  // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
-  // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32**
-  // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"??_8D at constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]]
-  // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8*
-  // CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
-  // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
-  // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"??0A at constructors@@QAE at XZ"(%"struct.constructors::A"* {{[^,]*}} %{{.*}})
+  // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 0
+  // CHECK-NEXT: store ptr @"??_8D at constructors@@7B@", ptr %[[vbptr_off]]
+  // CHECK-NEXT: getelementptr inbounds i8, ptr %{{.*}}, i32 4
+  // CHECK-NEXT: call x86_thiscallcc ptr @"??0A at constructors@@QAE at XZ"(ptr {{[^,]*}} %{{.*}})
   // CHECK-NEXT: br label %[[SKIP_VBASES]]
   //
   // CHECK: [[SKIP_VBASES]]
-  // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"??0C at constructors@@QAE at XZ"(%"struct.constructors::C"* {{[^,]*}} %{{.*}}, i32 0)
+  // CHECK: call x86_thiscallcc ptr @"??0C at constructors@@QAE at XZ"(ptr {{[^,]*}} %{{.*}}, i32 0)
   // CHECK: ret
 }
 
@@ -295,25 +279,20 @@ struct E : virtual C {
 };
 
 E::E() {
-  // CHECK: define dso_local x86_thiscallcc %"struct.constructors::E"* @"??0E at constructors@@QAE at XZ"(%"struct.constructors::E"* {{[^,]*}} returned {{[^,]*}} %this, i32 %is_most_derived) unnamed_addr
-  // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
-  // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]]
+  // CHECK: define dso_local x86_thiscallcc ptr @"??0E at constructors@@QAE at XZ"(ptr {{[^,]*}} returned {{[^,]*}} %this, i32 %is_most_derived) unnamed_addr
+  // CHECK: store i32 %is_most_derived, ptr %[[IS_MOST_DERIVED_VAR:.*]], align 4
+  // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, ptr %[[IS_MOST_DERIVED_VAR]]
   // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
   // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
   //
   // CHECK: [[INIT_VBASES]]
-  // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::E"* %{{.*}} to i8*
-  // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0
-  // CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to i32**
-  // CHECK-NEXT: store i32* getelementptr inbounds ([3 x i32], [3 x i32]* @"??_8E at constructors@@7B01@@", i32 0, i32 0), i32** %[[vbptr_E]]
-  // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 4
-  // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to i32**
-  // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"??_8E at constructors@@7BC at 1@@", i32 0, i32 0), i32** %[[vbptr_C]]
-  // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8*
-  // CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4
-  // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"*
-  // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"??0A at constructors@@QAE at XZ"(%"struct.constructors::A"* {{[^,]*}} %{{.*}})
-  // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"??0C at constructors@@QAE at XZ"(%"struct.constructors::C"* {{[^,]*}} %{{.*}}, i32 0)
+  // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 0
+  // CHECK-NEXT: store ptr @"??_8E at constructors@@7B01@@", ptr %[[offs]]
+  // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 4
+  // CHECK-NEXT: store ptr @"??_8E at constructors@@7BC at 1@@", ptr %[[offs]]
+  // CHECK-NEXT: getelementptr inbounds i8, ptr %{{.*}}, i32 4
+  // CHECK-NEXT: call x86_thiscallcc ptr @"??0A at constructors@@QAE at XZ"(ptr {{[^,]*}} %{{.*}})
+  // CHECK: call x86_thiscallcc ptr @"??0C at constructors@@QAE at XZ"(ptr {{[^,]*}} %{{.*}}, i32 0)
   // CHECK-NEXT: br label %[[SKIP_VBASES]]
   //
   // CHECK: [[SKIP_VBASES]]
@@ -327,7 +306,7 @@ struct F {
 };
 
 F::F() {}
-// CHECK: define dso_local x86_thiscallcc %"struct.constructors::F"* @"??0F at constructors@@QAE at XZ"
+// CHECK: define dso_local x86_thiscallcc ptr @"??0F at constructors@@QAE at XZ"
 
 } // end namespace constructors
 
@@ -355,7 +334,7 @@ struct D : B, C { ~D(); };
 void call_vbase_complete(D *d) {
   d->~D();
 // CHECK: define dso_local void @"?call_vbase_complete at dtors@@YAXPAUD at 1@@Z"
-// CHECK: call x86_thiscallcc void @"??_DD at dtors@@QAEXXZ"(%"struct.dtors::D"* {{[^,]*}} %{{[^,]+}})
+// CHECK: call x86_thiscallcc void @"??_DD at dtors@@QAEXXZ"(ptr {{[^,]*}} %{{[^,]+}})
 // CHECK: ret
 }
 
@@ -371,7 +350,7 @@ void call_vbase_complete(D *d) {
 void destroy_d_complete() {
   D d;
 // CHECK: define dso_local void @"?destroy_d_complete at dtors@@YAXXZ"
-// CHECK: call x86_thiscallcc void @"??_DD at dtors@@QAEXXZ"(%"struct.dtors::D"* {{[^,]*}} %{{[^,]+}})
+// CHECK: call x86_thiscallcc void @"??_DD at dtors@@QAEXXZ"(ptr {{[^,]*}} %{{[^,]+}})
 // CHECK: ret
 }
 
@@ -381,7 +360,7 @@ void destroy_d_complete() {
 void call_nv_deleting_dtor(D *d) {
   delete d;
 // CHECK: define dso_local void @"?call_nv_deleting_dtor at dtors@@YAXPAUD at 1@@Z"
-// CHECK: call x86_thiscallcc void @"??_DD at dtors@@QAEXXZ"(%"struct.dtors::D"* {{[^,]*}} %{{[^,]+}})
+// CHECK: call x86_thiscallcc void @"??_DD at dtors@@QAEXXZ"(ptr {{[^,]*}} %{{[^,]+}})
 // CHECK: call void @"??3 at YAXPAX@Z"
 // CHECK: ret
 }
@@ -398,12 +377,12 @@ struct B : virtual A {
 B::B(int *a) {}
 B::B(const char *a, ...) {}
 B::B(short *a) {}
-// CHECK: define dso_local x86_thiscallcc %"struct.test1::B"* @"??0B at test1@@QAE at PAH@Z"
-// CHECK:               (%"struct.test1::B"* {{[^,]*}} returned {{[^,]*}} %this, i32* %a, i32 %is_most_derived)
-// CHECK: define dso_local %"struct.test1::B"* @"??0B at test1@@QAA at PBDZZ"
-// CHECK:               (%"struct.test1::B"* {{[^,]*}} returned {{[^,]*}} %this, i32 %is_most_derived, i8* %a, ...)
-// CHECK: define dso_local x86_thiscallcc %"struct.test1::B"* @"??0B at test1@@QAE at PAF@Z"
-// CHECK:               (%"struct.test1::B"* {{[^,]*}} returned {{[^,]*}} %this, i16* %a, i32 %is_most_derived)
+// CHECK: define dso_local x86_thiscallcc ptr @"??0B at test1@@QAE at PAH@Z"
+// CHECK:               (ptr {{[^,]*}} returned {{[^,]*}} %this, ptr %a, i32 %is_most_derived)
+// CHECK: define dso_local ptr @"??0B at test1@@QAA at PBDZZ"
+// CHECK:               (ptr {{[^,]*}} returned {{[^,]*}} %this, i32 %is_most_derived, ptr %a, ...)
+// CHECK: define dso_local x86_thiscallcc ptr @"??0B at test1@@QAE at PAF@Z"
+// CHECK:               (ptr {{[^,]*}} returned {{[^,]*}} %this, ptr %a, i32 %is_most_derived)
 
 void construct_b() {
   int a;
@@ -411,10 +390,10 @@ void construct_b() {
   B b2("%d %d", 1, 2);
 }
 // CHECK-LABEL: define dso_local void @"?construct_b at test1@@YAXXZ"()
-// CHECK: call x86_thiscallcc %"struct.test1::B"* @"??0B at test1@@QAE at PAH@Z"
-// CHECK:               (%"struct.test1::B"* {{.*}}, i32* {{.*}}, i32 1)
-// CHECK: call %"struct.test1::B"* (%"struct.test1::B"*, i32, i8*, ...) @"??0B at test1@@QAA at PBDZZ"
-// CHECK:               (%"struct.test1::B"* {{.*}}, i32 1, i8* {{.*}}, i32 1, i32 2)
+// CHECK: call x86_thiscallcc ptr @"??0B at test1@@QAE at PAH@Z"
+// CHECK:               (ptr {{.*}}, ptr {{.*}}, i32 1)
+// CHECK: call ptr (ptr, i32, ptr, ...) @"??0B at test1@@QAA at PBDZZ"
+// CHECK:               (ptr {{.*}}, i32 1, ptr {{.*}}, i32 1, i32 2)
 }
 
 namespace implicit_copy_vtable {
@@ -445,11 +424,11 @@ struct X : virtual Y {
 };
 X::X(int) : X() {}
 }
-// CHECK: define dso_local x86_thiscallcc %"struct.delegating_ctor::X"* @"??0X at delegating_ctor@@QAE at H@Z"(
+// CHECK: define dso_local x86_thiscallcc ptr @"??0X at delegating_ctor@@QAE at H@Z"(
 // CHECK:  %[[is_most_derived_addr:.*]] = alloca i32, align 4
-// CHECK:  store i32 %is_most_derived, i32* %[[is_most_derived_addr]]
-// CHECK:  %[[is_most_derived:.*]] = load i32, i32* %[[is_most_derived_addr]]
-// CHECK:  call x86_thiscallcc {{.*}}* @"??0X at delegating_ctor@@QAE at XZ"({{.*}} i32 %[[is_most_derived]])
+// CHECK:  store i32 %is_most_derived, ptr %[[is_most_derived_addr]]
+// CHECK:  %[[is_most_derived:.*]] = load i32, ptr %[[is_most_derived_addr]]
+// CHECK:  call x86_thiscallcc ptr @"??0X at delegating_ctor@@QAE at XZ"({{.*}} i32 %[[is_most_derived]])
 
 // Dtor thunks for classes in anonymous namespaces should be internal, not
 // linkonce_odr.
@@ -461,17 +440,17 @@ struct A {
 void *getA() {
   return (void*)new A();
 }
-// CHECK: define internal x86_thiscallcc i8* @"??_GA@?A0x{{[^@]*}}@@UAEPAXI at Z"
-// CHECK:               (%"struct.(anonymous namespace)::A"* {{[^,]*}} %this, i32 %should_call_delete)
+// CHECK: define internal x86_thiscallcc ptr @"??_GA@?A0x{{[^@]*}}@@UAEPAXI at Z"
+// CHECK:               (ptr {{[^,]*}} %this, i32 %should_call_delete)
 // CHECK: define internal x86_thiscallcc void @"??1A@?A0x{{[^@]*}}@@UAE at XZ"
-// CHECK:               (%"struct.(anonymous namespace)::A"* {{[^,]*}} %this)
+// CHECK:               (ptr {{[^,]*}} %this)
 
 // Check that we correctly transform __stdcall to __thiscall for ctors and
 // dtors.
 class G {
  public:
   __stdcall G() {};
-// DTORS4: define linkonce_odr dso_local x86_thiscallcc %class.G* @"??0G@@QAE at XZ"
+// DTORS4: define linkonce_odr dso_local x86_thiscallcc ptr @"??0G@@QAE at XZ"
   __stdcall ~G() {};
 // DTORS4: define linkonce_odr dso_local x86_thiscallcc void @"??1G@@QAE at XZ"
 };

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-this-nullable.cpp b/clang/test/CodeGenCXX/microsoft-abi-this-nullable.cpp
index b0c60f05bceae..e0523f4cf4d1e 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-this-nullable.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-this-nullable.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -no-opaque-pointers -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
-// RUN: %clang_cc1 -no-opaque-pointers -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 -fno-delete-null-pointer-checks | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 -fno-delete-null-pointer-checks | FileCheck %s
 
 struct Left {
   virtual void left();
@@ -20,7 +20,7 @@ struct ChildOverride : Left, Right {
 extern "C" void foo(void *);
 
 void call_left_no_override(ChildNoOverride *child) {
-  // CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
+  // CHECK: %[[CHILD:.*]] = load ptr
   child->left();
 }
 
@@ -30,13 +30,10 @@ void call_right_no_override(ChildNoOverride *child) {
   child->right();
   // When calling a right base's virtual method, one needs to adjust `this` at the caller site.
   //
-  // CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildNoOverride* %[[CHILD]] to i8*
-  // CHECK: %[[RIGHT_i8:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
-  // CHECK: %[[RIGHT:.*]] = bitcast i8* %[[RIGHT_i8]] to %struct.Right*
+  // CHECK: %[[RIGHT_i8:.*]] = getelementptr inbounds i8, ptr %[[CHILD]], i32 4
   //
-  // CHECK: %[[VFPTR:.*]] = bitcast %struct.Right* %[[RIGHT]] to void (%struct.Right*)***
-  // CHECK: %[[VFTABLE:.*]] = load void (%struct.Right*)**, void (%struct.Right*)*** %[[VFPTR]]
-  // CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.Right*)*, void (%struct.Right*)** %[[VFTABLE]], i64 0
+  // CHECK: %[[VFTABLE:.*]] = load ptr, ptr %[[RIGHT_i8]]
+  // CHECK: %[[VFUN:.*]] = getelementptr inbounds ptr, ptr %[[VFTABLE]], i64 0
 }
 
 void ChildOverride::right() {
@@ -47,7 +44,7 @@ void call_right_override(ChildOverride *child) {
   child->right();
   // Ensure that `nonnull` and `dereferenceable(N)` are not emitted whether or not null is valid
   //
-  // CHECK: %[[RIGHT:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
-  // CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
-  // CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* noundef %[[RIGHT]])
+  // CHECK: %[[RIGHT:.*]] = getelementptr inbounds i8, ptr %[[CHILD]], i32 4
+  // CHECK: %[[VFUN_VALUE:.*]] = load ptr, ptr %[[VFUN]]
+  // CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](ptr noundef %[[RIGHT]])
 }

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp
index 88eab9489938a..38aa81253ccad 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp
@@ -1,8 +1,8 @@
-// RUN: %clang_cc1 -no-opaque-pointers -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 >%t 2>&1
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 >%t 2>&1
 // RUN: FileCheck --check-prefix=MANGLING %s < %t
 // RUN: FileCheck --check-prefix=XMANGLING %s < %t
 // RUN: FileCheck --check-prefix=CODEGEN %s < %t
-// RUN: %clang_cc1 -no-opaque-pointers -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s
 
 void foo(void *);
 
@@ -61,15 +61,15 @@ struct C : A, B {
 
 C::C() {}  // Emits vftable and forces thunk generation.
 
-// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef i8* @"??_EC@@W3AEPAXI at Z"(%struct.C* noundef %this, i32 noundef %should_call_delete) {{.*}} comdat
-// CODEGEN:   getelementptr i8, i8* {{.*}}, i32 -4
+// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_EC@@W3AEPAXI at Z"(ptr noundef %this, i32 noundef %should_call_delete) {{.*}} comdat
+// CODEGEN:   getelementptr i8, ptr {{.*}}, i32 -4
 // FIXME: should actually call _EC, not _GC.
-// CODEGEN:   call x86_thiscallcc noundef i8* @"??_GC@@UAEPAXI at Z"
+// CODEGEN:   call x86_thiscallcc noundef ptr @"??_GC@@UAEPAXI at Z"
 // CODEGEN: ret
 
-// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?public_f at C@@W3AEXXZ"(%struct.C*
-// CODEGEN:   getelementptr i8, i8* {{.*}}, i32 -4
-// CODEGEN:   call x86_thiscallcc void @"?public_f at C@@UAEXXZ"(%struct.C*
+// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?public_f at C@@W3AEXXZ"(ptr
+// CODEGEN:   getelementptr i8, ptr {{.*}}, i32 -4
+// CODEGEN:   call x86_thiscallcc void @"?public_f at C@@UAEXXZ"(ptr
 // CODEGEN: ret
 
 void zoo(C* obj) {
@@ -91,9 +91,9 @@ struct E : D {
 
 E::E() {}  // Emits vftable and forces thunk generation.
 
-// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc noundef %struct.C* @"?goo at E@@QAEPAUB@@XZ"{{.*}} comdat
-// CODEGEN:   call x86_thiscallcc noundef %struct.C* @"?goo at E@@UAEPAUC@@XZ"
-// CODEGEN:   getelementptr inbounds i8, i8* {{.*}}, i32 4
+// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc noundef ptr @"?goo at E@@QAEPAUB@@XZ"{{.*}} comdat
+// CODEGEN:   call x86_thiscallcc noundef ptr @"?goo at E@@UAEPAUC@@XZ"
+// CODEGEN:   getelementptr inbounds i8, ptr {{.*}}, i32 4
 // CODEGEN: ret
 
 struct F : virtual A, virtual B {
@@ -124,18 +124,15 @@ struct I : D {
 
 I::I() {}  // Emits vftable and forces thunk generation.
 
-// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc noundef %struct.{{[BF]}}* @"?goo at I@@QAEPAUB@@XZ"{{.*}} comdat
-// CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc noundef %struct.F* @"?goo at I@@UAEPAUF@@XZ"
-// CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8*
-// CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ORIG_RET_i8]], i32 4
-// CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32**
-// CODEGEN: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR]]
-// CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 2
-// CODEGEN: %[[VBASE_OFFSET:.*]] = load i32, i32* %[[VBASE_OFFSET_PTR]]
-// CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8, i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
-// CODEGEN: %[[RES:.*]] = bitcast i8* %[[RES_i8]] to %struct.F*
-// CODEGEN: phi %struct.F* {{.*}} %[[RES]]
-// CODEGEN: ret %struct.{{[BF]}}*
+// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc noundef ptr @"?goo at I@@QAEPAUB@@XZ"{{.*}} comdat
+// CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc noundef ptr @"?goo at I@@UAEPAUF@@XZ"
+// CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, ptr %[[ORIG_RET]], i32 4
+// CODEGEN: %[[VBTABLE:.*]] = load ptr, ptr %[[VBPTR_i8]]
+// CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = getelementptr inbounds i32, ptr %[[VBTABLE]], i32 2
+// CODEGEN: %[[VBASE_OFFSET:.*]] = load i32, ptr %[[VBASE_OFFSET_PTR]]
+// CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8, ptr %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
+// CODEGEN: phi ptr {{.*}} %[[RES_i8]]
+// CODEGEN: ret ptr
 
 namespace CrashOnThunksForAttributedType {
 // We used to crash on this because the type of foo is an AttributedType, not
@@ -160,5 +157,5 @@ struct E : D {
 E::E() {}
 E e;
 // Class with internal linkage has internal linkage thunks.
-// CODEGEN: define internal x86_thiscallcc noundef %struct.C* @"?goo at E@?A0x{{[^@]*}}@@QAEPAUB@@XZ"
+// CODEGEN: define internal x86_thiscallcc noundef ptr @"?goo at E@?A0x{{[^@]*}}@@QAEPAUB@@XZ"
 }

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
index 5b50353db583e..691fccf9930af 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -no-opaque-pointers %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
 
 // For now, just make sure x86_64 doesn't crash.
-// RUN: %clang_cc1 -no-opaque-pointers %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t
+// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t
 
 struct A {
   virtual void f();
@@ -25,28 +25,22 @@ D::D() {}  // Forces vftable emission.
 
 // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f at D@@$4PPPPPPPM at A@AEXXZ"
 // Note that the vtordisp is applied before really adjusting to D*.
-// CHECK: %[[COERCE_LOAD:.*]] = load %struct.D*, %struct.D** %{{.*}}
-// CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}}
-// CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8*
-// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4
-// CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32*
-// CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]]
+// CHECK: %[[ECX:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, ptr %[[ECX]], i32 -4
+// CHECK: %[[VTORDISP:.*]] = load i32, ptr %[[VTORDISP_PTR_i8]]
 // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
-// CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
-// CHECK: call x86_thiscallcc void @"?f at D@@UAEXXZ"(i8* noundef %[[ADJUSTED_i8]])
+// CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8, ptr %[[ECX]], i32 %[[VTORDISP_NEG]]
+// CHECK: call x86_thiscallcc void @"?f at D@@UAEXXZ"(ptr noundef %[[ADJUSTED_i8]])
 // CHECK: ret void
 
 // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f at D@@$4PPPPPPPI at 3AEXXZ"
-// CHECK: %[[COERCE_LOAD:.*]] = load %struct.D*, %struct.D** %{{.*}}
-// CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}}
-// CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8*
-// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -8
-// CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32*
-// CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]]
+// CHECK: %[[ECX:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, ptr %[[ECX]], i32 -8
+// CHECK: %[[VTORDISP:.*]] = load i32, ptr %[[VTORDISP_PTR_i8]]
 // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
-// CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
-// CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[VTORDISP_ADJUSTED_i8]], i32 -4
-// CHECK: call x86_thiscallcc void @"?f at D@@UAEXXZ"(i8* noundef %[[ADJUSTED_i8]])
+// CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8, ptr %[[ECX]], i32 %[[VTORDISP_NEG]]
+// CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8, ptr %[[VTORDISP_ADJUSTED_i8]], i32 -4
+// CHECK: call x86_thiscallcc void @"?f at D@@UAEXXZ"(ptr noundef %[[ADJUSTED_i8]])
 // CHECK: ret void
 
 struct E : virtual A {
@@ -66,21 +60,17 @@ struct G : virtual F, virtual E {
 
 G::G() {}  // Forces vftable emission.
 
-// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f at E@@$R4BA at M@PPPPPPPM at 7AEXXZ"(i8*
-// CHECK: %[[COERCE_LOAD:.*]] = load %struct.E*, %struct.E** %{{.*}}
-// CHECK: %[[ECX:.*]] = load %struct.E*, %struct.E** %{{.*}}
-// CHECK: %[[ECX_i8:.*]] = bitcast %struct.E* %[[ECX]] to i8*
-// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4
-// CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32*
-// CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]]
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f at E@@$R4BA at M@PPPPPPPM at 7AEXXZ"(ptr
+// CHECK: %[[ECX:.*]] = load ptr, ptr %{{.*}}
+// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, ptr %[[ECX]], i32 -4
+// CHECK: %[[VTORDISP:.*]] = load i32, ptr %[[VTORDISP_PTR_i8]]
 // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
-// CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
-// CHECK: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[VTORDISP_ADJUSTED_i8]], i32 -16
-// CHECK: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32**
-// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR]]
-// CHECK: %[[VBOFFSET_PTR:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 3
-// CHECK: %[[VBASE_OFFSET:.*]] = load i32, i32* %[[VBOFFSET_PTR]]
-// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
-// CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %[[VBASE]], i32 8
-// CHECK: call x86_thiscallcc void @"?f at E@@UAEXXZ"(i8* noundef %[[ARG_i8]])
+// CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8, ptr %[[ECX]], i32 %[[VTORDISP_NEG]]
+// CHECK: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, ptr %[[VTORDISP_ADJUSTED_i8]], i32 -16
+// CHECK: %[[VBTABLE:.*]] = load ptr, ptr %[[VBPTR_i8]]
+// CHECK: %[[VBOFFSET_PTR:.*]] = getelementptr inbounds i32, ptr %[[VBTABLE]], i32 3
+// CHECK: %[[VBASE_OFFSET:.*]] = load i32, ptr %[[VBOFFSET_PTR]]
+// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, ptr %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
+// CHECK: %[[ARG_i8:.*]] = getelementptr i8, ptr %[[VBASE]], i32 8
+// CHECK: call x86_thiscallcc void @"?f at E@@UAEXXZ"(ptr noundef %[[ARG_i8]])
 // CHECK: ret void

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
index f52a6cdb6fdeb..5726c483e5382 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -no-opaque-pointers %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=i386-pc-win32 -emit-llvm -o %t
+// RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=i386-pc-win32 -emit-llvm -o %t
 // RUN: FileCheck %s < %t
 // RUN: FileCheck --check-prefix=CHECK2 %s < %t
 
 // For now, just make sure x86_64 doesn't crash.
-// RUN: %clang_cc1 -no-opaque-pointers %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=x86_64-pc-win32 -emit-llvm -o %t
+// RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=x86_64-pc-win32 -emit-llvm -o %t
 
 struct VBase {
   virtual ~VBase();
@@ -20,32 +20,26 @@ struct B : virtual VBase {
 };
 
 B::B() {
-  // CHECK-LABEL: define dso_local x86_thiscallcc noundef %struct.B* @"??0B@@QAE at XZ"
-  // CHECK:   %[[THIS:.*]] = load %struct.B*, %struct.B**
+  // CHECK-LABEL: define dso_local x86_thiscallcc noundef ptr @"??0B@@QAE at XZ"
+  // CHECK:   %[[THIS:.*]] = load ptr, ptr
   // CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
 
   // Don't check the INIT_VBASES case as it's covered by the ctor tests.
 
   // CHECK: %[[SKIP_VBASES]]
-  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0
+  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i32 0
   // ...
-  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}}
-  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
-  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @"??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i32 %{{.*}}
+  // CHECK:   store ptr @"??_7B@@6B@", ptr %[[VFPTR_i8]]
 
   // Initialize vtorDisp:
-  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0
+  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i32 0
   // ...
   // CHECK:   %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
   // CHECK:   %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
-  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
-  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8, i8* %[[VBASE_i8]], i32 -4
-  // CHECK:   %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
-  // CHECK:   store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]
+  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i32 %[[VBASE_OFFSET]]
+  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8, ptr %[[VBASE_i8]], i32 -4
+  // CHECK:   store i32 %[[VTORDISP_VAL]], ptr %[[VTORDISP_i8]]
 
   // CHECK: ret
 }
@@ -53,174 +47,138 @@ B::B() {
 B::~B() {
   // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1B@@UAE at XZ"
   // Store initial this:
-  // CHECK:   %[[THIS:.*]] = alloca %struct.B*
-  // CHECK:   %[[THIS_ADDR:.*]] = alloca %struct.B*
-  // CHECK:   store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4
+  // CHECK:   %[[THIS_ADDR:.*]] = alloca ptr
+  // CHECK:   store ptr %{{.*}}, ptr %[[THIS_ADDR]], align 4
   // Reload and adjust the this parameter:
-  // CHECK:   %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
-  // CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8*
-  // CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8
-  // CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B*
+  // CHECK:   %[[THIS_RELOAD:.*]] = load ptr, ptr %[[THIS_ADDR]]
+  // CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_RELOAD]], i32 -8
 
   // Restore the vfptr that could have been changed by a subclass.
-  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0
+  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, ptr %[[THIS_ADJ_i8]], i32 0
   // ...
-  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}}
-  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
-  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @"??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
+  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_ADJ_i8]], i32 %{{.*}}
+  // CHECK:   store ptr @"??_7B@@6B@", ptr %[[VFPTR_i8]]
 
   // Initialize vtorDisp:
-  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0
+  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, ptr %[[THIS_ADJ_i8]], i32 0
   // ...
   // CHECK:   %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
   // CHECK:   %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
-  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
-  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8, i8* %[[VBASE_i8]], i32 -4
-  // CHECK:   %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
-  // CHECK:   store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]
+  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_ADJ_i8]], i32 %[[VBASE_OFFSET]]
+  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8, ptr %[[VBASE_i8]], i32 -4
+  // CHECK:   store i32 %[[VTORDISP_VAL]], ptr %[[VTORDISP_i8]]
 
   foo();  // Avoid the "trivial destructor" optimization.
 
   // CHECK: ret
 
-  // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B*
-  // CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** {{.*}}
-  // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK2: %[[B_i8:.*]] = getelementptr i8, i8* %[[THIS_i8]], i32 8
-  // CHECK2: call x86_thiscallcc void @"??1B@@UAE at XZ"(i8*{{[^,]*}} %[[B_i8]])
-  // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 8
-  // CHECK2: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
-  // CHECK2: call x86_thiscallcc void @"??1VBase@@UAE at XZ"(%struct.VBase* {{[^,]*}} %[[VBASE]])
+  // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"??_DB@@QAEXXZ"(ptr
+  // CHECK2: %[[THIS:.*]] = load ptr, ptr {{.*}}
+  // CHECK2: %[[B_i8:.*]] = getelementptr i8, ptr %[[THIS]], i32 8
+  // CHECK2: call x86_thiscallcc void @"??1B@@UAE at XZ"(ptr{{[^,]*}} %[[B_i8]])
+  // CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i32 8
+  // CHECK2: call x86_thiscallcc void @"??1VBase@@UAE at XZ"(ptr {{[^,]*}} %[[VBASE_i8]])
   // CHECK2: ret
 
-  // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef i8* @"??_GB@@UAEPAXI at Z"
-  // CHECK2:   store %struct.B* %{{.*}}, %struct.B** %[[THIS:.*]], align 4
-  // CHECK2:   store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR:.*]], align 4
-  // CHECK2:   %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
-  // CHECK2:   %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-  // CHECK2:   %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_PARAM_i8:.*]], i32 -8
-  // CHECK2:   %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
-  // CHECK2:   call x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B* {{[^,]*}} %[[THIS]])
+  // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_GB@@UAEPAXI at Z"
+  // CHECK2:   store ptr %{{.*}}, ptr %[[THIS_ADDR:.*]], align 4
+  // CHECK2:   %[[THIS_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_PARAM_i8:.*]], i32 -8
+  // CHECK2:   call x86_thiscallcc void @"??_DB@@QAEXXZ"(ptr {{[^,]*}} %[[THIS_i8]])
   // ...
   // CHECK2: ret
 }
 
 void B::foo() {
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"?foo at B@@UAEXXZ"(i8*
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"?foo at B@@UAEXXZ"(ptr
 //
 // B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we
 // need to adjust 'this' before use.
 //
 // Coerce this to correct type:
-// CHECK:   %[[THIS_STORE:.*]] = alloca %struct.B*
-// CHECK:   %[[THIS_ADDR:.*]] = alloca %struct.B*
-// CHECK:   %[[COERCE_VAL:.*]] = bitcast i8* %{{.*}} to %struct.B*
-// CHECK:   store %struct.B* %[[COERCE_VAL]], %struct.B** %[[THIS_STORE]], align 4
+// CHECK:   %[[THIS_ADDR:.*]] = alloca ptr
 //
 // Store initial this:
-// CHECK:   %[[THIS_INIT:.*]] = load %struct.B*, %struct.B** %[[THIS_STORE]]
-// CHECK:   store %struct.B* %[[THIS_INIT]], %struct.B** %[[THIS_ADDR]], align 4
+// CHECK:   store ptr {{.*}}, ptr %[[THIS_ADDR]], align 4
 //
 // Reload and adjust the this parameter:
-// CHECK:   %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
-// CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8*
-// CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8
-// CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B*
+// CHECK:   %[[THIS_RELOAD:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_RELOAD]], i32 -8
 
   field = 42;
-// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS8]], i32 0
-// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
-// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]]
-// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
-// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
+// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, ptr %[[THIS_ADJ_i8]], i32 0
+// CHECK: %[[VBTABLE:.*]] = load ptr, ptr %[[VBPTR]]
+// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, ptr %[[VBTABLE]], i32 1
+// CHECK: %[[VBOFFSET32:.*]] = load i32, ptr %[[VBENTRY]]
 // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
-// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
-// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS8]], i32 %[[VBOFFSET]]
-// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
-// CHECK: %[[FIELD:.*]] = getelementptr inbounds %struct.VBase, %struct.VBase* %[[VBASE]], i32 0, i32 1
-// CHECK: store i32 42, i32* %[[FIELD]], align 4
+// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_ADJ_i8]], i32 %[[VBOFFSET]]
+// CHECK: %[[FIELD:.*]] = getelementptr inbounds %struct.VBase, ptr %[[VBASE_i8]], i32 0, i32 1
+// CHECK: store i32 42, ptr %[[FIELD]], align 4
 //
 // CHECK: ret void
 }
 
 void call_vbase_bar(B *obj) {
-// CHECK-LABEL: define dso_local void @"?call_vbase_bar@@YAXPAUB@@@Z"(%struct.B* noundef %obj)
-// CHECK: %[[OBJ:.*]] = load %struct.B
+// CHECK-LABEL: define dso_local void @"?call_vbase_bar@@YAXPAUB@@@Z"(ptr noundef %obj)
+// CHECK: %[[OBJ:.*]] = load ptr
 
   obj->bar();
 // When calling a vbase's virtual method, one needs to adjust 'this'
 // at the caller site.
 //
-// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
-// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
-// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
-// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]]
-// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
-// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
+// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, ptr %[[OBJ]], i32 0
+// CHECK: %[[VBTABLE:.*]] = load ptr, ptr %[[VBPTR]]
+// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, ptr %[[VBTABLE]], i32 1
+// CHECK: %[[VBOFFSET32:.*]] = load i32, ptr %[[VBENTRY]]
 // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
-// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
+// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, ptr %[[OBJ]], i32 %[[VBOFFSET]]
 //
-// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
-// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
-// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
-// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]]
-// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
-// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
+// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, ptr %[[OBJ]], i32 0
+// CHECK: %[[VBTABLE:.*]] = load ptr, ptr %[[VBPTR]]
+// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, ptr %[[VBTABLE]], i32 1
+// CHECK: %[[VBOFFSET32:.*]] = load i32, ptr %[[VBENTRY]]
 // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
-// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
-// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
-// CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]]
-// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 2
-// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
+// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, ptr %[[OBJ]], i32 %[[VBOFFSET]]
+// CHECK: %[[VFTABLE:.*]] = load ptr, ptr %[[VBASE_i8]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds ptr, ptr %[[VFTABLE]], i64 2
+// CHECK: %[[VFUN_VALUE:.*]] = load ptr, ptr %[[VFUN]]
 //
-// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* noundef %[[VBASE]])
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](ptr noundef %[[VBASE]])
 //
 // CHECK: ret void
 }
 
 void delete_B(B *obj) {
-// CHECK-LABEL: define dso_local void @"?delete_B@@YAXPAUB@@@Z"(%struct.B* noundef %obj)
-// CHECK: %[[OBJ:.*]] = load %struct.B
+// CHECK-LABEL: define dso_local void @"?delete_B@@YAXPAUB@@@Z"(ptr noundef %obj)
+// CHECK: %[[OBJ:.*]] = load ptr
 
   delete obj;
-// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
-// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
-// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
-// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]]
-// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
-// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
+// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, ptr %[[OBJ]], i32 0
+// CHECK: %[[VBTABLE:.*]] = load ptr, ptr %[[VBPTR]]
+// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, ptr %[[VBTABLE]], i32 1
+// CHECK: %[[VBOFFSET32:.*]] = load i32, ptr %[[VBENTRY]]
 // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
-// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
+// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, ptr %[[OBJ]], i32 %[[VBOFFSET]]
 //
-// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
-// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
-// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
-// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]]
-// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
-// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
+// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, ptr %[[OBJ]], i32 0
+// CHECK: %[[VBTABLE:.*]] = load ptr, ptr %[[VBPTR]]
+// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, ptr %[[VBTABLE]], i32 1
+// CHECK: %[[VBOFFSET32:.*]] = load i32, ptr %[[VBENTRY]]
 // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
-// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
-// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (i8*, i32)***
-// CHECK: %[[VFTABLE:.*]] = load i8* (i8*, i32)**, i8* (i8*, i32)*** %[[VFPTR]]
-// CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (i8*, i32)*, i8* (i8*, i32)** %[[VFTABLE]], i64 0
-// CHECK: %[[VFUN_VALUE:.*]] = load i8* (i8*, i32)*, i8* (i8*, i32)** %[[VFUN]]
+// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, ptr %[[OBJ]], i32 %[[VBOFFSET]]
+// CHECK: %[[VFTABLE:.*]] = load ptr, ptr %[[VBASE_i8]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds ptr, ptr %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load ptr, ptr %[[VFUN]]
 //
-// CHECK: call x86_thiscallcc noundef i8* %[[VFUN_VALUE]](i8* {{[^,]*}} %[[VBASE]], i32 noundef 1)
+// CHECK: call x86_thiscallcc noundef ptr %[[VFUN_VALUE]](ptr {{[^,]*}} %[[VBASE]], i32 noundef 1)
 // CHECK: ret void
 }
 
 void call_complete_dtor() {
   // CHECK-LABEL: define dso_local void @"?call_complete_dtor@@YAXXZ"
   B b;
-  // CHECK: call x86_thiscallcc noundef %struct.B* @"??0B@@QAE at XZ"(%struct.B* {{[^,]*}} %[[B:.*]], i32 noundef 1)
+  // CHECK: call x86_thiscallcc noundef ptr @"??0B@@QAE at XZ"(ptr {{[^,]*}} %[[B:.*]], i32 noundef 1)
   // CHECK-NOT: getelementptr
-  // CHECK: call x86_thiscallcc void @"??_DB@@QAEXXZ"(%struct.B* {{[^,]*}} %[[B]])
+  // CHECK: call x86_thiscallcc void @"??_DB@@QAEXXZ"(ptr {{[^,]*}} %[[B]])
   // CHECK: ret
 }
 
@@ -231,7 +189,7 @@ struct C : B {
 
 // Used to crash on an assertion.
 C::C() {
-// CHECK-LABEL: define dso_local x86_thiscallcc noundef %struct.C* @"??0C@@QAE at XZ"
+// CHECK-LABEL: define dso_local x86_thiscallcc noundef ptr @"??0C@@QAE at XZ"
 }
 
 namespace multiple_vbases {
@@ -255,15 +213,15 @@ struct D : virtual A, virtual B, virtual C {
 };
 
 D::D() {
-  // CHECK-LABEL: define dso_local x86_thiscallcc noundef %"struct.multiple_vbases::D"* @"??0D at multiple_vbases@@QAE at XZ"
+  // CHECK-LABEL: define dso_local x86_thiscallcc noundef ptr @"??0D at multiple_vbases@@QAE at XZ"
   // Just make sure we emit 3 vtordisps after initializing vfptrs.
-  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D at multiple_vbases@@6BA at 1@@" to i32 (...)**), i32 (...)*** %{{.*}}
-  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D at multiple_vbases@@6BB at 1@@" to i32 (...)**), i32 (...)*** %{{.*}}
-  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7D at multiple_vbases@@6BC at 1@@" to i32 (...)**), i32 (...)*** %{{.*}}
+  // CHECK: store ptr @"??_7D at multiple_vbases@@6BA at 1@@", ptr %{{.*}}
+  // CHECK: store ptr @"??_7D at multiple_vbases@@6BB at 1@@", ptr %{{.*}}
+  // CHECK: store ptr @"??_7D at multiple_vbases@@6BC at 1@@", ptr %{{.*}}
   // ...
-  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
-  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
-  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
+  // CHECK: store i32 %{{.*}}, ptr %{{.*}}
+  // CHECK: store i32 %{{.*}}, ptr %{{.*}}
+  // CHECK: store i32 %{{.*}}, ptr %{{.*}}
   // CHECK: ret
 }
 }
@@ -295,29 +253,21 @@ struct D : virtual Z, B, C {
 } d;
 
 D::~D() {
-  // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1D at diamond@@UAE at XZ"(i8*{{.*}})
+  // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1D at diamond@@UAE at XZ"(ptr{{.*}})
   // Store initial this:
-  // CHECK: %[[THIS:.*]] = alloca %"struct.diamond::D"*
-  // CHECK: %[[THIS_ADDR:.*]] = alloca %"struct.diamond::D"*
-  // CHECK: store %"struct.diamond::D"* %{{.*}}, %"struct.diamond::D"** %[[THIS_ADDR]], align 4
+  // CHECK: %[[THIS_ADDR:.*]] = alloca ptr
+  // CHECK: store ptr %{{.*}}, ptr %[[THIS_ADDR]], align 4
   //
   // Reload and adjust the this parameter:
-  // CHECK: %[[THIS_RELOAD:.*]] = load %"struct.diamond::D"*, %"struct.diamond::D"** %[[THIS_ADDR]]
-  // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS_RELOAD]] to i8*
-  // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -24
-  // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.diamond::D"*
+  // CHECK: %[[THIS_RELOAD:.*]] = load ptr, ptr %[[THIS_ADDR]]
+  // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_RELOAD]], i32 -24
   //
-  // CHECK: %[[D_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to i8*
-  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, i8* %[[D_i8]], i32 4
-  // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.diamond::C"*
-  // CHECK: %[[C_i8:.*]] = bitcast %"struct.diamond::C"* %[[C]] to i8*
-  // CHECK: %[[ARG:.*]] = getelementptr i8, i8* %{{.*}}, i32 16
-  // CHECK: call x86_thiscallcc void @"??1C at diamond@@UAE at XZ"(i8*{{[^,]*}} %[[ARG]])
-
-  // CHECK: %[[B:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to %"struct.diamond::B"*
-  // CHECK: %[[B_i8:.*]] = bitcast %"struct.diamond::B"* %[[B]] to i8*
-  // CHECK: %[[ARG:.*]] = getelementptr i8, i8* %[[B_i8]], i32 4
-  // CHECK: call x86_thiscallcc void @"??1B at diamond@@UAE at XZ"(i8*{{[^,]*}} %[[ARG]])
+  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_ADJ_i8]], i32 4
+  // CHECK: %[[ARG:.*]] = getelementptr i8, ptr %{{.*}}, i32 16
+  // CHECK: call x86_thiscallcc void @"??1C at diamond@@UAE at XZ"(ptr{{[^,]*}} %[[ARG]])
+
+  // CHECK: %[[ARG:.*]] = getelementptr i8, ptr %[[THIS_ADJ_i8]], i32 4
+  // CHECK: call x86_thiscallcc void @"??1B at diamond@@UAE at XZ"(ptr{{[^,]*}} %[[ARG]])
   // CHECK: ret void
 }
 
@@ -332,20 +282,20 @@ struct C : B, A { C() {} };
 // call to B() from C().
 void callC() { C x; }
 
-// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef %"struct.test2::C"* @"??0C at test2@@QAE at XZ"
-// CHECK:           (%"struct.test2::C"* {{[^,]*}} returned align 4 dereferenceable(8) %this, i32 noundef %is_most_derived)
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??0C at test2@@QAE at XZ"
+// CHECK:           (ptr {{[^,]*}} returned align 4 dereferenceable(8) %this, i32 noundef %is_most_derived)
 // CHECK: br i1
 //   Virtual bases
-// CHECK: call x86_thiscallcc noundef %"struct.test2::A"* @"??0A at test2@@QAE at XZ"(%"struct.test2::A"* {{[^,]*}} %{{.*}})
+// CHECK: call x86_thiscallcc noundef ptr @"??0A at test2@@QAE at XZ"(ptr {{[^,]*}} %{{.*}})
 // CHECK: br label
 //   Non-virtual bases
-// CHECK: call x86_thiscallcc noundef %"struct.test2::B"* @"??0B at test2@@QAE at XZ"(%"struct.test2::B"* {{[^,]*}} %{{.*}}, i32 noundef 0)
-// CHECK: call x86_thiscallcc noundef %"struct.test2::A"* @"??0A at test2@@QAE at XZ"(%"struct.test2::A"* {{[^,]*}} %{{.*}})
+// CHECK: call x86_thiscallcc noundef ptr @"??0B at test2@@QAE at XZ"(ptr {{[^,]*}} %{{.*}}, i32 noundef 0)
+// CHECK: call x86_thiscallcc noundef ptr @"??0A at test2@@QAE at XZ"(ptr {{[^,]*}} %{{.*}})
 // CHECK: ret
 
-// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef %"struct.test2::B"* @"??0B at test2@@QAE at XZ"
-// CHECK2:           (%"struct.test2::B"* {{[^,]*}} returned align 4 dereferenceable(4) %this, i32 noundef %is_most_derived)
-// CHECK2: call x86_thiscallcc noundef %"struct.test2::A"* @"??0A at test2@@QAE at XZ"(%"struct.test2::A"* {{[^,]*}} %{{.*}})
+// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??0B at test2@@QAE at XZ"
+// CHECK2:           (ptr {{[^,]*}} returned align 4 dereferenceable(4) %this, i32 noundef %is_most_derived)
+// CHECK2: call x86_thiscallcc noundef ptr @"??0A at test2@@QAE at XZ"(ptr {{[^,]*}} %{{.*}})
 // CHECK2: ret
 
 }
@@ -372,18 +322,14 @@ struct D : B, C {
 };
 
 void D::bar() {
-  // CHECK-LABEL: define dso_local x86_thiscallcc void @"?bar at D@test3@@UAEXXZ"(%"struct.test3::D"* {{[^,]*}} %this)
+  // CHECK-LABEL: define dso_local x86_thiscallcc void @"?bar at D@test3@@UAEXXZ"(ptr {{[^,]*}} %this)
 
   C::foo();
   // Shouldn't need any vbtable lookups.  All we have to do is adjust to C*,
   // then compensate for the adjustment performed in the C::foo() prologue.
-  // CHECK-NOT: load i8*, i8**
-  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test3::D"* %{{.*}} to i8*
-  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 8
-  // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.test3::C"*
-  // CHECK: %[[C_i8:.*]] = bitcast %"struct.test3::C"* %[[C]] to i8*
-  // CHECK: %[[ARG:.*]] = getelementptr i8, i8* %[[C_i8]], i32 4
-  // CHECK: call x86_thiscallcc void @"?foo at C@test3@@UAEXXZ"(i8* noundef %[[ARG]])
+  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 8
+  // CHECK: %[[ARG:.*]] = getelementptr i8, ptr %[[C_i8]], i32 4
+  // CHECK: call x86_thiscallcc void @"?foo at C@test3@@UAEXXZ"(ptr noundef %[[ARG]])
   // CHECK: ret
 }
 }
@@ -406,27 +352,25 @@ struct C : virtual A, B {
 void foo(void*);
 
 C::~C() {
-  // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1C at test4@@UAE at XZ"(%"struct.test4::C"* {{[^,]*}} %this)
+  // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1C at test4@@UAE at XZ"(ptr {{[^,]*}} %this)
 
   // In this case "this" points to the most derived class, so no GEPs needed.
   // CHECK-NOT: getelementptr
-  // CHECK-NOT: bitcast
-  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to i32 (...)***
-  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7C at test4@@6BB at 1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
+  // CHECK: store ptr @"??_7C at test4@@6BB at 1@@", ptr %{{.*}}
 
   foo(this);
   // CHECK: ret
 }
 
 void destroy(C *obj) {
-  // CHECK-LABEL: define dso_local void @"?destroy at test4@@YAXPAUC at 1@@Z"(%"struct.test4::C"* noundef %obj)
+  // CHECK-LABEL: define dso_local void @"?destroy at test4@@YAXPAUC at 1@@Z"(ptr noundef %obj)
 
   delete obj;
-  // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to i8* (%"struct.test4::C"*, i32)***
-  // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::C"*, i32)**, i8* (%"struct.test4::C"*, i32)*** %[[VPTR]]
-  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::C"*, i32)*, i8* (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0
-  // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::C"*, i32)*, i8* (%"struct.test4::C"*, i32)** %[[VFTENTRY]]
-  // CHECK: call x86_thiscallcc noundef i8* %[[VFUN]](%"struct.test4::C"* {{[^,]*}} %[[OBJ]], i32 noundef 1)
+  // CHECK: %[[OBJ:.*]] = load ptr, ptr
+  // CHECK: %[[VFTABLE:.*]] = load ptr, ptr %[[OBJ]]
+  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds ptr, ptr %[[VFTABLE]], i64 0
+  // CHECK: %[[VFUN:.*]] = load ptr, ptr %[[VFTENTRY]]
+  // CHECK: call x86_thiscallcc noundef ptr %[[VFUN]](ptr {{[^,]*}} %[[OBJ]], i32 noundef 1)
   // CHECK: ret
 }
 
@@ -441,30 +385,24 @@ struct E : D, B, virtual A {
 };
 
 E::~E() {
-  // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1E at test4@@UAE at XZ"(i8*{{[^,]*}} %this.coerce)
+  // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1E at test4@@UAE at XZ"(ptr{{[^,]*}} %this)
 
   // In this case "this" points to the most derived class, so no GEPs needed.
-  // CHECK: bitcast i8* %this.coerce
   // CHECK-NOT: getelementptr
-  // CHECK-NOT: bitcast
-  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to i32 (...)***
-  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @"??_7E at test4@@6BD at 1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
+  // CHECK: store ptr @"??_7E at test4@@6BD at 1@@", ptr %{{.*}}
   foo(this);
 }
 
 void destroy(E *obj) {
-  // CHECK-LABEL: define dso_local void @"?destroy at test4@@YAXPAUE at 1@@Z"(%"struct.test4::E"* noundef %obj)
+  // CHECK-LABEL: define dso_local void @"?destroy at test4@@YAXPAUE at 1@@Z"(ptr noundef %obj)
 
   // CHECK-NOT: getelementptr
-  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
-  // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
-  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ:.*]] to i8*
-  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
-  // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to i8* (i8*, i32)***
-  // CHECK: %[[VFTABLE:.*]] = load i8* (i8*, i32)**, i8* (i8*, i32)*** %[[VPTR]]
-  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (i8*, i32)*, i8* (i8*, i32)** %[[VFTABLE]], i64 0
-  // CHECK: %[[VFUN:.*]] = load i8* (i8*, i32)*, i8* (i8*, i32)** %[[VFTENTRY]]
-  // CHECK: call x86_thiscallcc noundef i8* %[[VFUN]](i8*{{[^,]*}} %[[THIS_i8]], i32 noundef 1)
+  // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, ptr %[[OBJ]], i32 4
+  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, ptr %[[OBJ:.*]], i32 4
+  // CHECK: %[[VFTABLE:.*]] = load ptr, ptr %[[B_i8]]
+  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds ptr, ptr %[[VFTABLE]], i64 0
+  // CHECK: %[[VFUN:.*]] = load ptr, ptr %[[VFTENTRY]]
+  // CHECK: call x86_thiscallcc noundef ptr %[[VFUN]](ptr{{[^,]*}} %[[THIS_i8]], i32 noundef 1)
   delete obj;
 }
 
@@ -485,15 +423,13 @@ struct C : B {
 };
 
 C::C() : B() {}
-// CHECK-LABEL: define dso_local x86_thiscallcc noundef %"struct.test5::C"* @"??0C at test5@@QAE at XZ"(
-// CHECK:   %[[THIS:.*]] = load %"struct.test5::C"*, %"struct.test5::C"**
+// CHECK-LABEL: define dso_local x86_thiscallcc noundef ptr @"??0C at test5@@QAE at XZ"(
+// CHECK:   %[[THIS:.*]] = load ptr, ptr
 // CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
 
 // CHECK: %[[SKIP_VBASES]]
-// CHECK:   %[[B:.*]] = bitcast %"struct.test5::C"* %[[THIS]] to %"struct.test5::B"*
-// CHECK:   %[[B_i8:.*]] = bitcast %"struct.test5::B"* %[[B]] to i8*
-// CHECK:   %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[B_i8]], i32 4
-// CHECK:   call void @llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
+// CHECK:   %[[FIELD:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i32 4
+// CHECK:   call void @llvm.memset.p0.i32(ptr align 4 %[[FIELD]], i8 0, i32 4, i1 false)
 }
 
 namespace pr27621 {
@@ -509,9 +445,9 @@ struct C final : A, B {
 void callit(C *p) {
   static_cast<B*>(p)->g();
 }
-// CHECK-LABEL: define dso_local void @"?callit at pr27621@@YAXPAUC at 1@@Z"(%"struct.pr27621::C"* noundef %{{.*}})
-// CHECK: %[[B_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 4
-// CHECK: call x86_thiscallcc void @"?g at C@pr27621@@UAEXXZ"(i8* noundef %[[B_i8]])
+// CHECK-LABEL: define dso_local void @"?callit at pr27621@@YAXPAUC at 1@@Z"(ptr noundef %{{.*}})
+// CHECK: %[[B_i8:.*]] = getelementptr i8, ptr %{{.*}}, i32 4
+// CHECK: call x86_thiscallcc void @"?g at C@pr27621@@UAEXXZ"(ptr noundef %[[B_i8]])
 }
 
 namespace test6 {
@@ -525,15 +461,13 @@ class D : C {
   D();
 };
 D::D() : C() {}
-// CHECK-LABEL: define dso_local x86_thiscallcc noundef %"class.test6::D"* @"??0D at test6@@AAE at XZ"(
-// CHECK:   %[[THIS:.*]] = load %"class.test6::D"*, %"class.test6::D"**
+// CHECK-LABEL: define dso_local x86_thiscallcc noundef ptr @"??0D at test6@@AAE at XZ"(
+// CHECK:   %[[THIS:.*]] = load ptr, ptr
 // CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
 
 // CHECK: %[[SKIP_VBASES]]
-// CHECK:   %[[C:.*]] = bitcast %"class.test6::D"* %[[THIS]] to %"class.test6::C"*
-// CHECK:   %[[C_i8:.*]] = bitcast %"class.test6::C"* %[[C]] to i8*
-// CHECK:   %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[C_i8]], i32 8
-// CHECK:   call void @llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
+// CHECK:   %[[FIELD:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i32 8
+// CHECK:   call void @llvm.memset.p0.i32(ptr align 4 %[[FIELD]], i8 0, i32 4, i1 false)
 }
 
 namespace pr36921 {
@@ -546,12 +480,9 @@ struct B {
 struct C : virtual B {};
 struct D : virtual A, C {};
 D d;
-// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef i8* @"??_GD at pr36921@@UAEPAXI at Z"(
-// CHECK2:   %[[THIS:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"**
-// CHECK2:   %[[THIS_RELOAD:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"**
-// CHECK2:   %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.pr36921::D"* %[[THIS_RELOAD]] to i8*
-// CHECK2:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -4
-// CHECK2:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.pr36921::D"*
+// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_GD at pr36921@@UAEPAXI at Z"(
+// CHECK2:   %[[THIS_RELOAD:.*]] = load ptr, ptr
+// CHECK2:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_RELOAD]], i32 -4
 }
 
 namespace issue_60465 {
@@ -567,15 +498,14 @@ struct alignas(2 * sizeof(void *)) B : virtual A {
 };
 
 B::~B() {
-// The 'this' parameter should not have a type of %"struct.issue_60465::B"* and
+// The 'this' parameter should not have a type of ptr and
 // must not have 'align 8', since at least B's copy of A is only 'align 4'.
-// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1B at issue_60465@@UAE at XZ"(i8* noundef %this.coerce)
-// CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %{{.*}}, i32 -12
-// CHECK:   %[[THIS_ADJ:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.issue_60465::B"*
-// CHECK:   %[[X:.*]] = getelementptr inbounds %"struct.issue_60465::B", %"struct.issue_60465::B"* %[[THIS_ADJ]], i32 0, i32 1
-// CHECK:   store i8* null, i8** %[[X]], align 4
-// CHECK:   %[[Y:.*]] = getelementptr inbounds %"struct.issue_60465::B", %"struct.issue_60465::B"* %[[THIS_ADJ]], i32 0, i32 2
-// CHECK:   store i8* null, i8** %[[Y]], align 8
+// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1B at issue_60465@@UAE at XZ"(ptr noundef %this)
+// CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i32 -12
+// CHECK:   %[[X:.*]] = getelementptr inbounds %"struct.issue_60465::B", ptr %[[THIS_ADJ_i8]], i32 0, i32 1
+// CHECK:   store ptr null, ptr %[[X]], align 4
+// CHECK:   %[[Y:.*]] = getelementptr inbounds %"struct.issue_60465::B", ptr %[[THIS_ADJ_i8]], i32 0, i32 2
+// CHECK:   store ptr null, ptr %[[Y]], align 8
   x = nullptr;
   y = nullptr;
 }


        


More information about the cfe-commits mailing list