r263706 - [OPENMP 4.5] Allow to use private data members in 'copyprivate' clause.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 17 03:50:17 PDT 2016


Author: abataev
Date: Thu Mar 17 05:50:17 2016
New Revision: 263706

URL: http://llvm.org/viewvc/llvm-project?rev=263706&view=rev
Log:
[OPENMP 4.5] Allow to use private data members in 'copyprivate' clause.

OpenMP 4.5 allows privatization of non-static data members in non-static
member functions. This patch adds support of private data members in
'copyprivate' clauses.

Modified:
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/test/OpenMP/single_ast_print.cpp
    cfe/trunk/test/OpenMP/single_codegen.cpp

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=263706&r1=263705&r2=263706&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Thu Mar 17 05:50:17 2016
@@ -8929,52 +8929,37 @@ OMPClause *Sema::ActOnOpenMPCopyprivateC
   SmallVector<Expr *, 8> DstExprs;
   SmallVector<Expr *, 8> AssignmentOps;
   for (auto &RefExpr : VarList) {
-    assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
-    if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+    assert(RefExpr && "NULL expr in OpenMP linear clause.");
+    SourceLocation ELoc;
+    SourceRange ERange;
+    Expr *SimpleRefExpr = RefExpr;
+    auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
+                              /*AllowArraySection=*/false);
+    if (Res.second) {
       // It will be analyzed later.
       Vars.push_back(RefExpr);
       SrcExprs.push_back(nullptr);
       DstExprs.push_back(nullptr);
       AssignmentOps.push_back(nullptr);
-      continue;
     }
-
-    SourceLocation ELoc = RefExpr->getExprLoc();
-    // OpenMP [2.1, C/C++]
-    //  A list item is a variable name.
-    // OpenMP  [2.14.4.1, Restrictions, p.1]
-    //  A list item that appears in a copyin clause must be threadprivate.
-    DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
-    if (!DE || !isa<VarDecl>(DE->getDecl())) {
-      Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
-          << 0 << RefExpr->getSourceRange();
+    ValueDecl *D = Res.first;
+    if (!D)
       continue;
-    }
 
-    Decl *D = DE->getDecl();
-    VarDecl *VD = cast<VarDecl>(D);
-
-    QualType Type = VD->getType();
-    if (Type->isDependentType() || Type->isInstantiationDependentType()) {
-      // It will be analyzed later.
-      Vars.push_back(DE);
-      SrcExprs.push_back(nullptr);
-      DstExprs.push_back(nullptr);
-      AssignmentOps.push_back(nullptr);
-      continue;
-    }
+    QualType Type = D->getType();
+    auto *VD = dyn_cast<VarDecl>(D);
 
     // OpenMP [2.14.4.2, Restrictions, p.2]
     //  A list item that appears in a copyprivate clause may not appear in a
     //  private or firstprivate clause on the single construct.
