summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@outlook.com>2021-11-19 05:59:40 -0800
committerAlexey Bataev <a.bataev@outlook.com>2021-11-19 06:30:17 -0800
commit80256605f8c6aab8cb33ac3a3784aacd005087a3 (patch)
tree404b3343a59073ea21735e9ac7a8c34091debc44
parent8b76d33c593984a0fda6d756ee266d3eaa4b3b1b (diff)
downloadllvm-80256605f8c6aab8cb33ac3a3784aacd005087a3.tar.gz
[OpenMP] support depend clause for taskwait directive, by Deepak
Eachempati. This patch adds clang (parsing, sema, serialization, codegen) support for the 'depend' clause on the 'taskwait' directive. Reviewed By: ABataev Differential Revision: https://reviews.llvm.org/D113540
-rw-r--r--clang/docs/OpenMPSupport.rst2
-rw-r--r--clang/include/clang/AST/StmtOpenMP.h11
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/include/clang/Sema/Sema.h3
-rw-r--r--clang/lib/AST/StmtOpenMP.cpp14
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp53
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.h6
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp9
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp14
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp5
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp1
-rw-r--r--clang/test/OpenMP/taskwait_ast_print.cpp18
-rw-r--r--clang/test/OpenMP/taskwait_depend_codegen.cpp38
-rw-r--r--clang/test/OpenMP/taskwait_depend_messages.cpp62
-rw-r--r--clang/test/OpenMP/taskwait_messages.cpp5
-rw-r--r--openmp/runtime/test/ompt/tasks/taskwait-depend.c7
-rw-r--r--openmp/runtime/test/tasking/omp50_taskwait_depend.c11
17 files changed, 214 insertions, 47 deletions
diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index 0e3cd25e59e3..8b530b9febef 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -147,7 +147,7 @@ implementation.
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| task extension | task affinity | :part:`not upstream` | https://github.com/jklinkenberg/openmp/tree/task-affinity |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
-| task extension | clause: depend on the taskwait construct | :part:`worked on` | |
+| task extension | clause: depend on the taskwait construct | :part:`mostly done` | D113540 (regular codegen only) |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| task extension | depend objects and detachable tasks | :good:`done` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index 48b2dce152a6..d5b5c9580da9 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -2569,15 +2569,20 @@ public:
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
///
- static OMPTaskwaitDirective *
- Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
+ static OMPTaskwaitDirective *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses);
/// Creates an empty directive.
///
/// \param C AST context.
+ /// \param NumClauses Number of clauses.
///
- static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+ static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTaskwaitDirectiveClass;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 50c1e0a1746b..dc67f86f25ca 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10599,6 +10599,8 @@ def err_omp_depend_sink_unexpected_expr : Error<
"unexpected expression: number of expressions is larger than the number of associated loops">;
def err_omp_depend_sink_expected_plus_minus : Error<
"expected '+' or '-' operation">;
+def err_omp_taskwait_depend_mutexinoutset_not_allowed : Error<
+ "'mutexinoutset' modifier not allowed in 'depend' clause on 'taskwait' directive">;
def err_omp_depend_sink_source_not_allowed : Error<
"'depend(%select{source|sink:vec}0)' clause%select{|s}0 cannot be mixed with 'depend(%select{sink:vec|source}0)' clause%select{s|}0">;
def err_omp_depend_zero_length_array_section_not_allowed : Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 91c9feb40cba..43ce5d983217 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10753,7 +10753,8 @@ public:
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
SourceLocation EndLoc);
/// Called on well-formed '\#pragma omp taskwait'.
- StmtResult ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
+ StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
SourceLocation EndLoc);
/// Called on well-formed '\#pragma omp taskgroup'.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp
index aa28cd193736..b336a0637d5e 100644
--- a/clang/lib/AST/StmtOpenMP.cpp
+++ b/clang/lib/AST/StmtOpenMP.cpp
@@ -739,15 +739,19 @@ OMPBarrierDirective *OMPBarrierDirective::CreateEmpty(const ASTContext &C,
return new (C) OMPBarrierDirective();
}
-OMPTaskwaitDirective *OMPTaskwaitDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
- return new (C) OMPTaskwaitDirective(StartLoc, EndLoc);
+OMPTaskwaitDirective *
+OMPTaskwaitDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses) {
+ return createDirective<OMPTaskwaitDirective>(
+ C, Clauses, /*AssociatedStmt=*/nullptr, /*NumChildren=*/0, StartLoc,
+ EndLoc);
}
OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
EmptyShell) {
- return new (C) OMPTaskwaitDirective();
+ return createEmptyDirective<OMPTaskwaitDirective>(C, NumClauses);
}
OMPTaskgroupDirective *OMPTaskgroupDirective::Create(
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 8606e80418d7..75709b3c7e78 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6264,21 +6264,51 @@ Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
SharedLVal.getAlignment());
}
-void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
- SourceLocation Loc) {
+void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const OMPTaskDataTy &Data) {
if (!CGF.HaveInsertPoint())
return;
- if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
+ if (CGF.CGM.getLangOpts().OpenMPIRBuilder && Data.Dependences.empty()) {
+ // TODO: Need to support taskwait with dependences in the OpenMPIRBuilder.
OMPBuilder.createTaskwait(CGF.Builder);
} else {
- // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
- // global_tid);
- llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
- // Ignore return result until untied tasks are supported.
- CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_omp_taskwait),
- Args);
+ llvm::Value *ThreadID = getThreadID(CGF, Loc);
+ llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
+ auto &M = CGM.getModule();
+ Address DependenciesArray = Address::invalid();
+ llvm::Value *NumOfElements;
+ std::tie(NumOfElements, DependenciesArray) =
+ emitDependClause(CGF, Data.Dependences, Loc);
+ llvm::Value *DepWaitTaskArgs[6];
+ if (!Data.Dependences.empty()) {
+ DepWaitTaskArgs[0] = UpLoc;
+ DepWaitTaskArgs[1] = ThreadID;
+ DepWaitTaskArgs[2] = NumOfElements;
+ DepWaitTaskArgs[3] = DependenciesArray.getPointer();
+ DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
+ DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
+
+ CodeGenFunction::RunCleanupsScope LocalScope(CGF);
+
+ // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
+ // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
+ // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
+ // is specified.
+ CGF.EmitRuntimeCall(
+ OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps),
+ DepWaitTaskArgs);
+
+ } else {
+
+ // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
+ // global_tid);
+ llvm::Value *Args[] = {UpLoc, ThreadID};
+ // Ignore return result until untied tasks are supported.
+ CGF.EmitRuntimeCall(
+ OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
+ Args);
+ }
}
if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
@@ -13044,7 +13074,8 @@ Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
}
void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
- SourceLocation Loc) {
+ SourceLocation Loc,
+ const OMPTaskDataTy &Data) {
llvm_unreachable("Not supported in SIMD-only mode");
}
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h
index 14579ac6f6ff..527a23a8af6a 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -1547,7 +1547,8 @@ public:
LValue SharedLVal);
/// Emit code for 'taskwait' directive.
- virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc);
+ virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const OMPTaskDataTy &Data);
/// Emit code for 'cancellation point' construct.
/// \param CancelRegion Region kind for which the cancellation point must be
@@ -2385,7 +2386,8 @@ public:
LValue SharedLVal) override;
/// Emit code for 'taskwait' directive.
- void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc) override;
+ void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const OMPTaskDataTy &Data) override;
/// Emit code for 'cancellation point' construct.
/// \param CancelRegion Region kind for which the cancellation point must be
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 3ca50503c62c..4f14459e4d28 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -4845,7 +4845,14 @@ void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
}
void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
- CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc());
+ OMPTaskDataTy Data;
+ // Build list of dependences
+ for (const auto *C : S.getClausesOfKind<OMPDependClause>()) {
+ OMPTaskDataTy::DependData &DD =
+ Data.Dependences.emplace_back(C->getDependencyKind(), C->getModifier());
+ DD.DepExprs.append(C->varlist_begin(), C->varlist_end());
+ }
+ CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data);
}
void CodeGenFunction::EmitOMPTaskgroupDirective(
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index debc9c5df382..22ae5f59d41b 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -6046,11 +6046,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
break;
case OMPD_taskwait:
- assert(ClausesWithImplicit.empty() &&
- "No clauses are allowed for 'omp taskwait' directive");
assert(AStmt == nullptr &&
"No associated statement allowed for 'omp taskwait' directive");
- Res = ActOnOpenMPTaskwaitDirective(StartLoc, EndLoc);
+ Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
break;
case OMPD_taskgroup:
Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
@@ -10467,9 +10465,10 @@ StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
return OMPBarrierDirective::Create(Context, StartLoc, EndLoc);
}
-StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
+StmtResult Sema::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
SourceLocation EndLoc) {
- return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc);
+ return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc, Clauses);
}
StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
@@ -18444,6 +18443,11 @@ Sema::ActOnOpenMPDependClause(Expr *DepModifier, OpenMPDependClauseKind DepKind,
<< "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
return nullptr;
}
+ if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
+ DepKind == OMPC_DEPEND_mutexinoutset) {
+ Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
+ return nullptr;
+ }
if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
DSAStack->getCurrentDirective() == OMPD_depobj) &&
(DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 02910b763800..b82a334b763c 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2416,6 +2416,8 @@ void ASTStmtReader::VisitOMPBarrierDirective(OMPBarrierDirective *D) {
void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
@@ -3313,7 +3315,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_OMP_TASKWAIT_DIRECTIVE:
- S = OMPTaskwaitDirective::CreateEmpty(Context, Empty);
+ S = OMPTaskwaitDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
case STMT_OMP_TASKGROUP_DIRECTIVE:
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 9fdd86765c5a..2d92dec76dc9 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2380,6 +2380,7 @@ void ASTStmtWriter::VisitOMPBarrierDirective(OMPBarrierDirective *D) {
void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
VisitStmt(D);
+ Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE;
}
diff --git a/clang/test/OpenMP/taskwait_ast_print.cpp b/clang/test/OpenMP/taskwait_ast_print.cpp
index 9cbc46ef29f9..5b40242ece1c 100644
--- a/clang/test/OpenMP/taskwait_ast_print.cpp
+++ b/clang/test/OpenMP/taskwait_ast_print.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
-// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
-// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
-// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@@ -16,20 +16,26 @@ template <class T>
T tmain(T argc) {
static T a;
#pragma omp taskwait
+#pragma omp taskwait depend(in:a, argc)
return a + argc;
}
// CHECK: static T a;
// CHECK-NEXT: #pragma omp taskwait{{$}}
+// CHECK-NEXT: #pragma omp taskwait depend(in : a,argc){{$}}
// CHECK: static int a;
// CHECK-NEXT: #pragma omp taskwait
+// CHECK-NEXT: #pragma omp taskwait depend(in : a,argc){{$}}
// CHECK: static char a;
// CHECK-NEXT: #pragma omp taskwait
+// CHECK-NEXT: #pragma omp taskwait depend(in : a,argc){{$}}
int main(int argc, char **argv) {
static int a;
// CHECK: static int a;
#pragma omp taskwait
+#pragma omp taskwait depend(out:a, argc)
// CHECK-NEXT: #pragma omp taskwait
+ // CHECK-NEXT: #pragma omp taskwait depend(out : a,argc)
return tmain(argc) + tmain(argv[0][0]) + a;
}
diff --git a/clang/test/OpenMP/taskwait_depend_codegen.cpp b/clang/test/OpenMP/taskwait_depend_codegen.cpp
new file mode 100644
index 000000000000..5d1b03491147
--- /dev/null
+++ b/clang/test/OpenMP/taskwait_depend_codegen.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+template <class T>
+T tmain(T &argc) {
+ static T a;
+ #pragma omp taskwait depend(in:argc)
+ return a + argc;
+}
+int main(int argc, char **argv) {
+ int n = 0;
+ #pragma omp task shared(n,argc) depend(out:n)
+ n = argc;
+ return tmain(n);
+}
+
+// CHECK-LABEL: @main
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%{{.+}}* @{{.+}})
+// CHECK: [[ALLOC:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 1, i64 40, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* @{{.+}} to i32 (i32, i8*)*))
+// CHECK: %{{.+}} = call i32 @__kmpc_omp_task_with_deps(%{{.+}}* @{{.+}}, i32 [[GTID]], i8* [[ALLOC]], i32 1, i8* %{{[0-9]*}}, i32 0, i8* null)
+
+// CHECK-LABEL: tmain
+// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%{{.+}}* @{{.+}})
+// CHECK: call void @__kmpc_omp_wait_deps(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 1, i8* %{{.}}, i32 0, i8* null)
+
+
+#endif
diff --git a/clang/test/OpenMP/taskwait_depend_messages.cpp b/clang/test/OpenMP/taskwait_depend_messages.cpp
new file mode 100644
index 000000000000..40f8b5d0a9ab
--- /dev/null
+++ b/clang/test/OpenMP/taskwait_depend_messages.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+class vector {
+ public:
+ int operator[](int index) { return 0; }
+};
+
+int main(int argc, char **argv, char *env[]) {
+ vector vec;
+ typedef float V __attribute__((vector_size(16)));
+ V a;
+ auto arr = x; // expected-error {{use of undeclared identifier 'x'}}
+
+ #pragma omp taskwait depend // expected-error {{expected '(' after 'depend'}}
+ #pragma omp taskwait depend ( // expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after dependency type - ignoring}}
+ #pragma omp taskwait depend () // expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}}
+ #pragma omp taskwait depend (argc // expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp taskwait depend (source : argc) // expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
+ #pragma omp taskwait depend (source) // expected-error {{expected expression}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
+ #pragma omp taskwait depend(mutexinoutset: argc) // expected-error{{'mutexinoutset' modifier not allowed in 'depend' clause on 'taskwait' directive}}
+ #pragma omp taskwait depend (in : argc)) // expected-warning {{extra tokens at the end of '#pragma omp taskwait' are ignored}}
+ #pragma omp taskwait depend (out: ) // expected-error {{expected expression}}
+ #pragma omp taskwait depend (inout : foobool(argc)), depend (in, argc) // expected-error {{expected addressable lvalue expression, array element, array section or array shaping expression}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected expression}}
+
+ #pragma omp taskwait depend (out :S1) // expected-error {{'S1' does not refer to a value}}
+ #pragma omp taskwait depend(in : argv[1][1] = '2')
+ #pragma omp taskwait depend (in : vec[1]) // expected-error {{expected addressable lvalue expression, array element, array section or array shaping expression}}
+ #pragma omp taskwait depend (in : argv[0])
+ #pragma omp taskwait depend (in : ) // expected-error {{expected expression}}
+ #pragma omp taskwait depend (in : main)
+ #pragma omp taskwait depend(in : a[0]) // expected-error{{expected addressable lvalue expression, array element, array section or array shaping expression}}
+ #pragma omp taskwait depend (in : vec[1:2]) // expected-error {{ value is not an array or pointer}}
+ #pragma omp taskwait depend (in : argv[ // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ #pragma omp taskwait depend (in : argv[: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ #pragma omp taskwait depend (in : argv[:] // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp taskwait depend (in : argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ #pragma omp taskwait depend (in : argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp taskwait depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ #pragma omp taskwait depend (in : argv[-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}}
+ #pragma omp taskwait depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ #pragma omp taskwait depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp taskwait depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
+ #pragma omp taskwait depend(in:argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
+ #pragma omp taskwait depend(in:argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ #pragma omp taskwait depend(in:env[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
+ #pragma omp taskwait depend(in : argv[ : argc][1 : argc - 1])
+ #pragma omp taskwait depend(in : arr[0])
+ foo();
+
+ return 0;
+}
diff --git a/clang/test/OpenMP/taskwait_messages.cpp b/clang/test/OpenMP/taskwait_messages.cpp
index 793fb978b5b4..84257dc85d40 100644
--- a/clang/test/OpenMP/taskwait_messages.cpp
+++ b/clang/test/OpenMP/taskwait_messages.cpp
@@ -1,10 +1,11 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s -Wuninitialized
-// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s -Wuninitialized
template <class T>
T tmain(T argc) {
#pragma omp taskwait allocate(argc) // expected-error {{unexpected OpenMP clause 'allocate' in directive '#pragma omp taskwait'}}
+#pragma omp taskwait depend(in:argc) // expected-error {{unexpected OpenMP clause 'depend' in directive '#pragma omp taskwait'}}
;
#pragma omp taskwait untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp taskwait'}}
#pragma omp taskwait unknown // expected-warning {{extra tokens at the end of '#pragma omp taskwait' are ignored}}
diff --git a/openmp/runtime/test/ompt/tasks/taskwait-depend.c b/openmp/runtime/test/ompt/tasks/taskwait-depend.c
index 16d0ee3c66db..752486c2f144 100644
--- a/openmp/runtime/test/ompt/tasks/taskwait-depend.c
+++ b/openmp/runtime/test/ompt/tasks/taskwait-depend.c
@@ -7,10 +7,9 @@
// icc does not yet support taskwait with depend clause
// XFAIL: icc
-// clang does not yet support taskwait with depend clause
-// clang-12 introduced parsing, but no codegen
-// update expected result when codegen in clang was added
-// XFAIL: clang
+// support for taskwait with depend clause introduced in clang-14
+// UNSUPPORTED: clang-5, clang-6, clang-6, clang-8, clang-9, clang-10, clang-11,
+// clang-12, clang-13
#include "callback.h"
#include <omp.h>
diff --git a/openmp/runtime/test/tasking/omp50_taskwait_depend.c b/openmp/runtime/test/tasking/omp50_taskwait_depend.c
index ee134e9a3826..1e2b16616cc1 100644
--- a/openmp/runtime/test/tasking/omp50_taskwait_depend.c
+++ b/openmp/runtime/test/tasking/omp50_taskwait_depend.c
@@ -1,11 +1,12 @@
// RUN: %libomp-compile-and-run
// UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7, gcc-8
-// clang does not yet support taskwait with depend clause
-// clang-12 introduced parsing, but no codegen
-// TODO: update expected result when codegen in clang is added
+
+// support for taskwait with depend clause introduced in clang-14
+// UNSUPPORTED: clang-5, clang-6, clang-6, clang-8, clang-9, clang-10, clang-11,
+// clang-12, clang-13
+
// icc does not yet support taskwait with depend clause
-// TODO: update expected result when support for icc is added
-// XFAIL: clang, icc
+// XFAIL: icc
#include <stdio.h>
#include <stdlib.h>