[clang] [llvm] [clang][OpenMP] Add codegen for scope directive (PR #109197)
David Pagan via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 18 13:58:19 PDT 2024
https://github.com/ddpagan created https://github.com/llvm/llvm-project/pull/109197
Added codegen for scope directive, enabled allocate and firstprivate clauses, and added scope directive LIT test.
Testing
- LIT tests (including new scope test).
- OpenMP scope example test from 5.2 OpenMP API examples document.
- Three executable scope tests from OpenMP_VV/sollve_vv suite.
>From 8b7b24f56b970e6c331ca5b4977182a1f5d3b536 Mon Sep 17 00:00:00 2001
From: Dave Pagan <dave.pagan at amd.com>
Date: Fri, 23 Aug 2024 11:15:58 -0500
Subject: [PATCH] [clang][OpenMP] Add codegen for scope directive
Added codegen for scope directive, enabled allocate and firstprivate
clauses, and added scope directive LIT test.
Testing
- LIT tests (including new scope test).
- OpenMP scope example test from 5.2 OpenMP API examples document.
- Three executable scope tests from OpenMP_VV/sollve_vv suite.
---
clang/lib/CodeGen/CGStmt.cpp | 2 +-
clang/lib/CodeGen/CGStmtOpenMP.cpp | 26 +
clang/lib/CodeGen/CodeGenFunction.h | 1 +
clang/test/OpenMP/error_unsupport_feature.c | 8 -
clang/test/OpenMP/scope_codegen.cpp | 2267 +++++++++++++++++++
llvm/include/llvm/Frontend/OpenMP/OMP.td | 2 +
6 files changed, 2297 insertions(+), 9 deletions(-)
delete mode 100644 clang/test/OpenMP/error_unsupport_feature.c
create mode 100644 clang/test/OpenMP/scope_codegen.cpp
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index b138c87a853495..27cf3de531d8a4 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -420,7 +420,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
CGM.ErrorUnsupported(S, "OpenMP dispatch directive");
break;
case Stmt::OMPScopeDirectiveClass:
- CGM.ErrorUnsupported(S, "scope with FE outlining");
+ EmitOMPScopeDirective(cast<OMPScopeDirective>(*S));
break;
case Stmt::OMPMaskedDirectiveClass:
EmitOMPMaskedDirective(cast<OMPMaskedDirective>(*S));
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 8afe2abf2cc494..b11df8334766a8 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -4223,6 +4223,32 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
}
}
+void CodeGenFunction::EmitOMPScopeDirective(const OMPScopeDirective &S) {
+ {
+ // Emit code for 'scope' region
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ OMPPrivateScope PrivateScope(CGF);
+ (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
+ CGF.EmitOMPPrivateClause(S, PrivateScope);
+ CGF.EmitOMPReductionClauseInit(S, PrivateScope);
+ (void)PrivateScope.Privatize();
+ CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
+ CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
+ };
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_scope, CodeGen);
+ }
+ // Emit an implicit barrier at the end.
+ if (!S.getSingleClause<OMPNowaitClause>()) {
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_scope);
+ }
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
+}
+
void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
if (CGM.getLangOpts().OpenMPIRBuilder) {
llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 6802dc7f0c1598..2df17e83bae2ee 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3823,6 +3823,7 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S);
void EmitOMPForDirective(const OMPForDirective &S);
void EmitOMPForSimdDirective(const OMPForSimdDirective &S);
+ void EmitOMPScopeDirective(const OMPScopeDirective &S);
void EmitOMPSectionsDirective(const OMPSectionsDirective &S);
void EmitOMPSectionDirective(const OMPSectionDirective &S);
void EmitOMPSingleDirective(const OMPSingleDirective &S);
diff --git a/clang/test/OpenMP/error_unsupport_feature.c b/clang/test/OpenMP/error_unsupport_feature.c
deleted file mode 100644
index eb381b3bea1e1a..00000000000000
--- a/clang/test/OpenMP/error_unsupport_feature.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm-only -verify -fopenmp %s
-
-int main () {
- int r = 0;
-#pragma omp scope reduction(+:r) // expected-error {{cannot compile this scope with FE outlining yet}}
- r++;
- return r;
-}
diff --git a/clang/test/OpenMP/scope_codegen.cpp b/clang/test/OpenMP/scope_codegen.cpp
new file mode 100644
index 00000000000000..ef69b8302fa2de
--- /dev/null
+++ b/clang/test/OpenMP/scope_codegen.cpp
@@ -0,0 +1,2267 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _
+// RUN: %clang_cc1 -verify -Wno-vla -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s --check-prefix=CHECK1
+
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify -Wno-vla %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK1
+
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify -Wno-vla %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK4
+
+// RUN: %clang_cc1 -verify -Wno-vla -triple x86_64-apple-darwin10 -std=c++11 -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK5
+// RUN: %clang_cc1 -verify -Wno-vla -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK6
+
+// RUN: %clang_cc1 -verify -Wno-vla -fopenmp-simd -fopenmp-version=52 -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s --implicit-check-not="{{__kmpc|__tgt}}"
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -fnoopenmp-use-tls -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --implicit-check-not="{{__kmpc|__tgt}}"
+// RUN: %clang_cc1 -verify -Wno-vla -triple x86_64-apple-darwin10 -std=c++11 -fopenmp-simd -fopenmp-version=52 -fnoopenmp-use-tls -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --implicit-check-not="{{__kmpc|__tgt}}"
+// RUN: %clang_cc1 -verify -Wno-vla -fopenmp-simd -fopenmp-version=52 -fnoopenmp-use-tls -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s --implicit-check-not="{{__kmpc|__tgt}}"
+// expected-no-diagnostics
+
+typedef void **omp_allocator_handle_t;
+extern const omp_allocator_handle_t omp_null_allocator;
+extern const omp_allocator_handle_t omp_default_mem_alloc;
+extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
+extern const omp_allocator_handle_t omp_const_mem_alloc;
+extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
+extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
+extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
+extern const omp_allocator_handle_t omp_pteam_mem_alloc;
+extern const omp_allocator_handle_t omp_thread_mem_alloc;
+
+#ifndef ARRAY
+#ifndef HEADER
+#define HEADER
+
+class TestClass {
+public:
+ int a;
+ TestClass() : a(0) {}
+ TestClass(const TestClass &C) : a(C.a) {}
+ TestClass &operator=(const TestClass &) { return *this;}
+ ~TestClass(){};
+};
+
+
+TestClass tc;
+TestClass tc2[2];
+
+void foo() { extern void mayThrow(); mayThrow(); }
+
+struct SS {
+ int e;
+ int a;
+ int b : 4;
+ int &c;
+ SS(int &d) : a(0), b(0), c(d) {
+#pragma omp scope private(a, this->b, (this)->c) allocate(omp_default_mem_alloc:b) nowait
+ [&]() {
+ ++this->a, --b, (this)->c /= 1;
+#pragma omp parallel num_threads(b)
+#pragma omp scope firstprivate(a, this->b, (this)->c) reduction(+:e)
+ ++(this)->a, e+=1, this->c /= 1;
+ }();
+ }
+};
+
+template<typename T>
+struct SST {
+ T a;
+ SST() : a(T()) {
+#pragma omp target teams
+#pragma omp parallel firstprivate(a)
+#pragma omp scope private(this->a)
+ [&]() {
+ [&]() {
+ int c;
+ ++this->a;
+#pragma omp parallel firstprivate(a)
+#pragma omp scope private((this)->a) allocate(omp_cgroup_mem_alloc:a)
+ ++(this)->a;
+ }();
+ }();
+ }
+};
+
+int main() {
+ char a;
+ char a2[2];
+ TestClass &c = tc;
+ SST<double> sst;
+ SS ss(c.a);
+
+#pragma omp scope nowait
+ a = 2;
+#pragma omp scope
+ a = 2;
+#pragma omp scope firstprivate(a,c, tc) private(a2, tc2)
+ foo();
+ return a;
+}
+
+
+void parallel_single() {
+#pragma omp parallel
+#pragma omp scope
+ foo();
+}
+#endif
+#else
+struct St {
+ int a, b;
+ St() : a(0), b(0) {}
+ St &operator=(const St &) { return *this; };
+ ~St() {}
+};
+
+void array_func(int n, int a[n], St s[2]) {
+ int b,c;
+#pragma omp scope nowait firstprivate(b) allocate(omp_high_bw_mem_alloc:c) private(a,s) reduction(*:c)
+ ;
+}
+
+int main() {
+ int n;
+ int a[10];
+ St s[2];
+
+ array_func(n, a, s);
+ return 0;
+}
+#endif
+// CHECK1-LABEL: define {{[^@]+}}@__cxx_global_var_init
+// CHECK1-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: call void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) @tc)
+// CHECK1-NEXT: [[TMP0:%.*]] = call i32 @__cxa_atexit(ptr @_ZN9TestClassD1Ev, ptr @tc, ptr @__dso_handle) #[[ATTR3:[0-9]+]]
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZN9TestClassC1Ev
+// CHECK1-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1:[0-9]+]] comdat align 2 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: call void @_ZN9TestClassC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]])
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZN9TestClassD1Ev
+// CHECK1-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2:[0-9]+]] comdat align 2 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: call void @_ZN9TestClassD2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]]
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZN9TestClassC2Ev
+// CHECK1-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[CLASS_TESTCLASS:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK1-NEXT: store i32 0, ptr [[A]], align 4
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZN9TestClassD2Ev
+// CHECK1-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@__cxx_global_var_init.1
+// CHECK1-SAME: () #[[ATTR0]] personality ptr @__gxx_personality_v0 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
+// CHECK1-NEXT: br label [[ARRAYCTOR_LOOP:%.*]]
+// CHECK1: arrayctor.loop:
+// CHECK1-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ @tc2, [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ]
+// CHECK1-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
+// CHECK1-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+// CHECK1: invoke.cont:
+// CHECK1-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS:%.*]], ptr [[ARRAYCTOR_CUR]], i64 1
+// CHECK1-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], getelementptr inbounds ([[CLASS_TESTCLASS]], ptr @tc2, i64 2)
+// CHECK1-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]]
+// CHECK1: arrayctor.cont:
+// CHECK1-NEXT: [[TMP0:%.*]] = call i32 @__cxa_atexit(ptr @__cxx_global_array_dtor, ptr null, ptr @__dso_handle) #[[ATTR3]]
+// CHECK1-NEXT: ret void
+// CHECK1: lpad:
+// CHECK1-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 }
+// CHECK1-NEXT: cleanup
+// CHECK1-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
+// CHECK1-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 8
+// CHECK1-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
+// CHECK1-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK1-NEXT: [[ARRAYDESTROY_ISEMPTY:%.*]] = icmp eq ptr @tc2, [[ARRAYCTOR_CUR]]
+// CHECK1-NEXT: br i1 [[ARRAYDESTROY_ISEMPTY]], label [[ARRAYDESTROY_DONE1:%.*]], label [[ARRAYDESTROY_BODY:%.*]]
+// CHECK1: arraydestroy.body:
+// CHECK1-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[ARRAYCTOR_CUR]], [[LPAD]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ]
+// CHECK1-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1
+// CHECK1-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]]
+// CHECK1-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], @tc2
+// CHECK1-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE1]], label [[ARRAYDESTROY_BODY]]
+// CHECK1: arraydestroy.done1:
+// CHECK1-NEXT: br label [[EH_RESUME:%.*]]
+// CHECK1: eh.resume:
+// CHECK1-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
+// CHECK1-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK1-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
+// CHECK1-NEXT: [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
+// CHECK1-NEXT: resume { ptr, i32 } [[LPAD_VAL2]]
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@__cxx_global_array_dtor
+// CHECK1-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR0]] {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
+// CHECK1-NEXT: br label [[ARRAYDESTROY_BODY:%.*]]
+// CHECK1: arraydestroy.body:
+// CHECK1-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ getelementptr inbounds ([[CLASS_TESTCLASS:%.*]], ptr @tc2, i64 2), [[ENTRY:%.*]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ]
+// CHECK1-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1
+// CHECK1-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]]
+// CHECK1-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], @tc2
+// CHECK1-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE1:%.*]], label [[ARRAYDESTROY_BODY]]
+// CHECK1: arraydestroy.done1:
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_Z3foov
+// CHECK1-SAME: () #[[ATTR1]] {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: call void @_Z8mayThrowv()
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@main
+// CHECK1-SAME: () #[[ATTR5:[0-9]+]] personality ptr @__gxx_personality_v0 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK1-NEXT: [[A:%.*]] = alloca i8, align 1
+// CHECK1-NEXT: [[A2:%.*]] = alloca [2 x i8], align 1
+// CHECK1-NEXT: [[C:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[SST:%.*]] = alloca [[STRUCT_SST:%.*]], align 8
+// CHECK1-NEXT: [[SS:%.*]] = alloca [[STRUCT_SS:%.*]], align 8
+// CHECK1-NEXT: [[A1:%.*]] = alloca i8, align 1
+// CHECK1-NEXT: [[C2:%.*]] = alloca [[CLASS_TESTCLASS:%.*]], align 4
+// CHECK1-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[TC:%.*]] = alloca [[CLASS_TESTCLASS]], align 4
+// CHECK1-NEXT: [[A24:%.*]] = alloca [2 x i8], align 1
+// CHECK1-NEXT: [[TC2:%.*]] = alloca [2 x %class.TestClass], align 4
+// CHECK1-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2:[0-9]+]])
+// CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4
+// CHECK1-NEXT: store ptr @tc, ptr [[C]], align 8
+// CHECK1-NEXT: call void @_ZN3SSTIdEC1Ev(ptr noundef nonnull align 8 dereferenceable(8) [[SST]])
+// CHECK1-NEXT: call void @_ZN2SSC1ERi(ptr noundef nonnull align 8 dereferenceable(24) [[SS]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
+// CHECK1-NEXT: store i8 2, ptr [[A]], align 1
+// CHECK1-NEXT: store i8 2, ptr [[A]], align 1
+// CHECK1-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1:[0-9]+]], i32 [[TMP0]])
+// CHECK1-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
+// CHECK1-NEXT: store i8 [[TMP1]], ptr [[A1]], align 1
+// CHECK1-NEXT: invoke void @_ZN9TestClassC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[C2]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK1: invoke.cont:
+// CHECK1-NEXT: store ptr [[C2]], ptr [[TMP]], align 8
+// CHECK1-NEXT: invoke void @_ZN9TestClassC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[TC]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
+// CHECK1-NEXT: to label [[INVOKE_CONT3:%.*]] unwind label [[TERMINATE_LPAD]]
+// CHECK1: invoke.cont3:
+// CHECK1-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %class.TestClass], ptr [[TC2]], i32 0, i32 0
+// CHECK1-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAY_BEGIN]], i64 2
+// CHECK1-NEXT: br label [[ARRAYCTOR_LOOP:%.*]]
+// CHECK1: arrayctor.loop:
+// CHECK1-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[INVOKE_CONT3]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT5:%.*]] ]
+// CHECK1-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
+// CHECK1-NEXT: to label [[INVOKE_CONT5]] unwind label [[TERMINATE_LPAD]]
+// CHECK1: invoke.cont5:
+// CHECK1-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYCTOR_CUR]], i64 1
+// CHECK1-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]]
+// CHECK1-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]]
+// CHECK1: arrayctor.cont:
+// CHECK1-NEXT: invoke void @_Z3foov()
+// CHECK1-NEXT: to label [[INVOKE_CONT6:%.*]] unwind label [[TERMINATE_LPAD]]
+// CHECK1: invoke.cont6:
+// CHECK1-NEXT: [[ARRAY_BEGIN7:%.*]] = getelementptr inbounds [2 x %class.TestClass], ptr [[TC2]], i32 0, i32 0
+// CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAY_BEGIN7]], i64 2
+// CHECK1-NEXT: br label [[ARRAYDESTROY_BODY:%.*]]
+// CHECK1: arraydestroy.body:
+// CHECK1-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP2]], [[INVOKE_CONT6]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ]
+// CHECK1-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1
+// CHECK1-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]]
+// CHECK1-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN7]]
+// CHECK1-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE8:%.*]], label [[ARRAYDESTROY_BODY]]
+// CHECK1: arraydestroy.done8:
+// CHECK1-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TC]]) #[[ATTR3]]
+// CHECK1-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[C2]]) #[[ATTR3]]
+// CHECK1-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1]], i32 [[TMP0]])
+// CHECK1-NEXT: [[TMP3:%.*]] = load i8, ptr [[A]], align 1
+// CHECK1-NEXT: [[CONV:%.*]] = sext i8 [[TMP3]] to i32
+// CHECK1-NEXT: ret i32 [[CONV]]
+// CHECK1: terminate.lpad:
+// CHECK1-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 }
+// CHECK1-NEXT: catch ptr null
+// CHECK1-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0
+// CHECK1-NEXT: call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR10:[0-9]+]]
+// CHECK1-NEXT: unreachable
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZN3SSTIdEC1Ev
+// CHECK1-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: call void @_ZN3SSTIdEC2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]])
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZN2SSC1ERi
+// CHECK1-SAME: (ptr noundef nonnull align 8 dereferenceable(24) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[D:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[D_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[D]], ptr [[D_ADDR]], align 8
+// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 8
+// CHECK1-NEXT: call void @_ZN2SSC2ERi(ptr noundef nonnull align 8 dereferenceable(24) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]])
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZN9TestClassC1ERKS_
+// CHECK1-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[C]], ptr [[C_ADDR]], align 8
+// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C_ADDR]], align 8
+// CHECK1-NEXT: call void @_ZN9TestClassC2ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]])
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@__clang_call_terminate
+// CHECK1-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR7:[0-9]+]] comdat {
+// CHECK1-NEXT: [[TMP2:%.*]] = call ptr @__cxa_begin_catch(ptr [[TMP0]]) #[[ATTR3]]
+// CHECK1-NEXT: call void @_ZSt9terminatev() #[[ATTR10]]
+// CHECK1-NEXT: unreachable
+//
+//
+//
+//
+//
+//
+//
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZN2SSC2ERi
+// CHECK1-SAME: (ptr noundef nonnull align 8 dereferenceable(24) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[D:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 personality ptr @__gxx_personality_v0 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[D_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[A2:%.*]] = alloca i32, align 4
+// CHECK1-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[C3:%.*]] = alloca i32, align 4
+// CHECK1-NEXT: [[_TMP4:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8
+// CHECK1-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2]])
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[D]], ptr [[D_ADDR]], align 8
+// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_SS:%.*]], ptr [[THIS1]], i32 0, i32 1
+// CHECK1-NEXT: store i32 0, ptr [[A]], align 4
+// CHECK1-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2
+// CHECK1-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[B]], align 8
+// CHECK1-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -16
+// CHECK1-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 0
+// CHECK1-NEXT: store i8 [[BF_SET]], ptr [[B]], align 8
+// CHECK1-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 3
+// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[D_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[TMP1]], ptr [[C]], align 8
+// CHECK1-NEXT: store ptr [[A2]], ptr [[TMP]], align 8
+// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr @omp_default_mem_alloc, align 8
+// CHECK1-NEXT: [[DOTB__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr [[TMP2]])
+// CHECK1-NEXT: store ptr [[C3]], ptr [[_TMP4]], align 8
+// CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 0
+// CHECK1-NEXT: store ptr [[THIS1]], ptr [[TMP3]], align 8
+// CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 1
+// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8
+// CHECK1-NEXT: store ptr [[TMP5]], ptr [[TMP4]], align 8
+// CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 2
+// CHECK1-NEXT: store ptr [[DOTB__VOID_ADDR]], ptr [[TMP6]], align 8
+// CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 3
+// CHECK1-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP4]], align 8
+// CHECK1-NEXT: store ptr [[TMP8]], ptr [[TMP7]], align 8
+// CHECK1-NEXT: invoke void @_ZZN2SSC1ERiENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(32) [[REF_TMP]])
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK1: invoke.cont:
+// CHECK1-NEXT: [[TMP9:%.*]] = load ptr, ptr @omp_default_mem_alloc, align 8
+// CHECK1-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTB__VOID_ADDR]], ptr [[TMP9]])
+// CHECK1-NEXT: ret void
+// CHECK1: terminate.lpad:
+// CHECK1-NEXT: [[TMP10:%.*]] = landingpad { ptr, i32 }
+// CHECK1-NEXT: catch ptr null
+// CHECK1-NEXT: [[TMP11:%.*]] = extractvalue { ptr, i32 } [[TMP10]], 0
+// CHECK1-NEXT: call void @__clang_call_terminate(ptr [[TMP11]]) #[[ATTR10]]
+// CHECK1-NEXT: unreachable
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZZN2SSC1ERiENKUlvE_clEv
+// CHECK1-SAME: (ptr noundef nonnull align 8 dereferenceable(32) [[THIS:%.*]]) #[[ATTR2]] align 2 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2]])
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
+// CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 1
+// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8
+// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
+// CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP5]], 1
+// CHECK1-NEXT: store i32 [[INC]], ptr [[TMP4]], align 4
+// CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 2
+// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8
+// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
+// CHECK1-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP8]], -1
+// CHECK1-NEXT: store i32 [[DEC]], ptr [[TMP7]], align 4
+// CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 3
+// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8
+// CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4
+// CHECK1-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP11]], 1
+// CHECK1-NEXT: store i32 [[DIV]], ptr [[TMP10]], align 4
+// CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 2
+// CHECK1-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8
+// CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4
+// CHECK1-NEXT: call void @__kmpc_push_num_threads(ptr @[[GLOB2]], i32 [[TMP0]], i32 [[TMP14]])
+// CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 1
+// CHECK1-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8
+// CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 2
+// CHECK1-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8
+// CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 3
+// CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8
+// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 4, ptr @_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined, ptr [[TMP2]], ptr [[TMP16]], ptr [[TMP18]], ptr [[TMP20]])
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined
+// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]]) #[[ATTR8:[0-9]+]] {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[E:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[_TMP3:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[_TMP4:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[_TMP5:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[A6:%.*]] = alloca i32, align 4
+// CHECK1-NEXT: [[_TMP7:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[B8:%.*]] = alloca i32, align 4
+// CHECK1-NEXT: [[C9:%.*]] = alloca i32, align 4
+// CHECK1-NEXT: [[_TMP10:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[E11:%.*]] = alloca i32, align 4
+// CHECK1-NEXT: [[_TMP12:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8
+// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[C]], ptr [[C_ADDR]], align 8
+// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[C_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8
+// CHECK1-NEXT: store ptr [[TMP3]], ptr [[_TMP1]], align 8
+// CHECK1-NEXT: [[E2:%.*]] = getelementptr inbounds nuw [[STRUCT_SS:%.*]], ptr [[TMP0]], i32 0, i32 0
+// CHECK1-NEXT: store ptr [[E2]], ptr [[E]], align 8
+// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8
+// CHECK1-NEXT: store ptr [[TMP4]], ptr [[_TMP3]], align 8
+// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[E]], align 8
+// CHECK1-NEXT: store ptr [[TMP5]], ptr [[_TMP4]], align 8
+// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP1]], align 8
+// CHECK1-NEXT: store ptr [[TMP6]], ptr [[_TMP5]], align 8
+// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[_TMP3]], align 8
+// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
+// CHECK1-NEXT: store i32 [[TMP8]], ptr [[A6]], align 4
+// CHECK1-NEXT: store ptr [[A6]], ptr [[_TMP7]], align 8
+// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP2]], align 4
+// CHECK1-NEXT: store i32 [[TMP9]], ptr [[B8]], align 4
+// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[_TMP5]], align 8
+// CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4
+// CHECK1-NEXT: store i32 [[TMP11]], ptr [[C9]], align 4
+// CHECK1-NEXT: store ptr [[C9]], ptr [[_TMP10]], align 8
+// CHECK1-NEXT: [[TMP12:%.*]] = load ptr, ptr [[_TMP4]], align 8
+// CHECK1-NEXT: store i32 0, ptr [[E11]], align 4
+// CHECK1-NEXT: store ptr [[E11]], ptr [[_TMP12]], align 8
+// CHECK1-NEXT: [[TMP13:%.*]] = load ptr, ptr [[_TMP7]], align 8
+// CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4
+// CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP14]], 1
+// CHECK1-NEXT: store i32 [[INC]], ptr [[TMP13]], align 4
+// CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP12]], align 8
+// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
+// CHECK1-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP16]], 1
+// CHECK1-NEXT: store i32 [[ADD]], ptr [[TMP15]], align 4
+// CHECK1-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP10]], align 8
+// CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
+// CHECK1-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP18]], 1
+// CHECK1-NEXT: store i32 [[DIV]], ptr [[TMP17]], align 4
+// CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
+// CHECK1-NEXT: store ptr [[E11]], ptr [[TMP19]], align 8
+// CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
+// CHECK1-NEXT: [[TMP22:%.*]] = call i32 @__kmpc_reduce(ptr @[[GLOB3:[0-9]+]], i32 [[TMP21]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
+// CHECK1-NEXT: switch i32 [[TMP22]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
+// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// CHECK1-NEXT: ]
+// CHECK1: .omp.reduction.case1:
+// CHECK1-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP12]], align 4
+// CHECK1-NEXT: [[TMP24:%.*]] = load i32, ptr [[E11]], align 4
+// CHECK1-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP23]], [[TMP24]]
+// CHECK1-NEXT: store i32 [[ADD13]], ptr [[TMP12]], align 4
+// CHECK1-NEXT: call void @__kmpc_end_reduce(ptr @[[GLOB3]], i32 [[TMP21]], ptr @.gomp_critical_user_.reduction.var)
+// CHECK1-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
+// CHECK1: .omp.reduction.case2:
+// CHECK1-NEXT: [[TMP25:%.*]] = load i32, ptr [[E11]], align 4
+// CHECK1-NEXT: [[TMP26:%.*]] = atomicrmw add ptr [[TMP12]], i32 [[TMP25]] monotonic, align 4
+// CHECK1-NEXT: call void @__kmpc_end_reduce(ptr @[[GLOB3]], i32 [[TMP21]], ptr @.gomp_critical_user_.reduction.var)
+// CHECK1-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
+// CHECK1: .omp.reduction.default:
+// CHECK1-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined.omp.reduction.reduction_func
+// CHECK1-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR9:[0-9]+]] {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
+// CHECK1-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8
+// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR]], align 8
+// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
+// CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP3]], i64 0, i64 0
+// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8
+// CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP2]], i64 0, i64 0
+// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8
+// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
+// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP5]], align 4
+// CHECK1-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP8]], [[TMP9]]
+// CHECK1-NEXT: store i32 [[ADD]], ptr [[TMP7]], align 4
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_ZN9TestClassC2ERKS_
+// CHECK1-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[C]], ptr [[C_ADDR]], align 8
+// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[CLASS_TESTCLASS:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C_ADDR]], align 8
+// CHECK1-NEXT: [[A2:%.*]] = getelementptr inbounds nuw [[CLASS_TESTCLASS]], ptr [[TMP0]], i32 0, i32 0
+// CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[A2]], align 4
+// CHECK1-NEXT: store i32 [[TMP1]], ptr [[A]], align 4
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_Z15parallel_singlev
+// CHECK1-SAME: () #[[ATTR2]] {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 0, ptr @_Z15parallel_singlev.omp_outlined)
+// CHECK1-NEXT: ret void
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_Z15parallel_singlev.omp_outlined
+// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR8]] personality ptr @__gxx_personality_v0 {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK1-NEXT: invoke void @_Z3foov()
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK1: invoke.cont:
+// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4
+// CHECK1-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1]], i32 [[TMP1]])
+// CHECK1-NEXT: ret void
+// CHECK1: terminate.lpad:
+// CHECK1-NEXT: [[TMP2:%.*]] = landingpad { ptr, i32 }
+// CHECK1-NEXT: catch ptr null
+// CHECK1-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP2]], 0
+// CHECK1-NEXT: call void @__clang_call_terminate(ptr [[TMP3]]) #[[ATTR10]]
+// CHECK1-NEXT: unreachable
+//
+//
+// CHECK1-LABEL: define {{[^@]+}}@_GLOBAL__sub_I_scope_codegen.cpp
+// CHECK1-SAME: () #[[ATTR0]] {
+// CHECK1-NEXT: entry:
+// CHECK1-NEXT: call void @__cxx_global_var_init()
+// CHECK1-NEXT: call void @__cxx_global_var_init.1()
+// CHECK1-NEXT: ret void
+//
+//
+//
+//
+//
+//
+//
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@__cxx_global_var_init
+// CHECK4-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: call void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) @tc)
+// CHECK4-NEXT: [[TMP0:%.*]] = call i32 @__cxa_atexit(ptr @_ZN9TestClassD1Ev, ptr @tc, ptr @__dso_handle) #[[ATTR3:[0-9]+]]
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZN9TestClassC1Ev
+// CHECK4-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1:[0-9]+]] comdat align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: call void @_ZN9TestClassC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZN9TestClassD1Ev
+// CHECK4-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2:[0-9]+]] comdat align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: call void @_ZN9TestClassD2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]]
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZN9TestClassC2Ev
+// CHECK4-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[CLASS_TESTCLASS:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK4-NEXT: store i32 0, ptr [[A]], align 4
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZN9TestClassD2Ev
+// CHECK4-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@__cxx_global_var_init.1
+// CHECK4-SAME: () #[[ATTR0]] personality ptr @__gxx_personality_v0 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
+// CHECK4-NEXT: br label [[ARRAYCTOR_LOOP:%.*]]
+// CHECK4: arrayctor.loop:
+// CHECK4-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ @tc2, [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ]
+// CHECK4-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
+// CHECK4-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+// CHECK4: invoke.cont:
+// CHECK4-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS:%.*]], ptr [[ARRAYCTOR_CUR]], i64 1
+// CHECK4-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], getelementptr inbounds ([[CLASS_TESTCLASS]], ptr @tc2, i64 2)
+// CHECK4-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]]
+// CHECK4: arrayctor.cont:
+// CHECK4-NEXT: [[TMP0:%.*]] = call i32 @__cxa_atexit(ptr @__cxx_global_array_dtor, ptr null, ptr @__dso_handle) #[[ATTR3]]
+// CHECK4-NEXT: ret void
+// CHECK4: lpad:
+// CHECK4-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 }
+// CHECK4-NEXT: cleanup
+// CHECK4-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
+// CHECK4-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
+// CHECK4-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK4-NEXT: [[ARRAYDESTROY_ISEMPTY:%.*]] = icmp eq ptr @tc2, [[ARRAYCTOR_CUR]]
+// CHECK4-NEXT: br i1 [[ARRAYDESTROY_ISEMPTY]], label [[ARRAYDESTROY_DONE1:%.*]], label [[ARRAYDESTROY_BODY:%.*]]
+// CHECK4: arraydestroy.body:
+// CHECK4-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[ARRAYCTOR_CUR]], [[LPAD]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ]
+// CHECK4-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1
+// CHECK4-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]]
+// CHECK4-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], @tc2
+// CHECK4-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE1]], label [[ARRAYDESTROY_BODY]]
+// CHECK4: arraydestroy.done1:
+// CHECK4-NEXT: br label [[EH_RESUME:%.*]]
+// CHECK4: eh.resume:
+// CHECK4-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8
+// CHECK4-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
+// CHECK4-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
+// CHECK4-NEXT: [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
+// CHECK4-NEXT: resume { ptr, i32 } [[LPAD_VAL2]]
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@__cxx_global_array_dtor
+// CHECK4-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR0]] {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
+// CHECK4-NEXT: br label [[ARRAYDESTROY_BODY:%.*]]
+// CHECK4: arraydestroy.body:
+// CHECK4-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ getelementptr inbounds ([[CLASS_TESTCLASS:%.*]], ptr @tc2, i64 2), [[ENTRY:%.*]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ]
+// CHECK4-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1
+// CHECK4-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]]
+// CHECK4-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], @tc2
+// CHECK4-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE1:%.*]], label [[ARRAYDESTROY_BODY]]
+// CHECK4: arraydestroy.done1:
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_Z3foov
+// CHECK4-SAME: () #[[ATTR1]] {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: call void @_Z8mayThrowv()
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@main
+// CHECK4-SAME: () #[[ATTR5:[0-9]+]] personality ptr @__gxx_personality_v0 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK4-NEXT: [[A:%.*]] = alloca i8, align 1
+// CHECK4-NEXT: [[A2:%.*]] = alloca [2 x i8], align 1
+// CHECK4-NEXT: [[C:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[SST:%.*]] = alloca [[STRUCT_SST:%.*]], align 8
+// CHECK4-NEXT: [[SS:%.*]] = alloca [[STRUCT_SS:%.*]], align 8
+// CHECK4-NEXT: [[A1:%.*]] = alloca i8, align 1
+// CHECK4-NEXT: [[C2:%.*]] = alloca [[CLASS_TESTCLASS:%.*]], align 4
+// CHECK4-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[TC:%.*]] = alloca [[CLASS_TESTCLASS]], align 4
+// CHECK4-NEXT: [[A24:%.*]] = alloca [2 x i8], align 1
+// CHECK4-NEXT: [[TC2:%.*]] = alloca [2 x %class.TestClass], align 4
+// CHECK4-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2:[0-9]+]])
+// CHECK4-NEXT: store i32 0, ptr [[RETVAL]], align 4
+// CHECK4-NEXT: store ptr @tc, ptr [[C]], align 8
+// CHECK4-NEXT: call void @_ZN3SSTIdEC1Ev(ptr noundef nonnull align 8 dereferenceable(8) [[SST]])
+// CHECK4-NEXT: call void @_ZN2SSC1ERi(ptr noundef nonnull align 8 dereferenceable(24) [[SS]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
+// CHECK4-NEXT: store i8 2, ptr [[A]], align 1
+// CHECK4-NEXT: store i8 2, ptr [[A]], align 1
+// CHECK4-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1:[0-9]+]], i32 [[TMP0]])
+// CHECK4-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
+// CHECK4-NEXT: store i8 [[TMP1]], ptr [[A1]], align 1
+// CHECK4-NEXT: invoke void @_ZN9TestClassC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[C2]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
+// CHECK4-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK4: invoke.cont:
+// CHECK4-NEXT: store ptr [[C2]], ptr [[TMP]], align 8
+// CHECK4-NEXT: invoke void @_ZN9TestClassC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[TC]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
+// CHECK4-NEXT: to label [[INVOKE_CONT3:%.*]] unwind label [[TERMINATE_LPAD]]
+// CHECK4: invoke.cont3:
+// CHECK4-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %class.TestClass], ptr [[TC2]], i32 0, i32 0
+// CHECK4-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAY_BEGIN]], i64 2
+// CHECK4-NEXT: br label [[ARRAYCTOR_LOOP:%.*]]
+// CHECK4: arrayctor.loop:
+// CHECK4-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[INVOKE_CONT3]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT5:%.*]] ]
+// CHECK4-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
+// CHECK4-NEXT: to label [[INVOKE_CONT5]] unwind label [[TERMINATE_LPAD]]
+// CHECK4: invoke.cont5:
+// CHECK4-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYCTOR_CUR]], i64 1
+// CHECK4-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]]
+// CHECK4-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]]
+// CHECK4: arrayctor.cont:
+// CHECK4-NEXT: invoke void @_Z3foov()
+// CHECK4-NEXT: to label [[INVOKE_CONT6:%.*]] unwind label [[TERMINATE_LPAD]]
+// CHECK4: invoke.cont6:
+// CHECK4-NEXT: [[ARRAY_BEGIN7:%.*]] = getelementptr inbounds [2 x %class.TestClass], ptr [[TC2]], i32 0, i32 0
+// CHECK4-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAY_BEGIN7]], i64 2
+// CHECK4-NEXT: br label [[ARRAYDESTROY_BODY:%.*]]
+// CHECK4: arraydestroy.body:
+// CHECK4-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP2]], [[INVOKE_CONT6]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ]
+// CHECK4-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1
+// CHECK4-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]]
+// CHECK4-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN7]]
+// CHECK4-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE8:%.*]], label [[ARRAYDESTROY_BODY]]
+// CHECK4: arraydestroy.done8:
+// CHECK4-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TC]]) #[[ATTR3]]
+// CHECK4-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[C2]]) #[[ATTR3]]
+// CHECK4-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1]], i32 [[TMP0]])
+// CHECK4-NEXT: [[TMP3:%.*]] = load i8, ptr [[A]], align 1
+// CHECK4-NEXT: [[CONV:%.*]] = sext i8 [[TMP3]] to i32
+// CHECK4-NEXT: ret i32 [[CONV]]
+// CHECK4: terminate.lpad:
+// CHECK4-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 }
+// CHECK4-NEXT: catch ptr null
+// CHECK4-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0
+// CHECK4-NEXT: call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR10:[0-9]+]]
+// CHECK4-NEXT: unreachable
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZN3SSTIdEC1Ev
+// CHECK4-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: call void @_ZN3SSTIdEC2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZN2SSC1ERi
+// CHECK4-SAME: (ptr noundef nonnull align 8 dereferenceable(24) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[D:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[D_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[D]], ptr [[D_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 8
+// CHECK4-NEXT: call void @_ZN2SSC2ERi(ptr noundef nonnull align 8 dereferenceable(24) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZN9TestClassC1ERKS_
+// CHECK4-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[C]], ptr [[C_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C_ADDR]], align 8
+// CHECK4-NEXT: call void @_ZN9TestClassC2ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@__clang_call_terminate
+// CHECK4-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR7:[0-9]+]] comdat {
+// CHECK4-NEXT: [[TMP2:%.*]] = call ptr @__cxa_begin_catch(ptr [[TMP0]]) #[[ATTR3]]
+// CHECK4-NEXT: call void @_ZSt9terminatev() #[[ATTR10]]
+// CHECK4-NEXT: unreachable
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZN3SSTIdEC2Ev
+// CHECK4-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_SST:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK4-NEXT: store double 0.000000e+00, ptr [[A]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr @omp_cgroup_mem_alloc, align 8
+// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr @omp_null_allocator, align 8
+// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr @omp_default_mem_alloc, align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr @omp_large_cap_mem_alloc, align 8
+// CHECK4-NEXT: [[TMP4:%.*]] = load ptr, ptr @omp_const_mem_alloc, align 8
+// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr @omp_high_bw_mem_alloc, align 8
+// CHECK4-NEXT: [[TMP6:%.*]] = load ptr, ptr @omp_low_lat_mem_alloc, align 8
+// CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr @omp_pteam_mem_alloc, align 8
+// CHECK4-NEXT: [[TMP8:%.*]] = load ptr, ptr @omp_thread_mem_alloc, align 8
+// CHECK4-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70(ptr [[THIS1]], ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]], ptr [[TMP3]], ptr [[TMP4]], ptr [[TMP5]], ptr [[TMP6]], ptr [[TMP7]], ptr [[TMP8]]) #[[ATTR3]]
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70
+// CHECK4-SAME: (ptr noundef [[THIS:%.*]], ptr noundef [[OMP_CGROUP_MEM_ALLOC:%.*]], ptr noundef [[OMP_NULL_ALLOCATOR:%.*]], ptr noundef [[OMP_DEFAULT_MEM_ALLOC:%.*]], ptr noundef [[OMP_LARGE_CAP_MEM_ALLOC:%.*]], ptr noundef [[OMP_CONST_MEM_ALLOC:%.*]], ptr noundef [[OMP_HIGH_BW_MEM_ALLOC:%.*]], ptr noundef [[OMP_LOW_LAT_MEM_ALLOC:%.*]], ptr noundef [[OMP_PTEAM_MEM_ALLOC:%.*]], ptr noundef [[OMP_THREAD_MEM_ALLOC:%.*]]) #[[ATTR8:[0-9]+]] {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_CGROUP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_NULL_ALLOCATOR_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_DEFAULT_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_LARGE_CAP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_CONST_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_HIGH_BW_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_LOW_LAT_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_PTEAM_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_THREAD_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_CGROUP_MEM_ALLOC]], ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_NULL_ALLOCATOR]], ptr [[OMP_NULL_ALLOCATOR_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_DEFAULT_MEM_ALLOC]], ptr [[OMP_DEFAULT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_LARGE_CAP_MEM_ALLOC]], ptr [[OMP_LARGE_CAP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_CONST_MEM_ALLOC]], ptr [[OMP_CONST_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_HIGH_BW_MEM_ALLOC]], ptr [[OMP_HIGH_BW_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_LOW_LAT_MEM_ALLOC]], ptr [[OMP_LOW_LAT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_PTEAM_MEM_ALLOC]], ptr [[OMP_PTEAM_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_THREAD_MEM_ALLOC]], ptr [[OMP_THREAD_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr [[OMP_NULL_ALLOCATOR_ADDR]], align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr [[OMP_DEFAULT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP4:%.*]] = load ptr, ptr [[OMP_LARGE_CAP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[OMP_CONST_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP6:%.*]] = load ptr, ptr [[OMP_HIGH_BW_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr [[OMP_LOW_LAT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP8:%.*]] = load ptr, ptr [[OMP_PTEAM_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP9:%.*]] = load ptr, ptr [[OMP_THREAD_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB2]], i32 10, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70.omp_outlined, ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]], ptr [[TMP3]], ptr [[TMP4]], ptr [[TMP5]], ptr [[TMP6]], ptr [[TMP7]], ptr [[TMP8]], ptr [[TMP9]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70.omp_outlined
+// CHECK4-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef [[OMP_CGROUP_MEM_ALLOC:%.*]], ptr noundef [[OMP_NULL_ALLOCATOR:%.*]], ptr noundef [[OMP_DEFAULT_MEM_ALLOC:%.*]], ptr noundef [[OMP_LARGE_CAP_MEM_ALLOC:%.*]], ptr noundef [[OMP_CONST_MEM_ALLOC:%.*]], ptr noundef [[OMP_HIGH_BW_MEM_ALLOC:%.*]], ptr noundef [[OMP_LOW_LAT_MEM_ALLOC:%.*]], ptr noundef [[OMP_PTEAM_MEM_ALLOC:%.*]], ptr noundef [[OMP_THREAD_MEM_ALLOC:%.*]]) #[[ATTR8]] {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_CGROUP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_NULL_ALLOCATOR_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_DEFAULT_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_LARGE_CAP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_CONST_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_HIGH_BW_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_LOW_LAT_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_PTEAM_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_THREAD_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[A:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[A_CASTED:%.*]] = alloca i64, align 8
+// CHECK4-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK4-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_CGROUP_MEM_ALLOC]], ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_NULL_ALLOCATOR]], ptr [[OMP_NULL_ALLOCATOR_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_DEFAULT_MEM_ALLOC]], ptr [[OMP_DEFAULT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_LARGE_CAP_MEM_ALLOC]], ptr [[OMP_LARGE_CAP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_CONST_MEM_ALLOC]], ptr [[OMP_CONST_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_HIGH_BW_MEM_ALLOC]], ptr [[OMP_HIGH_BW_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_LOW_LAT_MEM_ALLOC]], ptr [[OMP_LOW_LAT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_PTEAM_MEM_ALLOC]], ptr [[OMP_PTEAM_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_THREAD_MEM_ALLOC]], ptr [[OMP_THREAD_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_SST:%.*]], ptr [[TMP0]], i32 0, i32 0
+// CHECK4-NEXT: store ptr [[A1]], ptr [[A]], align 8
+// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A]], align 8
+// CHECK4-NEXT: [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8
+// CHECK4-NEXT: store double [[TMP2]], ptr [[A_CASTED]], align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = load i64, ptr [[A_CASTED]], align 8
+// CHECK4-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 11, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70.omp_outlined.omp_outlined, ptr [[TMP0]], ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], ptr [[OMP_NULL_ALLOCATOR_ADDR]], ptr [[OMP_DEFAULT_MEM_ALLOC_ADDR]], ptr [[OMP_LARGE_CAP_MEM_ALLOC_ADDR]], ptr [[OMP_CONST_MEM_ALLOC_ADDR]], ptr [[OMP_HIGH_BW_MEM_ALLOC_ADDR]], ptr [[OMP_LOW_LAT_MEM_ALLOC_ADDR]], ptr [[OMP_PTEAM_MEM_ALLOC_ADDR]], ptr [[OMP_THREAD_MEM_ALLOC_ADDR]], i64 [[TMP3]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70.omp_outlined.omp_outlined
+// CHECK4-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_CGROUP_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_NULL_ALLOCATOR:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_DEFAULT_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_LARGE_CAP_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_CONST_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_HIGH_BW_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_LOW_LAT_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_PTEAM_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_THREAD_MEM_ALLOC:%.*]], i64 noundef [[A:%.*]]) #[[ATTR8]] personality ptr @__gxx_personality_v0 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_CGROUP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_NULL_ALLOCATOR_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_DEFAULT_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_LARGE_CAP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_CONST_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_HIGH_BW_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_LOW_LAT_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_PTEAM_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_THREAD_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
+// CHECK4-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[A1:%.*]] = alloca double, align 8
+// CHECK4-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON:%.*]], align 8
+// CHECK4-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK4-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_CGROUP_MEM_ALLOC]], ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_NULL_ALLOCATOR]], ptr [[OMP_NULL_ALLOCATOR_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_DEFAULT_MEM_ALLOC]], ptr [[OMP_DEFAULT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_LARGE_CAP_MEM_ALLOC]], ptr [[OMP_LARGE_CAP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_CONST_MEM_ALLOC]], ptr [[OMP_CONST_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_HIGH_BW_MEM_ALLOC]], ptr [[OMP_HIGH_BW_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_LOW_LAT_MEM_ALLOC]], ptr [[OMP_LOW_LAT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_PTEAM_MEM_ALLOC]], ptr [[OMP_PTEAM_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_THREAD_MEM_ALLOC]], ptr [[OMP_THREAD_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr [[OMP_NULL_ALLOCATOR_ADDR]], align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr [[OMP_DEFAULT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP4:%.*]] = load ptr, ptr [[OMP_LARGE_CAP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[OMP_CONST_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP6:%.*]] = load ptr, ptr [[OMP_HIGH_BW_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr [[OMP_LOW_LAT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP8:%.*]] = load ptr, ptr [[OMP_PTEAM_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP9:%.*]] = load ptr, ptr [[OMP_THREAD_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 8
+// CHECK4-NEXT: store ptr [[A1]], ptr [[_TMP2]], align 8
+// CHECK4-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 0
+// CHECK4-NEXT: store ptr [[TMP0]], ptr [[TMP10]], align 8
+// CHECK4-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 1
+// CHECK4-NEXT: [[TMP12:%.*]] = load ptr, ptr [[_TMP2]], align 8
+// CHECK4-NEXT: store ptr [[TMP12]], ptr [[TMP11]], align 8
+// CHECK4-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 2
+// CHECK4-NEXT: store ptr [[TMP1]], ptr [[TMP13]], align 8
+// CHECK4-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 3
+// CHECK4-NEXT: store ptr [[TMP2]], ptr [[TMP14]], align 8
+// CHECK4-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 4
+// CHECK4-NEXT: store ptr [[TMP3]], ptr [[TMP15]], align 8
+// CHECK4-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 5
+// CHECK4-NEXT: store ptr [[TMP4]], ptr [[TMP16]], align 8
+// CHECK4-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 6
+// CHECK4-NEXT: store ptr [[TMP5]], ptr [[TMP17]], align 8
+// CHECK4-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 7
+// CHECK4-NEXT: store ptr [[TMP6]], ptr [[TMP18]], align 8
+// CHECK4-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 8
+// CHECK4-NEXT: store ptr [[TMP7]], ptr [[TMP19]], align 8
+// CHECK4-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 9
+// CHECK4-NEXT: store ptr [[TMP8]], ptr [[TMP20]], align 8
+// CHECK4-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 10
+// CHECK4-NEXT: store ptr [[TMP9]], ptr [[TMP21]], align 8
+// CHECK4-NEXT: invoke void @_ZZN3SSTIdEC1EvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(88) [[REF_TMP]])
+// CHECK4-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK4: invoke.cont:
+// CHECK4-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK4-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
+// CHECK4-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1]], i32 [[TMP23]])
+// CHECK4-NEXT: ret void
+// CHECK4: terminate.lpad:
+// CHECK4-NEXT: [[TMP24:%.*]] = landingpad { ptr, i32 }
+// CHECK4-NEXT: catch ptr null
+// CHECK4-NEXT: [[TMP25:%.*]] = extractvalue { ptr, i32 } [[TMP24]], 0
+// CHECK4-NEXT: call void @__clang_call_terminate(ptr [[TMP25]]) #[[ATTR10]]
+// CHECK4-NEXT: unreachable
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZZN3SSTIdEC1EvENKUlvE_clEv
+// CHECK4-SAME: (ptr noundef nonnull align 8 dereferenceable(88) [[THIS:%.*]]) #[[ATTR1]] align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON_0:%.*]], align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CLASS_ANON:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK4-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0
+// CHECK4-NEXT: store ptr [[TMP1]], ptr [[TMP2]], align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 1
+// CHECK4-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 1
+// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8
+// CHECK4-NEXT: store ptr [[TMP5]], ptr [[TMP3]], align 8
+// CHECK4-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 2
+// CHECK4-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 2
+// CHECK4-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8
+// CHECK4-NEXT: store ptr [[TMP8]], ptr [[TMP6]], align 8
+// CHECK4-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 3
+// CHECK4-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 3
+// CHECK4-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP10]], align 8
+// CHECK4-NEXT: store ptr [[TMP11]], ptr [[TMP9]], align 8
+// CHECK4-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 4
+// CHECK4-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 4
+// CHECK4-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8
+// CHECK4-NEXT: store ptr [[TMP14]], ptr [[TMP12]], align 8
+// CHECK4-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 5
+// CHECK4-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 5
+// CHECK4-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 8
+// CHECK4-NEXT: store ptr [[TMP17]], ptr [[TMP15]], align 8
+// CHECK4-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 6
+// CHECK4-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 6
+// CHECK4-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8
+// CHECK4-NEXT: store ptr [[TMP20]], ptr [[TMP18]], align 8
+// CHECK4-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 7
+// CHECK4-NEXT: [[TMP22:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 7
+// CHECK4-NEXT: [[TMP23:%.*]] = load ptr, ptr [[TMP22]], align 8
+// CHECK4-NEXT: store ptr [[TMP23]], ptr [[TMP21]], align 8
+// CHECK4-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 8
+// CHECK4-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 8
+// CHECK4-NEXT: [[TMP26:%.*]] = load ptr, ptr [[TMP25]], align 8
+// CHECK4-NEXT: store ptr [[TMP26]], ptr [[TMP24]], align 8
+// CHECK4-NEXT: [[TMP27:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 9
+// CHECK4-NEXT: [[TMP28:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 9
+// CHECK4-NEXT: [[TMP29:%.*]] = load ptr, ptr [[TMP28]], align 8
+// CHECK4-NEXT: store ptr [[TMP29]], ptr [[TMP27]], align 8
+// CHECK4-NEXT: [[TMP30:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 10
+// CHECK4-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 10
+// CHECK4-NEXT: [[TMP32:%.*]] = load ptr, ptr [[TMP31]], align 8
+// CHECK4-NEXT: store ptr [[TMP32]], ptr [[TMP30]], align 8
+// CHECK4-NEXT: call void @_ZZZN3SSTIdEC1EvENKUlvE_clEvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(88) [[REF_TMP]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZZZN3SSTIdEC1EvENKUlvE_clEvENKUlvE_clEv
+// CHECK4-SAME: (ptr noundef nonnull align 8 dereferenceable(88) [[THIS:%.*]]) #[[ATTR2]] align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[C:%.*]] = alloca i32, align 4
+// CHECK4-NEXT: [[A_CASTED:%.*]] = alloca i64, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK4-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 1
+// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP2]], align 8
+// CHECK4-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8
+// CHECK4-NEXT: [[INC:%.*]] = fadd double [[TMP4]], 1.000000e+00
+// CHECK4-NEXT: store double [[INC]], ptr [[TMP3]], align 8
+// CHECK4-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 2
+// CHECK4-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP5]], align 8
+// CHECK4-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 1
+// CHECK4-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8
+// CHECK4-NEXT: [[TMP9:%.*]] = load double, ptr [[TMP8]], align 8
+// CHECK4-NEXT: store double [[TMP9]], ptr [[A_CASTED]], align 8
+// CHECK4-NEXT: [[TMP10:%.*]] = load i64, ptr [[A_CASTED]], align 8
+// CHECK4-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 3
+// CHECK4-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 8
+// CHECK4-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 4
+// CHECK4-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8
+// CHECK4-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 5
+// CHECK4-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8
+// CHECK4-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 6
+// CHECK4-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8
+// CHECK4-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 7
+// CHECK4-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8
+// CHECK4-NEXT: [[TMP21:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 8
+// CHECK4-NEXT: [[TMP22:%.*]] = load ptr, ptr [[TMP21]], align 8
+// CHECK4-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 9
+// CHECK4-NEXT: [[TMP24:%.*]] = load ptr, ptr [[TMP23]], align 8
+// CHECK4-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 10
+// CHECK4-NEXT: [[TMP26:%.*]] = load ptr, ptr [[TMP25]], align 8
+// CHECK4-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 11, ptr @_ZZZN3SSTIdEC1EvENKUlvE_clEvENKUlvE_clEv.omp_outlined, ptr [[TMP1]], ptr [[TMP6]], i64 [[TMP10]], ptr [[TMP12]], ptr [[TMP14]], ptr [[TMP16]], ptr [[TMP18]], ptr [[TMP20]], ptr [[TMP22]], ptr [[TMP24]], ptr [[TMP26]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZZZN3SSTIdEC1EvENKUlvE_clEvENKUlvE_clEv.omp_outlined
+// CHECK4-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_CGROUP_MEM_ALLOC:%.*]], i64 noundef [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_NULL_ALLOCATOR:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_DEFAULT_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_LARGE_CAP_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_CONST_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_HIGH_BW_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_LOW_LAT_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_PTEAM_MEM_ALLOC:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_THREAD_MEM_ALLOC:%.*]]) #[[ATTR8]] {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_CGROUP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
+// CHECK4-NEXT: [[OMP_NULL_ALLOCATOR_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_DEFAULT_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_LARGE_CAP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_CONST_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_HIGH_BW_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_LOW_LAT_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_PTEAM_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[OMP_THREAD_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK4-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_CGROUP_MEM_ALLOC]], ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_NULL_ALLOCATOR]], ptr [[OMP_NULL_ALLOCATOR_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_DEFAULT_MEM_ALLOC]], ptr [[OMP_DEFAULT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_LARGE_CAP_MEM_ALLOC]], ptr [[OMP_LARGE_CAP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_CONST_MEM_ALLOC]], ptr [[OMP_CONST_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_HIGH_BW_MEM_ALLOC]], ptr [[OMP_HIGH_BW_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_LOW_LAT_MEM_ALLOC]], ptr [[OMP_LOW_LAT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_PTEAM_MEM_ALLOC]], ptr [[OMP_PTEAM_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[OMP_THREAD_MEM_ALLOC]], ptr [[OMP_THREAD_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr [[OMP_NULL_ALLOCATOR_ADDR]], align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr [[OMP_DEFAULT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP4:%.*]] = load ptr, ptr [[OMP_LARGE_CAP_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[OMP_CONST_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP6:%.*]] = load ptr, ptr [[OMP_HIGH_BW_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr [[OMP_LOW_LAT_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP8:%.*]] = load ptr, ptr [[OMP_PTEAM_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: [[TMP9:%.*]] = load ptr, ptr [[OMP_THREAD_MEM_ALLOC_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 8
+// CHECK4-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK4-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4
+// CHECK4-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP1]], align 8
+// CHECK4-NEXT: [[DOTA__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP11]], i64 8, ptr [[TMP12]])
+// CHECK4-NEXT: store ptr [[DOTA__VOID_ADDR]], ptr [[_TMP1]], align 8
+// CHECK4-NEXT: [[TMP13:%.*]] = load ptr, ptr [[_TMP1]], align 8
+// CHECK4-NEXT: [[TMP14:%.*]] = load double, ptr [[TMP13]], align 8
+// CHECK4-NEXT: [[INC:%.*]] = fadd double [[TMP14]], 1.000000e+00
+// CHECK4-NEXT: store double [[INC]], ptr [[TMP13]], align 8
+// CHECK4-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP1]], align 8
+// CHECK4-NEXT: call void @__kmpc_free(i32 [[TMP11]], ptr [[DOTA__VOID_ADDR]], ptr [[TMP15]])
+// CHECK4-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1]], i32 [[TMP11]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZN2SSC2ERi
+// CHECK4-SAME: (ptr noundef nonnull align 8 dereferenceable(24) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[D:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 personality ptr @__gxx_personality_v0 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[D_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[A2:%.*]] = alloca i32, align 4
+// CHECK4-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[C3:%.*]] = alloca i32, align 4
+// CHECK4-NEXT: [[_TMP4:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2]])
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[D]], ptr [[D_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_SS:%.*]], ptr [[THIS1]], i32 0, i32 1
+// CHECK4-NEXT: store i32 0, ptr [[A]], align 4
+// CHECK4-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2
+// CHECK4-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[B]], align 8
+// CHECK4-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -16
+// CHECK4-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 0
+// CHECK4-NEXT: store i8 [[BF_SET]], ptr [[B]], align 8
+// CHECK4-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 3
+// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[D_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[TMP1]], ptr [[C]], align 8
+// CHECK4-NEXT: store ptr [[A2]], ptr [[TMP]], align 8
+// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr @omp_default_mem_alloc, align 8
+// CHECK4-NEXT: [[DOTB__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr [[TMP2]])
+// CHECK4-NEXT: store ptr [[C3]], ptr [[_TMP4]], align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 0
+// CHECK4-NEXT: store ptr [[THIS1]], ptr [[TMP3]], align 8
+// CHECK4-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 1
+// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8
+// CHECK4-NEXT: store ptr [[TMP5]], ptr [[TMP4]], align 8
+// CHECK4-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 2
+// CHECK4-NEXT: store ptr [[DOTB__VOID_ADDR]], ptr [[TMP6]], align 8
+// CHECK4-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 3
+// CHECK4-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP4]], align 8
+// CHECK4-NEXT: store ptr [[TMP8]], ptr [[TMP7]], align 8
+// CHECK4-NEXT: invoke void @_ZZN2SSC1ERiENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(32) [[REF_TMP]])
+// CHECK4-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK4: invoke.cont:
+// CHECK4-NEXT: [[TMP9:%.*]] = load ptr, ptr @omp_default_mem_alloc, align 8
+// CHECK4-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTB__VOID_ADDR]], ptr [[TMP9]])
+// CHECK4-NEXT: ret void
+// CHECK4: terminate.lpad:
+// CHECK4-NEXT: [[TMP10:%.*]] = landingpad { ptr, i32 }
+// CHECK4-NEXT: catch ptr null
+// CHECK4-NEXT: [[TMP11:%.*]] = extractvalue { ptr, i32 } [[TMP10]], 0
+// CHECK4-NEXT: call void @__clang_call_terminate(ptr [[TMP11]]) #[[ATTR10]]
+// CHECK4-NEXT: unreachable
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZZN2SSC1ERiENKUlvE_clEv
+// CHECK4-SAME: (ptr noundef nonnull align 8 dereferenceable(32) [[THIS:%.*]]) #[[ATTR2]] align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2]])
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 1
+// CHECK4-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8
+// CHECK4-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
+// CHECK4-NEXT: [[INC:%.*]] = add nsw i32 [[TMP5]], 1
+// CHECK4-NEXT: store i32 [[INC]], ptr [[TMP4]], align 4
+// CHECK4-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 2
+// CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8
+// CHECK4-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
+// CHECK4-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP8]], -1
+// CHECK4-NEXT: store i32 [[DEC]], ptr [[TMP7]], align 4
+// CHECK4-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 3
+// CHECK4-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8
+// CHECK4-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4
+// CHECK4-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP11]], 1
+// CHECK4-NEXT: store i32 [[DIV]], ptr [[TMP10]], align 4
+// CHECK4-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 2
+// CHECK4-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8
+// CHECK4-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4
+// CHECK4-NEXT: call void @__kmpc_push_num_threads(ptr @[[GLOB2]], i32 [[TMP0]], i32 [[TMP14]])
+// CHECK4-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 1
+// CHECK4-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8
+// CHECK4-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 2
+// CHECK4-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8
+// CHECK4-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 3
+// CHECK4-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8
+// CHECK4-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 4, ptr @_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined, ptr [[TMP2]], ptr [[TMP16]], ptr [[TMP18]], ptr [[TMP20]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined
+// CHECK4-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]]) #[[ATTR8]] {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[E:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[_TMP3:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[_TMP4:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[_TMP5:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[A6:%.*]] = alloca i32, align 4
+// CHECK4-NEXT: [[_TMP7:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[B8:%.*]] = alloca i32, align 4
+// CHECK4-NEXT: [[C9:%.*]] = alloca i32, align 4
+// CHECK4-NEXT: [[_TMP10:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[E11:%.*]] = alloca i32, align 4
+// CHECK4-NEXT: [[_TMP12:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8
+// CHECK4-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK4-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[C]], ptr [[C_ADDR]], align 8
+// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr [[C_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8
+// CHECK4-NEXT: store ptr [[TMP3]], ptr [[_TMP1]], align 8
+// CHECK4-NEXT: [[E2:%.*]] = getelementptr inbounds nuw [[STRUCT_SS:%.*]], ptr [[TMP0]], i32 0, i32 0
+// CHECK4-NEXT: store ptr [[E2]], ptr [[E]], align 8
+// CHECK4-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8
+// CHECK4-NEXT: store ptr [[TMP4]], ptr [[_TMP3]], align 8
+// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[E]], align 8
+// CHECK4-NEXT: store ptr [[TMP5]], ptr [[_TMP4]], align 8
+// CHECK4-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP1]], align 8
+// CHECK4-NEXT: store ptr [[TMP6]], ptr [[_TMP5]], align 8
+// CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr [[_TMP3]], align 8
+// CHECK4-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
+// CHECK4-NEXT: store i32 [[TMP8]], ptr [[A6]], align 4
+// CHECK4-NEXT: store ptr [[A6]], ptr [[_TMP7]], align 8
+// CHECK4-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP2]], align 4
+// CHECK4-NEXT: store i32 [[TMP9]], ptr [[B8]], align 4
+// CHECK4-NEXT: [[TMP10:%.*]] = load ptr, ptr [[_TMP5]], align 8
+// CHECK4-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4
+// CHECK4-NEXT: store i32 [[TMP11]], ptr [[C9]], align 4
+// CHECK4-NEXT: store ptr [[C9]], ptr [[_TMP10]], align 8
+// CHECK4-NEXT: [[TMP12:%.*]] = load ptr, ptr [[_TMP4]], align 8
+// CHECK4-NEXT: store i32 0, ptr [[E11]], align 4
+// CHECK4-NEXT: store ptr [[E11]], ptr [[_TMP12]], align 8
+// CHECK4-NEXT: [[TMP13:%.*]] = load ptr, ptr [[_TMP7]], align 8
+// CHECK4-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4
+// CHECK4-NEXT: [[INC:%.*]] = add nsw i32 [[TMP14]], 1
+// CHECK4-NEXT: store i32 [[INC]], ptr [[TMP13]], align 4
+// CHECK4-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP12]], align 8
+// CHECK4-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
+// CHECK4-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP16]], 1
+// CHECK4-NEXT: store i32 [[ADD]], ptr [[TMP15]], align 4
+// CHECK4-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP10]], align 8
+// CHECK4-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
+// CHECK4-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP18]], 1
+// CHECK4-NEXT: store i32 [[DIV]], ptr [[TMP17]], align 4
+// CHECK4-NEXT: [[TMP19:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
+// CHECK4-NEXT: store ptr [[E11]], ptr [[TMP19]], align 8
+// CHECK4-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK4-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
+// CHECK4-NEXT: [[TMP22:%.*]] = call i32 @__kmpc_reduce(ptr @[[GLOB3:[0-9]+]], i32 [[TMP21]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
+// CHECK4-NEXT: switch i32 [[TMP22]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
+// CHECK4-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// CHECK4-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// CHECK4-NEXT: ]
+// CHECK4: .omp.reduction.case1:
+// CHECK4-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP12]], align 4
+// CHECK4-NEXT: [[TMP24:%.*]] = load i32, ptr [[E11]], align 4
+// CHECK4-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP23]], [[TMP24]]
+// CHECK4-NEXT: store i32 [[ADD13]], ptr [[TMP12]], align 4
+// CHECK4-NEXT: call void @__kmpc_end_reduce(ptr @[[GLOB3]], i32 [[TMP21]], ptr @.gomp_critical_user_.reduction.var)
+// CHECK4-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
+// CHECK4: .omp.reduction.case2:
+// CHECK4-NEXT: [[TMP25:%.*]] = load i32, ptr [[E11]], align 4
+// CHECK4-NEXT: [[TMP26:%.*]] = atomicrmw add ptr [[TMP12]], i32 [[TMP25]] monotonic, align 4
+// CHECK4-NEXT: call void @__kmpc_end_reduce(ptr @[[GLOB3]], i32 [[TMP21]], ptr @.gomp_critical_user_.reduction.var)
+// CHECK4-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
+// CHECK4: .omp.reduction.default:
+// CHECK4-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined.omp.reduction.reduction_func
+// CHECK4-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR9:[0-9]+]] {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
+// CHECK4-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8
+// CHECK4-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR]], align 8
+// CHECK4-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
+// CHECK4-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP3]], i64 0, i64 0
+// CHECK4-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8
+// CHECK4-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP2]], i64 0, i64 0
+// CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8
+// CHECK4-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
+// CHECK4-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP5]], align 4
+// CHECK4-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP8]], [[TMP9]]
+// CHECK4-NEXT: store i32 [[ADD]], ptr [[TMP7]], align 4
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_ZN9TestClassC2ERKS_
+// CHECK4-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: store ptr [[C]], ptr [[C_ADDR]], align 8
+// CHECK4-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK4-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[CLASS_TESTCLASS:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C_ADDR]], align 8
+// CHECK4-NEXT: [[A2:%.*]] = getelementptr inbounds nuw [[CLASS_TESTCLASS]], ptr [[TMP0]], i32 0, i32 0
+// CHECK4-NEXT: [[TMP1:%.*]] = load i32, ptr [[A2]], align 4
+// CHECK4-NEXT: store i32 [[TMP1]], ptr [[A]], align 4
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_Z15parallel_singlev
+// CHECK4-SAME: () #[[ATTR2]] {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 0, ptr @_Z15parallel_singlev.omp_outlined)
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_Z15parallel_singlev.omp_outlined
+// CHECK4-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR8]] personality ptr @__gxx_personality_v0 {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK4-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK4-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK4-NEXT: invoke void @_Z3foov()
+// CHECK4-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK4: invoke.cont:
+// CHECK4-NEXT: [[TMP0:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK4-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4
+// CHECK4-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1]], i32 [[TMP1]])
+// CHECK4-NEXT: ret void
+// CHECK4: terminate.lpad:
+// CHECK4-NEXT: [[TMP2:%.*]] = landingpad { ptr, i32 }
+// CHECK4-NEXT: catch ptr null
+// CHECK4-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP2]], 0
+// CHECK4-NEXT: call void @__clang_call_terminate(ptr [[TMP3]]) #[[ATTR10]]
+// CHECK4-NEXT: unreachable
+//
+//
+// CHECK4-LABEL: define {{[^@]+}}@_GLOBAL__sub_I_scope_codegen.cpp
+// CHECK4-SAME: () #[[ATTR0]] {
+// CHECK4-NEXT: entry:
+// CHECK4-NEXT: call void @__cxx_global_var_init()
+// CHECK4-NEXT: call void @__cxx_global_var_init.1()
+// CHECK4-NEXT: ret void
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@__cxx_global_var_init
+// CHECK5-SAME: () #[[ATTR0:[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" !dbg [[DBG6:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: call void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) @tc), !dbg [[DBG9:![0-9]+]]
+// CHECK5-NEXT: [[TMP0:%.*]] = call i32 @__cxa_atexit(ptr @_ZN9TestClassD1Ev, ptr @tc, ptr @__dso_handle) #[[ATTR3:[0-9]+]], !dbg [[DBG12:![0-9]+]]
+// CHECK5-NEXT: ret void, !dbg [[DBG9]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZN9TestClassC1Ev
+// CHECK5-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1:[0-9]+]] align 2 !dbg [[DBG13:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: call void @_ZN9TestClassC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]), !dbg [[DBG14:![0-9]+]]
+// CHECK5-NEXT: ret void, !dbg [[DBG15:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZN9TestClassD1Ev
+// CHECK5-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2:[0-9]+]] align 2 !dbg [[DBG16:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: call void @_ZN9TestClassD2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]], !dbg [[DBG17:![0-9]+]]
+// CHECK5-NEXT: ret void, !dbg [[DBG18:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZN9TestClassC2Ev
+// CHECK5-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] align 2 !dbg [[DBG19:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[CLASS_TESTCLASS:%.*]], ptr [[THIS1]], i32 0, i32 0, !dbg [[DBG20:![0-9]+]]
+// CHECK5-NEXT: store i32 0, ptr [[A]], align 4, !dbg [[DBG20]]
+// CHECK5-NEXT: ret void, !dbg [[DBG21:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZN9TestClassD2Ev
+// CHECK5-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] align 2 !dbg [[DBG22:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: ret void, !dbg [[DBG23:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@__cxx_global_var_init.1
+// CHECK5-SAME: () #[[ATTR0]] section "__TEXT,__StaticInit,regular,pure_instructions" personality ptr @__gxx_personality_v0 !dbg [[DBG24:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
+// CHECK5-NEXT: br label [[ARRAYCTOR_LOOP:%.*]], !dbg [[DBG25:![0-9]+]]
+// CHECK5: arrayctor.loop:
+// CHECK5-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ @tc2, [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ], !dbg [[DBG25]]
+// CHECK5-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
+// CHECK5-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]], !dbg [[DBG25]]
+// CHECK5: invoke.cont:
+// CHECK5-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS:%.*]], ptr [[ARRAYCTOR_CUR]], i64 1, !dbg [[DBG25]]
+// CHECK5-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], getelementptr inbounds ([[CLASS_TESTCLASS]], ptr @tc2, i64 2), !dbg [[DBG25]]
+// CHECK5-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]], !dbg [[DBG25]]
+// CHECK5: arrayctor.cont:
+// CHECK5-NEXT: [[TMP0:%.*]] = call i32 @__cxa_atexit(ptr @__cxx_global_array_dtor, ptr null, ptr @__dso_handle) #[[ATTR3]], !dbg [[DBG27:![0-9]+]]
+// CHECK5-NEXT: ret void, !dbg [[DBG27]]
+// CHECK5: lpad:
+// CHECK5-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 }
+// CHECK5-NEXT: cleanup, !dbg [[DBG28:![0-9]+]]
+// CHECK5-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0, !dbg [[DBG28]]
+// CHECK5-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 8, !dbg [[DBG28]]
+// CHECK5-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1, !dbg [[DBG28]]
+// CHECK5-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4, !dbg [[DBG28]]
+// CHECK5-NEXT: [[ARRAYDESTROY_ISEMPTY:%.*]] = icmp eq ptr @tc2, [[ARRAYCTOR_CUR]], !dbg [[DBG25]]
+// CHECK5-NEXT: br i1 [[ARRAYDESTROY_ISEMPTY]], label [[ARRAYDESTROY_DONE1:%.*]], label [[ARRAYDESTROY_BODY:%.*]], !dbg [[DBG25]]
+// CHECK5: arraydestroy.body:
+// CHECK5-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[ARRAYCTOR_CUR]], [[LPAD]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ], !dbg [[DBG25]]
+// CHECK5-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1, !dbg [[DBG25]]
+// CHECK5-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]], !dbg [[DBG25]]
+// CHECK5-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], @tc2, !dbg [[DBG25]]
+// CHECK5-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE1]], label [[ARRAYDESTROY_BODY]], !dbg [[DBG25]]
+// CHECK5: arraydestroy.done1:
+// CHECK5-NEXT: br label [[EH_RESUME:%.*]], !dbg [[DBG25]]
+// CHECK5: eh.resume:
+// CHECK5-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 8, !dbg [[DBG25]]
+// CHECK5-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4, !dbg [[DBG25]]
+// CHECK5-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0, !dbg [[DBG25]]
+// CHECK5-NEXT: [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1, !dbg [[DBG25]]
+// CHECK5-NEXT: resume { ptr, i32 } [[LPAD_VAL2]], !dbg [[DBG25]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@__cxx_global_array_dtor
+// CHECK5-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR0]] section "__TEXT,__StaticInit,regular,pure_instructions" !dbg [[DBG29:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
+// CHECK5-NEXT: br label [[ARRAYDESTROY_BODY:%.*]], !dbg [[DBG30:![0-9]+]]
+// CHECK5: arraydestroy.body:
+// CHECK5-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ getelementptr inbounds ([[CLASS_TESTCLASS:%.*]], ptr @tc2, i64 2), [[ENTRY:%.*]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ], !dbg [[DBG30]]
+// CHECK5-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1, !dbg [[DBG30]]
+// CHECK5-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]], !dbg [[DBG30]]
+// CHECK5-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], @tc2, !dbg [[DBG30]]
+// CHECK5-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE1:%.*]], label [[ARRAYDESTROY_BODY]], !dbg [[DBG30]]
+// CHECK5: arraydestroy.done1:
+// CHECK5-NEXT: ret void, !dbg [[DBG30]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_Z3foov
+// CHECK5-SAME: () #[[ATTR1]] !dbg [[DBG31:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: call void @_Z8mayThrowv(), !dbg [[DBG32:![0-9]+]]
+// CHECK5-NEXT: ret void, !dbg [[DBG33:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@main
+// CHECK5-SAME: () #[[ATTR5:[0-9]+]] personality ptr @__gxx_personality_v0 !dbg [[DBG34:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK5-NEXT: [[A:%.*]] = alloca i8, align 1
+// CHECK5-NEXT: [[A2:%.*]] = alloca [2 x i8], align 1
+// CHECK5-NEXT: [[C:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[SST:%.*]] = alloca [[STRUCT_SST:%.*]], align 8
+// CHECK5-NEXT: [[SS:%.*]] = alloca [[STRUCT_SS:%.*]], align 8
+// CHECK5-NEXT: [[A1:%.*]] = alloca i8, align 1
+// CHECK5-NEXT: [[C2:%.*]] = alloca [[CLASS_TESTCLASS:%.*]], align 4
+// CHECK5-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[TC:%.*]] = alloca [[CLASS_TESTCLASS]], align 4
+// CHECK5-NEXT: [[A24:%.*]] = alloca [2 x i8], align 1
+// CHECK5-NEXT: [[TC2:%.*]] = alloca [2 x %class.TestClass], align 4
+// CHECK5-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2:[0-9]+]]), !dbg [[DBG35:![0-9]+]]
+// CHECK5-NEXT: store i32 0, ptr [[RETVAL]], align 4
+// CHECK5-NEXT: store ptr @tc, ptr [[C]], align 8, !dbg [[DBG36:![0-9]+]]
+// CHECK5-NEXT: call void @_ZN3SSTIdEC1Ev(ptr noundef nonnull align 8 dereferenceable(8) [[SST]]), !dbg [[DBG37:![0-9]+]]
+// CHECK5-NEXT: call void @_ZN2SSC1ERi(ptr noundef nonnull align 8 dereferenceable(24) [[SS]], ptr noundef nonnull align 4 dereferenceable(4) @tc), !dbg [[DBG38:![0-9]+]]
+// CHECK5-NEXT: store i8 2, ptr [[A]], align 1, !dbg [[DBG39:![0-9]+]]
+// CHECK5-NEXT: store i8 2, ptr [[A]], align 1, !dbg [[DBG40:![0-9]+]]
+// CHECK5-NEXT: call void @__kmpc_barrier(ptr @[[GLOB1:[0-9]+]], i32 [[TMP0]]), !dbg [[DBG41:![0-9]+]]
+// CHECK5-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1, !dbg [[DBG42:![0-9]+]]
+// CHECK5-NEXT: store i8 [[TMP1]], ptr [[A1]], align 1, !dbg [[DBG42]]
+// CHECK5-NEXT: invoke void @_ZN9TestClassC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[C2]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
+// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]], !dbg [[DBG43:![0-9]+]]
+// CHECK5: invoke.cont:
+// CHECK5-NEXT: store ptr [[C2]], ptr [[TMP]], align 8, !dbg [[DBG44:![0-9]+]]
+// CHECK5-NEXT: invoke void @_ZN9TestClassC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[TC]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
+// CHECK5-NEXT: to label [[INVOKE_CONT3:%.*]] unwind label [[TERMINATE_LPAD]], !dbg [[DBG45:![0-9]+]]
+// CHECK5: invoke.cont3:
+// CHECK5-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %class.TestClass], ptr [[TC2]], i32 0, i32 0, !dbg [[DBG46:![0-9]+]]
+// CHECK5-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAY_BEGIN]], i64 2, !dbg [[DBG46]]
+// CHECK5-NEXT: br label [[ARRAYCTOR_LOOP:%.*]], !dbg [[DBG46]]
+// CHECK5: arrayctor.loop:
+// CHECK5-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[INVOKE_CONT3]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT5:%.*]] ], !dbg [[DBG46]]
+// CHECK5-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
+// CHECK5-NEXT: to label [[INVOKE_CONT5]] unwind label [[TERMINATE_LPAD]], !dbg [[DBG46]]
+// CHECK5: invoke.cont5:
+// CHECK5-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYCTOR_CUR]], i64 1, !dbg [[DBG46]]
+// CHECK5-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]], !dbg [[DBG46]]
+// CHECK5-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]], !dbg [[DBG46]]
+// CHECK5: arrayctor.cont:
+// CHECK5-NEXT: invoke void @_Z3foov()
+// CHECK5-NEXT: to label [[INVOKE_CONT6:%.*]] unwind label [[TERMINATE_LPAD]], !dbg [[DBG47:![0-9]+]]
+// CHECK5: invoke.cont6:
+// CHECK5-NEXT: [[ARRAY_BEGIN7:%.*]] = getelementptr inbounds [2 x %class.TestClass], ptr [[TC2]], i32 0, i32 0, !dbg [[DBG47]]
+// CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAY_BEGIN7]], i64 2, !dbg [[DBG47]]
+// CHECK5-NEXT: br label [[ARRAYDESTROY_BODY:%.*]], !dbg [[DBG47]]
+// CHECK5: arraydestroy.body:
+// CHECK5-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP2]], [[INVOKE_CONT6]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ], !dbg [[DBG47]]
+// CHECK5-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1, !dbg [[DBG47]]
+// CHECK5-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]], !dbg [[DBG47]]
+// CHECK5-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN7]], !dbg [[DBG47]]
+// CHECK5-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE8:%.*]], label [[ARRAYDESTROY_BODY]], !dbg [[DBG47]]
+// CHECK5: arraydestroy.done8:
+// CHECK5-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TC]]) #[[ATTR3]], !dbg [[DBG47]]
+// CHECK5-NEXT: call void @_ZN9TestClassD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[C2]]) #[[ATTR3]], !dbg [[DBG47]]
+// CHECK5-NEXT: call void @__kmpc_barrier(ptr @[[GLOB4:[0-9]+]], i32 [[TMP0]]), !dbg [[DBG48:![0-9]+]]
+// CHECK5-NEXT: [[TMP3:%.*]] = load i8, ptr [[A]], align 1, !dbg [[DBG49:![0-9]+]]
+// CHECK5-NEXT: [[CONV:%.*]] = sext i8 [[TMP3]] to i32, !dbg [[DBG49]]
+// CHECK5-NEXT: ret i32 [[CONV]], !dbg [[DBG50:![0-9]+]]
+// CHECK5: terminate.lpad:
+// CHECK5-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 }
+// CHECK5-NEXT: catch ptr null, !dbg [[DBG43]]
+// CHECK5-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0, !dbg [[DBG43]]
+// CHECK5-NEXT: call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR10:[0-9]+]], !dbg [[DBG43]]
+// CHECK5-NEXT: unreachable, !dbg [[DBG43]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZN3SSTIdEC1Ev
+// CHECK5-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] align 2 !dbg [[DBG51:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: call void @_ZN3SSTIdEC2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]]), !dbg [[DBG52:![0-9]+]]
+// CHECK5-NEXT: ret void, !dbg [[DBG53:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZN2SSC1ERi
+// CHECK5-SAME: (ptr noundef nonnull align 8 dereferenceable(24) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[D:%.*]]) unnamed_addr #[[ATTR1]] align 2 !dbg [[DBG54:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[D_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[D]], ptr [[D_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 8, !dbg [[DBG55:![0-9]+]]
+// CHECK5-NEXT: call void @_ZN2SSC2ERi(ptr noundef nonnull align 8 dereferenceable(24) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]]), !dbg [[DBG55]]
+// CHECK5-NEXT: ret void, !dbg [[DBG56:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZN9TestClassC1ERKS_
+// CHECK5-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]]) unnamed_addr #[[ATTR1]] align 2 !dbg [[DBG57:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[C]], ptr [[C_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C_ADDR]], align 8, !dbg [[DBG58:![0-9]+]]
+// CHECK5-NEXT: call void @_ZN9TestClassC2ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]]), !dbg [[DBG58]]
+// CHECK5-NEXT: ret void, !dbg [[DBG59:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@__clang_call_terminate
+// CHECK5-SAME: (ptr noundef [[TMP0:%.*]]) #[[ATTR7:[0-9]+]] {
+// CHECK5-NEXT: [[TMP2:%.*]] = call ptr @__cxa_begin_catch(ptr [[TMP0]]) #[[ATTR3]]
+// CHECK5-NEXT: call void @_ZSt9terminatev() #[[ATTR10]]
+// CHECK5-NEXT: unreachable
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZN3SSTIdEC2Ev
+// CHECK5-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] align 2 !dbg [[DBG60:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_SST:%.*]], ptr [[THIS1]], i32 0, i32 0, !dbg [[DBG61:![0-9]+]]
+// CHECK5-NEXT: store double 0.000000e+00, ptr [[A]], align 8, !dbg [[DBG61]]
+// CHECK5-NEXT: [[TMP0:%.*]] = load ptr, ptr @omp_cgroup_mem_alloc, align 8, !dbg [[DBG62:![0-9]+]]
+// CHECK5-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70(ptr [[THIS1]], ptr [[TMP0]]) #[[ATTR3]], !dbg [[DBG62]]
+// CHECK5-NEXT: ret void, !dbg [[DBG63:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70
+// CHECK5-SAME: (ptr noundef [[THIS:%.*]], ptr noundef [[OMP_CGROUP_MEM_ALLOC:%.*]]) #[[ATTR8:[0-9]+]] !dbg [[DBG64:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[OMP_CGROUP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[OMP_CGROUP_MEM_ALLOC]], ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8, !dbg [[DBG65:![0-9]+]]
+// CHECK5-NEXT: [[TMP1:%.*]] = load ptr, ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8, !dbg [[DBG65]]
+// CHECK5-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB10:[0-9]+]], i32 2, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70.omp_outlined, ptr [[TMP0]], ptr [[TMP1]]), !dbg [[DBG65]]
+// CHECK5-NEXT: ret void, !dbg [[DBG66:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70.omp_outlined
+// CHECK5-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef [[OMP_CGROUP_MEM_ALLOC:%.*]]) #[[ATTR8]] !dbg [[DBG67:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[OMP_CGROUP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[A:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[A_CASTED:%.*]] = alloca i64, align 8
+// CHECK5-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK5-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[OMP_CGROUP_MEM_ALLOC]], ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8, !dbg [[DBG68:![0-9]+]]
+// CHECK5-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_SST:%.*]], ptr [[TMP0]], i32 0, i32 0, !dbg [[DBG69:![0-9]+]]
+// CHECK5-NEXT: store ptr [[A1]], ptr [[A]], align 8, !dbg [[DBG69]]
+// CHECK5-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A]], align 8, !dbg [[DBG69]]
+// CHECK5-NEXT: [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8, !dbg [[DBG70:![0-9]+]]
+// CHECK5-NEXT: store double [[TMP2]], ptr [[A_CASTED]], align 8, !dbg [[DBG70]]
+// CHECK5-NEXT: [[TMP3:%.*]] = load i64, ptr [[A_CASTED]], align 8, !dbg [[DBG70]]
+// CHECK5-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB8:[0-9]+]], i32 3, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70.omp_outlined.omp_outlined, ptr [[TMP0]], ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], i64 [[TMP3]]), !dbg [[DBG70]]
+// CHECK5-NEXT: ret void, !dbg [[DBG71:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN3SSTIdEC1Ev_l70.omp_outlined.omp_outlined
+// CHECK5-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_CGROUP_MEM_ALLOC:%.*]], i64 noundef [[A:%.*]]) #[[ATTR8]] personality ptr @__gxx_personality_v0 !dbg [[DBG72:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[OMP_CGROUP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
+// CHECK5-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[A1:%.*]] = alloca double, align 8
+// CHECK5-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON:%.*]], align 8
+// CHECK5-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK5-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[OMP_CGROUP_MEM_ALLOC]], ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK5-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8, !dbg [[DBG73:![0-9]+]]
+// CHECK5-NEXT: [[TMP1:%.*]] = load ptr, ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8, !dbg [[DBG73]]
+// CHECK5-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 8, !dbg [[DBG73]]
+// CHECK5-NEXT: store ptr [[A1]], ptr [[_TMP2]], align 8, !dbg [[DBG74:![0-9]+]]
+// CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 0, !dbg [[DBG75:![0-9]+]]
+// CHECK5-NEXT: store ptr [[TMP0]], ptr [[TMP2]], align 8, !dbg [[DBG75]]
+// CHECK5-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 1, !dbg [[DBG75]]
+// CHECK5-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP2]], align 8, !dbg [[DBG76:![0-9]+]]
+// CHECK5-NEXT: store ptr [[TMP4]], ptr [[TMP3]], align 8, !dbg [[DBG75]]
+// CHECK5-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 2, !dbg [[DBG75]]
+// CHECK5-NEXT: store ptr [[TMP1]], ptr [[TMP5]], align 8, !dbg [[DBG75]]
+// CHECK5-NEXT: invoke void @_ZZN3SSTIdEC1EvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(24) [[REF_TMP]])
+// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]], !dbg [[DBG75]]
+// CHECK5: invoke.cont:
+// CHECK5-NEXT: [[TMP6:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8, !dbg [[DBG77:![0-9]+]]
+// CHECK5-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4, !dbg [[DBG77]]
+// CHECK5-NEXT: call void @__kmpc_barrier(ptr @[[GLOB6:[0-9]+]], i32 [[TMP7]]), !dbg [[DBG77]]
+// CHECK5-NEXT: ret void, !dbg [[DBG77]]
+// CHECK5: terminate.lpad:
+// CHECK5-NEXT: [[TMP8:%.*]] = landingpad { ptr, i32 }
+// CHECK5-NEXT: catch ptr null, !dbg [[DBG75]]
+// CHECK5-NEXT: [[TMP9:%.*]] = extractvalue { ptr, i32 } [[TMP8]], 0, !dbg [[DBG75]]
+// CHECK5-NEXT: call void @__clang_call_terminate(ptr [[TMP9]]) #[[ATTR10]], !dbg [[DBG75]]
+// CHECK5-NEXT: unreachable, !dbg [[DBG75]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZZN3SSTIdEC1EvENKUlvE_clEv
+// CHECK5-SAME: (ptr noundef nonnull align 8 dereferenceable(24) [[THIS:%.*]]) #[[ATTR1]] align 2 !dbg [[DBG78:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON_0:%.*]], align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CLASS_ANON:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK5-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0, !dbg [[DBG79:![0-9]+]]
+// CHECK5-NEXT: store ptr [[TMP1]], ptr [[TMP2]], align 8, !dbg [[DBG79]]
+// CHECK5-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 1, !dbg [[DBG79]]
+// CHECK5-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 1, !dbg [[DBG80:![0-9]+]]
+// CHECK5-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8, !dbg [[DBG80]]
+// CHECK5-NEXT: store ptr [[TMP5]], ptr [[TMP3]], align 8, !dbg [[DBG79]]
+// CHECK5-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 2, !dbg [[DBG79]]
+// CHECK5-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[THIS1]], i32 0, i32 2, !dbg [[DBG80]]
+// CHECK5-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8, !dbg [[DBG80]]
+// CHECK5-NEXT: store ptr [[TMP8]], ptr [[TMP6]], align 8, !dbg [[DBG79]]
+// CHECK5-NEXT: call void @_ZZZN3SSTIdEC1EvENKUlvE_clEvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(24) [[REF_TMP]]), !dbg [[DBG79]]
+// CHECK5-NEXT: ret void, !dbg [[DBG81:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZZZN3SSTIdEC1EvENKUlvE_clEvENKUlvE_clEv
+// CHECK5-SAME: (ptr noundef nonnull align 8 dereferenceable(24) [[THIS:%.*]]) #[[ATTR2]] align 2 !dbg [[DBG84:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[C:%.*]] = alloca i32, align 4
+// CHECK5-NEXT: [[A_CASTED:%.*]] = alloca i64, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK5-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 1, !dbg [[DBG85:![0-9]+]]
+// CHECK5-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP2]], align 8, !dbg [[DBG85]]
+// CHECK5-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8, !dbg [[DBG86:![0-9]+]]
+// CHECK5-NEXT: [[INC:%.*]] = fadd double [[TMP4]], 1.000000e+00, !dbg [[DBG86]]
+// CHECK5-NEXT: store double [[INC]], ptr [[TMP3]], align 8, !dbg [[DBG86]]
+// CHECK5-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 2, !dbg [[DBG87:![0-9]+]]
+// CHECK5-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP5]], align 8, !dbg [[DBG87]]
+// CHECK5-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[THIS1]], i32 0, i32 1, !dbg [[DBG88:![0-9]+]]
+// CHECK5-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8, !dbg [[DBG88]]
+// CHECK5-NEXT: [[TMP9:%.*]] = load double, ptr [[TMP8]], align 8, !dbg [[DBG89:![0-9]+]]
+// CHECK5-NEXT: store double [[TMP9]], ptr [[A_CASTED]], align 8, !dbg [[DBG89]]
+// CHECK5-NEXT: [[TMP10:%.*]] = load i64, ptr [[A_CASTED]], align 8, !dbg [[DBG89]]
+// CHECK5-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB14:[0-9]+]], i32 3, ptr @_ZZZN3SSTIdEC1EvENKUlvE_clEvENKUlvE_clEv.omp_outlined, ptr [[TMP1]], ptr [[TMP6]], i64 [[TMP10]]), !dbg [[DBG89]]
+// CHECK5-NEXT: ret void, !dbg [[DBG90:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZZZN3SSTIdEC1EvENKUlvE_clEvENKUlvE_clEv.omp_outlined
+// CHECK5-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[OMP_CGROUP_MEM_ALLOC:%.*]], i64 noundef [[A:%.*]]) #[[ATTR8]] !dbg [[DBG91:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[OMP_CGROUP_MEM_ALLOC_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
+// CHECK5-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK5-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[OMP_CGROUP_MEM_ALLOC]], ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8
+// CHECK5-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8, !dbg [[DBG92:![0-9]+]]
+// CHECK5-NEXT: [[TMP1:%.*]] = load ptr, ptr [[OMP_CGROUP_MEM_ALLOC_ADDR]], align 8, !dbg [[DBG92]]
+// CHECK5-NEXT: store ptr [[A_ADDR]], ptr [[TMP]], align 8, !dbg [[DBG92]]
+// CHECK5-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8, !dbg [[DBG93:![0-9]+]]
+// CHECK5-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4, !dbg [[DBG93]]
+// CHECK5-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP1]], align 8, !dbg [[DBG94:![0-9]+]]
+// CHECK5-NEXT: [[DOTA__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP3]], i64 8, ptr [[TMP4]]), !dbg [[DBG93]]
+// CHECK5-NEXT: store ptr [[DOTA__VOID_ADDR]], ptr [[_TMP1]], align 8, !dbg [[DBG93]]
+// CHECK5-NEXT: [[TMP5:%.*]] = load ptr, ptr [[_TMP1]], align 8, !dbg [[DBG95:![0-9]+]]
+// CHECK5-NEXT: [[TMP6:%.*]] = load double, ptr [[TMP5]], align 8, !dbg [[DBG96:![0-9]+]]
+// CHECK5-NEXT: [[INC:%.*]] = fadd double [[TMP6]], 1.000000e+00, !dbg [[DBG96]]
+// CHECK5-NEXT: store double [[INC]], ptr [[TMP5]], align 8, !dbg [[DBG96]]
+// CHECK5-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP1]], align 8, !dbg [[DBG94]]
+// CHECK5-NEXT: call void @__kmpc_free(i32 [[TMP3]], ptr [[DOTA__VOID_ADDR]], ptr [[TMP7]]), !dbg [[DBG96]]
+// CHECK5-NEXT: call void @__kmpc_barrier(ptr @[[GLOB12:[0-9]+]], i32 [[TMP3]]), !dbg [[DBG97:![0-9]+]]
+// CHECK5-NEXT: ret void, !dbg [[DBG97]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZN2SSC2ERi
+// CHECK5-SAME: (ptr noundef nonnull align 8 dereferenceable(24) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[D:%.*]]) unnamed_addr #[[ATTR2]] align 2 personality ptr @__gxx_personality_v0 !dbg [[DBG98:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[D_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[A2:%.*]] = alloca i32, align 4
+// CHECK5-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[C3:%.*]] = alloca i32, align 4
+// CHECK5-NEXT: [[_TMP4:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB16:[0-9]+]]), !dbg [[DBG99:![0-9]+]]
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[D]], ptr [[D_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_SS:%.*]], ptr [[THIS1]], i32 0, i32 1, !dbg [[DBG100:![0-9]+]]
+// CHECK5-NEXT: store i32 0, ptr [[A]], align 4, !dbg [[DBG100]]
+// CHECK5-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 2, !dbg [[DBG101:![0-9]+]]
+// CHECK5-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[B]], align 8, !dbg [[DBG101]]
+// CHECK5-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -16, !dbg [[DBG101]]
+// CHECK5-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 0, !dbg [[DBG101]]
+// CHECK5-NEXT: store i8 [[BF_SET]], ptr [[B]], align 8, !dbg [[DBG101]]
+// CHECK5-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_SS]], ptr [[THIS1]], i32 0, i32 3, !dbg [[DBG102:![0-9]+]]
+// CHECK5-NEXT: [[TMP1:%.*]] = load ptr, ptr [[D_ADDR]], align 8, !dbg [[DBG103:![0-9]+]]
+// CHECK5-NEXT: store ptr [[TMP1]], ptr [[C]], align 8, !dbg [[DBG102]]
+// CHECK5-NEXT: store ptr [[A2]], ptr [[TMP]], align 8, !dbg [[DBG104:![0-9]+]]
+// CHECK5-NEXT: [[TMP2:%.*]] = load ptr, ptr @omp_default_mem_alloc, align 8, !dbg [[DBG105:![0-9]+]]
+// CHECK5-NEXT: [[DOTB__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr [[TMP2]]), !dbg [[DBG104]]
+// CHECK5-NEXT: store ptr [[C3]], ptr [[_TMP4]], align 8, !dbg [[DBG104]]
+// CHECK5-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 0, !dbg [[DBG106:![0-9]+]]
+// CHECK5-NEXT: store ptr [[THIS1]], ptr [[TMP3]], align 8, !dbg [[DBG106]]
+// CHECK5-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 1, !dbg [[DBG106]]
+// CHECK5-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP]], align 8, !dbg [[DBG107:![0-9]+]]
+// CHECK5-NEXT: store ptr [[TMP5]], ptr [[TMP4]], align 8, !dbg [[DBG106]]
+// CHECK5-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 2, !dbg [[DBG106]]
+// CHECK5-NEXT: store ptr [[DOTB__VOID_ADDR]], ptr [[TMP6]], align 8, !dbg [[DBG106]]
+// CHECK5-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[REF_TMP]], i32 0, i32 3, !dbg [[DBG106]]
+// CHECK5-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP4]], align 8, !dbg [[DBG107]]
+// CHECK5-NEXT: store ptr [[TMP8]], ptr [[TMP7]], align 8, !dbg [[DBG106]]
+// CHECK5-NEXT: invoke void @_ZZN2SSC1ERiENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(32) [[REF_TMP]])
+// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]], !dbg [[DBG106]]
+// CHECK5: invoke.cont:
+// CHECK5-NEXT: [[TMP9:%.*]] = load ptr, ptr @omp_default_mem_alloc, align 8, !dbg [[DBG105]]
+// CHECK5-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTB__VOID_ADDR]], ptr [[TMP9]]), !dbg [[DBG106]]
+// CHECK5-NEXT: ret void, !dbg [[DBG108:![0-9]+]]
+// CHECK5: terminate.lpad:
+// CHECK5-NEXT: [[TMP10:%.*]] = landingpad { ptr, i32 }
+// CHECK5-NEXT: catch ptr null, !dbg [[DBG106]]
+// CHECK5-NEXT: [[TMP11:%.*]] = extractvalue { ptr, i32 } [[TMP10]], 0, !dbg [[DBG106]]
+// CHECK5-NEXT: call void @__clang_call_terminate(ptr [[TMP11]]) #[[ATTR10]], !dbg [[DBG106]]
+// CHECK5-NEXT: unreachable, !dbg [[DBG106]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZZN2SSC1ERiENKUlvE_clEv
+// CHECK5-SAME: (ptr noundef nonnull align 8 dereferenceable(32) [[THIS:%.*]]) #[[ATTR2]] align 2 !dbg [[DBG109:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB22:[0-9]+]]), !dbg [[DBG110:![0-9]+]]
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK5-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
+// CHECK5-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 1, !dbg [[DBG111:![0-9]+]]
+// CHECK5-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8, !dbg [[DBG111]]
+// CHECK5-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4, !dbg [[DBG112:![0-9]+]]
+// CHECK5-NEXT: [[INC:%.*]] = add nsw i32 [[TMP5]], 1, !dbg [[DBG112]]
+// CHECK5-NEXT: store i32 [[INC]], ptr [[TMP4]], align 4, !dbg [[DBG112]]
+// CHECK5-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 2, !dbg [[DBG113:![0-9]+]]
+// CHECK5-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8, !dbg [[DBG113]]
+// CHECK5-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4, !dbg [[DBG114:![0-9]+]]
+// CHECK5-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP8]], -1, !dbg [[DBG114]]
+// CHECK5-NEXT: store i32 [[DEC]], ptr [[TMP7]], align 4, !dbg [[DBG114]]
+// CHECK5-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 3, !dbg [[DBG115:![0-9]+]]
+// CHECK5-NEXT: [[TMP10:%.*]] = load ptr, ptr [[TMP9]], align 8, !dbg [[DBG115]]
+// CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4, !dbg [[DBG116:![0-9]+]]
+// CHECK5-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP11]], 1, !dbg [[DBG116]]
+// CHECK5-NEXT: store i32 [[DIV]], ptr [[TMP10]], align 4, !dbg [[DBG116]]
+// CHECK5-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 2, !dbg [[DBG117:![0-9]+]]
+// CHECK5-NEXT: [[TMP13:%.*]] = load ptr, ptr [[TMP12]], align 8, !dbg [[DBG117]]
+// CHECK5-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4, !dbg [[DBG117]]
+// CHECK5-NEXT: call void @__kmpc_push_num_threads(ptr @[[GLOB22]], i32 [[TMP0]], i32 [[TMP14]]), !dbg [[DBG118:![0-9]+]]
+// CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 1, !dbg [[DBG119:![0-9]+]]
+// CHECK5-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 8, !dbg [[DBG119]]
+// CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 2, !dbg [[DBG120:![0-9]+]]
+// CHECK5-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8, !dbg [[DBG120]]
+// CHECK5-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_1]], ptr [[THIS1]], i32 0, i32 3, !dbg [[DBG121:![0-9]+]]
+// CHECK5-NEXT: [[TMP20:%.*]] = load ptr, ptr [[TMP19]], align 8, !dbg [[DBG121]]
+// CHECK5-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB24:[0-9]+]], i32 4, ptr @_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined, ptr [[TMP2]], ptr [[TMP16]], ptr [[TMP18]], ptr [[TMP20]]), !dbg [[DBG118]]
+// CHECK5-NEXT: ret void, !dbg [[DBG122:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined
+// CHECK5-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]]) #[[ATTR8]] !dbg [[DBG123:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[TMP:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[E:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[_TMP3:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[_TMP4:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[_TMP5:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[A6:%.*]] = alloca i32, align 4
+// CHECK5-NEXT: [[_TMP7:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[B8:%.*]] = alloca i32, align 4
+// CHECK5-NEXT: [[C9:%.*]] = alloca i32, align 4
+// CHECK5-NEXT: [[_TMP10:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[E11:%.*]] = alloca i32, align 4
+// CHECK5-NEXT: [[_TMP12:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8
+// CHECK5-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK5-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[C]], ptr [[C_ADDR]], align 8
+// CHECK5-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8, !dbg [[DBG124:![0-9]+]]
+// CHECK5-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8, !dbg [[DBG124]]
+// CHECK5-NEXT: [[TMP2:%.*]] = load ptr, ptr [[B_ADDR]], align 8, !dbg [[DBG124]]
+// CHECK5-NEXT: [[TMP3:%.*]] = load ptr, ptr [[C_ADDR]], align 8, !dbg [[DBG124]]
+// CHECK5-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8, !dbg [[DBG124]]
+// CHECK5-NEXT: store ptr [[TMP3]], ptr [[_TMP1]], align 8, !dbg [[DBG124]]
+// CHECK5-NEXT: [[E2:%.*]] = getelementptr inbounds nuw [[STRUCT_SS:%.*]], ptr [[TMP0]], i32 0, i32 0, !dbg [[DBG125:![0-9]+]]
+// CHECK5-NEXT: store ptr [[E2]], ptr [[E]], align 8, !dbg [[DBG125]]
+// CHECK5-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8, !dbg [[DBG126:![0-9]+]]
+// CHECK5-NEXT: store ptr [[TMP4]], ptr [[_TMP3]], align 8, !dbg [[DBG127:![0-9]+]]
+// CHECK5-NEXT: [[TMP5:%.*]] = load ptr, ptr [[E]], align 8, !dbg [[DBG128:![0-9]+]]
+// CHECK5-NEXT: store ptr [[TMP5]], ptr [[_TMP4]], align 8, !dbg [[DBG127]]
+// CHECK5-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP1]], align 8, !dbg [[DBG129:![0-9]+]]
+// CHECK5-NEXT: store ptr [[TMP6]], ptr [[_TMP5]], align 8, !dbg [[DBG127]]
+// CHECK5-NEXT: [[TMP7:%.*]] = load ptr, ptr [[_TMP3]], align 8, !dbg [[DBG130:![0-9]+]]
+// CHECK5-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4, !dbg [[DBG130]]
+// CHECK5-NEXT: store i32 [[TMP8]], ptr [[A6]], align 4, !dbg [[DBG130]]
+// CHECK5-NEXT: store ptr [[A6]], ptr [[_TMP7]], align 8, !dbg [[DBG127]]
+// CHECK5-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP2]], align 4, !dbg [[DBG131:![0-9]+]]
+// CHECK5-NEXT: store i32 [[TMP9]], ptr [[B8]], align 4, !dbg [[DBG131]]
+// CHECK5-NEXT: [[TMP10:%.*]] = load ptr, ptr [[_TMP5]], align 8, !dbg [[DBG132:![0-9]+]]
+// CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4, !dbg [[DBG132]]
+// CHECK5-NEXT: store i32 [[TMP11]], ptr [[C9]], align 4, !dbg [[DBG132]]
+// CHECK5-NEXT: store ptr [[C9]], ptr [[_TMP10]], align 8, !dbg [[DBG127]]
+// CHECK5-NEXT: [[TMP12:%.*]] = load ptr, ptr [[_TMP4]], align 8, !dbg [[DBG125]]
+// CHECK5-NEXT: store i32 0, ptr [[E11]], align 4, !dbg [[DBG125]]
+// CHECK5-NEXT: store ptr [[E11]], ptr [[_TMP12]], align 8, !dbg [[DBG127]]
+// CHECK5-NEXT: [[TMP13:%.*]] = load ptr, ptr [[_TMP7]], align 8, !dbg [[DBG126]]
+// CHECK5-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4, !dbg [[DBG133:![0-9]+]]
+// CHECK5-NEXT: [[INC:%.*]] = add nsw i32 [[TMP14]], 1, !dbg [[DBG133]]
+// CHECK5-NEXT: store i32 [[INC]], ptr [[TMP13]], align 4, !dbg [[DBG133]]
+// CHECK5-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP12]], align 8, !dbg [[DBG128]]
+// CHECK5-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4, !dbg [[DBG134:![0-9]+]]
+// CHECK5-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP16]], 1, !dbg [[DBG134]]
+// CHECK5-NEXT: store i32 [[ADD]], ptr [[TMP15]], align 4, !dbg [[DBG134]]
+// CHECK5-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP10]], align 8, !dbg [[DBG129]]
+// CHECK5-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4, !dbg [[DBG135:![0-9]+]]
+// CHECK5-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP18]], 1, !dbg [[DBG135]]
+// CHECK5-NEXT: store i32 [[DIV]], ptr [[TMP17]], align 4, !dbg [[DBG135]]
+// CHECK5-NEXT: [[TMP19:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0, !dbg [[DBG133]]
+// CHECK5-NEXT: store ptr [[E11]], ptr [[TMP19]], align 8, !dbg [[DBG133]]
+// CHECK5-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8, !dbg [[DBG133]]
+// CHECK5-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4, !dbg [[DBG133]]
+// CHECK5-NEXT: [[TMP22:%.*]] = call i32 @__kmpc_reduce(ptr @[[GLOB18:[0-9]+]], i32 [[TMP21]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var), !dbg [[DBG133]]
+// CHECK5-NEXT: switch i32 [[TMP22]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
+// CHECK5-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// CHECK5-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// CHECK5-NEXT: ], !dbg [[DBG133]]
+// CHECK5: .omp.reduction.case1:
+// CHECK5-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP12]], align 4, !dbg [[DBG125]]
+// CHECK5-NEXT: [[TMP24:%.*]] = load i32, ptr [[E11]], align 4, !dbg [[DBG125]]
+// CHECK5-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP23]], [[TMP24]], !dbg [[DBG136:![0-9]+]]
+// CHECK5-NEXT: store i32 [[ADD13]], ptr [[TMP12]], align 4, !dbg [[DBG136]]
+// CHECK5-NEXT: call void @__kmpc_end_reduce(ptr @[[GLOB18]], i32 [[TMP21]], ptr @.gomp_critical_user_.reduction.var), !dbg [[DBG133]]
+// CHECK5-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]], !dbg [[DBG133]]
+// CHECK5: .omp.reduction.case2:
+// CHECK5-NEXT: [[TMP25:%.*]] = load i32, ptr [[E11]], align 4, !dbg [[DBG125]]
+// CHECK5-NEXT: [[TMP26:%.*]] = atomicrmw add ptr [[TMP12]], i32 [[TMP25]] monotonic, align 4, !dbg [[DBG133]]
+// CHECK5-NEXT: call void @__kmpc_end_reduce(ptr @[[GLOB18]], i32 [[TMP21]], ptr @.gomp_critical_user_.reduction.var), !dbg [[DBG133]]
+// CHECK5-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]], !dbg [[DBG133]]
+// CHECK5: .omp.reduction.default:
+// CHECK5-NEXT: call void @__kmpc_barrier(ptr @[[GLOB20:[0-9]+]], i32 [[TMP21]]), !dbg [[DBG137:![0-9]+]]
+// CHECK5-NEXT: ret void, !dbg [[DBG137]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZZN2SSC1ERiENKUlvE_clEv.omp_outlined.omp.reduction.reduction_func
+// CHECK5-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR9:[0-9]+]] !dbg [[DBG138:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
+// CHECK5-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8
+// CHECK5-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR]], align 8, !dbg [[DBG139:![0-9]+]]
+// CHECK5-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8, !dbg [[DBG139]]
+// CHECK5-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP3]], i64 0, i64 0, !dbg [[DBG139]]
+// CHECK5-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8, !dbg [[DBG139]]
+// CHECK5-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP2]], i64 0, i64 0, !dbg [[DBG139]]
+// CHECK5-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8, !dbg [[DBG139]]
+// CHECK5-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4, !dbg [[DBG140:![0-9]+]]
+// CHECK5-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP5]], align 4, !dbg [[DBG140]]
+// CHECK5-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP8]], [[TMP9]], !dbg [[DBG141:![0-9]+]]
+// CHECK5-NEXT: store i32 [[ADD]], ptr [[TMP7]], align 4, !dbg [[DBG141]]
+// CHECK5-NEXT: ret void, !dbg [[DBG140]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_ZN9TestClassC2ERKS_
+// CHECK5-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]]) unnamed_addr #[[ATTR2]] align 2 !dbg [[DBG142:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: store ptr [[C]], ptr [[C_ADDR]], align 8
+// CHECK5-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK5-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[CLASS_TESTCLASS:%.*]], ptr [[THIS1]], i32 0, i32 0, !dbg [[DBG143:![0-9]+]]
+// CHECK5-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C_ADDR]], align 8, !dbg [[DBG144:![0-9]+]]
+// CHECK5-NEXT: [[A2:%.*]] = getelementptr inbounds nuw [[CLASS_TESTCLASS]], ptr [[TMP0]], i32 0, i32 0, !dbg [[DBG145:![0-9]+]]
+// CHECK5-NEXT: [[TMP1:%.*]] = load i32, ptr [[A2]], align 4, !dbg [[DBG145]]
+// CHECK5-NEXT: store i32 [[TMP1]], ptr [[A]], align 4, !dbg [[DBG143]]
+// CHECK5-NEXT: ret void, !dbg [[DBG146:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_Z15parallel_singlev
+// CHECK5-SAME: () #[[ATTR2]] !dbg [[DBG147:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB28:[0-9]+]], i32 0, ptr @_Z15parallel_singlev.omp_outlined), !dbg [[DBG148:![0-9]+]]
+// CHECK5-NEXT: ret void, !dbg [[DBG149:![0-9]+]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_Z15parallel_singlev.omp_outlined
+// CHECK5-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR8]] personality ptr @__gxx_personality_v0 !dbg [[DBG150:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK5-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK5-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK5-NEXT: invoke void @_Z3foov()
+// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]], !dbg [[DBG151:![0-9]+]]
+// CHECK5: invoke.cont:
+// CHECK5-NEXT: [[TMP0:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8, !dbg [[DBG152:![0-9]+]]
+// CHECK5-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4, !dbg [[DBG152]]
+// CHECK5-NEXT: call void @__kmpc_barrier(ptr @[[GLOB26:[0-9]+]], i32 [[TMP1]]), !dbg [[DBG152]]
+// CHECK5-NEXT: ret void, !dbg [[DBG152]]
+// CHECK5: terminate.lpad:
+// CHECK5-NEXT: [[TMP2:%.*]] = landingpad { ptr, i32 }
+// CHECK5-NEXT: catch ptr null, !dbg [[DBG151]]
+// CHECK5-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP2]], 0, !dbg [[DBG151]]
+// CHECK5-NEXT: call void @__clang_call_terminate(ptr [[TMP3]]) #[[ATTR10]], !dbg [[DBG151]]
+// CHECK5-NEXT: unreachable, !dbg [[DBG151]]
+//
+//
+// CHECK5-LABEL: define {{[^@]+}}@_GLOBAL__sub_I_scope_codegen.cpp
+// CHECK5-SAME: () #[[ATTR0]] section "__TEXT,__StaticInit,regular,pure_instructions" !dbg [[DBG153:![0-9]+]] {
+// CHECK5-NEXT: entry:
+// CHECK5-NEXT: call void @__cxx_global_var_init(), !dbg [[DBG154:![0-9]+]]
+// CHECK5-NEXT: call void @__cxx_global_var_init.1(), !dbg [[DBG154]]
+// CHECK5-NEXT: ret void
+//
+//
+// CHECK6-LABEL: define {{[^@]+}}@_Z10array_funciPiP2St
+// CHECK6-SAME: (i32 noundef [[N:%.*]], ptr noundef [[A:%.*]], ptr noundef [[S:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK6-NEXT: entry:
+// CHECK6-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
+// CHECK6-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8
+// CHECK6-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK6-NEXT: [[B:%.*]] = alloca i32, align 4
+// CHECK6-NEXT: [[C:%.*]] = alloca i32, align 4
+// CHECK6-NEXT: [[B1:%.*]] = alloca i32, align 4
+// CHECK6-NEXT: [[A2:%.*]] = alloca ptr, align 8
+// CHECK6-NEXT: [[S3:%.*]] = alloca ptr, align 8
+// CHECK6-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8
+// CHECK6-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i32, align 4
+// CHECK6-NEXT: [[TMP:%.*]] = alloca i32, align 4
+// CHECK6-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]])
+// CHECK6-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4
+// CHECK6-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8
+// CHECK6-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK6-NEXT: [[TMP1:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK6-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64
+// CHECK6-NEXT: [[TMP3:%.*]] = load i32, ptr [[B]], align 4
+// CHECK6-NEXT: store i32 [[TMP3]], ptr [[B1]], align 4
+// CHECK6-NEXT: [[TMP4:%.*]] = load ptr, ptr @omp_high_bw_mem_alloc, align 8
+// CHECK6-NEXT: [[DOTC__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr [[TMP4]])
+// CHECK6-NEXT: store i32 1, ptr [[DOTC__VOID_ADDR]], align 4
+// CHECK6-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
+// CHECK6-NEXT: store ptr [[DOTC__VOID_ADDR]], ptr [[TMP5]], align 8
+// CHECK6-NEXT: [[TMP6:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB2:[0-9]+]], i32 [[TMP0]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z10array_funciPiP2St.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
+// CHECK6-NEXT: switch i32 [[TMP6]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
+// CHECK6-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// CHECK6-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// CHECK6-NEXT: ]
+// CHECK6: .omp.reduction.case1:
+// CHECK6-NEXT: [[TMP7:%.*]] = load i32, ptr [[C]], align 4
+// CHECK6-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTC__VOID_ADDR]], align 4
+// CHECK6-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP7]], [[TMP8]]
+// CHECK6-NEXT: store i32 [[MUL]], ptr [[C]], align 4
+// CHECK6-NEXT: call void @__kmpc_end_reduce_nowait(ptr @[[GLOB2]], i32 [[TMP0]], ptr @.gomp_critical_user_.reduction.var)
+// CHECK6-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
+// CHECK6: .omp.reduction.case2:
+// CHECK6-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTC__VOID_ADDR]], align 4
+// CHECK6-NEXT: [[ATOMIC_LOAD:%.*]] = load atomic i32, ptr [[C]] monotonic, align 4
+// CHECK6-NEXT: br label [[ATOMIC_CONT:%.*]]
+// CHECK6: atomic_cont:
+// CHECK6-NEXT: [[TMP10:%.*]] = phi i32 [ [[ATOMIC_LOAD]], [[DOTOMP_REDUCTION_CASE2]] ], [ [[TMP15:%.*]], [[ATOMIC_CONT]] ]
+// CHECK6-NEXT: store i32 [[TMP10]], ptr [[TMP]], align 4
+// CHECK6-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP]], align 4
+// CHECK6-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTC__VOID_ADDR]], align 4
+// CHECK6-NEXT: [[MUL4:%.*]] = mul nsw i32 [[TMP11]], [[TMP12]]
+// CHECK6-NEXT: store i32 [[MUL4]], ptr [[ATOMIC_TEMP]], align 4
+// CHECK6-NEXT: [[TMP13:%.*]] = load i32, ptr [[ATOMIC_TEMP]], align 4
+// CHECK6-NEXT: [[TMP14:%.*]] = cmpxchg ptr [[C]], i32 [[TMP10]], i32 [[TMP13]] monotonic monotonic, align 4
+// CHECK6-NEXT: [[TMP15]] = extractvalue { i32, i1 } [[TMP14]], 0
+// CHECK6-NEXT: [[TMP16:%.*]] = extractvalue { i32, i1 } [[TMP14]], 1
+// CHECK6-NEXT: br i1 [[TMP16]], label [[ATOMIC_EXIT:%.*]], label [[ATOMIC_CONT]]
+// CHECK6: atomic_exit:
+// CHECK6-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
+// CHECK6: .omp.reduction.default:
+// CHECK6-NEXT: [[TMP17:%.*]] = load ptr, ptr @omp_high_bw_mem_alloc, align 8
+// CHECK6-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTC__VOID_ADDR]], ptr [[TMP17]])
+// CHECK6-NEXT: ret void
+//
+//
+// CHECK6-LABEL: define {{[^@]+}}@_Z10array_funciPiP2St.omp.reduction.reduction_func
+// CHECK6-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR2:[0-9]+]] {
+// CHECK6-NEXT: entry:
+// CHECK6-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8
+// CHECK6-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8
+// CHECK6-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
+// CHECK6-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8
+// CHECK6-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR]], align 8
+// CHECK6-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
+// CHECK6-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP3]], i64 0, i64 0
+// CHECK6-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8
+// CHECK6-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP2]], i64 0, i64 0
+// CHECK6-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8
+// CHECK6-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
+// CHECK6-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP5]], align 4
+// CHECK6-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP8]], [[TMP9]]
+// CHECK6-NEXT: store i32 [[MUL]], ptr [[TMP7]], align 4
+// CHECK6-NEXT: ret void
+//
+//
+// CHECK6-LABEL: define {{[^@]+}}@main
+// CHECK6-SAME: () #[[ATTR4:[0-9]+]] {
+// CHECK6-NEXT: entry:
+// CHECK6-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK6-NEXT: [[N:%.*]] = alloca i32, align 4
+// CHECK6-NEXT: [[A:%.*]] = alloca [10 x i32], align 16
+// CHECK6-NEXT: [[S:%.*]] = alloca [2 x %struct.St], align 16
+// CHECK6-NEXT: store i32 0, ptr [[RETVAL]], align 4
+// CHECK6-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.St], ptr [[S]], i32 0, i32 0
+// CHECK6-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], ptr [[ARRAY_BEGIN]], i64 2
+// CHECK6-NEXT: br label [[ARRAYCTOR_LOOP:%.*]]
+// CHECK6: arrayctor.loop:
+// CHECK6-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ]
+// CHECK6-NEXT: call void @_ZN2StC1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[ARRAYCTOR_CUR]])
+// CHECK6-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_ST]], ptr [[ARRAYCTOR_CUR]], i64 1
+// CHECK6-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]]
+// CHECK6-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]]
+// CHECK6: arrayctor.cont:
+// CHECK6-NEXT: [[TMP0:%.*]] = load i32, ptr [[N]], align 4
+// CHECK6-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[A]], i64 0, i64 0
+// CHECK6-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [2 x %struct.St], ptr [[S]], i64 0, i64 0
+// CHECK6-NEXT: call void @_Z10array_funciPiP2St(i32 noundef [[TMP0]], ptr noundef [[ARRAYDECAY]], ptr noundef [[ARRAYDECAY1]])
+// CHECK6-NEXT: store i32 0, ptr [[RETVAL]], align 4
+// CHECK6-NEXT: [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.St], ptr [[S]], i32 0, i32 0
+// CHECK6-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[ARRAY_BEGIN2]], i64 2
+// CHECK6-NEXT: br label [[ARRAYDESTROY_BODY:%.*]]
+// CHECK6: arraydestroy.body:
+// CHECK6-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP1]], [[ARRAYCTOR_CONT]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ]
+// CHECK6-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_ST]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1
+// CHECK6-NEXT: call void @_ZN2StD1Ev(ptr noundef nonnull align 4 dereferenceable(8) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR1:[0-9]+]]
+// CHECK6-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN2]]
+// CHECK6-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE3:%.*]], label [[ARRAYDESTROY_BODY]]
+// CHECK6: arraydestroy.done3:
+// CHECK6-NEXT: [[TMP2:%.*]] = load i32, ptr [[RETVAL]], align 4
+// CHECK6-NEXT: ret i32 [[TMP2]]
+//
+//
+// CHECK6-LABEL: define {{[^@]+}}@_ZN2StC1Ev
+// CHECK6-SAME: (ptr noundef nonnull align 4 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR0]] align 2 {
+// CHECK6-NEXT: entry:
+// CHECK6-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK6-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK6-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK6-NEXT: call void @_ZN2StC2Ev(ptr noundef nonnull align 4 dereferenceable(8) [[THIS1]])
+// CHECK6-NEXT: ret void
+//
+//
+// CHECK6-LABEL: define {{[^@]+}}@_ZN2StD1Ev
+// CHECK6-SAME: (ptr noundef nonnull align 4 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR0]] align 2 {
+// CHECK6-NEXT: entry:
+// CHECK6-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK6-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK6-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK6-NEXT: call void @_ZN2StD2Ev(ptr noundef nonnull align 4 dereferenceable(8) [[THIS1]]) #[[ATTR1]]
+// CHECK6-NEXT: ret void
+//
+//
+// CHECK6-LABEL: define {{[^@]+}}@_ZN2StC2Ev
+// CHECK6-SAME: (ptr noundef nonnull align 4 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR0]] align 2 {
+// CHECK6-NEXT: entry:
+// CHECK6-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK6-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK6-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK6-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_ST:%.*]], ptr [[THIS1]], i32 0, i32 0
+// CHECK6-NEXT: store i32 0, ptr [[A]], align 4
+// CHECK6-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_ST]], ptr [[THIS1]], i32 0, i32 1
+// CHECK6-NEXT: store i32 0, ptr [[B]], align 4
+// CHECK6-NEXT: ret void
+//
+//
+// CHECK6-LABEL: define {{[^@]+}}@_ZN2StD2Ev
+// CHECK6-SAME: (ptr noundef nonnull align 4 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR0]] align 2 {
+// CHECK6-NEXT: entry:
+// CHECK6-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
+// CHECK6-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
+// CHECK6-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
+// CHECK6-NEXT: ret void
+//
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 1f747df43eeb80..01515108ca1857 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -887,6 +887,8 @@ def OMP_scope : Directive<"scope"> {
let allowedClauses = [
VersionedClause<OMPC_Private, 51>,
VersionedClause<OMPC_Reduction, 51>,
+ VersionedClause<OMPC_FirstPrivate, 52>,
+ VersionedClause<OMPC_Allocate, 52>,
];
let allowedOnceClauses = [
VersionedClause<OMPC_NoWait, 51>,
More information about the cfe-commits
mailing list