-    if (!DSAStack->isThreadPrivate(VD)) {
-      auto DVar = DSAStack->getTopDSA(VD, false);
+    if (!VD || !DSAStack->isThreadPrivate(VD)) {
+      auto DVar = DSAStack->getTopDSA(D, false);
       if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
           DVar.RefExpr) {
         Diag(ELoc, diag::err_omp_wrong_dsa)
             << getOpenMPClauseName(DVar.CKind)
             << getOpenMPClauseName(OMPC_copyprivate);
-        ReportOriginalDSA(*this, DSAStack, VD, DVar);
+        ReportOriginalDSA(*this, DSAStack, D, DVar);
         continue;
       }
 
@@ -8982,12 +8967,12 @@ OMPClause *Sema::ActOnOpenMPCopyprivateC
       //  All list items that appear in a copyprivate clause must be either
       //  threadprivate or private in the enclosing context.
       if (DVar.CKind == OMPC_unknown) {
-        DVar = DSAStack->getImplicitDSA(VD, false);
+        DVar = DSAStack->getImplicitDSA(D, false);
         if (DVar.CKind == OMPC_shared) {
           Diag(ELoc, diag::err_omp_required_access)
               << getOpenMPClauseName(OMPC_copyprivate)
               << "threadprivate or private in the enclosing context";
-          ReportOriginalDSA(*this, DSAStack, VD, DVar);
+          ReportOriginalDSA(*this, DSAStack, D, DVar);
           continue;
         }
       }
@@ -8999,10 +8984,11 @@ OMPClause *Sema::ActOnOpenMPCopyprivateC
           << getOpenMPClauseName(OMPC_copyprivate) << Type
           << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
       bool IsDecl =
+          !VD ||
           VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
-      Diag(VD->getLocation(),
+      Diag(D->getLocation(),
            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
-          << VD;
+          << D;
       continue;
     }
 
@@ -9013,27 +8999,29 @@ OMPClause *Sema::ActOnOpenMPCopyprivateC
     Type = Context.getBaseElementType(Type.getNonReferenceType())
                .getUnqualifiedType();
     auto *SrcVD =
-        buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src",
-                     VD->hasAttrs() ? &VD->getAttrs() : nullptr);
-    auto *PseudoSrcExpr =
-        buildDeclRefExpr(*this, SrcVD, Type, DE->getExprLoc());
+        buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.src",
+                     D->hasAttrs() ? &D->getAttrs() : nullptr);
+    auto *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
     auto *DstVD =
-        buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst",
-                     VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+        buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.dst",
+                     D->hasAttrs() ? &D->getAttrs() : nullptr);
     auto *PseudoDstExpr =
-        buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc());
-    auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
+        buildDeclRefExpr(*this, DstVD, Type, ELoc);
+    auto AssignmentOp = BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
                                    PseudoDstExpr, PseudoSrcExpr);
     if (AssignmentOp.isInvalid())
       continue;
-    AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
+    AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
                                        /*DiscardedValue=*/true);
     if (AssignmentOp.isInvalid())
       continue;
 
     // No need to mark vars as copyprivate, they are already threadprivate or
     // implicitly private.
-    Vars.push_back(DE);
+    assert(VD || IsOpenMPCapturedDecl(D));
+    Vars.push_back(
+        VD ? RefExpr->IgnoreParens()
+           : buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
     SrcExprs.push_back(PseudoSrcExpr);
     DstExprs.push_back(PseudoDstExpr);
     AssignmentOps.push_back(AssignmentOp.get());

Modified: cfe/trunk/test/OpenMP/single_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/single_ast_print.cpp?rev=263706&r1=263705&r2=263706&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/single_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/single_ast_print.cpp Thu Mar 17 05:50:17 2016
@@ -8,15 +8,43 @@
 
 void foo() {}
 
+struct SS {
+  int a;
+  int b : 4;
+  int &c;
+  SS(int &d) : a(0), b(0), c(d) {
+#pragma omp parallel firstprivate(a, b, c)
+#pragma omp single copyprivate(a, this->b, (this)->c)
+// CHECK: #pragma omp parallel firstprivate(this->a,this->b,this->c)
+// CHECK-NEXT: #pragma omp single copyprivate(this->a,this->b,this->c)
+    ++this->a, --b, (this)->c /= 1;
+  }
+};
+
+template<typename T>
+struct SST {
+  T a;
+  SST() : a(T()) {
+// CHECK: #pragma omp parallel firstprivate(this->a)
+// CHECK-NEXT: #pragma omp single copyprivate(this->a)
+// CHECK: #pragma omp parallel firstprivate(this->a)
+// CHECK-NEXT: #pragma omp single copyprivate(this->a)
+#pragma omp parallel firstprivate(a)
+#pragma omp single copyprivate(this->a)
+    ++this->a;
+  }
+};
+
 template <class T, int N>
 T tmain(T argc) {
   T b = argc, c, d, e, f, g;
   static T a;
+  SST<T> sst;
 // CHECK: static T a;
 #pragma omp parallel private(g)
 #pragma omp single private(argc, b), firstprivate(c, d), nowait
   foo();
-  // CHECK-NEXT: #pragma omp parallel private(g)
+  // CHECK: #pragma omp parallel private(g)
   // CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(c,d) nowait
   // CHECK-NEXT: foo();
 #pragma omp parallel private(g)
@@ -31,11 +59,12 @@ T tmain(T argc) {
 int main(int argc, char **argv) {
   int b = argc, c, d, e, f, g;
   static int a;
+  SS ss(a);
 // CHECK: static int a;
 #pragma omp parallel private(g)
 #pragma omp single private(argc, b), firstprivate(argv, c), nowait
   foo();
-  // CHECK-NEXT: #pragma omp parallel private(g)
+  // CHECK: #pragma omp parallel private(g)
   // CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(argv,c) nowait
   // CHECK-NEXT: foo();
 #pragma omp parallel private(g)

Modified: cfe/trunk/test/OpenMP/single_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/single_codegen.cpp?rev=263706&r1=263705&r2=263706&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/single_codegen.cpp (original)
+++ cfe/trunk/test/OpenMP/single_codegen.cpp Thu Mar 17 05:50:17 2016
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
 // RUN: %clang_cc1 -fopenmp -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 -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
-// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fnoopenmp-use-tls -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -std=c++11 -fopenmp -fnoopenmp-use-tls -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
 // RUN: %clang_cc1 -verify -fopenmp -fnoopenmp-use-tls -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
 // expected-no-diagnostics
 // REQUIRES: x86-registered-target
@@ -19,7 +19,9 @@ public:
 };
 
 // CHECK-DAG:   [[TEST_CLASS_TY:%.+]] = type { i{{[0-9]+}} }
-// CHECK:       [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
+// CHECK-DAG:   [[SST_TY:%.+]] = type { double }
+// CHECK-DAG:   [[SS_TY:%.+]] = type { i32, i8, i32* }
+// CHECK-DAG:   [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
 // CHECK:       [[IMPLICIT_BARRIER_SINGLE_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 322, i32 0, i32 0, i8*
 
 // CHECK:       define void [[FOO:@.+]]()
@@ -30,6 +32,39 @@ TestClass tc2[2];
 
 void foo() {}
 
+struct SS {
+  int a;
+  int b : 4;
+  int &c;
+  SS(int &d) : a(0), b(0), c(d) {
+#pragma omp parallel firstprivate(a, b, c)
+#pragma omp single copyprivate(a, this->b, (this)->c)
+    [&]() {
+      ++this->a, --b, (this)->c /= 1;
+#pragma omp parallel firstprivate(a, b, c)
+#pragma omp single copyprivate(a, this->b, (this)->c)
+      ++(this)->a, --b, this->c /= 1;
+    }();
+  }
+};
+
+template<typename T>
+struct SST {
+  T a;
+  SST() : a(T()) {
+#pragma omp parallel firstprivate(a)
+#pragma omp single copyprivate(this->a)
+    [&]() {
+      [&]() {
+        ++this->a;
+#pragma omp parallel firstprivate(a)
+#pragma omp single copyprivate((this)->a)
+        ++(this)->a;
+      }();
+    }();
+  }
+};
+
 // CHECK-LABEL: @main
 // TERM_DEBUG-LABEL: @main
 int main() {
@@ -39,6 +74,8 @@ int main() {
   char a;
   char a2[2];
   TestClass &c = tc;
+  SST<double> sst;
+  SS ss(c.a);
 
 // CHECK:       [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:@.+]])
 // CHECK-DAG:   [[DID_IT:%.+]] = alloca i32,
@@ -186,3 +223,184 @@ void array_func(int n, int a[n], St s[2]
 // ARRAY: store i32* %{{.+}}, i32** %{{.+}},
 // ARRAY: store %struct.St* %{{.+}}, %struct.St** %{{.+}},
 #endif
+
+// CHECK-LABEL:@_ZN2SSC2ERi(
+// CHECK: call void ([[IDENT_T_TY]]*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call([[IDENT_T_TY]]* @{{.+}}, i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[SS_TY]]*, i32*, i32*, i32*)* [[SS_MICROTASK:@.+]] to void
+// CHECK-NEXT: ret void
+
+// CHECK: define internal void [[SS_MICROTASK]](i32* {{[^,]+}}, i32* {{[^,]+}}, [[SS_TY]]* {{.+}}, i32* {{.+}}, i32* {{.+}}, i32* {{.+}})
+// Private a
+// CHECK: alloca i32,
+// CHECK: alloca i32*,
+// Private b
+// CHECK: alloca i32,
+// Private c
+// CHECK: alloca i32,
+// CHECK: alloca i32*,
+// CHECK: [[DID_IT:%.+]] = alloca i32,
+// CHECK: store i32 0, i32* [[DID_IT]],
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_single([[IDENT_T_TY]]* @{{.+}}, i32 %{{.+}})
+// CHECK-NEXT: icmp ne i32 [[RES]], 0
+// CHECK-NEXT: br i1
+
+// CHECK: getelementptr inbounds [[CAP_TY:%.+]], [[CAP_TY]]* [[CAP:%.+]], i32 0, i32 0
+// CHECK: getelementptr inbounds [[CAP_TY]], [[CAP_TY]]* [[CAP]], i32 0, i32 1
+// CHECK-NEXT: load i32*, i32** %
+// CHECK-NEXT: store i32* %
+// CHECK-NEXT: getelementptr inbounds [[CAP_TY]], [[CAP_TY]]* [[CAP]], i32 0, i32 2
+// CHECK-NEXT: store i32* %
+// CHECK-NEXT: getelementptr inbounds [[CAP_TY]], [[CAP_TY]]* [[CAP]], i32 0, i32 3
+// CHECK-NEXT: load i32*, i32** %
+// CHECK-NEXT: store i32* %
+// CHECK-LABEL: invoke void @_ZZN2SSC1ERiENKUlvE_clEv(
+// CHECK-SAME: [[CAP_TY]]* [[CAP]])
+
+// CHECK: store i32 1, i32* [[DID_IT]],
+// CHECK: call void @__kmpc_end_single([[IDENT_T_TY]]* @{{.+}}, i32 %{{.+}})
+// CHECK: br label
+
+// CHECK: call void @__kmpc_end_single(%{{.+}}* @{{.+}}, i32 %{{.+}})
+// CHECK: br label
+
+// CHECK: getelementptr inbounds [3 x i8*], [3 x i8*]* [[LIST:%.+]], i64 0, i64 0
+// CHECK: load i32*, i32** %
+// CHECK-NEXT: bitcast i32* %
+// CHECK-NEXT: store i8* %
+// CHECK: getelementptr inbounds [3 x i8*], [3 x i8*]* [[LIST]], i64 0, i64 1
+// CHECK-NEXT: bitcast i32* %
+// CHECK-NEXT: store i8* %
+// CHECK: getelementptr inbounds [3 x i8*], [3 x i8*]* [[LIST]], i64 0, i64 2
+// CHECK: load i32*, i32** %
+// CHECK-NEXT: bitcast i32* %
+// CHECK-NEXT: store i8* %
+// CHECK-NEXT: bitcast [3 x i8*]* [[LIST]] to i8*
+// CHECK-NEXT: load i32, i32* [[DID_IT]],
+// CHECK-NEXT: call void @__kmpc_copyprivate([[IDENT_T_TY]]* @{{.+}}, i32 %{{.+}}, i64 24, i8* %{{.+}}, void (i8*, i8*)* [[COPY_FUNC:@[^,]+]], i32 %{{.+}})
+// CHECK-NEXT: ret void
+
+// CHECK-LABEL: @_ZZN2SSC1ERiENKUlvE_clEv(
+// CHECK: getelementptr inbounds [[CAP_TY]], [[CAP_TY]]* [[CAP:%.+]], i32 0, i32 1
+// CHECK-NEXT: load i32*, i32** %
+// CHECK-NEXT: load i32, i32* %
+// CHECK-NEXT: add nsw i32 %{{.+}}, 1
+// CHECK-NEXT: store i32 %
+// CHECK-NEXT: getelementptr inbounds [[CAP_TY]], [[CAP_TY]]* [[CAP]], i32 0, i32 2
+// CHECK-NEXT: load i32*, i32** %
+// CHECK-NEXT: load i32, i32* %
+// CHECK-NEXT: add nsw i32 %{{.+}}, -1
+// CHECK-NEXT: store i32 %
+// CHECK-NEXT: getelementptr inbounds [[CAP_TY]], [[CAP_TY]]* [[CAP]], i32 0, i32 3
+// CHECK-NEXT: load i32*, i32** %
+// CHECK-NEXT: load i32, i32* %
+// CHECK-NEXT: sdiv i32 %{{.+}}, 1
+// CHECK-NEXT: store i32 %
+// CHECK-NEXT: getelementptr inbounds [[CAP_TY]], [[CAP_TY]]* [[CAP]], i32 0, i32 1
+// CHECK-NEXT: load i32*, i32** %
+// CHECK-NEXT: getelementptr inbounds [[CAP_TY]], [[CAP_TY]]* [[CAP]], i32 0, i32 2
+// CHECK-NEXT: load i32*, i32** %
+// CHECK-NEXT: getelementptr inbounds [[CAP_TY]], [[CAP_TY]]* [[CAP]], i32 0, i32 3
+// CHECK-NEXT: load i32*, i32** %
+// CHECK-NEXT: call void ([[IDENT_T_TY]]*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call([[IDENT_T_TY]]* @{{.+}}, i32 4, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[SS_TY]]*, i32*, i32*, i32*)* [[SS_MICROTASK1:@.+]] to void
+// CHECK-NEXT: ret void
+
+// CHECK: define internal void [[COPY_FUNC]](i8*, i8*)
+// CHECK: ret void
+
+// CHECK: define internal void [[SS_MICROTASK1]](i32* {{[^,]+}}, i32* {{[^,]+}}, [[SS_TY]]* {{.+}}, i32* {{.+}}, i32* {{.+}}, i32* {{.+}})
+// Private a
+// CHECK: alloca i32,
+// CHECK: alloca i32*,
+// Private b
+// CHECK: alloca i32,
+// Private c
+// CHECK: alloca i32,
+// CHECK: alloca i32*,
+// CHECK: [[DID_IT:%.+]] = alloca i32,
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_single([[IDENT_T_TY]]* @{{.+}}, i32 %{{.+}})
+// CHECK-NEXT: icmp ne i32 [[RES]], 0
+// CHECK-NEXT: br i1
+
+// CHECK-NOT: getelementptr inbounds
+// CHECK: load i32*, i32** %
+// CHECK-NEXT: load i32, i32* %
+// CHECK-NEXT: add nsw i32 %{{.+}}, 1
+// CHECK-NEXT: store i32 %
+// CHECK-NOT: getelementptr inbounds
+// CHECK: load i32, i32* %
+// CHECK-NEXT: add nsw i32 %{{.+}}, -1
+// CHECK-NEXT: store i32 %
+// CHECK-NOT: getelementptr inbounds
+// CHECK: load i32*, i32** %
+// CHECK-NEXT: load i32, i32* %
+// CHECK-NEXT: sdiv i32 %{{.+}}, 1
+// CHECK-NEXT: store i32 %
+// CHECK-NEXT: store i32 1, i32* [[DID_IT]],
+// CHECK-NEXT: call void @__kmpc_end_single([[IDENT_T_TY]]* @{{.+}}, i32 %{{.+}})
+// CHECK-NEXT: br label
+
+// CHECK: getelementptr inbounds [3 x i8*], [3 x i8*]* [[LIST:%.+]], i64 0, i64 0
+// CHECK: load i32*, i32** %
+// CHECK-NEXT: bitcast i32* %
+// CHECK-NEXT: store i8* %
+// CHECK: getelementptr inbounds [3 x i8*], [3 x i8*]* [[LIST]], i64 0, i64 1
+// CHECK-NEXT: bitcast i32* %
+// CHECK-NEXT: store i8* %
+// CHECK: getelementptr inbounds [3 x i8*], [3 x i8*]* [[LIST]], i64 0, i64 2
+// CHECK: load i32*, i32** %
+// CHECK-NEXT: bitcast i32* %
+// CHECK-NEXT: store i8* %
+// CHECK-NEXT: bitcast [3 x i8*]* [[LIST]] to i8*
+// CHECK-NEXT: load i32, i32* [[DID_IT]],
+// CHECK-NEXT: call void @__kmpc_copyprivate([[IDENT_T_TY]]* @{{.+}}, i32 %{{.+}}, i64 24, i8* %{{.+}}, void (i8*, i8*)* [[COPY_FUNC:@[^,]+]], i32 %{{.+}})
+// CHECK-NEXT:  ret void
+
+// CHECK: define internal void [[COPY_FUNC]](i8*, i8*)
+// CHECK: ret void
+
+// CHECK-LABEL: @_ZN3SSTIdEC2Ev
+// CHECK: getelementptr inbounds [[SST_TY]], [[SST_TY]]* %{{.+}}, i32 0, i32 0
+// CHECK-NEXT: store double 0.000000e+00, double* %
+// CHECK-NEXT: getelementptr inbounds [[SST_TY]], [[SST_TY]]* %{{.+}}, i32 0, i32 0
+// CHECK-NEXT: store double* %
+// CHECK-NEXT: load double*, double** %
+// CHECK-NEXT: call void ([[IDENT_T_TY]]*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call([[IDENT_T_TY]]* @{{.+}}, i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[SST_TY]]*, double*)* [[SST_MICROTASK:@.+]] to void
+// CHECK-NEXT: ret void
+
+// CHECK: define internal void [[SST_MICROTASK]](i32* {{[^,]+}}, i32* {{[^,]+}}, [[SST_TY]]* {{.+}}, double* {{.+}})
+// CHECK: [[RES:%.+]] = call i32 @__kmpc_single([[IDENT_T_TY]]* @{{.+}}, i32 %{{.+}})
+// CHECK-NEXT: icmp ne i32 [[RES]], 0
+// CHECK-NEXT: br i1
+
+// CHECK: getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 1
+// CHECK-NEXT: load double*, double** %
+// CHECK-NEXT: store double* %
+// CHECK-LABEL: invoke void @_ZZN3SSTIdEC1EvENKUlvE_clEv(
+
+// CHECK: store i32 1, i32* [[DID_IT]],
+// CHECK-NEXT: call void @__kmpc_end_single([[IDENT_T_TY]]* @{{.+}}, i32 %{{.+}})
+// CHECK-NEXT: br label
+
+// CHECK: call void @__kmpc_end_single([[IDENT_T_TY]]* @{{.+}}, i32 %{{.+}})
+// CHECK-NEXT: br label
+
+// CHECK: getelementptr inbounds [1 x i8*], [1 x i8*]* [[LIST:%.+]], i64 0, i64 0
+// CHECK: load double*, double** %
+// CHECK-NEXT: bitcast double* %
+// CHECK-NEXT: store i8* %
+// CHECK-NEXT: bitcast [1 x i8*]* [[LIST]] to i8*
+// CHECK-NEXT: load i32, i32* [[DID_IT]],
+// CHECK-NEXT: call void @__kmpc_copyprivate([[IDENT_T_TY]]* @{{.+}}, i32 %{{.+}}, i64 8, i8* %{{.+}}, void (i8*, i8*)* [[COPY_FUNC:@[^,]+]], i32 %{{.+}})
+// CHECK-NEXT:  ret void
+
+// CHECK-LABEL: @_ZZN3SSTIdEC1EvENKUlvE_clEv(
+// CHECK: getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 1
+// CHECK-NEXT: getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i32 0, i32 1
+// CHECK-NEXT: load double*, double** %
+// CHECK-NEXT: store double* %
+// CHECK-LABEL: call void @_ZZZN3SSTIdEC1EvENKUlvE_clEvENKUlvE_clEv(
+// CHECK-NEXT: ret void
+
+// CHECK: define internal void [[COPY_FUNC]](i8*, i8*)
+// CHECK: ret void
+
+// CHECK-LABEL: @_ZZZN3SSTIdEC1EvENKUlvE_clEvENKUlvE_clEv(




More information about the cfe-commits mailing list